Shutting Down

For an orderly shutdown of an SSL/TLS connection, the SSL/TLS protocols require transmission of close messages. Therefore, when an application is done with the SSL/TLS connection, it should first obtain the close messages from the SSLEngine, then transmit them to the peer using its transport mechanism, and finally shut down the transport mechanism. Here is an example.
// Indicate that application is done with engine
engine.closeOutbound();
while (!engine.isOutboundDone()) {
 // Get close message
 SSLEngineResult res = engine.wrap(empty, myNetData);
 // Check res statuses
 // Send close message to peer
 while(myNetData().hasRemaining()) {
  int num = socketChannel.write(myNetData);
  if (num == -1) {
   // handle closed channel
  } else if (num == 0) {
   // no bytes written; try again later
  }
  myNetData().compact();
 }
}
// Close transport
socketChannel.close();

In addition to an application explicitly closing the SSLEngine, the SSLEngine might be closed by the peer (via receipt of a close message while it is processing handshake data), or by the SSLEngine encountering an error while processing application or handshake data, indicated by throwing an SSLException. In such cases, the application should invoke SSLEngine.wrap() to get the close message and send it to the peer until SSLEngine.isOutboundDone() returns true, as shown in the previous example, or the SSLEngineResult.getStatus() returns CLOSED.

In addition to orderly shutdowns, there can also be unorderly shutdowns in which the transport link is severed before close messages are exchanged. In the previous examples, the application might get -1 when trying to read or write to the non-blocking SocketChannel. When you get to the end of your input data, you should call engine.closeInbound(), which will verify with the SSLEngine that the remote peer has closed cleanly from the SSL/TLS perspective, and then the application should still try to shutdown cleanly by using the procedure described previously. Obviously, unlike SSLSocket, the application using SSLEngine must deal with more state transitions, statuses and programming than when using SSLEngine.