src/main/java/org/java_websocket/SSLSocketChannel2.java
private synchronized void processHandshake() throws IOException {
        if( sslEngine.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING )
            return; // since this may be called either from a reading or a writing thread and because this method is synchronized it is necessary to double check if we are still handshaking.
        if( !tasks.isEmpty() ) {
            Iterator<Future<?>> it = tasks.iterator();
            while ( it.hasNext() ) {
                Future<?> f = it.next();
                if( f.isDone() ) {
                    it.remove();
                } else {
                    if( isBlocking() )
                        consumeFutureUninterruptible( f );
                    return;
                }
            }
        }

        if( sslEngine.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_UNWRAP ) {
            if( !isBlocking() || readEngineResult.getStatus() == Status.BUFFER_UNDERFLOW ) {
                inCrypt.compact();
                int read = socketChannel.read( inCrypt );
                if( read == -1 ) {
                    throw new IOException( "connection closed unexpectedly by peer" );
                }
                inCrypt.flip();
            }
            inData.compact();
            unwrap();
            if( readEngineResult.getHandshakeStatus() == HandshakeStatus.FINISHED ) {
                createBuffers( sslEngine.getSession() );
                return;
            }
        }
        consumeDelegatedTasks();
        if( tasks.isEmpty() || sslEngine.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_WRAP ) {
            socketChannel.write( wrap( emptybuffer ) );
            if( writeEngineResult.getHandshakeStatus() == HandshakeStatus.FINISHED ) {
                createBuffers( sslEngine.getSession() );
                return;
            }
        }
        assert ( sslEngine.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING );// this function could only leave NOT_HANDSHAKING after createBuffers was called unless #190 occurs which means that nio wrap/unwrap never return HandshakeStatus.FINISHED

        bufferallocations = 1; // look at variable declaration why this line exists and #190. Without this line buffers would not be be recreated when #190 AND a rehandshake occur.
    }
private synchronized void processHandshake() throws IOException {
        if( sslEngine.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING )
            return; // since this may be called either from a reading or a writing thread and because this method is synchronized it is necessary to double check if we are still handshaking.
        if( !tasks.isEmpty() ) {
            Iterator<Future<?>> it = tasks.iterator();
            while ( it.hasNext() ) {
                Future<?> f = it.next();
                if( f.isDone() ) {
                    it.remove();
                } else {
                    if( isBlocking() )
                        consumeFutureUninterruptible( f );
                    return;
                }
            }
        }

        if( sslEngine.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_UNWRAP ) {
            if( !isBlocking() || readEngineResult.getStatus() == Status.BUFFER_UNDERFLOW ) {
                inCrypt.compact();
                int read = socketChannel.read( inCrypt );
                if( read == -1 ) {
                    throw new IOException( "connection closed unexpectedly by peer" );
                }
                inCrypt.flip();
            }
            inData.compact();
            unwrap();
            if( readEngineResult.getHandshakeStatus() == HandshakeStatus.FINISHED ) {
                createBuffers( sslEngine.getSession() );
                return;
            }
        }
        consumeDelegatedTasks();
        if( tasks.isEmpty() || sslEngine.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_WRAP ) {
            socketChannel.write( wrap( emptybuffer ) );
            if( writeEngineResult.getHandshakeStatus() == HandshakeStatus.FINISHED ) {
                createBuffers( sslEngine.getSession() );
                return;
            }
        }
        assert ( sslEngine.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING );// this function could only leave NOT_HANDSHAKING after createBuffers was called unless #190 occurs which means that nio wrap/unwrap never return HandshakeStatus.FINISHED

        bufferallocations = 1; // look at variable declaration why this line exists and #190. Without this line buffers would not be be recreated when #190 AND a rehandshake occur.
    }
This method will do whatever necessary to process the sslengine handshake.
Thats why it's called both from the {@link #read(ByteBuffer)} and {@link #write(ByteBuffer)}