private SSLEngineResult handshakeUnwrap(SSLEngine engine, ByteBuffer input,
                                            CodecCallback callback) throws IOException {
        SSLEngineResult result;
        SSLEngineResult.Status status;
        ByteBuffer output = allocate();
        while (true) {
            result = engineUnwrap(engine, input, output);
            status = result.getStatus();
            output.flip();
            int producedSize = output.remaining();
            if (producedSize > 0) {
                callback.onDecrypt(output);
            }
            if (status == SSLEngineResult.Status.BUFFER_OVERFLOW) {
                int bufferSize = engine.getSession().getApplicationBufferSize() - producedSize;
                if (bufferSize < 0) {
                    bufferSize = engine.getSession().getApplicationBufferSize();
                }
                output = allocate(bufferSize);
            } else if (status == SSLEngineResult.Status.BUFFER_UNDERFLOW) {
                // Store the remaining packet and wait next encrypted buffer.
                if (input.hasRemaining()) {
                    callback.onPending(ByteBuffer.wrap(input.array(), input.position(),
                            input.remaining()));
                    // Clear all data.
                    input.position(0);
                    input.limit(0);
                }
                break;
            } else if (status == SSLEngineResult.Status.CLOSED) {
                mEngineClosed = true;
                break;
            } else {
                // It is status OK.
                break;
            }
        }
        return result;
    }
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