void handshake(SSLEngine engine, ByteBuffer input, CodecCallback callback)
            throws IOException {
        if (!mHandshakeStarted) {
            engine.beginHandshake();
            mHandshakeStarted = true;
        }
        SSLEngineResult.HandshakeStatus status = engine.getHandshakeStatus();
        while (!mHandshakeFinished) {
            if (mEngineClosed) {
                throw new IOException("Handshake failed: Engine is closed.");
            }
            if (status == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
                // Should never happen
                throw new IOException("Handshake failed: Invalid handshake status: " + status);
            } else if (status == SSLEngineResult.HandshakeStatus.FINISHED) {
                mHandshakeFinished = true;
                NetBareLog.i("SSL handshake finished!");
                if (input.hasRemaining()) {
                    decode(engine, input, callback);
                }
            } else if (status == SSLEngineResult.HandshakeStatus.NEED_WRAP) {
                status = handshakeWrap(engine, callback).getHandshakeStatus();
            } else if (status == SSLEngineResult.HandshakeStatus.NEED_UNWRAP) {
                // Wait next encrypted buffer.
                if (!input.hasRemaining()) {
                    break;
                }
                status = handshakeUnwrap(engine, input, callback).getHandshakeStatus();
            } else if (status == SSLEngineResult.HandshakeStatus.NEED_TASK) {
                runDelegatedTasks(engine);
            }
        }
    }
Try to encrypt a plaintext packet. If SSL handshake has finished, then encode it,
otherwise add it to queue and wait handshake finished.

@param buffer The plaintext packet.
@param callback A callback to observe actions and receive output packets.
@throws IOException If an I/O error has occurred.
netbare-core/src/main/java/com/github/megatronking/netbare/ssl/SSLCodec.java