quik_core/
frame.rs

1use quik_util::*;
2
3use crate::common::{ConnectionId, StreamId, VarInt};
4
5pub enum Frame<'a> {
6    Padding,
7    Ping,
8    Ack(Ack),
9    ResetStream(ResetStream),
10    StopSending(StopSending),
11    Crypto(Crypto<'a>),
12    NewToken(NewToken<'a>),
13    Stream(Stream<'a>),
14    MaxData(MaxData),
15    MaxStreamData(MaxStreamData),
16    MaxStreams(MaxStreams),
17    DataBlocked(DataBlocked),
18    StreamDataBlocked(StreamDataBlocked),
19    StreamsBlocked(StreamsBlocked),
20    NewConnectionId(NewConnectionId),
21    RetireConnectionId(RetireConnectionId),
22    PathChallenge(PathChallenge),
23    PathResponse(PathResponse),
24    ConnectionClose(ConnectionClose<'a>),
25    HandshakeDone,
26}
27
28pub struct Padding;
29
30pub struct Ping;
31
32pub struct AckRange {
33    pub gap: VarInt,
34    pub range_length: VarInt,
35}
36
37pub struct EcnCounts {
38    pub ect0: VarInt,
39    pub ect1: VarInt,
40    pub ce: VarInt,
41}
42
43pub struct Ack {
44    pub largest_acked: VarInt,
45    pub ack_delay: VarInt,
46    pub ack_range_count: VarInt,
47    pub first_ack_range: VarInt,
48    pub ack_ranges: Vec<AckRange>,
49    pub ecn_counts: Option<EcnCounts>,
50}
51
52pub struct ResetStream {
53    pub stream_id: StreamId,
54    pub err_code: VarInt,
55    pub final_size: VarInt,
56}
57
58pub struct StopSending {
59    pub stream_id: StreamId,
60    pub err_code: VarInt,
61}
62
63pub struct Crypto<'a> {
64    pub data: &'a [u8],
65}
66
67pub struct NewToken<'a> {
68    pub token: &'a [u8],
69}
70
71pub struct Stream<'a> {
72    pub stream_id: StreamId,
73    pub fin: bool,
74    pub data: &'a [u8],
75}
76
77pub struct MaxData {
78    pub max_data: VarInt,
79}
80
81pub struct MaxStreamData {
82    pub stream_id: StreamId,
83    pub max_stream_data: VarInt,
84}
85
86pub struct MaxStreams {
87    pub max_streams: VarInt,
88}
89
90pub struct DataBlocked {
91    pub max_data: VarInt,
92}
93
94pub struct StreamDataBlocked {
95    pub stream_id: StreamId,
96    pub max_stream_data: VarInt,
97}
98
99pub struct StreamsBlocked {
100    pub max_streams: VarInt,
101}
102
103pub struct NewConnectionId {
104    pub seq_num: VarInt,
105    pub retire_prior_to: VarInt,
106    pub cid: ConnectionId,
107    pub stateless_reset_token: u128,
108}
109
110pub struct RetireConnectionId {
111    pub seq_num: VarInt,
112}
113
114pub struct PathChallenge {
115    pub data: u64,
116}
117
118pub struct PathResponse {
119    pub data: u64,
120}
121
122pub struct ConnectionClose<'a> {
123    pub err_code: VarInt,
124    // Some when it's a QUIC err rather than a application error
125    pub frame_type: Option<VarInt>,
126    pub reason_phrase: &'a [u8],
127}
128
129pub struct HandshakeDone;
130
131impl<'a> Frame<'a> {
132    pub fn parse_multiple(mut data: &'a [u8]) -> impl Iterator<Item = Result<Frame<'a>>> {
133        std::iter::from_fn(move || {
134            if !data.is_empty() {
135                Some(Frame::parse(data).map(|(frame, rem_data)| {
136                    data = rem_data;
137                    frame
138                }))
139            } else {
140                None
141            }
142        })
143    }
144
145    pub fn parse(mut data: &'a [u8]) -> Result<(Frame<'a>, &'a [u8])> {
146        let typ: usize = VarInt::parse(&mut data)?.into();
147        let frame = match typ {
148            0x00 => {
149                // Padding
150                // https://datatracker.ietf.org/doc/html/rfc9000#name-padding-frames
151                Frame::Padding
152            }
153            0x01 => {
154                // Ping
155                // https://datatracker.ietf.org/doc/html/rfc9000#name-ping-frames
156                Frame::Ping
157            }
158            0x02..=0x03 => {
159                // Ack
160                // https://datatracker.ietf.org/doc/html/rfc9000#name-ack-frames
161                let largest_acked = VarInt::parse(&mut data)?;
162                let ack_delay = VarInt::parse(&mut data)?;
163                let ack_range_count = VarInt::parse(&mut data)?;
164                let first_ack_range = VarInt::parse(&mut data)?;
165
166                let ack_ranges = (0..ack_range_count.clone().into())
167                    .map(|_| {
168                        let gap = VarInt::parse(&mut data)?;
169                        let range_length = VarInt::parse(&mut data)?;
170                        Ok(AckRange { gap, range_length })
171                    })
172                    .collect::<Result<Vec<_>>>()?;
173
174                let ecn_counts = if typ == 0x03 {
175                    let ect0 = VarInt::parse(&mut data)?;
176                    let ect1 = VarInt::parse(&mut data)?;
177                    let ce = VarInt::parse(&mut data)?;
178                    Some(EcnCounts { ect0, ect1, ce })
179                } else {
180                    None
181                };
182
183                Frame::Ack(Ack {
184                    largest_acked,
185                    ack_delay,
186                    ack_range_count,
187                    first_ack_range,
188                    ack_ranges,
189                    ecn_counts,
190                })
191            }
192            0x04 => {
193                // Reset Stream
194                // https://datatracker.ietf.org/doc/html/rfc9000#name-reset_stream-frames
195                let stream_id = VarInt::parse(&mut data)?;
196                let err_code = VarInt::parse(&mut data)?;
197                let final_size = VarInt::parse(&mut data)?;
198
199                Frame::ResetStream(ResetStream {
200                    stream_id,
201                    err_code,
202                    final_size,
203                })
204            }
205            0x05 => {
206                // Stop Sending
207                // https://datatracker.ietf.org/doc/html/rfc9000#name-stop_sending-frames
208                let stream_id = VarInt::parse(&mut data)?;
209                let err_code = VarInt::parse(&mut data)?;
210
211                Frame::StopSending(StopSending {
212                    stream_id,
213                    err_code,
214                })
215            }
216            0x06 => {
217                // Crypto
218                // https://datatracker.ietf.org/doc/html/rfc9000#name-crypto-frames
219                let offset = VarInt::parse(&mut data)?;
220                let length = VarInt::parse(&mut data)?;
221                let crypto_data = data.extract(Some(offset.into()), Some(length.into()))?;
222
223                Frame::Crypto(Crypto { data: crypto_data })
224            }
225            0x07 => {
226                // New Token
227                // https://datatracker.ietf.org/doc/html/rfc9000#name-new_token-frames
228                let token_length = VarInt::parse(&mut data)?;
229                let token = data.slice(token_length.into())?;
230
231                Frame::NewToken(NewToken { token })
232            }
233            0x08..=0x0f => {
234                // Stream
235                // https://datatracker.ietf.org/doc/html/rfc9000#name-stream-frames
236                let off_bit = typ & 0b100;
237                let len_bit = typ & 0b010;
238                let fin_bit = typ & 0b001;
239
240                let stream_id = VarInt::parse(&mut data)?;
241                let offset = if off_bit != 0 {
242                    Some(VarInt::parse(&mut data)?.into())
243                } else {
244                    None
245                };
246                let length = if len_bit != 0 {
247                    Some(VarInt::parse(&mut data)?.into())
248                } else {
249                    None
250                };
251                let stream_data = data.extract(offset.into(), length.into())?;
252
253                Frame::Stream(Stream {
254                    stream_id,
255                    data: stream_data,
256                    fin: fin_bit != 0,
257                })
258            }
259            0x10 => {
260                // Max Data
261                // https://datatracker.ietf.org/doc/html/rfc9000#name-max_data-frames
262                let max_data = VarInt::parse(&mut data)?;
263
264                Frame::MaxData(MaxData { max_data })
265            }
266            0x11 => {
267                // Max Stream Data
268                // https://datatracker.ietf.org/doc/html/rfc9000#name-max_stream_data-frames
269                let stream_id = VarInt::parse(&mut data)?;
270                let max_stream_data = VarInt::parse(&mut data)?;
271
272                Frame::MaxStreamData(MaxStreamData {
273                    stream_id,
274                    max_stream_data,
275                })
276            }
277            0x12..=0x13 => {
278                // Max Streams
279                // https://datatracker.ietf.org/doc/html/rfc9000#name-max_streams-frames
280                let max_streams = VarInt::parse(&mut data)?;
281                // TODO 0x12 is bidirectional, 0x13 is unidirectional. Does this matter?
282
283                Frame::MaxStreams(MaxStreams { max_streams })
284            }
285            0x14 => {
286                // Data Blocked
287                // https://datatracker.ietf.org/doc/html/rfc9000#name-data_blocked-frames
288                let max_data = VarInt::parse(&mut data)?;
289
290                Frame::DataBlocked(DataBlocked { max_data })
291            }
292            0x15 => {
293                // Stream Data Blocked
294                // https://datatracker.ietf.org/doc/html/rfc9000#name-stream_data_blocked-frames
295                let stream_id = VarInt::parse(&mut data)?;
296                let max_stream_data = VarInt::parse(&mut data)?;
297
298                Frame::StreamDataBlocked(StreamDataBlocked {
299                    stream_id,
300                    max_stream_data,
301                })
302            }
303            0x16..=0x17 => {
304                // Streams Blocked
305                // https://datatracker.ietf.org/doc/html/rfc9000#name-streams_blocked-frames
306                let max_streams = VarInt::parse(&mut data)?;
307                // TODO 0x16 is bidirectional, 0x17 is unidirectional. Does this matter?
308
309                Frame::StreamsBlocked(StreamsBlocked { max_streams })
310            }
311            0x18 => {
312                // New Connection ID
313                // https://datatracker.ietf.org/doc/html/rfc9000#name-new_connection_id-frames
314                let seq_num = VarInt::parse(&mut data)?;
315                let retire_prior_to = VarInt::parse(&mut data)?;
316                let cid = ConnectionId::parse(&mut data)?;
317                let stateless_reset_token = data.read_u128::<NetworkEndian>()?;
318
319                Frame::NewConnectionId(NewConnectionId {
320                    seq_num,
321                    retire_prior_to,
322                    cid,
323                    stateless_reset_token,
324                })
325            }
326            0x19 => {
327                // Retire Connection ID
328                // https://datatracker.ietf.org/doc/html/rfc9000#name-retire_connection_id-frames
329                let seq_num = VarInt::parse(&mut data)?;
330
331                Frame::RetireConnectionId(RetireConnectionId { seq_num })
332            }
333            0x1a => {
334                // Path Challenge
335                // https://datatracker.ietf.org/doc/html/rfc9000#name-path_challenge-frames
336                let data = data.read_u64::<NetworkEndian>()?;
337
338                Frame::PathChallenge(PathChallenge { data })
339            }
340            0x1b => {
341                // Path Response
342                // https://datatracker.ietf.org/doc/html/rfc9000#name-path_response-frames
343                let data = data.read_u64::<NetworkEndian>()?;
344
345                Frame::PathResponse(PathResponse { data })
346            }
347            0x1c..=0x1d => {
348                // Connection Close
349                // https://datatracker.ietf.org/doc/html/rfc9000#name-connection_close-frames
350                let err_code = VarInt::parse(&mut data)?;
351                let frame_type = if typ == 0x1c {
352                    Some(VarInt::parse(&mut data)?)
353                } else {
354                    None
355                };
356                let reason_phrase_length = VarInt::parse(&mut data)?;
357                let reason_phrase = data.slice(reason_phrase_length.into())?;
358
359                Frame::ConnectionClose(ConnectionClose {
360                    err_code,
361                    frame_type,
362                    reason_phrase,
363                })
364            }
365            0x1e => {
366                // Handshake Done
367                // https://datatracker.ietf.org/doc/html/rfc9000#name-handshake_done-frames
368                Frame::HandshakeDone
369            }
370            _ => Err("Unknown frame type")?,
371        };
372
373        Ok((frame, data))
374    }
375}