1use bytes::{Buf, BufMut, Bytes, BytesMut};
35
36pub const MAX_VARINT: u64 = (1 << 62) - 1;
38
39pub const FRAME_DATA: u64 = 0x0;
41pub const FRAME_HEADERS: u64 = 0x1;
43pub const FRAME_CANCEL_PUSH: u64 = 0x3;
45pub const FRAME_SETTINGS: u64 = 0x4;
47pub const FRAME_PUSH_PROMISE: u64 = 0x5;
49pub const FRAME_GOAWAY: u64 = 0x7;
51pub const FRAME_MAX_PUSH_ID: u64 = 0xd;
53
54#[allow(dead_code)]
58pub const SETTINGS_QPACK_MAX_TABLE_CAPACITY: u64 = 0x1;
59#[allow(dead_code)]
63pub const SETTINGS_MAX_FIELD_SECTION_SIZE: u64 = 0x6;
64#[allow(dead_code)]
68pub const SETTINGS_QPACK_BLOCKED_STREAMS: u64 = 0x7;
69#[allow(dead_code)]
73pub const SETTINGS_ENABLE_CONNECT_PROTOCOL: u64 = 0x8;
74#[allow(dead_code)]
78pub const SETTINGS_H3_DATAGRAM: u64 = 0x33;
79
80pub type Setting = (u64, u64);
82
83#[derive(Debug, Clone, Default, PartialEq, Eq)]
89pub struct Settings {
90 entries: Vec<Setting>,
91}
92
93impl Settings {
94 #[inline]
96 pub fn new() -> Self {
97 Self::default()
98 }
99
100 #[inline]
102 pub fn insert(&mut self, id: u64, value: u64) {
103 self.entries.push((id, value));
104 }
105
106 #[inline]
108 pub fn get(&self, id: u64) -> Option<u64> {
109 self.entries
110 .iter()
111 .find_map(|(i, v)| (*i == id).then_some(*v))
112 }
113
114 #[inline]
116 pub fn iter(&self) -> impl Iterator<Item = Setting> + '_ {
117 self.entries.iter().copied()
118 }
119}
120
121#[derive(Debug, Clone, PartialEq, Eq)]
128pub enum Frame {
129 Data(Bytes),
131 Headers(Bytes),
133 Settings(Settings),
136 CancelPush(u64),
138 PushPromise { push_id: u64, field_section: Bytes },
141 Goaway(u64),
144 MaxPushId(u64),
146}
147
148impl Frame {
149 #[inline]
158 pub fn is_known(&self) -> bool {
159 matches!(
160 self,
161 Frame::Data(_)
162 | Frame::Headers(_)
163 | Frame::Settings(_)
164 | Frame::CancelPush(_)
165 | Frame::PushPromise { .. }
166 | Frame::Goaway(_)
167 | Frame::MaxPushId(_)
168 )
169 }
170
171 #[inline]
173 pub fn encode(&self, dst: &mut BytesMut) {
174 match self {
175 Frame::Data(payload) => {
176 write_varint(FRAME_DATA, dst);
177 write_varint(payload.len() as u64, dst);
178 dst.extend_from_slice(payload);
179 }
180 Frame::Headers(payload) => {
181 write_varint(FRAME_HEADERS, dst);
182 write_varint(payload.len() as u64, dst);
183 dst.extend_from_slice(payload);
184 }
185 Frame::Settings(settings) => {
186 write_varint(FRAME_SETTINGS, dst);
187 let len: usize = settings
188 .entries
189 .iter()
190 .map(|(id, value)| varint_size(*id) + varint_size(*value))
191 .sum();
192 write_varint(len as u64, dst);
193 for (id, value) in &settings.entries {
194 write_varint(*id, dst);
195 write_varint(*value, dst);
196 }
197 }
198 Frame::CancelPush(push_id) => {
199 write_varint(FRAME_CANCEL_PUSH, dst);
200 write_varint(varint_size(*push_id) as u64, dst);
201 write_varint(*push_id, dst);
202 }
203 Frame::PushPromise {
204 push_id,
205 field_section,
206 } => {
207 write_varint(FRAME_PUSH_PROMISE, dst);
208 write_varint((varint_size(*push_id) + field_section.len()) as u64, dst);
209 write_varint(*push_id, dst);
210 dst.extend_from_slice(field_section);
211 }
212 Frame::Goaway(stream_id) => {
213 write_varint(FRAME_GOAWAY, dst);
214 write_varint(varint_size(*stream_id) as u64, dst);
215 write_varint(*stream_id, dst);
216 }
217 Frame::MaxPushId(push_id) => {
218 write_varint(FRAME_MAX_PUSH_ID, dst);
219 write_varint(varint_size(*push_id) as u64, dst);
220 write_varint(*push_id, dst);
221 }
222 }
223 }
224}
225
226#[derive(Debug, Clone, Copy, PartialEq, Eq)]
231pub enum FrameError {
232 Frame,
236 Unexpected(u64),
240 Settings,
244}
245
246impl FrameError {
247 pub const fn h3_code(self) -> u64 {
249 use crate::h3::H3Error;
250 match self {
251 FrameError::Frame => H3Error::FrameError.code(),
252 FrameError::Unexpected(_) => H3Error::FrameUnexpected.code(),
253 FrameError::Settings => H3Error::Settings.code(),
254 }
255 }
256}
257
258#[derive(Debug, Default)]
264pub struct FrameDecoder {
265 buf: Bytes,
270}
271
272impl FrameDecoder {
273 #[inline]
275 pub fn new() -> Self {
276 Self::default()
277 }
278
279 #[inline]
281 pub fn extend(&mut self, data: Bytes) {
282 if data.is_empty() {
283 return;
284 }
285 if self.buf.is_empty() {
286 self.buf = data;
287 return;
288 }
289
290 let mut joined = BytesMut::with_capacity(self.buf.len() + data.len());
291 joined.extend_from_slice(&self.buf);
292 joined.extend_from_slice(&data);
293 self.buf = joined.freeze();
294 }
295
296 #[inline]
298 pub fn buffered(&self) -> usize {
299 self.buf.len()
300 }
301
302 #[inline]
309 pub fn next_frame(&mut self) -> Result<Option<Frame>, FrameError> {
310 loop {
311 let Some((ty, type_len)) = parse_varint(&self.buf)? else {
312 return Ok(None);
313 };
314 if matches!(ty, 0x02 | 0x06 | 0x08 | 0x09) {
315 return Err(FrameError::Unexpected(ty));
316 }
317 let Some((len, len_len)) = parse_varint(&self.buf[type_len..])? else {
318 return Ok(None);
319 };
320 let header_len = type_len + len_len;
321 let Some(total) = header_len.checked_add(len as usize) else {
322 return Err(FrameError::Frame);
323 };
324 if total > self.buf.len() {
325 return Ok(None);
326 }
327 if !is_known_frame_type(ty) {
328 self.buf.advance(total);
329 continue;
330 }
331 let mut chunk = self.buf.split_to(total);
332 let payload = chunk.split_off(header_len);
333 let frame = match ty {
334 FRAME_DATA => Frame::Data(payload),
335 FRAME_HEADERS => Frame::Headers(payload),
336 FRAME_CANCEL_PUSH => Frame::CancelPush(take_varint(&payload)?),
337 FRAME_SETTINGS => Frame::Settings(parse_settings(&payload)?),
338 FRAME_PUSH_PROMISE => {
339 let Some((push_id, id_len)) = parse_varint(&payload)? else {
340 return Err(FrameError::Frame);
341 };
342 Frame::PushPromise {
343 push_id,
344 field_section: payload.slice(id_len..),
345 }
346 }
347 FRAME_GOAWAY => Frame::Goaway(take_varint(&payload)?),
348 FRAME_MAX_PUSH_ID => Frame::MaxPushId(take_varint(&payload)?),
349 _ => unreachable!("unknown types are skipped above"),
350 };
351 return Ok(Some(frame));
352 }
353 }
354}
355
356impl FrameDecoder {
357 #[inline]
362 pub fn peek_frame_type(&self) -> Option<u64> {
363 match parse_varint(&self.buf) {
364 Ok(Some((ty, _))) => Some(ty),
365 _ => None,
366 }
367 }
368}
369
370#[inline]
371fn is_known_frame_type(ty: u64) -> bool {
372 matches!(
373 ty,
374 FRAME_DATA
375 | FRAME_HEADERS
376 | FRAME_CANCEL_PUSH
377 | FRAME_SETTINGS
378 | FRAME_PUSH_PROMISE
379 | FRAME_GOAWAY
380 | FRAME_MAX_PUSH_ID
381 )
382}
383
384#[inline]
387fn is_grease(v: u64) -> bool {
388 v >= 0x21 && (v - 0x21).is_multiple_of(0x1f)
389}
390
391#[inline]
392fn is_reserved_setting(id: u64) -> bool {
393 (0x02..=0x05).contains(&id)
394}
395
396#[inline]
397fn parse_settings(payload: &[u8]) -> Result<Settings, FrameError> {
398 let mut settings = Settings::new();
399 let mut rest = payload;
400 while !rest.is_empty() {
401 let Some((id, id_len)) = parse_varint(rest)? else {
402 return Err(FrameError::Frame);
403 };
404 rest = &rest[id_len..];
405 let Some((value, value_len)) = parse_varint(rest)? else {
406 return Err(FrameError::Frame);
407 };
408 rest = &rest[value_len..];
409 if is_reserved_setting(id) {
410 return Err(FrameError::Settings);
411 }
412 if settings.get(id).is_some() {
413 return Err(FrameError::Settings);
414 }
415 if !is_grease(id) {
416 settings.insert(id, value);
417 }
418 }
419 Ok(settings)
420}
421
422#[inline]
427fn take_varint(buf: &[u8]) -> Result<u64, FrameError> {
428 let Some((value, n)) = parse_varint(buf)? else {
429 return Err(FrameError::Frame);
430 };
431 if n != buf.len() {
432 return Err(FrameError::Frame);
433 }
434 Ok(value)
435}
436
437const MIN_VARINT: [u64; 4] = [0, 1 << 6, 1 << 14, 1 << 30];
441
442#[inline]
452pub(crate) fn parse_varint(buf: &[u8]) -> Result<Option<(u64, usize)>, FrameError> {
453 let Some(&first) = buf.first() else {
454 return Ok(None);
455 };
456 let len = 1usize << (first >> 6);
457 if buf.len() < len {
458 return Ok(None);
459 }
460 let mut value = u64::from(first & 0x3f);
461 for &byte in &buf[1..len] {
462 value = (value << 8) | u64::from(byte);
463 }
464 if len > 1 && value < MIN_VARINT[usize::from(first >> 6)] {
468 return Err(FrameError::Frame);
469 }
470 Ok(Some((value, len)))
471}
472
473#[inline]
475pub fn varint_size(value: u64) -> usize {
476 if value < (1 << 6) {
477 1
478 } else if value < (1 << 14) {
479 2
480 } else if value < (1 << 30) {
481 4
482 } else {
483 8
484 }
485}
486
487#[inline]
490pub fn write_varint(value: u64, dst: &mut BytesMut) {
491 debug_assert!(value <= MAX_VARINT, "varint out of range: {value:#x}");
492 if value < (1 << 6) {
493 dst.put_u8(value as u8);
494 } else if value < (1 << 14) {
495 dst.put_u16((0b01 << 14) | value as u16);
496 } else if value < (1 << 30) {
497 dst.put_u32((0b10 << 30) | value as u32);
498 } else {
499 dst.put_u64((0b11 << 62) | value);
500 }
501}
502
503#[cfg(test)]
504mod tests {
505 use super::*;
506
507 #[inline]
508 fn decode_all(decoder: &mut FrameDecoder) -> Result<Vec<Frame>, FrameError> {
509 let mut frames = Vec::new();
510 while let Some(frame) = decoder.next_frame()? {
511 frames.push(frame);
512 }
513 Ok(frames)
514 }
515
516 #[inline]
517 fn encode_frames(frames: &[Frame]) -> Bytes {
518 let mut buf = BytesMut::new();
519 for frame in frames {
520 frame.encode(&mut buf);
521 }
522 buf.freeze()
523 }
524
525 #[test]
526 fn round_trip_all_frame_types() {
527 let mut settings = Settings::new();
528 settings.insert(SETTINGS_QPACK_MAX_TABLE_CAPACITY, 4096);
529 settings.insert(SETTINGS_MAX_FIELD_SECTION_SIZE, 100);
530 settings.insert(SETTINGS_QPACK_BLOCKED_STREAMS, 2);
531 settings.insert(0x21, 7); let frames = [
534 Frame::Data(Bytes::from_static(b"hello world")),
535 Frame::Headers(Bytes::from_static(b"\x3f\xbd\x01")),
536 Frame::Settings(settings),
537 Frame::CancelPush(7),
538 Frame::PushPromise {
539 push_id: 1,
540 field_section: Bytes::from_static(b"\x05\x00\x80"),
541 },
542 Frame::Goaway(2),
543 Frame::MaxPushId(0),
544 Frame::Data(Bytes::new()),
545 Frame::Headers(Bytes::new()),
546 ];
547 let mut decoder = FrameDecoder::new();
548 decoder.extend(encode_frames(&frames));
549 let got = decode_all(&mut decoder).expect("all frames parse");
550
551 let mut expected = frames.to_vec();
553 expected[2] = Frame::Settings(settings_without_grease());
554 assert_eq!(got, expected);
555 }
556
557 #[inline]
558 fn settings_without_grease() -> Settings {
559 let mut s = Settings::new();
560 s.insert(SETTINGS_QPACK_MAX_TABLE_CAPACITY, 4096);
561 s.insert(SETTINGS_MAX_FIELD_SECTION_SIZE, 100);
562 s.insert(SETTINGS_QPACK_BLOCKED_STREAMS, 2);
563 s
564 }
565
566 #[test]
567 fn incremental_byte_at_a_time() {
568 let wire = encode_frames(&[
569 Frame::Headers(Bytes::from_static(b"abc")),
570 Frame::Data(Bytes::from_static(b"xy")),
571 ]);
572 let mut decoder = FrameDecoder::new();
573 let mut got = Vec::new();
574 for (i, &byte) in wire.iter().enumerate() {
575 decoder.extend(Bytes::copy_from_slice(&[byte]));
576 while let Some(frame) = decoder.next_frame().unwrap() {
577 got.push(frame);
578 }
579 if i < 4 {
580 assert!(got.is_empty(), "frame appeared early at byte {i}");
581 }
582 if i == 4 {
583 assert_eq!(got, vec![Frame::Headers(Bytes::from_static(b"abc"))]);
586 }
587 }
588 assert_eq!(
589 got,
590 vec![
591 Frame::Headers(Bytes::from_static(b"abc")),
592 Frame::Data(Bytes::from_static(b"xy")),
593 ]
594 );
595 assert_eq!(decoder.buffered(), 0);
596 }
597
598 #[test]
599 fn truncated_prefixes_are_incomplete() {
600 let mut decoder = FrameDecoder::new();
602 decoder.extend(Bytes::from_static(&[0x00]));
603 assert_eq!(decoder.next_frame().unwrap(), None);
604 decoder.extend(Bytes::from_static(&[0x05]));
606 assert_eq!(decoder.next_frame().unwrap(), None);
607 decoder.extend(Bytes::from_static(b"he"));
609 assert_eq!(decoder.next_frame().unwrap(), None);
610 decoder.extend(Bytes::from_static(b"llo"));
612 assert_eq!(
613 decode_all(&mut decoder).unwrap(),
614 vec![Frame::Data(Bytes::from_static(b"hello"))]
615 );
616
617 let mut decoder = FrameDecoder::new();
620 decoder.extend(Bytes::from_static(&[
621 0x01, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
622 ]));
623 assert_eq!(decoder.next_frame().unwrap(), None);
624 assert_eq!(decoder.buffered(), 10);
625 }
626
627 #[test]
628 fn forbidden_http2_frames() {
629 for ty in [0x02u8, 0x06, 0x08, 0x09] {
630 let mut decoder = FrameDecoder::new();
631 decoder.extend(Bytes::copy_from_slice(&[ty, 0x01, 0x00]));
632 let err = decoder.next_frame().unwrap_err();
633 assert_eq!(err, FrameError::Unexpected(u64::from(ty)));
634 assert_eq!(err.h3_code(), 0x0105);
635 }
636 }
637
638 #[test]
639 fn unknown_and_grease_frames_are_skipped() {
640 let mut wire = BytesMut::new();
643 Frame::Headers(Bytes::from_static(b"first")).encode(&mut wire);
644 write_varint(0x42, &mut wire);
645 write_varint(3, &mut wire);
646 wire.extend_from_slice(b"xyz");
647 write_varint(0x21, &mut wire);
648 write_varint(2, &mut wire);
649 wire.extend_from_slice(&[0xde, 0xad]);
650 Frame::Data(Bytes::from_static(b"last")).encode(&mut wire);
651
652 let mut decoder = FrameDecoder::new();
653 decoder.extend(wire.freeze());
654 let frames = decode_all(&mut decoder).unwrap();
655 assert_eq!(
656 frames,
657 vec![
658 Frame::Headers(Bytes::from_static(b"first")),
659 Frame::Data(Bytes::from_static(b"last")),
660 ]
661 );
662 assert_eq!(decoder.buffered(), 0);
663 }
664
665 #[test]
666 fn settings_payload_validation() {
667 let mut decoder = FrameDecoder::new();
669 decoder.extend(Bytes::from_static(&[0x04, 0x00]));
670 assert_eq!(
671 decode_all(&mut decoder).unwrap(),
672 vec![Frame::Settings(Settings::new())]
673 );
674
675 let mut wire = BytesMut::new();
677 Frame::Settings({
678 let mut s = Settings::new();
679 s.insert(0x06, 1);
680 s.insert(0x06, 2);
681 s
682 })
683 .encode(&mut wire);
684 let mut decoder = FrameDecoder::new();
685 decoder.extend(wire.freeze());
686 let err = decoder.next_frame().unwrap_err();
687 assert_eq!(err, FrameError::Settings);
688 assert_eq!(err.h3_code(), 0x0109);
689
690 for id in 0x02..=0x05 {
692 let mut wire = BytesMut::new();
693 Frame::Settings({
694 let mut s = Settings::new();
695 s.insert(id, 0);
696 s
697 })
698 .encode(&mut wire);
699 let mut decoder = FrameDecoder::new();
700 decoder.extend(wire.freeze());
701 assert_eq!(decoder.next_frame().unwrap_err(), FrameError::Settings);
702 }
703
704 let mut s = Settings::new();
707 s.insert(0x0100, 5);
708 s.insert(SETTINGS_ENABLE_CONNECT_PROTOCOL, 1);
709 let mut wire = BytesMut::new();
710 Frame::Settings(s.clone()).encode(&mut wire);
711 let mut decoder = FrameDecoder::new();
712 decoder.extend(wire.freeze());
713 match decode_all(&mut decoder).unwrap()[0].clone() {
714 Frame::Settings(got) => {
715 assert_eq!(got.get(0x0100), Some(5));
716 assert_eq!(got.get(SETTINGS_ENABLE_CONNECT_PROTOCOL), Some(1));
717 }
718 other => panic!("expected Settings, got {other:?}"),
719 }
720
721 let mut decoder = FrameDecoder::new();
723 decoder.extend(Bytes::from_static(&[0x04, 0x01, 0x06]));
724 assert_eq!(decoder.next_frame().unwrap_err(), FrameError::Frame);
725 }
726
727 #[test]
728 fn fixed_value_frames_reject_bad_payloads() {
729 let mut decoder = FrameDecoder::new();
731 decoder.extend(Bytes::from_static(&[0x03, 0x00]));
732 assert_eq!(decoder.next_frame().unwrap_err(), FrameError::Frame);
733
734 let mut decoder = FrameDecoder::new();
736 decoder.extend(Bytes::from_static(&[0x03, 0x02, 0x01, 0x00]));
737 assert_eq!(decoder.next_frame().unwrap_err(), FrameError::Frame);
738
739 let mut decoder = FrameDecoder::new();
741 decoder.extend(Bytes::from_static(&[0x03, 0x02, 0x40, 0x05]));
742 assert_eq!(decoder.next_frame().unwrap_err(), FrameError::Frame);
743
744 let mut decoder = FrameDecoder::new();
746 decoder.extend(Bytes::from_static(&[0x07, 0x01, 0x05]));
747 assert_eq!(decode_all(&mut decoder).unwrap(), vec![Frame::Goaway(5)]);
748
749 let mut decoder = FrameDecoder::new();
751 decoder.extend(Bytes::from_static(&[0x40, 0x00, 0x00]));
752 assert_eq!(decoder.next_frame().unwrap_err(), FrameError::Frame);
753
754 let mut decoder = FrameDecoder::new();
756 decoder.extend(Bytes::from_static(&[0x00, 0x40, 0x00]));
757 assert_eq!(decoder.next_frame().unwrap_err(), FrameError::Frame);
758 }
759
760 #[test]
761 fn push_promise_shapes() {
762 let mut decoder = FrameDecoder::new();
764 decoder.extend(Bytes::from_static(&[0x05, 0x04, 0x01, b'a', b'b', b'c']));
765 assert_eq!(
766 decode_all(&mut decoder).unwrap(),
767 vec![Frame::PushPromise {
768 push_id: 1,
769 field_section: Bytes::from_static(b"abc"),
770 }]
771 );
772
773 let mut decoder = FrameDecoder::new();
775 decoder.extend(Bytes::from_static(&[0x05, 0x01, 0x01]));
776 assert_eq!(
777 decode_all(&mut decoder).unwrap(),
778 vec![Frame::PushPromise {
779 push_id: 1,
780 field_section: Bytes::new(),
781 }]
782 );
783
784 let mut decoder = FrameDecoder::new();
786 decoder.extend(Bytes::from_static(&[0x05, 0x00]));
787 assert_eq!(decoder.next_frame().unwrap_err(), FrameError::Frame);
788 }
789
790 #[test]
791 fn varint_edge_encodings() {
792 for value in [
795 (1 << 6) - 1,
796 1 << 6,
797 (1 << 14) - 1,
798 1 << 14,
799 (1 << 30) - 1,
800 1 << 30,
801 MAX_VARINT,
802 ] {
803 let mut wire = BytesMut::new();
804 write_varint(value, &mut wire);
805 assert_eq!(wire.len(), varint_size(value));
806 let (got, n) = parse_varint(&wire).unwrap().unwrap();
807 assert_eq!(got, value);
808 assert_eq!(n, wire.len());
809 }
810
811 assert_eq!(parse_varint(&[0x40, 0x00]), Err(FrameError::Frame)); assert_eq!(
814 parse_varint(&[0x80, 0x00, 0x00, 0x40]),
815 Err(FrameError::Frame)
816 ); assert_eq!(parse_varint(&[0x40, 0x40]), Ok(Some((64, 2))));
818 assert_eq!(parse_varint(&[0x40]), Ok(None));
820 assert_eq!(parse_varint(&[]), Ok(None));
821 }
822
823 #[test]
824 fn clean_eof_with_truncated_frame_is_detectable() {
825 let mut decoder = FrameDecoder::new();
826 decoder.extend(Bytes::from_static(&[0x01, 0x05, b'a', b'b']));
827 assert_eq!(decoder.next_frame().unwrap(), None);
828 assert_eq!(decoder.buffered(), 4);
830 }
831}