USNavalResearchLaboratory / norm

NACK-Oriented Reliable Multicast (NORM) implementation & tools (RFCs 5740, 5401)
https://www.nrl.navy.mil/Our-Work/Areas-of-Research/Information-Technology/NCS/NORM/
Other
96 stars 33 forks source link

Unable to build for Android #40

Closed agrossmann09 closed 2 years ago

agrossmann09 commented 2 years ago

I am currently trying to build norm to use in an android project. I have tried both the gradle and ant method listed in the repo. The issue with the gradle directory is that it seems to be an empty gradle project. On the other hand the ant method under the android-ndk directory is not compatible with newer android studio versions. When I try to setup the project I continue to receive an error because the android tool is deprecated and doesn't include the options required by the README.

Are there any other methods to compile this with a modern gradle dependent android apk?

agrossmann09 commented 2 years ago

Note: I can build and implement norm on both my raspberry Pi and mac book pro. I want to test communication between all three devices.

bebopagogo commented 2 years ago

Hi @agrossmann09 - Thanks for pointing this out. Somehow the Android files didn't get put on to GitHub from our SVN repository. I think it was because I had a .gitignore for "lib" directories which happens to be the name of the directory with the Android NORM library build files that were missing. I did a test build with the old-ish Android Studio install (3.1.1) I have and it built successfully. Note only the NORM library is built. I should add some of the command-line examples as build options for testing purposes. Let me know if this resolves your issues.

agrossmann09 commented 2 years ago

Hi, thank you for the quick response. I am testing out the new code now but I am still encountering an issue. I have NDK installed through the sdk manager and configured local.properties to define ndk.dir to point to my new ndk directory. However I am receiving this message:

Configure project :lib NDK is missing a "platforms" directory. If you are using NDK, verify the ndk.dir is set to a valid NDK directory. It is currently set to /Users/Owner/Library/Android/sdk/ndk/23.0.7599858. If you are not using NDK, unset the NDK variable from ANDROID_NDK_HOME or local.properties to remove this warning.

FAILURE: Build failed with an exception.

agrossmann09 commented 2 years ago

I also don't know if I should create a separate issue for this, but when I have a sender and receiver active and leave the session with my sender and rejoin. The receiver won't process any new connection from the senders session id. The RFC states that it should drop any previous state it has with the old session and treat the instance as a new one.

bebopagogo commented 2 years ago

When you use NormStartSender() on your sender application, are you making sure that you are using a new sessionId (aka instanceId)  value?  This is how the receiver differentiates when a sender it has previously heard has left/rejoined.

For simplicity in my examples I use a time-seeded random sessionId value but something more deterministic could be done as well.

agrossmann09 commented 2 years ago

I hope I understand this correctly by the receiver reserves resources for each session it keeps track of. Lets say for scalability reasons we create and disconnect many sessions. Will resource constraints be a problem if we continually leave the session. I am thinking of a situation where we might not want the session to be continually running. I know we can set the TTL on the recv end but was just curious.

bebopagogo commented 2 years ago

With regards to you Android Studio question, I don't use it often enough to have an offhand answer to your question. From the error message you are getting, perhaps you need to also install a target platform component (like x86 or ARM, etc processor) for it to build an appropriate library?

bebopagogo commented 2 years ago

It doesn't keep history on the sender instanceId so in actuality as soon as it sees a new instanceId, it drops all state for the prior instance of a given sender NormNodeId. So, if a another new instanceId shows up that is different from the current one, even if it is one that was used previously, it will have the same effect.

agrossmann09 commented 2 years ago

Again thank you for explaining the functionality to me. So if I understand correctly lets say I have comms between a sender and recv. If halfway through those comms if another sender with a different instanceID sends a message, then the previous comms with the original sender would be dropped?

bebopagogo commented 2 years ago

That's correct. That also means if the previous transmission has not successfully completed, it will be lost. If you want to ensure that does not happen, consider using the optional ACK mechanism for receipt confirmation before the prior sender instance exits. The "example" applications (normMsgr, normStreamer, normCast) illustrate this.

agrossmann09 commented 2 years ago

I think what attracted me to norm was the lack of receipt confirmation. Is there a way to configure norm so that if another sender is queuing a data object, not to send that object until the floor is clear so that it doesn't interrupt another sender?

agrossmann09 commented 2 years ago

I was also able to get around my android problem and then hit another. I am now using ndk version 20.0.5594570, but encountered this error: Invalid revision: 3.18.1-g262b90

agrossmann09 commented 2 years ago

Okay I was able to solve my issue with the ndk. I needed to upgrade my android version to 27 and in the CMakeLists.txt change it to android 27. Before that I also needed to downgrade my cmake version. This is just a work around and not a solution.

agrossmann09 commented 2 years ago

Once I have the binaries built, what is the usage? Can I develop my own app with the libraries built and if so which ones do I have to implement in my custom gradle file?

bebopagogo commented 2 years ago

I think what attracted me to norm was the lack of receipt confirmation. Is there a way to configure norm so that if another sender is queuing a data object, not to send that object until the floor is clear so that it doesn't interrupt another sender?

NORM does not have a built-in floor control protocol. One could use the NORM API to do something since there are notifications issued when object reception starts/stops and a sort of carrier-sense multiple access floor control protocol could written at the application layer using those cues (e.g. with random backoff timeouts some multiple of GRTT to reduce floor access "collisions" and perhaps use lowest or highest NormNodeId to give priority access on a "collision" ... although that approach would bias access ... I suppose a rule to give precedence to the node that has gone longest withoout floor access longest and then break a tie with the low (or high) node id could be used .... It would be fun to implement ;-)

bebopagogo commented 2 years ago

Once I have the binaries built, what is the usage? Can I develop my own app with the libraries built and if so which ones do I have to implement in my custom gradle file?

Yes - once you have built the NORM libraries you can link those to your own NDK code. I think we have also build and used the NORM JNI binding for some Android apps in the past. Personally, I have been using a cross-platform C++ GUI framework where specific submodules can be specified via source file and I just include the NORM and Protolib source files as submodules of the project (That particular framework then generates the Android Studio projects for me so I haven't delved much myself into the details of creating proper Android Studio projects from scratch). For a command-line NDK service or application on Android, you can just do your own NDK project. The MGEN project I also have here on Github builds the "mgen" command-line executable as an Android executable.

bebopagogo commented 2 years ago

(BTW - this line of discussion might be a better fit to the NORM "Discussions" area rather than under an "Issue")

agrossmann09 commented 2 years ago

Okay, I will move my discussion on android to the "Discussions." Thank you for answering my other question.

agrossmann09 commented 2 years ago

Or were you referring to my 'floor' question should be moved to "Discussions"? I am still having trouble with Android. I have a .aar file now and was able to import it, but the only class available is BuildConfig.

bebopagogo commented 2 years ago

Yes - I was thinking more about the "floor control" protocol question if it become more of a discussion thread. The Android issues we keep here if you want although now that we have resolved the Android build of the norm library, your questions are more in the vein of Android development issues. I have limited experience with that and some of those question may be more quickly/better addressed in an Android development forum. I am happy to help as I can and certainly will address anything from the NORM code standpoint that I can.

The current gradle files build the NDK NORM library as a static library that can be linked against from other NDK code. The JNI code is also compiled and a shared library is built "libmil_navy_nrl_norm.so" that would be used with a JAR file so that the Java API binding could be used for an Android Java application. I don't think the current gradle config builds the JAR file. The other build system (e.g., waf) do provide means to build the JAR file. I need to check with someone on my team who has used the NORM Java API on Android on how they built the JAR, etc. It may be the case that was done with the older Android build approach prior to Android Studio use of gradle.

agrossmann09 commented 2 years ago

Okay. I assumed gradle might be the easiest form of building the libraries I needed since the method in the makefile uses outdated tools. I am more than happy to walk through that method if it produces the jar files needed, I am just not familiar with those build tools and how to get them to work on a newer system.

bebopagogo commented 2 years ago

I'm in work meetings, etc but I'm doing a little web searching to see what would need to be added to the gradle file to also build the JAR file and a .aar if that what is needed to better support Android NORM app development. It looks like this may be possible and if you determine how to do that I would be happy to accept a pull request or incorporate that into the gradle configuration files.

agrossmann09 commented 2 years ago

Okay I will do some research as well and see if I can get it to build the jar. When you get time to answer as I know you are working, will norm perform packet fragmentation if my bytebuffer or file is over 1500 bytes? It seems protolib crashes when sending over 1440 bytes.

bebopagogo commented 2 years ago

Yes - NORM fragments data into the configured "segment size" that is set as part of the NormStartSender() API.

Which Protolib class/method are you referring to? There are some operating system limits and defaults that can come into play. For example, UDP datagrams are often limited to an 8192 byte max. I'm not sure where the 1440 max may come from. Some of my code examples may not be as rigorous as they should be and may exhibit such issues, but the ProtoSocket APIs should work (or not) with crash issues. If you do find a bug like that, let me know

agrossmann09 commented 2 years ago

I'm sorry to return back to this thread but I was able to get everything built and used in an Android application. It involved building the ant jar and bundling into the .aar. Then the app just needs to run a couple of tasks, which I detail in the README, and everything works. I have a branch created but I don't think I can push. Please let me know if you would like me to continue with the push/merge and review.

bebopagogo commented 2 years ago

I accepted the pull request. Feel free to close this issue if you are satisfied.