Skip to main content

Module frame

Module frame 

Source
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_FRAME is what stops a peer naming a length this server would then allocate for, and BufferBudget is 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§

BufferBudget
What one connection may hold in FrameDecoder payload buffers, as a counter every request stream on it shares (D77).
FrameDecoder
An incremental frame decoder, fed chunks as they arrive.
FrameReader
A FrameDecoder wired 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::next produces.
StreamKind
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.