public RawFrame read()

in httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/FrameInputBuffer.java [108:186]


    public RawFrame read(final ByteBuffer src, final ReadableByteChannel channel) throws IOException {
        for (;;) {
            if (src != null) {
                if (buffer.hasRemaining()) {
                    buffer.compact();
                } else {
                    buffer.clear();
                }
                final int remaining = buffer.remaining();
                final int n = src.remaining();
                if (remaining >= n) {
                    buffer.put(src);
                    metrics.incrementBytesTransferred(n);
                } else {
                    final int limit = src.limit();
                    src.limit(remaining);
                    buffer.put(src);
                    src.limit(limit);
                    metrics.incrementBytesTransferred(remaining);
                }
                buffer.flip();
            }
            switch (state) {
                case HEAD_EXPECTED:
                    if (buffer.remaining() >= FrameConsts.HEAD_LEN) {
                        final int lengthAndType = buffer.getInt();
                        payloadLen = lengthAndType >> 8;
                        if (payloadLen > maxFramePayloadSize) {
                            throw new H2ConnectionException(H2Error.FRAME_SIZE_ERROR, "Frame size exceeds maximum");
                        }
                        type = lengthAndType & 0xff;
                        flags = buffer.get();
                        streamId = Math.abs(buffer.getInt());
                        state = State.PAYLOAD_EXPECTED;
                    } else {
                        break;
                    }
                case PAYLOAD_EXPECTED:
                    if (buffer.remaining() >= payloadLen) {
                        if ((flags & FrameFlag.PADDED.getValue()) > 0) {
                            if (payloadLen == 0) {
                                throw new H2ConnectionException(H2Error.PROTOCOL_ERROR, "Inconsistent padding");
                            }
                            buffer.mark();
                            final int padding = buffer.get();
                            if (payloadLen < padding + 1) {
                                throw new H2ConnectionException(H2Error.PROTOCOL_ERROR, "Inconsistent padding");
                            }
                            buffer.reset();
                        }
                        final ByteBuffer payload = payloadLen > 0 ? ByteBuffer.wrap(bytes, buffer.position(), payloadLen) : null;
                        buffer.position(buffer.position() + payloadLen);
                        state = State.HEAD_EXPECTED;
                        metrics.incrementFramesTransferred();
                        return new RawFrame(type, flags, streamId, payload);
                    }
            }
            if (buffer.hasRemaining()) {
                buffer.compact();
            } else {
                buffer.clear();
            }
            final int bytesRead = channel.read(buffer);
            buffer.flip();
            if (bytesRead > 0) {
                metrics.incrementBytesTransferred(bytesRead);
            }
            if (bytesRead == 0) {
                break;
            } else if (bytesRead < 0) {
                if (state != State.HEAD_EXPECTED || buffer.hasRemaining()) {
                    throw new H2CorruptFrameException("Corrupt or incomplete HTTP2 frame");
                } else {
                    throw new ConnectionClosedException();
                }
            }
        }
        return null;
    }