pub struct FrameDecoder { /* private fields */ }Expand description
An incremental frame decoder, fed chunks as they arrive.
Written the same way as crate::capsule::CapsuleDecoder, and for the same
reason: frames do not align with stream chunks in either direction, so the
decoder has to be a state machine that can be fed a byte at a time – which
is exactly how the tests below feed it.
Public, though nothing outside this module constructs one at run time:
FrameReader is what the server uses, and crate::h3api deliberately
re-exports neither. What needs this is tests/it_fuzz.rs, where the
properties about chunk boundaries and about which frame type belongs on which
stream are worth far more when they can be stated against the state machine
itself – a byte at a time, at chosen split points, on a StreamKind the
test picks – than against a loopback QUIC connection whose packetisation is
quinn’s to decide. It is documented rather than hidden because this module’s
own prose already names it as the design’s centre.
Implementations§
Source§impl FrameDecoder
impl FrameDecoder
Sourcepub fn new(stream: StreamKind, budget: Arc<BufferBudget>) -> Self
pub fn new(stream: StreamKind, budget: Arc<BufferBudget>) -> Self
A decoder positioned at the start of a stream’s frame sequence, drawing
on budget for whatever it has to buffer.
Sourcepub fn push(&mut self, chunk: Bytes)
pub fn push(&mut self, chunk: Bytes)
Hands the decoder the next chunk of stream.
Only legal once Self::next_item has asked for more, which is the only
state in which the previous chunk is spent.
Sourcepub fn connect_completed(&mut self)
pub fn connect_completed(&mut self)
Narrows the frame rules to the ones RFC 9114 §4.4 gives a tunnel.
Called once the 2xx answering a CONNECT has gone out, which is what “completed” means in that section. From here a HEADERS frame is a connection error like every other known type but DATA, and it is refused from its header rather than after its payload – so a peer cannot hold the connection’s buffering budget with field sections it was never allowed to send.
Sourcepub fn at_frame_boundary(&self) -> bool
pub fn at_frame_boundary(&self) -> bool
Whether the stream could end here without truncating a frame.
RFC 9114 §7.1: “When a stream terminates cleanly, if the last frame on the stream was truncated, this MUST be treated as a connection error of type H3_FRAME_ERROR.”
Trait Implementations§
Source§impl Debug for FrameDecoder
impl Debug for FrameDecoder
Source§impl Drop for FrameDecoder
impl Drop for FrameDecoder
Source§fn drop(&mut self)
fn drop(&mut self)
Returns the budget a half-received frame was holding (D77).
The guard that makes the accounting sound: a stream can end at any
point, and most of the ways it ends are the peer’s to choose – a
RESET_STREAM, a STOP_SENDING answered, the request deadline of D76
expiring, the connection going away. None of them reaches the decoding
loop, and a share not returned on any one of them would be a slow leak
of the connection’s own allowance, ending in a peer being refused a
request it was entitled to.