src/main/java/org/java_websocket/SSLSocketChannel2.java
public int read(ByteBuffer dst) throws IOException {
        while (true) {
            if (!dst.hasRemaining())
                return 0;
            if (!isHandShakeComplete()) {
                if (isBlocking()) {
                    while (!isHandShakeComplete()) {
                        processHandshake();
                    }
                } else {
                    processHandshake();
                    if (!isHandShakeComplete()) {
                        return 0;
                    }
                }
            }
            // assert ( bufferallocations > 1 ); //see #190
            //if( bufferallocations <= 1 ) {
            //	createBuffers( sslEngine.getSession() );
            //}
		/* 1. When "dst" is smaller than "inData" readRemaining will fill "dst" with data decoded in a previous read call.
		 * 2. When "inCrypt" contains more data than "inData" has remaining space, unwrap has to be called on more time(readRemaining)
		 */
            int purged = readRemaining(dst);
            if (purged != 0)
                return purged;

		/* We only continue when we really need more data from the network.
		 * Thats the case if inData is empty or inCrypt holds to less data than necessary for decryption
		 */
            assert (inData.position() == 0);
            inData.clear();

            if (!inCrypt.hasRemaining())
                inCrypt.clear();
            else
                inCrypt.compact();

            if (isBlocking() || readEngineResult.getStatus() == Status.BUFFER_UNDERFLOW)
                if (socketChannel.read(inCrypt) == -1) {
                    return -1;
                }
            inCrypt.flip();
            unwrap();

            int transfered = transfereTo(inData, dst);
            if (transfered == 0 && isBlocking()) {
                continue;
            }
            return transfered;
        }
    }
public int read(ByteBuffer dst) throws IOException {
        while (true) {
            if (!dst.hasRemaining())
                return 0;
            if (!isHandShakeComplete()) {
                if (isBlocking()) {
                    while (!isHandShakeComplete()) {
                        processHandshake();
                    }
                } else {
                    processHandshake();
                    if (!isHandShakeComplete()) {
                        return 0;
                    }
                }
            }
            // assert ( bufferallocations > 1 ); //see #190
            //if( bufferallocations <= 1 ) {
            //	createBuffers( sslEngine.getSession() );
            //}
		/* 1. When "dst" is smaller than "inData" readRemaining will fill "dst" with data decoded in a previous read call.
		 * 2. When "inCrypt" contains more data than "inData" has remaining space, unwrap has to be called on more time(readRemaining)
		 */
            int purged = readRemaining(dst);
            if (purged != 0)
                return purged;

		/* We only continue when we really need more data from the network.
		 * Thats the case if inData is empty or inCrypt holds to less data than necessary for decryption
		 */
            assert (inData.position() == 0);
            inData.clear();

            if (!inCrypt.hasRemaining())
                inCrypt.clear();
            else
                inCrypt.compact();

            if (isBlocking() || readEngineResult.getStatus() == Status.BUFFER_UNDERFLOW)
                if (socketChannel.read(inCrypt) == -1) {
                    return -1;
                }
            inCrypt.flip();
            unwrap();

            int transfered = transfereTo(inData, dst);
            if (transfered == 0 && isBlocking()) {
                continue;
            }
            return transfered;
        }
    }
Blocks when in blocking mode until at least one byte has been decoded.<br>
When not in blocking mode 0 may be returned.

@return the number of bytes read.