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;
}