Skip to main content

net_wire/quic/
frame.rs

1//! RFC 9000 core frame parsing.
2
3mod ack;
4mod connection_close;
5mod connection_id;
6mod control;
7mod crypto;
8mod parse;
9mod path;
10mod stream;
11mod token;
12
13pub use ack::{QuicAckFrame, QuicAckRange, QuicAckRanges, QuicEcnCounts};
14pub use connection_close::QuicConnectionCloseFrame;
15pub use connection_id::{QuicNewConnectionIdFrame, QuicRetireConnectionIdFrame};
16pub use control::{
17    QuicDataBlockedFrame, QuicMaxDataFrame, QuicMaxStreamDataFrame, QuicMaxStreamsFrame,
18    QuicResetStreamFrame, QuicStopSendingFrame, QuicStreamDataBlockedFrame, QuicStreamDirection,
19    QuicStreamsBlockedFrame,
20};
21pub use crypto::QuicCryptoFrame;
22pub use parse::{QuicFrameField, QuicFrameParseError};
23pub use path::{QuicPathChallengeFrame, QuicPathResponseFrame};
24pub use stream::QuicStreamFrame;
25pub use token::QuicNewTokenFrame;
26
27use core::iter::FusedIterator;
28
29use super::varint::QuicVarInt;
30
31/// A checked borrowed PADDING frame view.
32#[derive(Clone, Copy, Debug, Eq, PartialEq)]
33pub struct QuicPaddingFrame<'a> {
34    bytes: &'a [u8],
35    frame_type: QuicVarInt<'a>,
36}
37
38impl<'a> QuicPaddingFrame<'a> {
39    /// Returns the exact encoded frame bytes.
40    pub const fn as_bytes(self) -> &'a [u8] {
41        self.bytes
42    }
43
44    /// Returns the exact encoded frame-type variable integer.
45    pub const fn frame_type(self) -> QuicVarInt<'a> {
46        self.frame_type
47    }
48}
49
50/// A checked borrowed PING frame view.
51#[derive(Clone, Copy, Debug, Eq, PartialEq)]
52pub struct QuicPingFrame<'a> {
53    bytes: &'a [u8],
54    frame_type: QuicVarInt<'a>,
55}
56
57impl<'a> QuicPingFrame<'a> {
58    /// Returns the exact encoded frame bytes.
59    pub const fn as_bytes(self) -> &'a [u8] {
60        self.bytes
61    }
62
63    /// Returns the exact encoded frame-type variable integer.
64    pub const fn frame_type(self) -> QuicVarInt<'a> {
65        self.frame_type
66    }
67}
68
69/// A checked borrowed HANDSHAKE_DONE frame view.
70#[derive(Clone, Copy, Debug, Eq, PartialEq)]
71pub struct QuicHandshakeDoneFrame<'a> {
72    bytes: &'a [u8],
73    frame_type: QuicVarInt<'a>,
74}
75
76impl<'a> QuicHandshakeDoneFrame<'a> {
77    /// Returns the exact encoded frame bytes.
78    pub const fn as_bytes(self) -> &'a [u8] {
79        self.bytes
80    }
81
82    /// Returns the exact encoded frame-type variable integer.
83    pub const fn frame_type(self) -> QuicVarInt<'a> {
84        self.frame_type
85    }
86}
87
88/// A checked borrowed QUIC frame.
89#[derive(Clone, Copy, Debug, Eq, PartialEq)]
90pub enum QuicFrame<'a> {
91    /// An RFC 9000 PADDING frame.
92    Padding(QuicPaddingFrame<'a>),
93    /// An RFC 9000 PING frame.
94    Ping(QuicPingFrame<'a>),
95    /// An RFC 9000 ACK or ACK_ECN frame.
96    Ack(QuicAckFrame<'a>),
97    /// An RFC 9000 NEW_TOKEN frame.
98    NewToken(QuicNewTokenFrame<'a>),
99    /// An RFC 9000 CRYPTO frame.
100    Crypto(QuicCryptoFrame<'a>),
101    /// An RFC 9000 STREAM frame.
102    Stream(QuicStreamFrame<'a>),
103    /// An RFC 9000 RESET_STREAM frame.
104    ResetStream(QuicResetStreamFrame<'a>),
105    /// An RFC 9000 STOP_SENDING frame.
106    StopSending(QuicStopSendingFrame<'a>),
107    /// An RFC 9000 MAX_DATA frame.
108    MaxData(QuicMaxDataFrame<'a>),
109    /// An RFC 9000 MAX_STREAM_DATA frame.
110    MaxStreamData(QuicMaxStreamDataFrame<'a>),
111    /// An RFC 9000 MAX_STREAMS frame.
112    MaxStreams(QuicMaxStreamsFrame<'a>),
113    /// An RFC 9000 DATA_BLOCKED frame.
114    DataBlocked(QuicDataBlockedFrame<'a>),
115    /// An RFC 9000 STREAM_DATA_BLOCKED frame.
116    StreamDataBlocked(QuicStreamDataBlockedFrame<'a>),
117    /// An RFC 9000 STREAMS_BLOCKED frame.
118    StreamsBlocked(QuicStreamsBlockedFrame<'a>),
119    /// An RFC 9000 NEW_CONNECTION_ID frame.
120    NewConnectionId(QuicNewConnectionIdFrame<'a>),
121    /// An RFC 9000 RETIRE_CONNECTION_ID frame.
122    RetireConnectionId(QuicRetireConnectionIdFrame<'a>),
123    /// An RFC 9000 PATH_CHALLENGE frame.
124    PathChallenge(QuicPathChallengeFrame<'a>),
125    /// An RFC 9000 PATH_RESPONSE frame.
126    PathResponse(QuicPathResponseFrame<'a>),
127    /// An RFC 9000 CONNECTION_CLOSE frame.
128    ConnectionClose(QuicConnectionCloseFrame<'a>),
129    /// An RFC 9000 HANDSHAKE_DONE frame.
130    HandshakeDone(QuicHandshakeDoneFrame<'a>),
131}
132
133impl<'a> QuicFrame<'a> {
134    /// Parses exactly one frame, returning its unconsumed input suffix.
135    pub fn parse(bytes: &'a [u8]) -> Result<(Self, &'a [u8]), QuicFrameParseError> {
136        parse_at(bytes, 0)
137    }
138
139    /// Returns the exact encoded frame bytes.
140    pub const fn as_bytes(self) -> &'a [u8] {
141        match self {
142            Self::Padding(frame) => frame.as_bytes(),
143            Self::Ping(frame) => frame.as_bytes(),
144            Self::Ack(frame) => frame.as_bytes(),
145            Self::NewToken(frame) => frame.as_bytes(),
146            Self::Crypto(frame) => frame.as_bytes(),
147            Self::Stream(frame) => frame.as_bytes(),
148            Self::ResetStream(frame) => frame.as_bytes(),
149            Self::StopSending(frame) => frame.as_bytes(),
150            Self::MaxData(frame) => frame.as_bytes(),
151            Self::MaxStreamData(frame) => frame.as_bytes(),
152            Self::MaxStreams(frame) => frame.as_bytes(),
153            Self::DataBlocked(frame) => frame.as_bytes(),
154            Self::StreamDataBlocked(frame) => frame.as_bytes(),
155            Self::StreamsBlocked(frame) => frame.as_bytes(),
156            Self::NewConnectionId(frame) => frame.as_bytes(),
157            Self::RetireConnectionId(frame) => frame.as_bytes(),
158            Self::PathChallenge(frame) => frame.as_bytes(),
159            Self::PathResponse(frame) => frame.as_bytes(),
160            Self::ConnectionClose(frame) => frame.as_bytes(),
161            Self::HandshakeDone(frame) => frame.as_bytes(),
162        }
163    }
164
165    /// Returns the exact encoded frame-type variable integer.
166    pub const fn frame_type(self) -> QuicVarInt<'a> {
167        match self {
168            Self::Padding(frame) => frame.frame_type(),
169            Self::Ping(frame) => frame.frame_type(),
170            Self::Ack(frame) => frame.frame_type(),
171            Self::NewToken(frame) => frame.frame_type(),
172            Self::Crypto(frame) => frame.frame_type(),
173            Self::Stream(frame) => frame.frame_type(),
174            Self::ResetStream(frame) => frame.frame_type(),
175            Self::StopSending(frame) => frame.frame_type(),
176            Self::MaxData(frame) => frame.frame_type(),
177            Self::MaxStreamData(frame) => frame.frame_type(),
178            Self::MaxStreams(frame) => frame.frame_type(),
179            Self::DataBlocked(frame) => frame.frame_type(),
180            Self::StreamDataBlocked(frame) => frame.frame_type(),
181            Self::StreamsBlocked(frame) => frame.frame_type(),
182            Self::NewConnectionId(frame) => frame.frame_type(),
183            Self::RetireConnectionId(frame) => frame.frame_type(),
184            Self::PathChallenge(frame) => frame.frame_type(),
185            Self::PathResponse(frame) => frame.frame_type(),
186            Self::ConnectionClose(frame) => frame.frame_type(),
187            Self::HandshakeDone(frame) => frame.frame_type(),
188        }
189    }
190}
191
192/// A validated complete borrowed QUIC plaintext frame sequence.
193#[derive(Clone, Copy, Debug, Eq, PartialEq)]
194pub struct QuicFrames<'a> {
195    bytes: &'a [u8],
196}
197
198impl<'a> QuicFrames<'a> {
199    /// Parses and validates a complete nonempty plaintext frame sequence.
200    pub fn parse(bytes: &'a [u8]) -> Result<Self, QuicFrameParseError> {
201        if bytes.is_empty() {
202            return Err(QuicFrameParseError::EmptySequence);
203        }
204
205        for frame in QuicFrameIter::new(bytes) {
206            frame?;
207        }
208        Ok(Self { bytes })
209    }
210
211    /// Returns the exact complete frame-sequence bytes.
212    pub const fn as_bytes(self) -> &'a [u8] {
213        self.bytes
214    }
215
216    /// Returns a fresh iterator over this already validated frame sequence.
217    pub const fn iter(self) -> QuicFrameIter<'a> {
218        QuicFrameIter::new(self.bytes)
219    }
220}
221
222/// A fallible fused iterator over a borrowed QUIC frame sequence.
223#[derive(Clone, Debug)]
224pub struct QuicFrameIter<'a> {
225    remaining: &'a [u8],
226    offset: usize,
227    failed: bool,
228}
229
230impl<'a> QuicFrameIter<'a> {
231    /// Creates an iterator that can expose a valid prefix before the first parse error.
232    pub const fn new(bytes: &'a [u8]) -> Self {
233        Self {
234            remaining: bytes,
235            offset: 0,
236            failed: false,
237        }
238    }
239}
240
241impl<'a> Iterator for QuicFrameIter<'a> {
242    type Item = Result<QuicFrame<'a>, QuicFrameParseError>;
243
244    fn next(&mut self) -> Option<Self::Item> {
245        if self.failed || self.remaining.is_empty() {
246            return None;
247        }
248
249        match parse_at(self.remaining, self.offset) {
250            Ok((frame, suffix)) => {
251                let consumed = frame.as_bytes().len();
252                self.remaining = suffix;
253                self.offset += consumed;
254                Some(Ok(frame))
255            }
256            Err(error) => {
257                self.failed = true;
258                self.remaining = &[];
259                Some(Err(error))
260            }
261        }
262    }
263}
264
265impl FusedIterator for QuicFrameIter<'_> {}
266
267fn parse_at<'a>(
268    bytes: &'a [u8],
269    offset: usize,
270) -> Result<(QuicFrame<'a>, &'a [u8]), QuicFrameParseError> {
271    let frame_type = QuicVarInt::parse(bytes)
272        .map_err(|error| QuicFrameParseError::FrameType { offset, error })?;
273    let frame_len = frame_type.byte_len();
274    let frame_bytes = &bytes[..frame_len];
275    let suffix = &bytes[frame_len..];
276
277    match frame_type.value() {
278        0 => Ok((
279            QuicFrame::Padding(QuicPaddingFrame {
280                bytes: frame_bytes,
281                frame_type,
282            }),
283            suffix,
284        )),
285        1 => Ok((
286            QuicFrame::Ping(QuicPingFrame {
287                bytes: frame_bytes,
288                frame_type,
289            }),
290            suffix,
291        )),
292        2 | 3 => ack::parse_ack(bytes, frame_type, offset)
293            .map(|(frame, suffix)| (QuicFrame::Ack(frame), suffix)),
294        7 => token::parse_new_token(bytes, frame_type, offset)
295            .map(|(frame, suffix)| (QuicFrame::NewToken(frame), suffix)),
296        6 => crypto::parse_crypto(bytes, frame_type, offset)
297            .map(|(frame, suffix)| (QuicFrame::Crypto(frame), suffix)),
298        0x08..=0x0f => stream::parse_stream(bytes, frame_type, offset)
299            .map(|(frame, suffix)| (QuicFrame::Stream(frame), suffix)),
300        4 => control::parse_reset_stream(bytes, frame_type, offset)
301            .map(|(frame, suffix)| (QuicFrame::ResetStream(frame), suffix)),
302        5 => control::parse_stop_sending(bytes, frame_type, offset)
303            .map(|(frame, suffix)| (QuicFrame::StopSending(frame), suffix)),
304        0x10 => control::parse_max_data(bytes, frame_type, offset)
305            .map(|(frame, suffix)| (QuicFrame::MaxData(frame), suffix)),
306        0x11 => control::parse_max_stream_data(bytes, frame_type, offset)
307            .map(|(frame, suffix)| (QuicFrame::MaxStreamData(frame), suffix)),
308        0x12 => control::parse_max_streams(
309            bytes,
310            frame_type,
311            offset,
312            QuicStreamDirection::Bidirectional,
313        )
314        .map(|(frame, suffix)| (QuicFrame::MaxStreams(frame), suffix)),
315        0x13 => control::parse_max_streams(
316            bytes,
317            frame_type,
318            offset,
319            QuicStreamDirection::Unidirectional,
320        )
321        .map(|(frame, suffix)| (QuicFrame::MaxStreams(frame), suffix)),
322        0x14 => control::parse_data_blocked(bytes, frame_type, offset)
323            .map(|(frame, suffix)| (QuicFrame::DataBlocked(frame), suffix)),
324        0x15 => control::parse_stream_data_blocked(bytes, frame_type, offset)
325            .map(|(frame, suffix)| (QuicFrame::StreamDataBlocked(frame), suffix)),
326        0x16 => control::parse_streams_blocked(
327            bytes,
328            frame_type,
329            offset,
330            QuicStreamDirection::Bidirectional,
331        )
332        .map(|(frame, suffix)| (QuicFrame::StreamsBlocked(frame), suffix)),
333        0x17 => control::parse_streams_blocked(
334            bytes,
335            frame_type,
336            offset,
337            QuicStreamDirection::Unidirectional,
338        )
339        .map(|(frame, suffix)| (QuicFrame::StreamsBlocked(frame), suffix)),
340        0x18 => connection_id::parse_new_connection_id(bytes, frame_type, offset)
341            .map(|(frame, suffix)| (QuicFrame::NewConnectionId(frame), suffix)),
342        0x19 => connection_id::parse_retire_connection_id(bytes, frame_type, offset)
343            .map(|(frame, suffix)| (QuicFrame::RetireConnectionId(frame), suffix)),
344        0x1a => path::parse_path_challenge(bytes, frame_type, offset)
345            .map(|(frame, suffix)| (QuicFrame::PathChallenge(frame), suffix)),
346        0x1b => path::parse_path_response(bytes, frame_type, offset)
347            .map(|(frame, suffix)| (QuicFrame::PathResponse(frame), suffix)),
348        0x1c | 0x1d => connection_close::parse_connection_close(bytes, frame_type, offset)
349            .map(|(frame, suffix)| (QuicFrame::ConnectionClose(frame), suffix)),
350        0x1e => Ok((
351            QuicFrame::HandshakeDone(QuicHandshakeDoneFrame {
352                bytes: frame_bytes,
353                frame_type,
354            }),
355            suffix,
356        )),
357        value => Err(QuicFrameParseError::UnsupportedFrameType {
358            value,
359            length: frame_type.encoded_len(),
360            offset,
361        }),
362    }
363}