Expand description
The HTTP/3 frame layer (RFC 9114 §7).
Every HTTP/3 stream carries the same shape:
Type (varint) | Length (varint) | Frame Payload (Length bytes)Two properties decide the design of FrameDecoder, and they pull in
opposite directions:
- DATA must not be buffered. A CONNECT tunnel’s payload arrives as DATA
frames, and this proxy exists to move them: a reader that accumulated a
whole frame before handing it on would add a copy and a latency step to
every packet. So DATA payload is handed out in exactly the chunks quinn
delivered it in, as [
Bytes] slices of those chunks. - Everything else must be buffered, because it cannot be acted on
piecewise, and its declared length is a varint that may claim 2^62 bytes.
MAX_BUFFERED_FRAMEis what stops a peer naming a length this server would then allocate for, andBufferBudgetis what stops it naming an allowed length on every stream at once (D77).
Unknown frame types are skipped by their declared length without being buffered at all (RFC 9114 §9). That is what lets the protocol be extended, and it is exercised on every connection: clients send reserved “grease” types precisely to catch a peer that cannot skip them.
A frame’s type is judged before its length, and which verdict it earns depends on the stream it arrived on. SETTINGS on a request stream is a connection error at any size, so refusing it for being large would be answering a question the peer did not ask – and charging the buffering budget for a frame that was never allowed there would let a peer hold the budget with frames it is not entitled to send at all.
The decoder is pure: it holds every byte of state, and FrameReader is
the twenty lines that feed it from a QUIC stream. That split is what makes
the frame layer testable a byte at a time, and what makes FrameReader
cancel-safe – the only await is the read, and nothing it produces is lost
by dropping the future. tunnel::udp reads request streams inside a
select! with a timeout, so that property is load-bearing.
Structs§
- Buffer
Budget - What one connection may hold in
FrameDecoderpayload buffers, as a counter every request stream on it shares (D77). - Frame
Decoder - An incremental frame decoder, fed chunks as they arrive.
- Frame
Reader - A
FrameDecoderwired to a QUIC receive stream. - Settings
- The peer’s SETTINGS, reduced to what this server acts on.
Enums§
- Error
- Why the frame reader stopped.
- Frame
- A fully received non-DATA frame.
- Item
- What
FrameReader::nextproduces. - Stream
Kind - Which of this server’s streams a decoder is reading.
Constants§
- CANCEL_
PUSH - CANCEL_PUSH (RFC 9114 §7.2.3).
- DATA
- DATA (RFC 9114 §7.2.1).
- GOAWAY
- GOAWAY (RFC 9114 §7.2.6).
- HEADERS
- HEADERS (RFC 9114 §7.2.2).
- MAX_
PUSH_ ID - MAX_PUSH_ID (RFC 9114 §7.2.7).
- PUSH_
PROMISE - PUSH_PROMISE (RFC 9114 §7.2.5).
- SETTINGS
- SETTINGS (RFC 9114 §7.2.4).
- SETTING_
ENABLE_ CONNECT_ PROTOCOL SETTINGS_ENABLE_CONNECT_PROTOCOL(RFC 9220 §3).- SETTING_
H3_ DATAGRAM SETTINGS_H3_DATAGRAM(RFC 9297 §2.1.1).- SETTING_
MAX_ FIELD_ SECTION_ SIZE SETTINGS_MAX_FIELD_SECTION_SIZE(RFC 9114 §7.2.4.1).- SETTING_
QPACK_ BLOCKED_ STREAMS SETTINGS_QPACK_BLOCKED_STREAMS(RFC 9204 §5).- SETTING_
QPACK_ MAX_ TABLE_ CAPACITY SETTINGS_QPACK_MAX_TABLE_CAPACITY(RFC 9204 §5).
Functions§
- put_
header - Writes a frame header: type and payload length.