NIO, SSLEngine, Android
I really like writing networking code for Android using Java NIO.
It’s scalable, it is a good fit for Android’s event-driven architecture. It’s easy to clean up at any point, which is especially important since Android manages process lifecycles on its own.
There is no built-in support in NIO for SSL-encrypted sockets, though.
In the “old” (non-NIO) Java networking classes, you could instantiate an SSLSocket or SSLServerSocket, and then pass it to code that didn’t have to be at all aware that it’s working with an encrypted socket. This makes adding SSL support really easy.
Implementing SSL support for NIO based networking is done by using a special class, SSLEngine, that handles SSL handshaking and conversions between encrypted and decrypted data. SSLEngine is not integrated with NIO sockets at all (or any other I/O, for that matter), and, as a consequence, it’s quite difficult to use. Supposedly, this is to make SSLEngine more flexible, but personally I don’t understand this – SSL is used for network IO. I don’t see using SSL to connect a pair of files on disk, or strings in memory.
Unfortunatley, there exists a bug that prevents anyone from successfully using SSLEngine on Android:
The code crashes at some point during SSL handshaking, when it’s pretty much done and is ready to create an SSLSession (a class that reprensets an established secure link between the client and the server).
The bug is fixed in Froyo, but that doesn’t help anyone who needs to support the versions of Android that are actually out there.
I am unable to find a workaround. Tried using reflection to set certains fields to non-null values (them being null is the immediate cause of this problem), but this didn’t work, as the fields are package-level, but public.
The really ironic thing is that this bug was known to the Android team at least since Cupcake (version 1.5). Here is a link to automated test source for SSLEngine:
Note this comment towards the end of the file:
@KnownFailure(“Handshake Status is never finished. NPE in ”
+ “ClientSessionContext$HostAndPort.hashCode() when host is null”)
I guess fixing this didn’t make the shortlist for any release until Froyo. All I can say, is “too bad”.