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 quiche::h3::frame::Frame as QFrame;
30use quiche::h3::Error as H3Error;
31use quiche::h3::Result;
32use quiche::Connection;
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(
119        &mut self, qconn: &mut Connection,
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's to Retry's because state_buf must be
145                        // resized to fit 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's to Retry's because state_buf must be
155                        // resized to fit 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(
209        &mut self, qconn: &mut Connection, 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 =
286                    qpack_decoder.decode(header_block, u64::MAX).unwrap();
287
288                Ok(H3iFrame::Headers(headers.into()))
289            },
290            _ => Ok(qframe.into()),
291        }
292    }
293}
294
295impl std::fmt::Debug for FrameParser {
296    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
297        let s = format!(
298            "FrameParser {{ stream: {}, type: {:?}, length: {:?} }}",
299            self.stream_id, self.ty, self.len,
300        );
301
302        write!(f, "{}", s)
303    }
304}
305
306impl Default for FrameParser {
307    fn default() -> Self {
308        Self {
309            ty: None,
310            len: None,
311            curr_state: FrameState::default(),
312            stream_id: 0,
313            state_buf: vec![0],
314            state_offset: 0,
315            state_len: 1,
316        }
317    }
318}
319
320#[cfg(test)]
321mod tests {
322    use super::*;
323    use quiche::h3::frame::Frame;
324    use quiche::h3::testing::*;
325
326    fn session() -> Result<Session> {
327        Session::new()
328    }
329
330    // See https://datatracker.ietf.org/doc/html/rfc9000#name-variable-length-integer-enc for
331    // encoding scheme. 64 is the lowest number that can be parsed with a 2-byte
332    // varint, so it's used in all tests so they're easier to reason about
333    #[test]
334    fn simple_case() {
335        let mut s = session().unwrap();
336        s.handshake().unwrap();
337
338        let mut parser = FrameParser::new(0);
339        let expected = Frame::Data {
340            payload: vec![1, 2, 3, 4, 5],
341        };
342        s.send_frame_client(expected.clone(), 0, true)
343            .expect("first");
344
345        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
346        assert_eq!(res, FrameParseResult::FrameParsed {
347            h3i_frame: H3iFrame::QuicheH3(expected),
348            fin: true
349        });
350    }
351
352    #[test]
353    fn type_precedes_split() {
354        let mut s = session().unwrap();
355        s.handshake().unwrap();
356
357        let mut parser = FrameParser::new(0);
358        let expected = Frame::Data {
359            payload: vec![10; 10],
360        };
361        s.send_arbitrary_stream_data_client(&[0], 0, false)
362            .expect("first");
363        let res = parser.try_parse_frame(&mut s.pipe.server);
364        assert_eq!(res, Err(H3Error::TransportError(quiche::Error::Done)));
365
366        s.send_arbitrary_stream_data_client(&[10; 11], 0, true)
367            .expect("second");
368        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
369        assert_eq!(res, FrameParseResult::FrameParsed {
370            h3i_frame: H3iFrame::QuicheH3(expected),
371            fin: true
372        });
373    }
374
375    #[test]
376    fn type_multiple_bytes() {
377        let mut s = session().unwrap();
378        s.handshake().unwrap();
379
380        let mut parser = FrameParser::new(0);
381        let expected = Frame::Unknown {
382            raw_type: 64,
383            payload: vec![1, 2, 3, 4, 5],
384        };
385        s.send_arbitrary_stream_data_client(&[64, 64, 5, 1, 2, 3, 4, 5], 0, true)
386            .expect("first");
387
388        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
389        assert_eq!(res, FrameParseResult::Retry);
390
391        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
392        assert_eq!(res, FrameParseResult::FrameParsed {
393            h3i_frame: H3iFrame::QuicheH3(expected),
394            fin: true
395        });
396    }
397
398    #[test]
399    fn type_multiple_buffers() {
400        let mut s = session().unwrap();
401        s.handshake().unwrap();
402
403        let mut parser = FrameParser::new(0);
404        let expected = Frame::Unknown {
405            raw_type: 64,
406            payload: vec![1, 2, 3, 4, 5],
407        };
408
409        s.send_arbitrary_stream_data_client(&[64], 0, false)
410            .expect("first");
411        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
412        assert_eq!(res, FrameParseResult::Retry);
413
414        let res = parser.try_parse_frame(&mut s.pipe.server);
415        assert_eq!(res, Err(H3Error::TransportError(quiche::Error::Done)));
416
417        s.send_arbitrary_stream_data_client(&[64, 5, 1, 2, 3, 4, 5], 0, true)
418            .expect("second");
419        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
420        assert_eq!(res, FrameParseResult::FrameParsed {
421            h3i_frame: H3iFrame::QuicheH3(expected),
422            fin: true
423        });
424    }
425
426    #[test]
427    fn type_multiple_buffers_precedes_split() {
428        let mut s = session().unwrap();
429        s.handshake().unwrap();
430
431        let mut parser = FrameParser::default();
432        let expected = Frame::Unknown {
433            raw_type: 64,
434            payload: vec![1, 2, 3, 4, 5],
435        };
436
437        s.send_arbitrary_stream_data_client(&[64, 64], 0, false)
438            .expect("first");
439        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
440        assert_eq!(res, FrameParseResult::Retry);
441
442        let res = parser.try_parse_frame(&mut s.pipe.server);
443        assert_eq!(res, Err(H3Error::TransportError(quiche::Error::Done)));
444
445        s.send_arbitrary_stream_data_client(&[5, 1, 2, 3, 4, 5], 0, false)
446            .expect("second");
447        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
448        assert_eq!(res, FrameParseResult::FrameParsed {
449            h3i_frame: H3iFrame::QuicheH3(expected),
450            fin: false
451        });
452    }
453
454    #[test]
455    fn len_precedes_split() {
456        let mut s = session().unwrap();
457        s.handshake().unwrap();
458
459        let mut parser = FrameParser::default();
460        let expected = Frame::Data {
461            payload: vec![57; 10],
462        };
463
464        s.send_arbitrary_stream_data_client(&[0, 10], 0, false)
465            .expect("first");
466        let res = parser.try_parse_frame(&mut s.pipe.server);
467        assert_eq!(res, Err(H3Error::TransportError(quiche::Error::Done)));
468
469        s.send_arbitrary_stream_data_client(&[57; 10], 0, true)
470            .expect("second");
471        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
472        assert_eq!(res, FrameParseResult::FrameParsed {
473            h3i_frame: H3iFrame::QuicheH3(expected),
474            fin: true
475        });
476    }
477
478    #[test]
479    fn len_multiple_bytes() {
480        let mut s = session().unwrap();
481        s.handshake().unwrap();
482
483        let mut b = vec![0, 64, 64];
484        let mut payload = vec![0; 64];
485        let mut parser = FrameParser::default();
486        let expected = Frame::Data {
487            payload: payload.clone(),
488        };
489        b.append(&mut payload);
490
491        s.send_arbitrary_stream_data_client(&b, 0, true)
492            .expect("first");
493        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
494        assert_eq!(res, FrameParseResult::Retry);
495
496        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
497        assert_eq!(res, FrameParseResult::FrameParsed {
498            h3i_frame: H3iFrame::QuicheH3(expected),
499            fin: true
500        });
501    }
502
503    #[test]
504    fn len_multiple_buffers() {
505        let mut s = session().unwrap();
506        s.handshake().unwrap();
507
508        let mut parser = FrameParser::default();
509        let expected = Frame::Data {
510            payload: vec![64; 64],
511        };
512
513        s.send_arbitrary_stream_data_client(&[0, 64], 0, false)
514            .expect("first");
515        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
516        assert_eq!(res, FrameParseResult::Retry);
517
518        let res = parser.try_parse_frame(&mut s.pipe.server);
519        assert_eq!(res, Err(H3Error::TransportError(quiche::Error::Done)));
520
521        s.send_arbitrary_stream_data_client(&[64; 65], 0, true)
522            .expect("second");
523        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
524        assert_eq!(res, FrameParseResult::FrameParsed {
525            h3i_frame: H3iFrame::QuicheH3(expected),
526            fin: true
527        });
528    }
529
530    #[test]
531    fn len_multiple_buffers_precedes_split() {
532        let mut s = session().unwrap();
533        s.handshake().unwrap();
534
535        let mut parser = FrameParser::default();
536        let expected = Frame::Data {
537            payload: vec![0; 64],
538        };
539
540        s.send_arbitrary_stream_data_client(&[0, 64, 64], 0, false)
541            .expect("first");
542        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
543        assert_eq!(res, FrameParseResult::Retry);
544
545        let res = parser.try_parse_frame(&mut s.pipe.server);
546        assert_eq!(res, Err(H3Error::TransportError(quiche::Error::Done)));
547
548        s.send_arbitrary_stream_data_client(&[0; 64], 0, true)
549            .expect("second");
550        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
551        assert_eq!(res, FrameParseResult::FrameParsed {
552            h3i_frame: H3iFrame::QuicheH3(expected),
553            fin: true
554        });
555    }
556
557    #[test]
558    fn no_val() {
559        let mut s = session().unwrap();
560        s.handshake().unwrap();
561
562        let mut parser = FrameParser::default();
563        let first = Frame::Unknown {
564            raw_type: 64,
565            payload: vec![],
566        };
567        let second = Frame::Data {
568            payload: vec![1, 2, 3],
569        };
570
571        s.send_arbitrary_stream_data_client(&[64, 64, 0, 0, 3, 1, 2, 3], 0, true)
572            .expect("first");
573        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
574        assert_eq!(res, FrameParseResult::Retry);
575
576        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
577        assert_eq!(res, FrameParseResult::FrameParsed {
578            h3i_frame: H3iFrame::QuicheH3(first),
579            fin: false
580        });
581
582        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
583        assert_eq!(res, FrameParseResult::FrameParsed {
584            h3i_frame: H3iFrame::QuicheH3(second),
585            fin: true
586        });
587    }
588
589    #[test]
590    fn val_multiple_buffers() {
591        let mut s = session().unwrap();
592        s.handshake().unwrap();
593
594        let mut parser = FrameParser::default();
595        let expected = Frame::Data {
596            payload: vec![1, 2, 3, 4, 5],
597        };
598
599        s.send_arbitrary_stream_data_client(&[0, 5, 1], 0, false)
600            .expect("first");
601        let res = parser.try_parse_frame(&mut s.pipe.server);
602        assert_eq!(res, Err(H3Error::TransportError(quiche::Error::Done)));
603
604        s.send_arbitrary_stream_data_client(&[2, 3, 4, 5], 0, false)
605            .expect("second");
606        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
607        assert_eq!(res, FrameParseResult::FrameParsed {
608            h3i_frame: H3iFrame::QuicheH3(expected),
609            fin: false
610        });
611    }
612
613    #[test]
614    fn val_doesnt_extend_to_buffer_end() {
615        let mut s = session().unwrap();
616        s.handshake().unwrap();
617
618        let mut parser = FrameParser::default();
619        let expected = Frame::Data {
620            payload: vec![1, 2, 3, 4, 5],
621        };
622
623        s.send_arbitrary_stream_data_client(&[0, 5, 1, 2, 3, 4, 5, 0], 0, true)
624            .expect("first");
625        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
626        assert_eq!(res, FrameParseResult::FrameParsed {
627            h3i_frame: H3iFrame::QuicheH3(expected),
628            fin: false
629        });
630
631        let res = parser.try_parse_frame(&mut s.pipe.server);
632        assert_eq!(res, Err(H3Error::TransportError(quiche::Error::Done)));
633        assert_eq!(parser.ty, Some(0));
634        assert_eq!(parser.curr_state, FrameState::Len);
635    }
636
637    #[test]
638    fn multiple_frames_in_buffer() {
639        let mut s = session().unwrap();
640        s.handshake().unwrap();
641
642        let mut parser = FrameParser::default();
643        let first = Frame::Data {
644            payload: vec![1, 2, 3],
645        };
646        let second = Frame::Data {
647            payload: vec![1, 2, 3, 4],
648        };
649
650        s.send_arbitrary_stream_data_client(
651            &[0, 3, 1, 2, 3, 0, 4, 1, 2, 3, 4],
652            0,
653            true,
654        )
655        .expect("first");
656        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
657        assert_eq!(res, FrameParseResult::FrameParsed {
658            h3i_frame: H3iFrame::QuicheH3(first),
659            fin: false
660        });
661        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
662        assert_eq!(res, FrameParseResult::FrameParsed {
663            h3i_frame: H3iFrame::QuicheH3(second),
664            fin: true
665        });
666    }
667
668    #[test]
669    fn multiple_frames_multiple_buffers() {
670        let mut s = session().unwrap();
671        s.handshake().unwrap();
672
673        let mut parser = FrameParser::default();
674        let first = Frame::Data {
675            payload: vec![1, 2, 3],
676        };
677        let second = Frame::Data {
678            payload: vec![1, 2, 3, 4],
679        };
680        let third = Frame::Data {
681            payload: vec![1, 2, 3],
682        };
683
684        s.send_arbitrary_stream_data_client(
685            &[0, 3, 1, 2, 3, 0, 4, 1, 2, 3, 4, 0, 3, 1],
686            0,
687            false,
688        )
689        .expect("first");
690        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
691        assert_eq!(res, FrameParseResult::FrameParsed {
692            h3i_frame: H3iFrame::QuicheH3(first),
693            fin: false
694        });
695        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
696        assert_eq!(res, FrameParseResult::FrameParsed {
697            h3i_frame: H3iFrame::QuicheH3(second),
698            fin: false
699        });
700
701        let res = parser.try_parse_frame(&mut s.pipe.server);
702        assert_eq!(res, Err(H3Error::TransportError(quiche::Error::Done)));
703        assert_eq!(parser.ty, Some(0));
704        assert_eq!(parser.len, Some(3));
705        assert_eq!(parser.state_buf, vec![1, 0, 0]);
706
707        s.send_arbitrary_stream_data_client(&[2, 3], 0, true)
708            .expect("second");
709        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
710        assert_eq!(res, FrameParseResult::FrameParsed {
711            h3i_frame: H3iFrame::QuicheH3(third),
712            fin: true
713        });
714    }
715
716    #[test]
717    fn multiple_frames_nonzero_stream() {
718        let mut s = session().unwrap();
719        s.handshake().unwrap();
720
721        let mut parser = FrameParser::default();
722        let first = Frame::Data {
723            payload: vec![1, 2, 3],
724        };
725        let second = Frame::Data {
726            payload: vec![1, 2, 3, 4, 5],
727        };
728
729        s.send_arbitrary_stream_data_client(&[0, 3, 1, 2, 3], 0, true)
730            .expect("first");
731        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
732        assert_eq!(res, FrameParseResult::FrameParsed {
733            h3i_frame: H3iFrame::QuicheH3(first.clone()),
734            fin: true
735        });
736
737        parser = FrameParser::new(4);
738        s.send_arbitrary_stream_data_client(&[0, 5, 1, 2, 3, 4, 5], 4, false)
739            .expect("second");
740        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
741        assert_eq!(res, FrameParseResult::FrameParsed {
742            h3i_frame: H3iFrame::QuicheH3(second),
743            fin: false
744        });
745
746        s.send_arbitrary_stream_data_client(&[0, 3, 1, 2, 3], 4, true)
747            .expect("third");
748        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
749        assert_eq!(res, FrameParseResult::FrameParsed {
750            h3i_frame: H3iFrame::QuicheH3(first),
751            fin: true
752        });
753    }
754
755    #[test]
756    fn interrupted() {
757        let mut s = session().unwrap();
758        s.handshake().unwrap();
759
760        let mut parser = FrameParser::default();
761        s.send_arbitrary_stream_data_client(&[0, 3, 1, 2], 0, true)
762            .expect("send");
763
764        assert_eq!(
765            parser.try_parse_frame(&mut s.pipe.server),
766            Ok(FrameParseResult::Interrupted(InterruptCause::FinBit))
767        );
768    }
769
770    #[test]
771    fn stream_reset() {
772        let mut s = session().unwrap();
773        s.handshake().unwrap();
774
775        let mut parser = FrameParser::default();
776        let expected = Frame::Data {
777            payload: vec![1, 2, 3, 4, 5],
778        };
779
780        s.send_arbitrary_stream_data_client(&[0, 5, 1, 2, 3, 4, 5], 0, false)
781            .expect("first");
782        let res = parser.try_parse_frame(&mut s.pipe.server).unwrap();
783        assert_eq!(res, FrameParseResult::FrameParsed {
784            h3i_frame: H3iFrame::QuicheH3(expected),
785            fin: false
786        });
787
788        s.pipe
789            .client
790            .stream_shutdown(0, quiche::Shutdown::Write, 0)
791            .expect("shutdown");
792        s.pipe.advance().expect("advance");
793        assert_eq!(
794            parser.try_parse_frame(&mut s.pipe.server),
795            Ok(FrameParseResult::Interrupted(InterruptCause::ResetStream(
796                0
797            )))
798        );
799    }
800}