public RawFrame read(final InputStream inStream) throws IOException {
fillBuffer(inStream, FrameConsts.HEAD_LEN);
final int payloadOff = FrameConsts.HEAD_LEN;
final int payloadLen = (buffer[off] & 0xff) << 16 | (buffer[off + 1] & 0xff) << 8 | (buffer[off + 2] & 0xff);
final int type = buffer[off + 3] & 0xff;
final int flags = buffer[off + 4] & 0xff;
final int streamId = Math.abs(buffer[off + 5] & 0xff) << 24 | (buffer[off + 6] & 0xff << 16) | (buffer[off + 7] & 0xff) << 8 | (buffer[off + 8] & 0xff);
if (payloadLen > maxFramePayloadSize) {
throw new H2ConnectionException(H2Error.FRAME_SIZE_ERROR, "Frame size exceeds maximum");
}
final int frameLen = payloadOff + payloadLen;
fillBuffer(inStream, frameLen);
if ((flags & FrameFlag.PADDED.getValue()) > 0) {
if (payloadLen == 0) {
throw new H2ConnectionException(H2Error.PROTOCOL_ERROR, "Inconsistent padding");
}
final int padding = buffer[off + FrameConsts.HEAD_LEN] & 0xff;
if (payloadLen < padding + 1) {
throw new H2ConnectionException(H2Error.PROTOCOL_ERROR, "Inconsistent padding");
}
}
final ByteBuffer payload = payloadLen > 0 ? ByteBuffer.wrap(buffer, off + payloadOff, payloadLen) : null;
final RawFrame frame = new RawFrame(type, flags, streamId, payload);
off += frameLen;
dataLen -= frameLen;
this.metrics.incrementFramesTransferred();
return frame;
}