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;
33use quiche::Connection;
34
35use crate::frame::H3iFrame;
36
37/// Max stream state size in bytes (2MB).
38const MAX_STREAM_STATE_SIZE: usize = 2_000_000;
39
40#[derive(Debug, Default, PartialEq, Eq)]
41enum FrameState {
42    #[default]
43    Type,
44    Len,
45    Val,
46}
47
48#[derive(Debug, Eq, PartialEq)]
49/// The reason that frame parsing was interrupted.
50pub enum InterruptCause {
51    FinBit,
52    ResetStream(u64),
53}
54
55#[derive(Debug, Eq, PartialEq)]
56/// Represents different frame parsing outcomes.
57pub enum FrameParseResult {
58    /// The frame was unable to be parsed at the current moment. This signifies
59    /// that the stream is retryable without another I/O cycle. If another
60    /// I/O cycle is needed, a [`quiche::h3::Error::TransportError`]
61    /// containing [`quiche::Error::Done`] will be returned.
62    Retry,
63    /// A frame has been successfully parsed. `fin` denotes if the FIN bit was
64    /// set.
65    FrameParsed { h3i_frame: H3iFrame, fin: bool },
66    /// A frame is in the middle of being parsed, but either a FIN bit or a
67    /// RESET_STREAM was received.
68    Interrupted(InterruptCause),
69}
70
71/// Parses [`H3iFrame`]s from a QUIC stream.
72///
73/// Each `FrameParser` instance is bound to a single stream when created.
74/// [`FrameParser::try_parse_frame()`] will attempt to pull stream data from a
75/// [`quiche::Connection`] and build a complete frame.
76///
77/// There are various success and failure criteria, see `try_parse_frame()` for
78/// specific guidance.
79pub(crate) struct FrameParser {
80    ty: Option<u64>,
81    len: Option<u64>,
82
83    stream_id: u64,
84
85    curr_state: FrameState,
86    state_buf: Vec<u8>,
87    state_offset: usize,
88    state_len: usize,
89}
90
91impl FrameParser {
92    pub(crate) fn new(stream_id: u64) -> Self {
93        Self {
94            stream_id,
95            ..Default::default()
96        }
97    }
98
99    /// Attempt to pull stream data from a [`quiche::Connection`] and build a
100    /// complete frame.
101    ///
102    /// On success, [FrameParseResult::FrameParsed] is returned. The caller
103    /// should keep calling try_parse_frame() to read a series of frames
104    /// from the stream.
105    ///
106    /// [FrameParseResult::Retry] signifies that the parser's internal state
107    /// requires another attempt to read stream data, but the stream is
108    /// still readable. `try_parse_frame()` should be retried without
109    /// executing another I/O cycle.
110    ///
111    /// If the available stream data does not provide a complete frame, a
112    /// [`quiche::h3::Error::TransportError`] containing [`quiche::Error::Done`]
113    /// is returned. Callers should execute an I/O cycle before calling
114    /// try_parse_frame() again.
115    ///
116    /// If the stream is terminated, either by FIN or reset,
117    /// [FrameParseResult::Interrupted] is returned. The caller should cease
118    /// calling methods on the stream since the stream is closed.
119    pub(crate) fn try_parse_frame(
120        &mut self, qconn: &mut Connection,
121    ) -> Result<FrameParseResult> {
122        loop {
123            let (len, fin) = match self.try_fill_buffer(qconn, self.stream_id) {
124                Ok((l, f)) => (l, f),
125                Err(H3Error::TransportError(quiche::Error::StreamReset(err))) =>
126                    return Ok(FrameParseResult::Interrupted(
127                        InterruptCause::ResetStream(err),
128                    )),
129                Err(e) => return Err(e),
130            };
131
132            log::trace!(
133                "{} stream={} read bytes={len:?}",
134                qconn.trace_id(),
135                self.stream_id
136            );
137
138            if fin && self.frame_incomplete() {
139                return Ok(FrameParseResult::Interrupted(InterruptCause::FinBit));
140            };
141
142            match self.curr_state {
143                FrameState::Type => {
144                    let Ok(varint) = self.try_consume_varint() else {
145                        // Map Error::Done's to Retry's because state_buf must be
146                        // resized to fit a larger varint
147                        return Ok(FrameParseResult::Retry);
148                    };
149
150                    self.set_frame_type(varint)?;
151                    self.state_transition(FrameState::Len, 1)?;
152                },
153                FrameState::Len => {
154                    let Ok(varint) = self.try_consume_varint() else {
155                        // Map Error::Done's to Retry's because state_buf must be
156                        // resized to fit a larger varint
157                        return Ok(FrameParseResult::Retry);
158                    };
159
160                    self.set_frame_len(varint)?;
161                    self.state_transition(
162                        FrameState::Val,
163                        self.len.expect("frame len is not set") as usize,
164                    )?;
165                },
166                FrameState::Val => {
167                    if self.state_buffer_complete() {
168                        let h3i_frame = self.build_h3i_frame()?;
169                        // unwraps are safe now
170                        let ty = match self.ty.unwrap() {
171                            0x0 => "DATA".to_string(),
172                            0x1 => "HEADERS".to_string(),
173                            0x3 => "CANCEL_PUSH".to_string(),
174                            0x4 => "SETTINGS".to_string(),
175                            0x5 => "PUSH_PROMISE".to_string(),
176                            0x7 => "GOAWAY".to_string(),
177                            0xd => "MAX_PUSH_AWAY".to_string(),
178                            _ => format!("UNKNOWN val={}", self.ty.unwrap()),
179                        };
180                        log::info!(
181                            "{} stream={} frame rx ty={} len={}",
182                            qconn.trace_id(),
183                            self.stream_id,
184                            ty,
185                            self.len.unwrap()
186                        );
187
188                        // Reset the states for the next frame
189                        *self = Self::new(self.stream_id);
190                        return Ok(FrameParseResult::FrameParsed {
191                            h3i_frame,
192                            fin,
193                        });
194                    };
195
196                    // No need to map to Retry here since we've exhausted the
197                    // received bytes and must try another I/O
198                    // cycle
199                    return Err(H3Error::TransportError(quiche::Error::Done));
200                },
201            }
202        }
203    }
204
205    fn frame_incomplete(&self) -> bool {
206        !self.state_buf.is_empty() && !self.state_buffer_complete()
207    }
208
209    fn try_fill_buffer(
210        &mut self, qconn: &mut Connection, stream_id: u64,
211    ) -> Result<(usize, bool)> {
212        if self.state_buffer_complete() {
213            return Ok((0, qconn.stream_finished(stream_id)));
214        }
215
216        let buf = &mut self.state_buf[self.state_offset..self.state_len];
217        match qconn.stream_recv(stream_id, buf) {
218            Ok((len, fin)) => {
219                self.state_offset += len;
220                Ok((len, fin))
221            },
222            Err(e) => Err(H3Error::TransportError(e)),
223        }
224    }
225
226    fn try_consume_varint(&mut self) -> Result<u64> {
227        if self.state_offset == 1 {
228            self.state_len = octets::varint_parse_len(self.state_buf[0]);
229            self.state_buf.resize(self.state_len, 0);
230        }
231
232        if !self.state_buffer_complete() {
233            return Err(H3Error::TransportError(quiche::Error::Done));
234        }
235
236        let varint = octets::Octets::with_slice(&self.state_buf).get_varint()?;
237        Ok(varint)
238    }
239
240    fn state_buffer_complete(&self) -> bool {
241        self.state_offset == self.state_len
242    }
243
244    fn state_transition(
245        &mut self, new_state: FrameState, expected_len: usize,
246    ) -> Result<()> {
247        // A peer can influence the size of the state buffer (e.g. with the
248        // payload size of a GREASE frame), so we need to limit the maximum
249        // size to avoid DoS.
250        if expected_len > MAX_STREAM_STATE_SIZE {
251            return Err(quiche::h3::Error::ExcessiveLoad);
252        }
253
254        self.state_buf.resize(expected_len, 0);
255        self.curr_state = new_state;
256        self.state_offset = 0;
257        self.state_len = expected_len;
258
259        Ok(())
260    }
261
262    fn set_frame_type(&mut self, ty: u64) -> Result<()> {
263        self.ty = Some(ty);
264        self.state_transition(FrameState::Len, 1)?;
265
266        Ok(())
267    }
268
269    fn set_frame_len(&mut self, len: u64) -> Result<()> {
270        self.len = Some(len);
271        self.state_transition(FrameState::Val, len as usize)?;
272
273        Ok(())
274    }
275
276    fn build_h3i_frame(&mut self) -> Result<H3iFrame> {
277        let qframe = QFrame::from_bytes(
278            self.ty.expect("frame ty not set"),
279            self.len.expect("frame len not set"),
280            &self.state_buf,
281        )?;
282
283        match qframe {
284            QFrame::Headers { ref header_block } => {
285                let mut qpack_decoder = quiche::h3::qpack::Decoder::new();
286                let headers =
287                    qpack_decoder.decode(header_block, u64::MAX).unwrap();
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 stream_reset() {
773        let mut s = session().unwrap();
774        s.handshake().unwrap();
775
776        let mut parser = FrameParser::default();
777        let expected = Frame::Data {
778            payload: vec![1, 2, 3, 4, 5],
779        };
780
781        s.send_arbitrary_stream_data_client(&[0, 5, 1, 2, 3, 4, 5], 0, false)
782            .expect("first");
783        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
784        assert_eq!(res, FrameParseResult::FrameParsed {
785            h3i_frame: H3iFrame::QuicheH3(expected),
786            fin: false
787        });
788
789        s.pipe
790            .client
791            .stream_shutdown(0, quiche::Shutdown::Write, 0)
792            .expect("shutdown");
793        s.pipe.advance().expect("advance");
794        assert_eq!(
795            parser.try_parse_frame(&mut s.pipe.server),
796            Ok(FrameParseResult::Interrupted(InterruptCause::ResetStream(
797                0
798            )))
799        );
800    }
801}