if (mTrace) trace("handshake deferred: already complete");
if (mTrace) debug("handshake deferred: already complete");
    private boolean handshake(ByteBuffer rbb) throws IOException {        if (mHandshakeComplete) {            if (mTrace) trace("handshake deferred: already complete");            return mHandshakeComplete;        }                if (rbb != null && !rbb.hasRemaining()) {            if (mDebug) debug("handshake deferred: no bytes in input");            return mHandshakeComplete;        }                if (!getNextFilter().flush()) {            return mHandshakeComplete;        }                switch (mHandshakeStatus) {        case NEED_UNWRAP:            unwrap: while (mHandshakeStatus == HandshakeStatus.NEED_UNWRAP) {                rbb.flip();                ensureUnwrappedCapacity();                SSLEngineResult result = mSSLEngine.unwrap(rbb, mUnwrapped);                rbb.compact();                if (mDebug) debug("handshake: unwrap result " + toString(result));                mHandshakeStatus = result.getHandshakeStatus();                switch (result.getStatus()) {                case OK:                    switch(mHandshakeStatus) {                    case NOT_HANDSHAKING:                         throw new IOException("TLS handshake: NOT_HANDSHAKING while handshaking");                    case NEED_TASK:                        mHandshakeStatus = runTasks();                        break;                    case FINISHED:                        handshakeCompleted();                        break unwrap;                    }                    break;                case BUFFER_UNDERFLOW:                    if (mDebug) debug("handshake: need more bytes");                    mConnection.enableReadInterest();                    break unwrap;                                    case BUFFER_OVERFLOW:                case CLOSED:                    throw new IOException("TLS handshake: in unwrap got " + result.getStatus());                }            }            if (mHandshakeStatus != HandshakeStatus.NEED_WRAP) {                break;            }            /* Falling through, because while unwrapping, we were asked to wrap. */                    case NEED_WRAP:            wrap: while (true) {                ByteBuffer dest = ByteBuffer.allocate(mPacketBufferSize);                SSLEngineResult result = mSSLEngine.wrap(mHandshakeBB, dest);                dest.flip();                mHandshakeStatus = result.getHandshakeStatus();                if (mDebug) debug("handshake: wrap result " + toString(result));                switch (result.getStatus()) {                case OK:                    if (mDebug) debug("handshake: writing wrapped bytes");                    getNextFilter().write(dest);                    if (mHandshakeStatus == HandshakeStatus.NEED_TASK) {                        mHandshakeStatus = runTasks();                    }                    switch (mHandshakeStatus) {                    case FINISHED:                        handshakeCompleted();                        break wrap;                    case NEED_UNWRAP:                        mConnection.enableReadInterest();                        break wrap;                    case NEED_WRAP:                        break;                    default:                        throw new IOException("TLS handshake: can not deal with handshake status (wrap): " + mHandshakeStatus);                    }                    break;                case BUFFER_OVERFLOW:                case BUFFER_UNDERFLOW:                case CLOSED:                    throw new IOException("TLS handshake: in wrap got status " + result.getStatus());                }            }            break;                default:            throw new IOException("TLS handshake: can not deal with handshake status: " + mHandshakeStatus);        }                return mHandshakeComplete;    }