Package io.github.mahmoudimus.http3
Class Http3FrameReader
java.lang.Object
io.github.mahmoudimus.http3.Http3FrameReader
Reads HTTP/3 frames from one QUIC stream's bytes, one call per frame, validating everything that
can be checked from a frame on its own (RFC 9114 §7). Meant to be driven by one (virtual) thread
per stream; it buffers nothing itself, so give it a
BufferedInputStream or
similar. Not thread-safe.
Http3FrameReader reader = new Http3FrameReader(requestStreamInput);
Http3StreamValidator validator = Http3StreamValidator.forRequestStream(streamId, Role.SERVER);
for (Http3Frame frame; (frame = reader.readFrame()) != null; ) {
validator.onFrame(frame);
switch (frame) {
case Http3Frame.Headers h -> fields = qpack.decode(streamId, h.fieldSection());
case Http3Frame.Data d -> body.write(d.data());
default -> {}
}
}
validator.onEndOfStream();
What it enforces:
- A payload of at most
setMaxFramePayloadSize(int)bytes (default 64 KiB), checked before anything is allocated; a longer one is a connection error H3_EXCESSIVE_LOAD. DATA is the exception: HTTP/3 gives DATA frame boundaries no meaning, so a longer DATA frame is returned as consecutiveHttp3Frame.Datapieces of at most that size, and memory per frame stays bounded by the limit either way. - Payloads that hold exactly their fields (CANCEL_PUSH, GOAWAY, MAX_PUSH_ID, SETTINGS, PUSH_PROMISE), and frames cut short by the end of the stream: connection error H3_FRAME_ERROR.
- The HTTP/2 frame types that HTTP/3 forbids (0x02, 0x06, 0x08, 0x09): connection error H3_FRAME_UNEXPECTED.
- SETTINGS: no identifier twice, none of the HTTP/2-only identifiers, and valid values for the defined ones (connection error H3_SETTINGS_ERROR).
Frames of unknown and reserved types are returned as Http3Frame.Unknown, so they can
be relayed, unless setDeliverUnknownFrames(boolean) turns that off; then they are
skipped without allocating their payload. Which frames may appear on which stream, and in what
order, is Http3StreamValidator's job.
Every error is a connection error, and the reader must not be used after one.
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final intThe default limit on a frame payload, 64 KiB. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionintThe largest payload accepted.static Http3FrameReaderof(ByteBuffer buf) A reader over the remaining bytes of a buffer, which it consumes.static Http3Frameparse(ByteBuffer buf, int maxFramePayloadSize) Parses one whole frame at the buffer's position, for callers that collect a stream's bytes in a buffer.Reads the next frame.longReads the stream type that starts every unidirectional stream (RFC 9114 §6.2); seeHttp3StreamType.voidsetDeliverUnknownFrames(boolean deliverUnknownFrames) Return frames of unknown and reserved types asHttp3Frame.Unknown(the default) or skip them.voidsetMaxFramePayloadSize(int maxFramePayloadSize) The largest payload accepted (and the largest piece a long DATA frame is returned in).
-
Field Details
-
DEFAULT_MAX_FRAME_PAYLOAD_SIZE
public static final int DEFAULT_MAX_FRAME_PAYLOAD_SIZEThe default limit on a frame payload, 64 KiB.- See Also:
-
-
Constructor Details
-
Http3FrameReader
A reader for one stream.- Parameters:
in- the stream's bytes; give it a buffered stream
-
-
Method Details
-
of
A reader over the remaining bytes of a buffer, which it consumes.- Parameters:
buf- the bytes- Returns:
- the reader
-
setMaxFramePayloadSize
public void setMaxFramePayloadSize(int maxFramePayloadSize) The largest payload accepted (and the largest piece a long DATA frame is returned in).- Parameters:
maxFramePayloadSize- the limit in bytes, 1 to 2^31-9
-
maxFramePayloadSize
public int maxFramePayloadSize()The largest payload accepted.- Returns:
- the limit in bytes
-
setDeliverUnknownFrames
public void setDeliverUnknownFrames(boolean deliverUnknownFrames) Return frames of unknown and reserved types asHttp3Frame.Unknown(the default) or skip them.- Parameters:
deliverUnknownFrames- whether to return them
-
readStreamType
Reads the stream type that starts every unidirectional stream (RFC 9114 §6.2); seeHttp3StreamType. Call it once, before the firstreadFrame().- Returns:
- the type, or -1 if the stream ended before all of it arrived (which a receiver must tolerate)
- Throws:
IOException- if reading fails
-
readFrame
Reads the next frame.- Returns:
- the frame, or null if the stream ended cleanly between frames
- Throws:
Http3Exception- if the frame breaks the protocol or a limit, or the stream ends inside itIOException
-
parse
Parses one whole frame at the buffer's position, for callers that collect a stream's bytes in a buffer. The limit applies to every frame type here, DATA included; read long DATA frames with a reader over a stream instead.- Parameters:
buf- the stream's bytes so farmaxFramePayloadSize- the largest payload accepted- Returns:
- the frame, with the position moved past it; or null, with the position unchanged, if the buffer holds only part of it
- Throws:
Http3Exception- asreadFrame(), and H3_EXCESSIVE_LOAD for a DATA frame longer thanmaxFramePayloadSize
-