private boolean wrapNonAppData(ChannelHandlerContext ctx, boolean inUnwrap) throws SSLException {
        ByteBuf out = null;
        ByteBufAllocator alloc = ctx.alloc();
        try {
            // Only continue to loop if the handler was not removed in the meantime.
            // See https://github.com/netty/netty/issues/5860
            outer: while (!ctx.isRemoved()) {
                if (out == null) {
                    // As this is called for the handshake we have no real idea how big the buffer needs to be.
                    // That said 2048 should give us enough room to include everything like ALPN / NPN data.
                    // If this is not enough we will increase the buffer in wrap(...).
                    out = allocateOutNetBuf(ctx, 2048, 1);
                }
                SSLEngineResult result = wrap(alloc, engine, Unpooled.EMPTY_BUFFER, out);

                if (result.bytesProduced() > 0) {
                    ctx.write(out);
                    if (inUnwrap) {
                        needsFlush = true;
                    }
                    out = null;
                }

                HandshakeStatus status = result.getHandshakeStatus();
                switch (status) {
                    case FINISHED:
                        setHandshakeSuccess();
                        return false;
                    case NEED_TASK:
                        if (!runDelegatedTasks(inUnwrap)) {
                            // We scheduled a task on the delegatingTaskExecutor, so stop processing as we will
                            // resume once the task completes.
                            break outer;
                        }
                        break;
                    case NEED_UNWRAP:
                        if (inUnwrap) {
                            // If we asked for a wrap, the engine requested an unwrap, and we are in unwrap there is
                            // no use in trying to call wrap again because we have already attempted (or will after we
                            // return) to feed more data to the engine.
                            return false;
                        }

                        unwrapNonAppData(ctx);
                        break;
                    case NEED_WRAP:
                        break;
                    case NOT_HANDSHAKING:
                        setHandshakeSuccessIfStillHandshaking();
                        // Workaround for TLS False Start problem reported at:
                        // https://github.com/netty/netty/issues/1108#issuecomment-14266970
                        if (!inUnwrap) {
                            unwrapNonAppData(ctx);
                        }
                        return true;
                    default:
                        throw new IllegalStateException("Unknown handshake status: " + result.getHandshakeStatus());
                }

                // Check if did not produce any bytes and if so break out of the loop, but only if we did not process
                // a task as last action. It's fine to not produce any data as part of executing a task.
                if (result.bytesProduced() == 0 && status != HandshakeStatus.NEED_TASK) {
                    break;
                }

                // It should not consume empty buffers when it is not handshaking
                // Fix for Android, where it was encrypting empty buffers even when not handshaking
                if (result.bytesConsumed() == 0 && result.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING) {
                    break;
                }
            }
        }  finally {
            if (out != null) {
                out.release();
            }
        }
        return false;
    }
private boolean wrapNonAppData ( ChannelHandlerContext ctx , boolean inUnwrap ) throws SSLException { ByteBuf out = null ; ByteBufAllocator alloc = ctx . alloc ( ) ; try { outer : while ( ! ctx . isRemoved ( ) ) { if ( out == null ) { out = allocateOutNetBuf ( ctx , 2048 , 1 ) ; } SSLEngineResult result = wrap ( alloc , engine , Unpooled . EMPTY_BUFFER , out ) ; if ( result . bytesProduced ( ) > 0 ) { ctx . write ( out ) ; if ( inUnwrap ) { needsFlush = true ; } out = null ; } HandshakeStatus status = result . getHandshakeStatus ( ) ; switch ( status ) { case FINISHED : setHandshakeSuccess ( ) ; return false ; case NEED_TASK : if ( ! runDelegatedTasks ( inUnwrap ) ) { break outer ; } break ; case NEED_UNWRAP : if ( inUnwrap ) { return false ; } unwrapNonAppData ( ctx ) ; break ; case NEED_WRAP : break ; case NOT_HANDSHAKING : setHandshakeSuccessIfStillHandshaking ( ) ; if ( ! inUnwrap ) { unwrapNonAppData ( ctx ) ; } return true ; default : throw new IllegalStateException ( "Unknown handshake status: " + result . getHandshakeStatus ( ) ) ; } if ( result . bytesProduced ( ) == 0 && status != HandshakeStatus . NEED_TASK ) { break ; } if ( result . bytesConsumed ( ) == 0 && result . getHandshakeStatus ( ) == HandshakeStatus . NOT_HANDSHAKING ) { break ; } } } finally { if ( out != null ) { out . release ( ) ; } } return false ; }
This method will not call
{@link #setHandshakeFailure(ChannelHandlerContext, Throwable, boolean, boolean, boolean)} or
{@link #setHandshakeFailure(ChannelHandlerContext, Throwable)}.
@return {@code true} if this method ends on {@link SSLEngineResult.HandshakeStatus#NOT_HANDSHAKING}.