public int handshake(boolean read, boolean write) throws IOException {
if ( initHandshakeComplete ) return 0; //we have done our initial handshake
if (!flush(netOutBuffer)) return SelectionKey.OP_WRITE; //we still have data to write
SSLEngineResult handshake = null;
while (!initHandshakeComplete) {
switch ( initHandshakeStatus ) {
case NOT_HANDSHAKING: {
//should never happen
throw new IOException("NOT_HANDSHAKING during handshake");
}
case FINISHED: {
//we are complete if we have delivered the last package
initHandshakeComplete = !netOutBuffer.hasRemaining();
//return 0 if we are complete, otherwise we still have data to write
return initHandshakeComplete?0:SelectionKey.OP_WRITE;
}
case NEED_WRAP: {
//perform the wrap function
handshake = handshakeWrap(write);
if ( handshake.getStatus() == Status.OK ){
if (initHandshakeStatus == HandshakeStatus.NEED_TASK)
initHandshakeStatus = tasks();
} else {
//wrap should always work with our buffers
throw new IOException("Unexpected status:" + handshake.getStatus() + " during handshake WRAP.");
}
if ( initHandshakeStatus != HandshakeStatus.NEED_UNWRAP || (!flush(netOutBuffer)) ) {
//should actually return OP_READ if we have NEED_UNWRAP
return SelectionKey.OP_WRITE;
}
//fall down to NEED_UNWRAP on the same call, will result in a
//BUFFER_UNDERFLOW if it needs data
}
case NEED_UNWRAP: {
//perform the unwrap function
handshake = handshakeUnwrap(read);
if ( handshake.getStatus() == Status.OK ) {
if (initHandshakeStatus == HandshakeStatus.NEED_TASK)
initHandshakeStatus = tasks();
} else if ( handshake.getStatus() == Status.BUFFER_UNDERFLOW ){
//read more data, reregister for OP_READ
return SelectionKey.OP_READ;
} else {
throw new IOException("Invalid handshake status:"+initHandshakeStatus+" during handshake UNWRAP.");
}//switch