Shutting Down
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
.