Skip to main content

h3i/
frame_parser.rs

1// Copyright (C) 2024, Cloudflare, Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8//     * Redistributions of source code must retain the above copyright notice,
9//       this list of conditions and the following disclaimer.
10//
11//     * Redistributions in binary form must reproduce the above copyright
12//       notice, this list of conditions and the following disclaimer in the
13//       documentation and/or other materials provided with the distribution.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
19// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27//! Stateful parsing of QUIC streams into HTTP/3 frames.
28
29use crate::quiche;
30use quiche::h3::frame::Frame as QFrame;
31use quiche::h3::Error as H3Error;
32use quiche::h3::Result;
33
34use crate::frame::H3iFrame;
35
36/// Max stream state size in bytes (2MB).
37const MAX_STREAM_STATE_SIZE: usize = 2_000_000;
38
39#[derive(Debug, Default, PartialEq, Eq)]
40enum FrameState {
41    #[default]
42    Type,
43    Len,
44    Val,
45}
46
47#[derive(Debug, Eq, PartialEq)]
48/// The reason that frame parsing was interrupted.
49pub enum InterruptCause {
50    FinBit,
51    ResetStream(u64),
52}
53
54#[derive(Debug, Eq, PartialEq)]
55/// Represents different frame parsing outcomes.
56pub enum FrameParseResult {
57    /// The frame was unable to be parsed at the current moment. This signifies
58    /// that the stream is retryable without another I/O cycle. If another
59    /// I/O cycle is needed, a [`quiche::h3::Error::TransportError`]
60    /// containing [`quiche::Error::Done`] will be returned.
61    Retry,
62    /// A frame has been successfully parsed. `fin` denotes if the FIN bit was
63    /// set.
64    FrameParsed { h3i_frame: H3iFrame, fin: bool },
65    /// A frame is in the middle of being parsed, but either a FIN bit or a
66    /// RESET_STREAM was received.
67    Interrupted(InterruptCause),
68}
69
70/// Parses [`H3iFrame`]s from a QUIC stream.
71///
72/// Each `FrameParser` instance is bound to a single stream when created.
73/// [`FrameParser::try_parse_frame()`] will attempt to pull stream data from a
74/// [`quiche::Connection`] and build a complete frame.
75///
76/// There are various success and failure criteria, see `try_parse_frame()` for
77/// specific guidance.
78pub(crate) struct FrameParser {
79    ty: Option<u64>,
80    len: Option<u64>,
81
82    stream_id: u64,
83
84    curr_state: FrameState,
85    state_buf: Vec<u8>,
86    state_offset: usize,
87    state_len: usize,
88}
89
90impl FrameParser {
91    pub(crate) fn new(stream_id: u64) -> Self {
92        Self {
93            stream_id,
94            ..Default::default()
95        }
96    }
97
98    /// Attempt to pull stream data from a [`quiche::Connection`] and build a
99    /// complete frame.
100    ///
101    /// On success, [FrameParseResult::FrameParsed] is returned. The caller
102    /// should keep calling try_parse_frame() to read a series of frames
103    /// from the stream.
104    ///
105    /// [FrameParseResult::Retry] signifies that the parser's internal state
106    /// requires another attempt to read stream data, but the stream is
107    /// still readable. `try_parse_frame()` should be retried without
108    /// executing another I/O cycle.
109    ///
110    /// If the available stream data does not provide a complete frame, a
111    /// [`quiche::h3::Error::TransportError`] containing [`quiche::Error::Done`]
112    /// is returned. Callers should execute an I/O cycle before calling
113    /// try_parse_frame() again.
114    ///
115    /// If the stream is terminated, either by FIN or reset,
116    /// [FrameParseResult::Interrupted] is returned. The caller should cease
117    /// calling methods on the stream since the stream is closed.
118    pub(crate) fn try_parse_frame<F: quiche::BufFactory>(
119        &mut self, qconn: &mut quiche::Connection<F>,
120    ) -> Result<FrameParseResult> {
121        loop {
122            let (len, fin) = match self.try_fill_buffer(qconn, self.stream_id) {
123                Ok((l, f)) => (l, f),
124                Err(H3Error::TransportError(quiche::Error::StreamReset(err))) =>
125                    return Ok(FrameParseResult::Interrupted(
126                        InterruptCause::ResetStream(err),
127                    )),
128                Err(e) => return Err(e),
129            };
130
131            log::trace!(
132                "{} stream={} read bytes={len:?}",
133                qconn.trace_id(),
134                self.stream_id
135            );
136
137            if fin && self.frame_incomplete() {
138                return Ok(FrameParseResult::Interrupted(InterruptCause::FinBit));
139            };
140
141            match self.curr_state {
142                FrameState::Type => {
143                    let Ok(varint) = self.try_consume_varint() else {
144                        // Map `Error::Done` to `Retry` because `state_buf` must
145                        // be resized before it can hold a larger varint.
146                        return Ok(FrameParseResult::Retry);
147                    };
148
149                    self.set_frame_type(varint)?;
150                    self.state_transition(FrameState::Len, 1)?;
151                },
152                FrameState::Len => {
153                    let Ok(varint) = self.try_consume_varint() else {
154                        // Map `Error::Done` to `Retry` because `state_buf` must
155                        // be resized before it can hold a larger varint.
156                        return Ok(FrameParseResult::Retry);
157                    };
158
159                    self.set_frame_len(varint)?;
160                    self.state_transition(
161                        FrameState::Val,
162                        self.len.expect("frame len is not set") as usize,
163                    )?;
164                },
165                FrameState::Val => {
166                    if self.state_buffer_complete() {
167                        let h3i_frame = self.build_h3i_frame()?;
168                        // unwraps are safe now
169                        let ty = match self.ty.unwrap() {
170                            0x0 => "DATA".to_string(),
171                            0x1 => "HEADERS".to_string(),
172                            0x3 => "CANCEL_PUSH".to_string(),
173                            0x4 => "SETTINGS".to_string(),
174                            0x5 => "PUSH_PROMISE".to_string(),
175                            0x7 => "GOAWAY".to_string(),
176                            0xd => "MAX_PUSH_AWAY".to_string(),
177                            _ => format!("UNKNOWN val={}", self.ty.unwrap()),
178                        };
179                        log::info!(
180                            "{} stream={} frame rx ty={} len={}",
181                            qconn.trace_id(),
182                            self.stream_id,
183                            ty,
184                            self.len.unwrap()
185                        );
186
187                        // Reset the states for the next frame
188                        *self = Self::new(self.stream_id);
189                        return Ok(FrameParseResult::FrameParsed {
190                            h3i_frame,
191                            fin,
192                        });
193                    };
194
195                    // No need to map to Retry here since we've exhausted the
196                    // received bytes and must try another I/O
197                    // cycle
198                    return Err(H3Error::TransportError(quiche::Error::Done));
199                },
200            }
201        }
202    }
203
204    fn frame_incomplete(&self) -> bool {
205        !self.state_buf.is_empty() && !self.state_buffer_complete()
206    }
207
208    fn try_fill_buffer<F: quiche::BufFactory>(
209        &mut self, qconn: &mut quiche::Connection<F>, stream_id: u64,
210    ) -> Result<(usize, bool)> {
211        if self.state_buffer_complete() {
212            return Ok((0, qconn.stream_finished(stream_id)));
213        }
214
215        let buf = &mut self.state_buf[self.state_offset..self.state_len];
216        match qconn.stream_recv(stream_id, buf) {
217            Ok((len, fin)) => {
218                self.state_offset += len;
219                Ok((len, fin))
220            },
221            Err(e) => Err(H3Error::TransportError(e)),
222        }
223    }
224
225    fn try_consume_varint(&mut self) -> Result<u64> {
226        if self.state_offset == 1 {
227            self.state_len = octets::varint_parse_len(self.state_buf[0]);
228            self.state_buf.resize(self.state_len, 0);
229        }
230
231        if !self.state_buffer_complete() {
232            return Err(H3Error::TransportError(quiche::Error::Done));
233        }
234
235        let varint = octets::Octets::with_slice(&self.state_buf).get_varint()?;
236        Ok(varint)
237    }
238
239    fn state_buffer_complete(&self) -> bool {
240        self.state_offset == self.state_len
241    }
242
243    fn state_transition(
244        &mut self, new_state: FrameState, expected_len: usize,
245    ) -> Result<()> {
246        // A peer can influence the size of the state buffer (e.g. with the
247        // payload size of a GREASE frame), so we need to limit the maximum
248        // size to avoid DoS.
249        if expected_len > MAX_STREAM_STATE_SIZE {
250            return Err(quiche::h3::Error::ExcessiveLoad);
251        }
252
253        self.state_buf.resize(expected_len, 0);
254        self.curr_state = new_state;
255        self.state_offset = 0;
256        self.state_len = expected_len;
257
258        Ok(())
259    }
260
261    fn set_frame_type(&mut self, ty: u64) -> Result<()> {
262        self.ty = Some(ty);
263        self.state_transition(FrameState::Len, 1)?;
264
265        Ok(())
266    }
267
268    fn set_frame_len(&mut self, len: u64) -> Result<()> {
269        self.len = Some(len);
270        self.state_transition(FrameState::Val, len as usize)?;
271
272        Ok(())
273    }
274
275    fn build_h3i_frame(&mut self) -> Result<H3iFrame> {
276        let qframe = QFrame::from_bytes(
277            self.ty.expect("frame ty not set"),
278            self.len.expect("frame len not set"),
279            &self.state_buf,
280        )?;
281
282        match qframe {
283            QFrame::Headers { ref header_block } => {
284                let mut qpack_decoder = quiche::h3::qpack::Decoder::new();
285                let headers = qpack_decoder
286                    .decode(header_block, u64::MAX)
287                    .map_err(|_| H3Error::QpackDecompressionFailed)?;
288
289                Ok(H3iFrame::Headers(headers.into()))
290            },
291            _ => Ok(qframe.into()),
292        }
293    }
294}
295
296impl std::fmt::Debug for FrameParser {
297    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
298        let s = format!(
299            "FrameParser {{ stream: {}, type: {:?}, length: {:?} }}",
300            self.stream_id, self.ty, self.len,
301        );
302
303        write!(f, "{s}")
304    }
305}
306
307impl Default for FrameParser {
308    fn default() -> Self {
309        Self {
310            ty: None,
311            len: None,
312            curr_state: FrameState::default(),
313            stream_id: 0,
314            state_buf: vec![0],
315            state_offset: 0,
316            state_len: 1,
317        }
318    }
319}
320
321#[cfg(test)]
322mod tests {
323    use super::*;
324    use quiche::h3::frame::Frame;
325    use quiche::h3::testing::*;
326
327    fn session() -> Result<Session> {
328        Session::new()
329    }
330
331    // See https://datatracker.ietf.org/doc/html/rfc9000#name-variable-length-integer-enc for
332    // encoding scheme. 64 is the lowest number that can be parsed with a 2-byte
333    // varint, so it's used in all tests so they're easier to reason about
334    #[test]
335    fn simple_case() {
336        let mut s = session().unwrap();
337        s.handshake().unwrap();
338
339        let mut parser = FrameParser::new(0);
340        let expected = Frame::Data {
341            payload: vec![1, 2, 3, 4, 5],
342        };
343        s.send_frame_client(expected.clone(), 0, true)
344            .expect("first");
345
346        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
347        assert_eq!(res, FrameParseResult::FrameParsed {
348            h3i_frame: H3iFrame::QuicheH3(expected),
349            fin: true
350        });
351    }
352
353    #[test]
354    fn type_precedes_split() {
355        let mut s = session().unwrap();
356        s.handshake().unwrap();
357
358        let mut parser = FrameParser::new(0);
359        let expected = Frame::Data {
360            payload: vec![10; 10],
361        };
362        s.send_arbitrary_stream_data_client(&[0], 0, false)
363            .expect("first");
364        let res = parser.try_parse_frame(&mut s.pipe.server);
365        assert_eq!(res, Err(H3Error::TransportError(quiche::Error::Done)));
366
367        s.send_arbitrary_stream_data_client(&[10; 11], 0, true)
368            .expect("second");
369        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
370        assert_eq!(res, FrameParseResult::FrameParsed {
371            h3i_frame: H3iFrame::QuicheH3(expected),
372            fin: true
373        });
374    }
375
376    #[test]
377    fn type_multiple_bytes() {
378        let mut s = session().unwrap();
379        s.handshake().unwrap();
380
381        let mut parser = FrameParser::new(0);
382        let expected = Frame::Unknown {
383            raw_type: 64,
384            payload: vec![1, 2, 3, 4, 5],
385        };
386        s.send_arbitrary_stream_data_client(&[64, 64, 5, 1, 2, 3, 4, 5], 0, true)
387            .expect("first");
388
389        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
390        assert_eq!(res, FrameParseResult::Retry);
391
392        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
393        assert_eq!(res, FrameParseResult::FrameParsed {
394            h3i_frame: H3iFrame::QuicheH3(expected),
395            fin: true
396        });
397    }
398
399    #[test]
400    fn type_multiple_buffers() {
401        let mut s = session().unwrap();
402        s.handshake().unwrap();
403
404        let mut parser = FrameParser::new(0);
405        let expected = Frame::Unknown {
406            raw_type: 64,
407            payload: vec![1, 2, 3, 4, 5],
408        };
409
410        s.send_arbitrary_stream_data_client(&[64], 0, false)
411            .expect("first");
412        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
413        assert_eq!(res, FrameParseResult::Retry);
414
415        let res = parser.try_parse_frame(&mut s.pipe.server);
416        assert_eq!(res, Err(H3Error::TransportError(quiche::Error::Done)));
417
418        s.send_arbitrary_stream_data_client(&[64, 5, 1, 2, 3, 4, 5], 0, true)
419            .expect("second");
420        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
421        assert_eq!(res, FrameParseResult::FrameParsed {
422            h3i_frame: H3iFrame::QuicheH3(expected),
423            fin: true
424        });
425    }
426
427    #[test]
428    fn type_multiple_buffers_precedes_split() {
429        let mut s = session().unwrap();
430        s.handshake().unwrap();
431
432        let mut parser = FrameParser::default();
433        let expected = Frame::Unknown {
434            raw_type: 64,
435            payload: vec![1, 2, 3, 4, 5],
436        };
437
438        s.send_arbitrary_stream_data_client(&[64, 64], 0, false)
439            .expect("first");
440        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
441        assert_eq!(res, FrameParseResult::Retry);
442
443        let res = parser.try_parse_frame(&mut s.pipe.server);
444        assert_eq!(res, Err(H3Error::TransportError(quiche::Error::Done)));
445
446        s.send_arbitrary_stream_data_client(&[5, 1, 2, 3, 4, 5], 0, false)
447            .expect("second");
448        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
449        assert_eq!(res, FrameParseResult::FrameParsed {
450            h3i_frame: H3iFrame::QuicheH3(expected),
451            fin: false
452        });
453    }
454
455    #[test]
456    fn len_precedes_split() {
457        let mut s = session().unwrap();
458        s.handshake().unwrap();
459
460        let mut parser = FrameParser::default();
461        let expected = Frame::Data {
462            payload: vec![57; 10],
463        };
464
465        s.send_arbitrary_stream_data_client(&[0, 10], 0, false)
466            .expect("first");
467        let res = parser.try_parse_frame(&mut s.pipe.server);
468        assert_eq!(res, Err(H3Error::TransportError(quiche::Error::Done)));
469
470        s.send_arbitrary_stream_data_client(&[57; 10], 0, true)
471            .expect("second");
472        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
473        assert_eq!(res, FrameParseResult::FrameParsed {
474            h3i_frame: H3iFrame::QuicheH3(expected),
475            fin: true
476        });
477    }
478
479    #[test]
480    fn len_multiple_bytes() {
481        let mut s = session().unwrap();
482        s.handshake().unwrap();
483
484        let mut b = vec![0, 64, 64];
485        let mut payload = vec![0; 64];
486        let mut parser = FrameParser::default();
487        let expected = Frame::Data {
488            payload: payload.clone(),
489        };
490        b.append(&mut payload);
491
492        s.send_arbitrary_stream_data_client(&b, 0, true)
493            .expect("first");
494        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
495        assert_eq!(res, FrameParseResult::Retry);
496
497        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
498        assert_eq!(res, FrameParseResult::FrameParsed {
499            h3i_frame: H3iFrame::QuicheH3(expected),
500            fin: true
501        });
502    }
503
504    #[test]
505    fn len_multiple_buffers() {
506        let mut s = session().unwrap();
507        s.handshake().unwrap();
508
509        let mut parser = FrameParser::default();
510        let expected = Frame::Data {
511            payload: vec![64; 64],
512        };
513
514        s.send_arbitrary_stream_data_client(&[0, 64], 0, false)
515            .expect("first");
516        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
517        assert_eq!(res, FrameParseResult::Retry);
518
519        let res = parser.try_parse_frame(&mut s.pipe.server);
520        assert_eq!(res, Err(H3Error::TransportError(quiche::Error::Done)));
521
522        s.send_arbitrary_stream_data_client(&[64; 65], 0, true)
523            .expect("second");
524        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
525        assert_eq!(res, FrameParseResult::FrameParsed {
526            h3i_frame: H3iFrame::QuicheH3(expected),
527            fin: true
528        });
529    }
530
531    #[test]
532    fn len_multiple_buffers_precedes_split() {
533        let mut s = session().unwrap();
534        s.handshake().unwrap();
535
536        let mut parser = FrameParser::default();
537        let expected = Frame::Data {
538            payload: vec![0; 64],
539        };
540
541        s.send_arbitrary_stream_data_client(&[0, 64, 64], 0, false)
542            .expect("first");
543        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
544        assert_eq!(res, FrameParseResult::Retry);
545
546        let res = parser.try_parse_frame(&mut s.pipe.server);
547        assert_eq!(res, Err(H3Error::TransportError(quiche::Error::Done)));
548
549        s.send_arbitrary_stream_data_client(&[0; 64], 0, true)
550            .expect("second");
551        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
552        assert_eq!(res, FrameParseResult::FrameParsed {
553            h3i_frame: H3iFrame::QuicheH3(expected),
554            fin: true
555        });
556    }
557
558    #[test]
559    fn no_val() {
560        let mut s = session().unwrap();
561        s.handshake().unwrap();
562
563        let mut parser = FrameParser::default();
564        let first = Frame::Unknown {
565            raw_type: 64,
566            payload: vec![],
567        };
568        let second = Frame::Data {
569            payload: vec![1, 2, 3],
570        };
571
572        s.send_arbitrary_stream_data_client(&[64, 64, 0, 0, 3, 1, 2, 3], 0, true)
573            .expect("first");
574        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
575        assert_eq!(res, FrameParseResult::Retry);
576
577        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
578        assert_eq!(res, FrameParseResult::FrameParsed {
579            h3i_frame: H3iFrame::QuicheH3(first),
580            fin: false
581        });
582
583        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
584        assert_eq!(res, FrameParseResult::FrameParsed {
585            h3i_frame: H3iFrame::QuicheH3(second),
586            fin: true
587        });
588    }
589
590    #[test]
591    fn val_multiple_buffers() {
592        let mut s = session().unwrap();
593        s.handshake().unwrap();
594
595        let mut parser = FrameParser::default();
596        let expected = Frame::Data {
597            payload: vec![1, 2, 3, 4, 5],
598        };
599
600        s.send_arbitrary_stream_data_client(&[0, 5, 1], 0, false)
601            .expect("first");
602        let res = parser.try_parse_frame(&mut s.pipe.server);
603        assert_eq!(res, Err(H3Error::TransportError(quiche::Error::Done)));
604
605        s.send_arbitrary_stream_data_client(&[2, 3, 4, 5], 0, false)
606            .expect("second");
607        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
608        assert_eq!(res, FrameParseResult::FrameParsed {
609            h3i_frame: H3iFrame::QuicheH3(expected),
610            fin: false
611        });
612    }
613
614    #[test]
615    fn val_doesnt_extend_to_buffer_end() {
616        let mut s = session().unwrap();
617        s.handshake().unwrap();
618
619        let mut parser = FrameParser::default();
620        let expected = Frame::Data {
621            payload: vec![1, 2, 3, 4, 5],
622        };
623
624        s.send_arbitrary_stream_data_client(&[0, 5, 1, 2, 3, 4, 5, 0], 0, true)
625            .expect("first");
626        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
627        assert_eq!(res, FrameParseResult::FrameParsed {
628            h3i_frame: H3iFrame::QuicheH3(expected),
629            fin: false
630        });
631
632        let res = parser.try_parse_frame(&mut s.pipe.server);
633        assert_eq!(res, Err(H3Error::TransportError(quiche::Error::Done)));
634        assert_eq!(parser.ty, Some(0));
635        assert_eq!(parser.curr_state, FrameState::Len);
636    }
637
638    #[test]
639    fn multiple_frames_in_buffer() {
640        let mut s = session().unwrap();
641        s.handshake().unwrap();
642
643        let mut parser = FrameParser::default();
644        let first = Frame::Data {
645            payload: vec![1, 2, 3],
646        };
647        let second = Frame::Data {
648            payload: vec![1, 2, 3, 4],
649        };
650
651        s.send_arbitrary_stream_data_client(
652            &[0, 3, 1, 2, 3, 0, 4, 1, 2, 3, 4],
653            0,
654            true,
655        )
656        .expect("first");
657        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
658        assert_eq!(res, FrameParseResult::FrameParsed {
659            h3i_frame: H3iFrame::QuicheH3(first),
660            fin: false
661        });
662        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
663        assert_eq!(res, FrameParseResult::FrameParsed {
664            h3i_frame: H3iFrame::QuicheH3(second),
665            fin: true
666        });
667    }
668
669    #[test]
670    fn multiple_frames_multiple_buffers() {
671        let mut s = session().unwrap();
672        s.handshake().unwrap();
673
674        let mut parser = FrameParser::default();
675        let first = Frame::Data {
676            payload: vec![1, 2, 3],
677        };
678        let second = Frame::Data {
679            payload: vec![1, 2, 3, 4],
680        };
681        let third = Frame::Data {
682            payload: vec![1, 2, 3],
683        };
684
685        s.send_arbitrary_stream_data_client(
686            &[0, 3, 1, 2, 3, 0, 4, 1, 2, 3, 4, 0, 3, 1],
687            0,
688            false,
689        )
690        .expect("first");
691        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
692        assert_eq!(res, FrameParseResult::FrameParsed {
693            h3i_frame: H3iFrame::QuicheH3(first),
694            fin: false
695        });
696        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
697        assert_eq!(res, FrameParseResult::FrameParsed {
698            h3i_frame: H3iFrame::QuicheH3(second),
699            fin: false
700        });
701
702        let res = parser.try_parse_frame(&mut s.pipe.server);
703        assert_eq!(res, Err(H3Error::TransportError(quiche::Error::Done)));
704        assert_eq!(parser.ty, Some(0));
705        assert_eq!(parser.len, Some(3));
706        assert_eq!(parser.state_buf, vec![1, 0, 0]);
707
708        s.send_arbitrary_stream_data_client(&[2, 3], 0, true)
709            .expect("second");
710        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
711        assert_eq!(res, FrameParseResult::FrameParsed {
712            h3i_frame: H3iFrame::QuicheH3(third),
713            fin: true
714        });
715    }
716
717    #[test]
718    fn multiple_frames_nonzero_stream() {
719        let mut s = session().unwrap();
720        s.handshake().unwrap();
721
722        let mut parser = FrameParser::default();
723        let first = Frame::Data {
724            payload: vec![1, 2, 3],
725        };
726        let second = Frame::Data {
727            payload: vec![1, 2, 3, 4, 5],
728        };
729
730        s.send_arbitrary_stream_data_client(&[0, 3, 1, 2, 3], 0, true)
731            .expect("first");
732        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
733        assert_eq!(res, FrameParseResult::FrameParsed {
734            h3i_frame: H3iFrame::QuicheH3(first.clone()),
735            fin: true
736        });
737
738        parser = FrameParser::new(4);
739        s.send_arbitrary_stream_data_client(&[0, 5, 1, 2, 3, 4, 5], 4, false)
740            .expect("second");
741        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
742        assert_eq!(res, FrameParseResult::FrameParsed {
743            h3i_frame: H3iFrame::QuicheH3(second),
744            fin: false
745        });
746
747        s.send_arbitrary_stream_data_client(&[0, 3, 1, 2, 3], 4, true)
748            .expect("third");
749        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
750        assert_eq!(res, FrameParseResult::FrameParsed {
751            h3i_frame: H3iFrame::QuicheH3(first),
752            fin: true
753        });
754    }
755
756    #[test]
757    fn interrupted() {
758        let mut s = session().unwrap();
759        s.handshake().unwrap();
760
761        let mut parser = FrameParser::default();
762        s.send_arbitrary_stream_data_client(&[0, 3, 1, 2], 0, true)
763            .expect("send");
764
765        assert_eq!(
766            parser.try_parse_frame(&mut s.pipe.server),
767            Ok(FrameParseResult::Interrupted(InterruptCause::FinBit))
768        );
769    }
770
771    #[test]
772    fn headers_decode_error() {
773        let mut s = session().unwrap();
774        s.handshake().unwrap();
775
776        let mut parser = FrameParser::default();
777
778        // HEADERS frame whose field section references the QPACK dynamic
779        // table, which is not supported.
780        s.send_arbitrary_stream_data_client(&[1, 3, 0, 0, 0x80], 0, true)
781            .expect("send");
782
783        assert_eq!(
784            parser.try_parse_frame(&mut s.pipe.server),
785            Err(H3Error::QpackDecompressionFailed)
786        );
787    }
788
789    #[test]
790    fn stream_reset() {
791        let mut s = session().unwrap();
792        s.handshake().unwrap();
793
794        let mut parser = FrameParser::default();
795        let expected = Frame::Data {
796            payload: vec![1, 2, 3, 4, 5],
797        };
798
799        s.send_arbitrary_stream_data_client(&[0, 5, 1, 2, 3, 4, 5], 0, false)
800            .expect("first");
801        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
802        assert_eq!(res, FrameParseResult::FrameParsed {
803            h3i_frame: H3iFrame::QuicheH3(expected),
804            fin: false
805        });
806
807        s.pipe
808            .client
809            .stream_shutdown(0, quiche::Shutdown::Write, 0)
810            .expect("shutdown");
811        s.pipe.advance().expect("advance");
812        assert_eq!(
813            parser.try_parse_frame(&mut s.pipe.server),
814            Ok(FrameParseResult::Interrupted(InterruptCause::ResetStream(
815                0
816            )))
817        );
818    }
819}