1use std::convert::From;
12
13use kawa::repr::Slice;
14use nom::{
15 Err, IResult, Parser,
16 bytes::complete::{tag, take},
17 combinator::{complete, map},
18 error::{ErrorKind, ParseError},
19 multi::many0,
20 number::complete::{be_u8, be_u16, be_u24, be_u32},
21};
22use sozu_command::logging::ansi_palette;
23
24macro_rules! log_module_context {
29 () => {{
30 let (open, reset, _, _, _) = ansi_palette();
31 format!("{open}MUX-PARSER{reset}\t >>>", open = open, reset = reset)
32 }};
33}
34
35pub const FRAME_HEADER_SIZE: usize = 9;
39
40pub const STREAM_ID_MASK: u32 = 0x7FFFFFFF;
42
43pub const FLAG_END_STREAM: u8 = 0x1;
46pub const FLAG_END_HEADERS: u8 = 0x4;
48pub const FLAG_PADDED: u8 = 0x8;
50pub const FLAG_PRIORITY: u8 = 0x20;
52pub const FLAG_ACK: u8 = 0x1;
54
55pub const PRIORITY_PAYLOAD_SIZE: u32 = 5;
57pub const RST_STREAM_PAYLOAD_SIZE: u32 = 4;
58pub const SETTINGS_ENTRY_SIZE: u32 = 6;
59pub const PING_PAYLOAD_SIZE: u32 = 8;
60pub const WINDOW_UPDATE_PAYLOAD_SIZE: u32 = 4;
61pub const GOAWAY_PAYLOAD_SIZE: u32 = 8;
62
63pub const SETTINGS_HEADER_TABLE_SIZE: u16 = 1;
65pub const SETTINGS_ENABLE_PUSH: u16 = 2;
66pub const SETTINGS_MAX_CONCURRENT_STREAMS: u16 = 3;
67pub const SETTINGS_INITIAL_WINDOW_SIZE: u16 = 4;
68pub const SETTINGS_MAX_FRAME_SIZE: u16 = 5;
69pub const SETTINGS_MAX_HEADER_LIST_SIZE: u16 = 6;
70pub const SETTINGS_ENABLE_CONNECT_PROTOCOL: u16 = 8;
71pub const SETTINGS_NO_RFC7540_PRIORITIES: u16 = 9;
72pub const SETTINGS_COUNT: u32 = 8;
74
75#[derive(Clone, Debug, PartialEq)]
78pub struct FrameHeader {
79 pub payload_len: u32,
80 pub frame_type: FrameType,
81 pub flags: u8,
82 pub stream_id: u32,
83}
84
85#[derive(Clone, Debug, PartialEq)]
86pub enum FrameType {
87 Data,
88 Headers,
89 Priority,
90 RstStream,
91 Settings,
92 PushPromise,
93 Ping,
94 GoAway,
95 WindowUpdate,
96 Continuation,
97 PriorityUpdate,
101 Unknown(u8),
106}
107
108impl std::str::FromStr for H2Error {
109 type Err = ();
110
111 fn from_str(s: &str) -> Result<Self, ()> {
112 match s {
113 "NO_ERROR" => Ok(H2Error::NoError),
114 "PROTOCOL_ERROR" => Ok(H2Error::ProtocolError),
115 "INTERNAL_ERROR" => Ok(H2Error::InternalError),
116 "FLOW_CONTROL_ERROR" => Ok(H2Error::FlowControlError),
117 "SETTINGS_TIMEOUT" => Ok(H2Error::SettingsTimeout),
118 "STREAM_CLOSED" => Ok(H2Error::StreamClosed),
119 "FRAME_SIZE_ERROR" => Ok(H2Error::FrameSizeError),
120 "REFUSED_STREAM" => Ok(H2Error::RefusedStream),
121 "CANCEL" => Ok(H2Error::Cancel),
122 "COMPRESSION_ERROR" => Ok(H2Error::CompressionError),
123 "CONNECT_ERROR" => Ok(H2Error::ConnectError),
124 "ENHANCE_YOUR_CALM" => Ok(H2Error::EnhanceYourCalm),
125 "INADEQUATE_SECURITY" => Ok(H2Error::InadequateSecurity),
126 "HTTP_1_1_REQUIRED" => Ok(H2Error::HTTP11Required),
127 _ => Err(()),
128 }
129 }
130}
131
132#[derive(Clone, Debug, PartialEq)]
133pub struct ParserError<'a> {
134 pub input: &'a [u8],
135 pub kind: ParserErrorKind,
136}
137
138#[derive(Clone, Debug, PartialEq)]
139pub enum ParserErrorKind {
140 Nom(ErrorKind),
141 H2(H2Error),
142}
143
144#[derive(Clone, Copy, Debug, PartialEq)]
145#[repr(u32)]
146pub enum H2Error {
147 NoError = 0x0,
148 ProtocolError = 0x1,
149 InternalError = 0x2,
150 FlowControlError = 0x3,
151 SettingsTimeout = 0x4,
152 StreamClosed = 0x5,
153 FrameSizeError = 0x6,
154 RefusedStream = 0x7,
155 Cancel = 0x8,
156 CompressionError = 0x9,
157 ConnectError = 0xa,
158 EnhanceYourCalm = 0xb,
159 InadequateSecurity = 0xc,
160 HTTP11Required = 0xd,
161}
162
163impl TryFrom<u32> for H2Error {
164 type Error = u32;
165
166 fn try_from(code: u32) -> Result<Self, u32> {
167 match code {
168 0x0 => Ok(H2Error::NoError),
169 0x1 => Ok(H2Error::ProtocolError),
170 0x2 => Ok(H2Error::InternalError),
171 0x3 => Ok(H2Error::FlowControlError),
172 0x4 => Ok(H2Error::SettingsTimeout),
173 0x5 => Ok(H2Error::StreamClosed),
174 0x6 => Ok(H2Error::FrameSizeError),
175 0x7 => Ok(H2Error::RefusedStream),
176 0x8 => Ok(H2Error::Cancel),
177 0x9 => Ok(H2Error::CompressionError),
178 0xa => Ok(H2Error::ConnectError),
179 0xb => Ok(H2Error::EnhanceYourCalm),
180 0xc => Ok(H2Error::InadequateSecurity),
181 0xd => Ok(H2Error::HTTP11Required),
182 other => Err(other),
183 }
184 }
185}
186
187impl H2Error {
188 pub const fn as_str(&self) -> &'static str {
190 match self {
191 H2Error::NoError => "NO_ERROR",
192 H2Error::ProtocolError => "PROTOCOL_ERROR",
193 H2Error::InternalError => "INTERNAL_ERROR",
194 H2Error::FlowControlError => "FLOW_CONTROL_ERROR",
195 H2Error::SettingsTimeout => "SETTINGS_TIMEOUT",
196 H2Error::StreamClosed => "STREAM_CLOSED",
197 H2Error::FrameSizeError => "FRAME_SIZE_ERROR",
198 H2Error::RefusedStream => "REFUSED_STREAM",
199 H2Error::Cancel => "CANCEL",
200 H2Error::CompressionError => "COMPRESSION_ERROR",
201 H2Error::ConnectError => "CONNECT_ERROR",
202 H2Error::EnhanceYourCalm => "ENHANCE_YOUR_CALM",
203 H2Error::InadequateSecurity => "INADEQUATE_SECURITY",
204 H2Error::HTTP11Required => "HTTP_1_1_REQUIRED",
205 }
206 }
207}
208
209impl std::fmt::Display for H2Error {
210 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
211 f.write_str(self.as_str())
212 }
213}
214
215impl<'a> ParserError<'a> {
216 pub fn new(input: &'a [u8], error: ParserErrorKind) -> ParserError<'a> {
217 ParserError { input, kind: error }
218 }
219 pub fn new_h2(input: &'a [u8], error: H2Error) -> ParserError<'a> {
220 ParserError {
221 input,
222 kind: ParserErrorKind::H2(error),
223 }
224 }
225}
226
227impl<'a> ParseError<&'a [u8]> for ParserError<'a> {
228 fn from_error_kind(input: &'a [u8], kind: ErrorKind) -> Self {
229 ParserError {
230 input,
231 kind: ParserErrorKind::Nom(kind),
232 }
233 }
234
235 fn append(input: &'a [u8], kind: ErrorKind, _other: Self) -> Self {
236 ParserError {
237 input,
238 kind: ParserErrorKind::Nom(kind),
239 }
240 }
241}
242
243impl<'a> From<(&'a [u8], ErrorKind)> for ParserError<'a> {
244 fn from((input, kind): (&'a [u8], ErrorKind)) -> Self {
245 ParserError {
246 input,
247 kind: ParserErrorKind::Nom(kind),
248 }
249 }
250}
251
252pub fn preface(i: &[u8]) -> IResult<&[u8], &[u8]> {
253 tag(&b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"[..])(i)
254}
255
256macro_rules! ensure_frame_size {
264 ($input:expr, $cond:expr) => {
265 if !($cond) {
266 return Err(Err::Failure(ParserError::new_h2(
267 $input,
268 H2Error::FrameSizeError,
269 )));
270 }
271 };
272}
273
274pub fn frame_header(
287 input: &[u8],
288 max_frame_size: u32,
289) -> IResult<&[u8], FrameHeader, ParserError<'_>> {
290 let in_len = input.len();
291 let (i, payload_len) = be_u24(input)?;
292 if payload_len > max_frame_size {
293 return Err(Err::Failure(ParserError::new_h2(
294 i,
295 H2Error::FrameSizeError,
296 )));
297 }
298
299 let (i, t) = be_u8(i)?;
300 let frame_type = convert_frame_type(t);
301 let (i, flags) = be_u8(i)?;
302 let (i, raw_stream_id) = be_u32(i)?;
303 let stream_id = raw_stream_id & STREAM_ID_MASK;
304 debug_assert!(i.len() <= in_len, "parser must not grow its input");
309 debug_assert_eq!(
310 i.len(),
311 in_len - FRAME_HEADER_SIZE,
312 "frame_header must consume exactly the 9-byte header"
313 );
314 debug_assert!(
315 payload_len <= max_frame_size,
316 "frame_header must enforce the size bound it was given"
317 );
318 debug_assert_eq!(
319 stream_id & !STREAM_ID_MASK,
320 0,
321 "reserved high bit must be masked off the stream id"
322 );
323
324 let valid_stream_id = match frame_type {
329 FrameType::Data
330 | FrameType::Headers
331 | FrameType::Priority
332 | FrameType::RstStream
333 | FrameType::PushPromise
334 | FrameType::Continuation => stream_id != 0,
335 FrameType::Settings | FrameType::Ping | FrameType::GoAway | FrameType::PriorityUpdate => {
338 stream_id == 0
339 }
340 FrameType::WindowUpdate | FrameType::Unknown(_) => true,
341 };
342 if !valid_stream_id {
343 error!("{} invalid stream_id: {}", log_module_context!(), stream_id);
344 return Err(Err::Failure(ParserError::new_h2(i, H2Error::ProtocolError)));
345 }
346
347 Ok((
348 i,
349 FrameHeader {
350 payload_len,
351 frame_type,
352 flags,
353 stream_id,
354 },
355 ))
356}
357
358fn convert_frame_type(t: u8) -> FrameType {
364 trace!("{} got frame type: {}", log_module_context!(), t);
365 match t {
366 0 => FrameType::Data,
367 1 => FrameType::Headers,
368 2 => FrameType::Priority,
369 3 => FrameType::RstStream,
370 4 => FrameType::Settings,
371 5 => FrameType::PushPromise,
372 6 => FrameType::Ping,
373 7 => FrameType::GoAway,
374 8 => FrameType::WindowUpdate,
375 9 => FrameType::Continuation,
376 0x10 => FrameType::PriorityUpdate,
378 other => FrameType::Unknown(other),
379 }
380}
381
382#[derive(Clone, Debug)]
383pub enum Frame {
384 Data(Data),
385 Headers(Headers),
386 Priority(Priority),
387 RstStream(RstStream),
388 Settings(Settings),
389 PushPromise(PushPromise),
390 Ping(Ping),
391 GoAway(GoAway),
392 WindowUpdate(WindowUpdate),
393 Continuation(Continuation),
394 PriorityUpdate(PriorityUpdate),
398 Unknown(u8),
401}
402
403#[derive(Clone, Debug, PartialEq)]
405pub struct PriorityUpdate {
406 pub prioritized_stream_id: u32,
410 pub priority_field_value: Vec<u8>,
414}
415
416pub fn frame_body<'a>(
417 i: &'a [u8],
418 header: &FrameHeader,
419) -> IResult<&'a [u8], Frame, ParserError<'a>> {
420 let in_len = i.len();
421 let f = match header.frame_type {
422 FrameType::Data => data_frame(i, header)?,
423 FrameType::Headers => headers_frame(i, header)?,
424 FrameType::Priority => {
425 ensure_frame_size!(i, header.payload_len == PRIORITY_PAYLOAD_SIZE);
426 priority_frame(i, header)?
427 }
428 FrameType::RstStream => {
429 ensure_frame_size!(i, header.payload_len == RST_STREAM_PAYLOAD_SIZE);
430 rst_stream_frame(i, header)?
431 }
432 FrameType::PushPromise => push_promise_frame(i, header)?,
433 FrameType::Continuation => continuation_frame(i, header)?,
434 FrameType::Settings => {
435 ensure_frame_size!(
437 i,
438 !(header.flags & FLAG_ACK != 0 && header.payload_len != 0)
439 );
440 ensure_frame_size!(i, header.payload_len.is_multiple_of(SETTINGS_ENTRY_SIZE));
441 settings_frame(i, header)?
442 }
443 FrameType::Ping => {
444 ensure_frame_size!(i, header.payload_len == PING_PAYLOAD_SIZE);
445 ping_frame(i, header)?
446 }
447 FrameType::GoAway => {
448 ensure_frame_size!(i, header.payload_len >= GOAWAY_PAYLOAD_SIZE);
451 goaway_frame(i, header)?
452 }
453 FrameType::WindowUpdate => {
454 ensure_frame_size!(i, header.payload_len == WINDOW_UPDATE_PAYLOAD_SIZE);
455 window_update_frame(i, header)?
456 }
457 FrameType::PriorityUpdate => priority_update_frame(i, header)?,
459 FrameType::Unknown(_) => unknown_frame(i, header)?,
461 };
462
463 debug_assert!(
466 f.0.len() <= in_len,
467 "frame body parser must not grow its input"
468 );
469 debug_assert!(
470 f.0.len() <= in_len.saturating_sub(header.payload_len as usize),
471 "frame body must consume at least the declared payload_len bytes"
472 );
473 Ok(f)
474}
475
476#[derive(Clone, Debug)]
477pub struct Data {
478 pub stream_id: u32,
479 pub payload: Slice,
480 pub end_stream: bool,
481}
482
483fn strip_padding<'a>(
497 i: &'a [u8],
498 flags: u8,
499 error_input: &'a [u8],
500) -> IResult<&'a [u8], u8, ParserError<'a>> {
501 let in_len = i.len();
502 let (i, pad_length) = if flags & FLAG_PADDED != 0 {
503 let (i, pad_length) = be_u8(i)?;
504 (i, pad_length)
505 } else {
506 (i, 0)
507 };
508 debug_assert_eq!(
511 i.len(),
512 in_len - (flags & FLAG_PADDED != 0) as usize,
513 "strip_padding consumes the pad-length byte iff PADDED is set"
514 );
515
516 if (pad_length as usize) > i.len() {
517 return Err(Err::Failure(ParserError::new_h2(
518 error_input,
519 H2Error::ProtocolError,
520 )));
521 }
522
523 debug_assert!(
526 pad_length as usize <= i.len(),
527 "strip_padding must reject pad_length larger than the remaining payload"
528 );
529 Ok((i, pad_length))
530}
531
532fn unpad<'a>(
538 i: &'a [u8],
539 pad_length: u8,
540 error_input: &'a [u8],
541) -> Result<&'a [u8], Err<ParserError<'a>>> {
542 let in_len = i.len();
543 let content_len = i
544 .len()
545 .checked_sub(pad_length as usize)
546 .ok_or_else(|| Err::Failure(ParserError::new_h2(error_input, H2Error::ProtocolError)))?;
547 debug_assert!(
550 content_len <= in_len,
551 "unpad must not grow the content slice"
552 );
553 debug_assert_eq!(
554 content_len + pad_length as usize,
555 in_len,
556 "content and padding must exactly partition the input"
557 );
558 Ok(&i[..content_len])
559}
560
561pub fn data_frame<'a>(
562 input: &'a [u8],
563 header: &FrameHeader,
564) -> IResult<&'a [u8], Frame, ParserError<'a>> {
565 let in_len = input.len();
566 let (remaining, i) = take(header.payload_len)(input)?;
567
568 let (i, pad_length) = strip_padding(i, header.flags, input)?;
569 let payload = unpad(i, pad_length, input)?;
570
571 debug_assert_eq!(
575 remaining.len(),
576 in_len - header.payload_len as usize,
577 "data_frame must consume exactly payload_len bytes"
578 );
579 debug_assert!(
580 payload.len() <= header.payload_len as usize,
581 "data payload must fit within the declared frame payload"
582 );
583 debug_assert!(
584 pad_length as usize <= header.payload_len as usize,
585 "padding must not exceed the frame payload"
586 );
587
588 Ok((
589 remaining,
590 Frame::Data(Data {
591 stream_id: header.stream_id,
592 payload: Slice::new(input, payload),
593 end_stream: header.flags & FLAG_END_STREAM != 0,
594 }),
595 ))
596}
597
598#[derive(Clone, Debug)]
599pub struct Headers {
600 pub stream_id: u32,
601 pub priority: Option<PriorityPart>,
602 pub header_block_fragment: Slice,
603 pub end_stream: bool,
605 pub end_headers: bool,
606}
607
608#[derive(Clone, Debug, PartialEq)]
609pub struct StreamDependency {
610 pub exclusive: bool,
611 pub stream_id: u32,
612}
613
614fn stream_dependency(i: &[u8]) -> IResult<&[u8], StreamDependency, ParserError<'_>> {
615 let (i, stream) = map(be_u32, |i| StreamDependency {
616 exclusive: i & 0x80000000 != 0,
617 stream_id: i & STREAM_ID_MASK,
618 })
619 .parse(i)?;
620 Ok((i, stream))
621}
622
623pub fn headers_frame<'a>(
624 input: &'a [u8],
625 header: &FrameHeader,
626) -> IResult<&'a [u8], Frame, ParserError<'a>> {
627 let in_len = input.len();
628 let (remaining, i) = take(header.payload_len)(input)?;
629
630 let (i, pad_length) = strip_padding(i, header.flags, input)?;
631
632 let (i, priority) = if header.flags & FLAG_PRIORITY != 0 {
633 let (i, stream_dependency) = stream_dependency(i)?;
634 let (i, weight) = be_u8(i)?;
635 (
636 i,
637 Some(PriorityPart::Rfc7540 {
638 stream_dependency,
639 weight,
640 }),
641 )
642 } else {
643 (i, None)
644 };
645
646 let header_block_fragment = unpad(i, pad_length, input)?;
647
648 debug_assert_eq!(
652 remaining.len(),
653 in_len - header.payload_len as usize,
654 "headers_frame must consume exactly payload_len bytes"
655 );
656 debug_assert!(
657 header_block_fragment.len() <= header.payload_len as usize,
658 "header block fragment must fit within the declared frame payload"
659 );
660
661 Ok((
662 remaining,
663 Frame::Headers(Headers {
664 stream_id: header.stream_id,
665 priority,
666 header_block_fragment: Slice::new(input, header_block_fragment),
667 end_stream: header.flags & FLAG_END_STREAM != 0,
668 end_headers: header.flags & FLAG_END_HEADERS != 0,
669 }),
670 ))
671}
672
673#[derive(Clone, Debug, PartialEq)]
674pub enum PriorityPart {
675 Rfc7540 {
676 stream_dependency: StreamDependency,
677 weight: u8,
678 },
679 Rfc9218 {
680 urgency: u8, incremental: bool,
682 },
683}
684
685#[derive(Clone, Debug, PartialEq)]
686pub struct Priority {
687 pub stream_id: u32,
688 pub inner: PriorityPart,
689}
690
691pub fn priority_frame<'a>(
692 input: &'a [u8],
693 header: &FrameHeader,
694) -> IResult<&'a [u8], Frame, ParserError<'a>> {
695 let in_len = input.len();
701 let (i, data) = take(header.payload_len)(input)?;
702 debug_assert_eq!(
705 i.len(),
706 in_len - header.payload_len as usize,
707 "priority_frame must consume exactly payload_len bytes"
708 );
709 debug_assert_eq!(
710 data.len(),
711 PRIORITY_PAYLOAD_SIZE as usize,
712 "PRIORITY payload must be exactly 5 bytes"
713 );
714 let (_, (stream_dependency, weight)) = (stream_dependency, be_u8).parse(data)?;
715 Ok((
716 i,
717 Frame::Priority(Priority {
718 stream_id: header.stream_id,
719 inner: PriorityPart::Rfc7540 {
720 stream_dependency,
721 weight,
722 },
723 }),
724 ))
725}
726
727#[derive(Clone, Debug, PartialEq)]
728pub struct RstStream {
729 pub stream_id: u32,
730 pub error_code: u32,
731}
732
733pub fn rst_stream_frame<'a>(
734 input: &'a [u8],
735 header: &FrameHeader,
736) -> IResult<&'a [u8], Frame, ParserError<'a>> {
737 let in_len = input.len();
742 let (i, data) = take(header.payload_len)(input)?;
743 debug_assert_eq!(
746 i.len(),
747 in_len - header.payload_len as usize,
748 "rst_stream_frame must consume exactly payload_len bytes"
749 );
750 debug_assert_eq!(
751 data.len(),
752 RST_STREAM_PAYLOAD_SIZE as usize,
753 "RST_STREAM payload must be exactly 4 bytes"
754 );
755 let (_, error_code) = be_u32(data)?;
756 Ok((
757 i,
758 Frame::RstStream(RstStream {
759 stream_id: header.stream_id,
760 error_code,
761 }),
762 ))
763}
764
765#[derive(Clone, Debug, PartialEq)]
766pub struct Settings {
767 pub settings: Vec<Setting>,
768 pub ack: bool,
769}
770
771#[derive(Clone, Debug, PartialEq)]
772pub struct Setting {
773 pub identifier: u16,
774 pub value: u32,
775}
776
777pub const MAX_SETTINGS_ENTRIES: usize = 64;
787
788pub fn settings_frame<'a>(
789 input: &'a [u8],
790 header: &FrameHeader,
791) -> IResult<&'a [u8], Frame, ParserError<'a>> {
792 if header.payload_len / SETTINGS_ENTRY_SIZE > MAX_SETTINGS_ENTRIES as u32 {
796 return Err(Err::Failure(ParserError::new_h2(
797 input,
798 H2Error::FrameSizeError,
799 )));
800 }
801
802 let in_len = input.len();
803 let (i, data) = take(header.payload_len)(input)?;
804
805 let (_, settings) = many0(map(complete((be_u16, be_u32)), |(identifier, value)| {
806 Setting { identifier, value }
807 }))
808 .parse(data)?;
809
810 debug_assert_eq!(
814 i.len(),
815 in_len - header.payload_len as usize,
816 "settings_frame must consume exactly payload_len bytes"
817 );
818 debug_assert_eq!(
819 settings.len(),
820 header.payload_len as usize / SETTINGS_ENTRY_SIZE as usize,
821 "one SETTINGS entry decodes per 6 payload bytes"
822 );
823 debug_assert!(
824 settings.len() <= MAX_SETTINGS_ENTRIES,
825 "settings_frame must honour the MAX_SETTINGS_ENTRIES allocation cap"
826 );
827
828 Ok((
829 i,
830 Frame::Settings(Settings {
831 settings,
832 ack: header.flags & FLAG_ACK != 0,
833 }),
834 ))
835}
836
837#[derive(Clone, Debug)]
846pub struct PushPromise;
847
848pub fn push_promise_frame<'a>(
849 input: &'a [u8],
850 header: &FrameHeader,
851) -> IResult<&'a [u8], Frame, ParserError<'a>> {
852 let (_remaining, _payload) = take(header.payload_len)(input)?;
855 Err(Err::Failure(ParserError::new_h2(
856 input,
857 H2Error::ProtocolError,
858 )))
859}
860
861#[derive(Clone, Debug, PartialEq)]
862pub struct Ping {
863 pub payload: [u8; 8],
864 pub ack: bool,
865}
866
867pub fn ping_frame<'a>(
868 input: &'a [u8],
869 header: &FrameHeader,
870) -> IResult<&'a [u8], Frame, ParserError<'a>> {
871 let in_len = input.len();
875 let (i, data) = take(header.payload_len)(input)?;
876
877 debug_assert_eq!(
882 i.len(),
883 in_len - header.payload_len as usize,
884 "ping_frame must consume exactly payload_len bytes"
885 );
886 debug_assert_eq!(
887 data.len(),
888 PING_PAYLOAD_SIZE as usize,
889 "PING payload must be exactly 8 bytes for the opaque-data copy"
890 );
891
892 let mut p = Ping {
893 payload: [0; 8],
894 ack: header.flags & FLAG_ACK != 0,
895 };
896 p.payload[..8].copy_from_slice(&data[..8]);
897
898 Ok((i, Frame::Ping(p)))
899}
900
901#[derive(Clone, Debug)]
902pub struct GoAway {
903 pub last_stream_id: u32,
904 pub error_code: u32,
905 pub additional_debug_data: Slice,
906}
907
908pub fn goaway_frame<'a>(
909 input: &'a [u8],
910 header: &FrameHeader,
911) -> IResult<&'a [u8], Frame, ParserError<'a>> {
912 let in_len = input.len();
913 let (remaining, i) = take(header.payload_len)(input)?;
914 let (i, raw_last_stream_id) = be_u32(i)?;
915 let last_stream_id = raw_last_stream_id & STREAM_ID_MASK;
917 let (additional_debug_data, error_code) = be_u32(i)?;
918 debug_assert_eq!(
922 remaining.len(),
923 in_len - header.payload_len as usize,
924 "goaway_frame must consume exactly payload_len bytes"
925 );
926 debug_assert_eq!(
927 additional_debug_data.len(),
928 header.payload_len as usize - GOAWAY_PAYLOAD_SIZE as usize,
929 "GOAWAY debug data is payload_len minus the 8-byte fixed prefix"
930 );
931 debug_assert_eq!(
932 last_stream_id & !STREAM_ID_MASK,
933 0,
934 "GOAWAY last_stream_id reserved high bit must be masked"
935 );
936 Ok((
937 remaining,
938 Frame::GoAway(GoAway {
939 last_stream_id,
940 error_code,
941 additional_debug_data: Slice::new(input, additional_debug_data),
942 }),
943 ))
944}
945
946#[derive(Clone, Debug, PartialEq)]
947pub struct WindowUpdate {
948 pub stream_id: u32,
949 pub increment: u32,
950}
951
952pub fn window_update_frame<'a>(
953 input: &'a [u8],
954 header: &FrameHeader,
955) -> IResult<&'a [u8], Frame, ParserError<'a>> {
956 let in_len = input.len();
960 let (i, data) = take(header.payload_len)(input)?;
961 debug_assert_eq!(
964 i.len(),
965 in_len - header.payload_len as usize,
966 "window_update_frame must consume exactly payload_len bytes"
967 );
968 debug_assert_eq!(
969 data.len(),
970 WINDOW_UPDATE_PAYLOAD_SIZE as usize,
971 "WINDOW_UPDATE payload must be exactly 4 bytes"
972 );
973 let (_, increment) = be_u32(data)?;
974 let increment = increment & STREAM_ID_MASK;
975 debug_assert!(
977 increment <= STREAM_ID_MASK,
978 "window-size increment must be a 31-bit value"
979 );
980
981 Ok((
989 i,
990 Frame::WindowUpdate(WindowUpdate {
991 stream_id: header.stream_id,
992 increment,
993 }),
994 ))
995}
996
997#[derive(Clone, Debug)]
1005pub struct Continuation;
1006
1007pub fn continuation_frame<'a>(
1008 input: &'a [u8],
1009 header: &FrameHeader,
1010) -> IResult<&'a [u8], Frame, ParserError<'a>> {
1011 let in_len = input.len();
1013 let (remaining, _) = take(header.payload_len)(input)?;
1014 debug_assert_eq!(
1015 remaining.len(),
1016 in_len - header.payload_len as usize,
1017 "continuation_frame must consume exactly payload_len bytes"
1018 );
1019 Ok((remaining, Frame::Continuation(Continuation)))
1020}
1021
1022pub fn unknown_frame<'a>(
1027 input: &'a [u8],
1028 header: &FrameHeader,
1029) -> IResult<&'a [u8], Frame, ParserError<'a>> {
1030 let in_len = input.len();
1031 let (remaining, _payload) = take(header.payload_len)(input)?;
1032 debug_assert_eq!(
1033 remaining.len(),
1034 in_len - header.payload_len as usize,
1035 "unknown_frame must consume exactly payload_len bytes"
1036 );
1037 let raw = match header.frame_type {
1038 FrameType::Unknown(t) => t,
1039 _ => 0,
1040 };
1041 Ok((remaining, Frame::Unknown(raw)))
1042}
1043
1044pub fn priority_update_frame<'a>(
1061 input: &'a [u8],
1062 header: &FrameHeader,
1063) -> IResult<&'a [u8], Frame, ParserError<'a>> {
1064 if header.payload_len < PRIORITY_UPDATE_MIN_PAYLOAD {
1065 return Err(Err::Failure(ParserError::new_h2(
1066 input,
1067 H2Error::FrameSizeError,
1068 )));
1069 }
1070 let value_len = (header.payload_len - PRIORITY_UPDATE_MIN_PAYLOAD) as usize;
1079 if value_len > PRIORITY_UPDATE_MAX_VALUE {
1080 return Err(Err::Failure(ParserError::new_h2(
1081 input,
1082 H2Error::ProtocolError,
1083 )));
1084 }
1085 let in_len = input.len();
1086 let (remaining, payload) = take(header.payload_len)(input)?;
1087 let (raw_id_bytes, value_bytes) = payload.split_at(PRIORITY_UPDATE_MIN_PAYLOAD as usize);
1088 debug_assert_eq!(
1092 remaining.len(),
1093 in_len - header.payload_len as usize,
1094 "priority_update_frame must consume exactly payload_len bytes"
1095 );
1096 debug_assert_eq!(
1097 raw_id_bytes.len(),
1098 PRIORITY_UPDATE_MIN_PAYLOAD as usize,
1099 "PRIORITY_UPDATE stream-id prefix must be exactly 4 bytes"
1100 );
1101 debug_assert!(
1102 value_bytes.len() <= PRIORITY_UPDATE_MAX_VALUE,
1103 "priority field value must respect the PRIORITY_UPDATE_MAX_VALUE cap"
1104 );
1105 let prioritized_stream_id = u32::from_be_bytes([
1106 raw_id_bytes[0],
1107 raw_id_bytes[1],
1108 raw_id_bytes[2],
1109 raw_id_bytes[3],
1110 ]) & STREAM_ID_MASK;
1111 debug_assert_eq!(
1112 prioritized_stream_id & !STREAM_ID_MASK,
1113 0,
1114 "prioritized_stream_id reserved high bit must be masked"
1115 );
1116 Ok((
1117 remaining,
1118 Frame::PriorityUpdate(PriorityUpdate {
1119 prioritized_stream_id,
1120 priority_field_value: value_bytes.to_vec(),
1121 }),
1122 ))
1123}
1124
1125pub const PRIORITY_UPDATE_MIN_PAYLOAD: u32 = 4;
1129
1130pub const PRIORITY_UPDATE_MAX_VALUE: usize = 1024;
1138
1139#[cfg(test)]
1140mod tests {
1141 use super::*;
1142
1143 const DEFAULT_MAX_FRAME_SIZE: u32 = 1 << 14;
1145
1146 #[test]
1152 fn test_settings_ack_with_payload_rejected() {
1153 let input = [
1155 0x00, 0x00, 0x06, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64,
1161 ];
1162
1163 let (remaining, header) =
1164 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1165 assert_eq!(header.frame_type, FrameType::Settings);
1166 assert_eq!(header.flags & FLAG_ACK, FLAG_ACK);
1167 assert_eq!(header.payload_len, 6);
1168
1169 let result = frame_body(remaining, &header);
1170 assert!(
1171 result.is_err(),
1172 "SETTINGS ACK with non-empty payload must be rejected"
1173 );
1174 match result {
1175 Err(nom::Err::Failure(e)) => {
1176 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1177 }
1178 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1179 }
1180 }
1181
1182 #[test]
1188 fn test_settings_ack_empty_accepted() {
1189 let input = [
1190 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, ];
1195
1196 let (remaining, header) =
1197 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1198 assert_eq!(header.frame_type, FrameType::Settings);
1199 assert_eq!(header.flags & FLAG_ACK, FLAG_ACK);
1200
1201 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
1202 match frame {
1203 Frame::Settings(settings) => {
1204 assert!(settings.ack, "ACK flag must be set");
1205 assert!(
1206 settings.settings.is_empty(),
1207 "should have no settings entries"
1208 );
1209 }
1210 other => panic!("expected Frame::Settings, got {other:?}"),
1211 }
1212 }
1213
1214 #[test]
1219 fn test_window_update_max_increment() {
1220 let input = [
1221 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFF, ];
1227
1228 let (remaining, header) =
1229 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1230 assert_eq!(header.frame_type, FrameType::WindowUpdate);
1231 assert_eq!(header.stream_id, 1);
1232
1233 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
1234 match frame {
1235 Frame::WindowUpdate(wu) => {
1236 assert_eq!(wu.increment, 0x7FFFFFFF);
1237 assert_eq!(wu.stream_id, 1);
1238 }
1239 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1240 }
1241 }
1242
1243 #[test]
1249 fn test_window_update_zero_increment_parsed() {
1250 let input = [
1252 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
1258
1259 let (remaining, header) =
1260 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1261 assert_eq!(header.frame_type, FrameType::WindowUpdate);
1262
1263 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
1264 match frame {
1265 Frame::WindowUpdate(wu) => {
1266 assert_eq!(wu.stream_id, 0);
1267 assert_eq!(wu.increment, 0);
1268 }
1269 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1270 }
1271
1272 let input2 = [
1274 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, ];
1280
1281 let (remaining2, header2) =
1282 frame_header(&input2, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1283 let (_, frame2) =
1284 frame_body(remaining2, &header2).expect("second frame body parses cleanly");
1285 match frame2 {
1286 Frame::WindowUpdate(wu) => {
1287 assert_eq!(wu.stream_id, 3);
1288 assert_eq!(wu.increment, 0);
1289 }
1290 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1291 }
1292 }
1293
1294 #[test]
1302 fn test_unknown_frame_type_is_ignored() {
1303 let input = [
1304 0x00, 0x00, 0x04, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef, ];
1310
1311 let (remaining, header) = frame_header(&input, DEFAULT_MAX_FRAME_SIZE)
1312 .expect("unknown frame header must parse cleanly");
1313 assert!(matches!(header.frame_type, FrameType::Unknown(0xFF)));
1314 assert_eq!(header.payload_len, 4);
1315
1316 let (after, frame) =
1317 frame_body(remaining, &header).expect("unknown frame body must be consumed");
1318 assert!(after.is_empty(), "payload bytes must be consumed");
1319 match frame {
1320 Frame::Unknown(0xFF) => {}
1321 other => panic!("expected Frame::Unknown(0xFF), got {other:?}"),
1322 }
1323 }
1324
1325 #[test]
1330 fn test_priority_update_empty_field_parses() {
1331 let input = [
1332 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1338 ];
1339
1340 let (remaining, header) = frame_header(&input, DEFAULT_MAX_FRAME_SIZE)
1341 .expect("PRIORITY_UPDATE header must parse");
1342 assert!(matches!(header.frame_type, FrameType::PriorityUpdate));
1343 let (_, frame) = frame_body(remaining, &header).expect("body must be consumed");
1344 match frame {
1345 Frame::PriorityUpdate(PriorityUpdate {
1346 prioritized_stream_id,
1347 ref priority_field_value,
1348 }) => {
1349 assert_eq!(prioritized_stream_id, 1);
1350 assert!(priority_field_value.is_empty());
1351 }
1352 other => panic!("expected Frame::PriorityUpdate, got {other:?}"),
1353 }
1354 }
1355
1356 #[test]
1360 fn test_priority_update_with_priority_field_parses() {
1361 let value = b"u=0, i";
1362 let mut input = vec![
1363 0x00,
1364 0x00,
1365 0x04 + value.len() as u8, 0x10, 0x00, 0x00,
1369 0x00,
1370 0x00,
1371 0x00, 0x00,
1373 0x00,
1374 0x00,
1375 0x05, ];
1377 input.extend_from_slice(value);
1378
1379 let (remaining, header) =
1380 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("header parses");
1381 assert!(matches!(header.frame_type, FrameType::PriorityUpdate));
1382 let (_, frame) = frame_body(remaining, &header).expect("body parses");
1383 match frame {
1384 Frame::PriorityUpdate(PriorityUpdate {
1385 prioritized_stream_id,
1386 ref priority_field_value,
1387 }) => {
1388 assert_eq!(prioritized_stream_id, 5);
1389 assert_eq!(priority_field_value.as_slice(), value);
1390 }
1391 other => panic!("expected Frame::PriorityUpdate, got {other:?}"),
1392 }
1393 }
1394
1395 #[test]
1398 fn test_priority_update_payload_below_min_is_frame_size_error() {
1399 let input = [
1400 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1402 ];
1403 let (remaining, header) =
1404 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("header parses");
1405 let result = frame_body(remaining, &header);
1406 match result {
1407 Err(Err::Failure(e)) => {
1408 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1409 }
1410 other => panic!("expected FRAME_SIZE_ERROR, got {other:?}"),
1411 }
1412 }
1413
1414 #[test]
1420 fn test_priority_update_oversized_value_is_protocol_error() {
1421 let payload_len = (PRIORITY_UPDATE_MIN_PAYLOAD as usize) + PRIORITY_UPDATE_MAX_VALUE + 1;
1423 let mut input = Vec::with_capacity(9 + payload_len);
1424 input.push(((payload_len >> 16) & 0xff) as u8);
1426 input.push(((payload_len >> 8) & 0xff) as u8);
1427 input.push((payload_len & 0xff) as u8);
1428 input.push(0x10); input.push(0x00); input.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]); input.extend_from_slice(&[0x00, 0x00, 0x00, 0x01]); input.extend(std::iter::repeat_n(b'a', PRIORITY_UPDATE_MAX_VALUE + 1));
1433 let (remaining, header) =
1436 frame_header(&input, payload_len as u32 + 1).expect("header parses");
1437 match frame_body(remaining, &header) {
1438 Err(Err::Failure(e)) => {
1439 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1440 }
1441 other => {
1442 panic!("expected PROTOCOL_ERROR for oversized PRIORITY_UPDATE value, got {other:?}")
1443 }
1444 }
1445 }
1446
1447 #[test]
1450 fn test_priority_update_at_max_value_accepted() {
1451 let payload_len = (PRIORITY_UPDATE_MIN_PAYLOAD as usize) + PRIORITY_UPDATE_MAX_VALUE;
1452 let mut input = Vec::with_capacity(9 + payload_len);
1453 input.push(((payload_len >> 16) & 0xff) as u8);
1454 input.push(((payload_len >> 8) & 0xff) as u8);
1455 input.push((payload_len & 0xff) as u8);
1456 input.push(0x10);
1457 input.push(0x00);
1458 input.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]);
1459 input.extend_from_slice(&[0x00, 0x00, 0x00, 0x01]);
1460 input.extend(std::iter::repeat_n(b'a', PRIORITY_UPDATE_MAX_VALUE));
1461 let (remaining, header) =
1462 frame_header(&input, payload_len as u32 + 1).expect("header parses");
1463 match frame_body(remaining, &header) {
1464 Ok((_, Frame::PriorityUpdate(pu))) => {
1465 assert_eq!(pu.priority_field_value.len(), PRIORITY_UPDATE_MAX_VALUE);
1466 }
1467 other => panic!("expected Frame::PriorityUpdate at the cap boundary, got {other:?}"),
1468 }
1469 }
1470
1471 #[test]
1476 fn test_priority_update_on_non_zero_stream_is_protocol_error() {
1477 let input = [
1478 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, ];
1484 match frame_header(&input, DEFAULT_MAX_FRAME_SIZE) {
1485 Err(Err::Failure(e)) => {
1486 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1487 }
1488 other => panic!("expected PROTOCOL_ERROR, got {other:?}"),
1489 }
1490 }
1491
1492 #[test]
1497 fn test_settings_payload_not_multiple_of_6_rejected() {
1498 let input = [
1499 0x00, 0x00, 0x05, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, ];
1505
1506 let (remaining, header) =
1507 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1508 assert_eq!(header.frame_type, FrameType::Settings);
1509
1510 let result = frame_body(remaining, &header);
1511 assert!(
1512 result.is_err(),
1513 "odd-size SETTINGS payload must be rejected"
1514 );
1515 match result {
1516 Err(nom::Err::Failure(e)) => {
1517 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1518 }
1519 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1520 }
1521 }
1522
1523 #[test]
1528 fn test_settings_frame_over_cap_rejected() {
1529 let n_entries: u16 = (MAX_SETTINGS_ENTRIES as u16) + 1;
1531 let payload_len = u32::from(n_entries) * SETTINGS_ENTRY_SIZE;
1532 let mut input = Vec::with_capacity(9 + payload_len as usize);
1533 input.extend_from_slice(&payload_len.to_be_bytes()[1..]); input.push(0x04); input.push(0x00); input.extend_from_slice(&[0, 0, 0, 0]); for i in 0..n_entries {
1538 input.extend_from_slice(&i.to_be_bytes()); input.extend_from_slice(&0u32.to_be_bytes()); }
1541
1542 let (remaining, header) =
1543 frame_header(&input, 16_777_215).expect("frame header parses cleanly");
1544 assert_eq!(header.frame_type, FrameType::Settings);
1545
1546 let result = frame_body(remaining, &header);
1547 assert!(
1548 result.is_err(),
1549 "SETTINGS frame over MAX_SETTINGS_ENTRIES must be rejected"
1550 );
1551 match result {
1552 Err(nom::Err::Failure(e)) => {
1553 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1554 }
1555 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1556 }
1557 }
1558
1559 #[test]
1561 fn test_settings_frame_at_cap_accepted() {
1562 let n_entries: u16 = MAX_SETTINGS_ENTRIES as u16;
1563 let payload_len = u32::from(n_entries) * SETTINGS_ENTRY_SIZE;
1564 let mut input = Vec::with_capacity(9 + payload_len as usize);
1565 input.extend_from_slice(&payload_len.to_be_bytes()[1..]);
1566 input.push(0x04);
1567 input.push(0x00);
1568 input.extend_from_slice(&[0, 0, 0, 0]);
1569 for _ in 0..n_entries {
1570 input.extend_from_slice(&0u16.to_be_bytes());
1571 input.extend_from_slice(&0u32.to_be_bytes());
1572 }
1573
1574 let (remaining, header) =
1575 frame_header(&input, 16_777_215).expect("frame header parses cleanly");
1576 let result = frame_body(remaining, &header);
1577 assert!(result.is_ok(), "exactly MAX_SETTINGS_ENTRIES must parse");
1578 }
1579
1580 #[test]
1584 fn test_rst_stream_wrong_payload_size_rejected() {
1585 let input = [
1587 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
1593
1594 let (remaining, header) =
1595 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1596 assert_eq!(header.frame_type, FrameType::RstStream);
1597
1598 let result = frame_body(remaining, &header);
1599 assert!(
1600 result.is_err(),
1601 "wrong RST_STREAM payload size must be rejected"
1602 );
1603 match result {
1604 Err(nom::Err::Failure(e)) => {
1605 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1606 }
1607 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1608 }
1609 }
1610
1611 #[test]
1615 fn test_ping_wrong_payload_size_rejected() {
1616 let input = [
1617 0x00, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, ];
1623
1624 let (remaining, header) =
1625 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1626 assert_eq!(header.frame_type, FrameType::Ping);
1627
1628 let result = frame_body(remaining, &header);
1629 assert!(result.is_err(), "wrong PING payload size must be rejected");
1630 match result {
1631 Err(nom::Err::Failure(e)) => {
1632 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1633 }
1634 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1635 }
1636 }
1637
1638 #[test]
1643 fn test_frame_exceeding_max_frame_size_rejected() {
1644 let input = [
1646 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, ];
1651
1652 let result = frame_header(&input, DEFAULT_MAX_FRAME_SIZE);
1653 assert!(result.is_err(), "oversized frame must be rejected");
1654 match result {
1655 Err(nom::Err::Failure(e)) => {
1656 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1657 }
1658 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1659 }
1660 }
1661
1662 #[test]
1666 fn test_settings_on_nonzero_stream_rejected() {
1667 let input = [
1668 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, ];
1673
1674 let result = frame_header(&input, DEFAULT_MAX_FRAME_SIZE);
1675 assert!(
1676 result.is_err(),
1677 "SETTINGS on non-zero stream must be rejected"
1678 );
1679 match result {
1680 Err(nom::Err::Failure(e)) => {
1681 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1682 }
1683 other => panic!("expected Failure(ProtocolError), got {other:?}"),
1684 }
1685 }
1686
1687 #[test]
1691 fn test_data_on_stream_zero_rejected() {
1692 let input = [
1693 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCA, 0xFE,
1698 ];
1699
1700 let result = frame_header(&input, DEFAULT_MAX_FRAME_SIZE);
1701 assert!(result.is_err(), "DATA on stream 0 must be rejected");
1702 match result {
1703 Err(nom::Err::Failure(e)) => {
1704 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1705 }
1706 other => panic!("expected Failure(ProtocolError), got {other:?}"),
1707 }
1708 }
1709
1710 #[test]
1715 fn test_window_update_reserved_bit_masked() {
1716 let input = [
1717 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, ];
1723
1724 let (remaining, header) =
1725 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1726 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
1727 match frame {
1728 Frame::WindowUpdate(wu) => {
1729 assert_eq!(
1730 wu.increment, 1,
1731 "reserved bit must be masked to yield increment=1"
1732 );
1733 }
1734 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1735 }
1736 }
1737
1738 fn build_frame_header(payload_len: u32, frame_type: u8, flags: u8, stream_id: u32) -> Vec<u8> {
1742 vec![
1743 ((payload_len >> 16) & 0xFF) as u8,
1744 ((payload_len >> 8) & 0xFF) as u8,
1745 (payload_len & 0xFF) as u8,
1746 frame_type,
1747 flags,
1748 ((stream_id >> 24) & 0xFF) as u8,
1749 ((stream_id >> 16) & 0xFF) as u8,
1750 ((stream_id >> 8) & 0xFF) as u8,
1751 (stream_id & 0xFF) as u8,
1752 ]
1753 }
1754
1755 fn build_raw_frame(
1757 payload_len: u32,
1758 frame_type: u8,
1759 flags: u8,
1760 stream_id: u32,
1761 payload: &[u8],
1762 ) -> Vec<u8> {
1763 let mut raw = build_frame_header(payload_len, frame_type, flags, stream_id);
1764 raw.extend_from_slice(payload);
1765 raw
1766 }
1767
1768 #[test]
1771 fn test_preface_valid() {
1772 let input = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
1773 let (remaining, matched) = preface(input).expect("should parse preface");
1774 assert!(remaining.is_empty());
1775 assert_eq!(matched, input.as_slice());
1776 }
1777
1778 #[test]
1779 fn test_preface_invalid() {
1780 let input = b"GET / HTTP/1.1\r\n";
1781 let result = preface(input);
1782 assert!(result.is_err(), "invalid preface should fail");
1783 }
1784
1785 #[test]
1786 fn test_preface_with_trailing_data() {
1787 let mut input = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".to_vec();
1788 input.extend_from_slice(b"extra stuff");
1789 let (remaining, _) = preface(&input).expect("should parse preface");
1790 assert_eq!(remaining, b"extra stuff");
1791 }
1792
1793 #[test]
1796 fn test_frame_header_settings_basic() {
1797 let raw = build_frame_header(0, 4, 0, 0);
1798 let (remaining, header) =
1799 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1800 assert!(remaining.is_empty());
1801 assert_eq!(header.payload_len, 0);
1802 assert_eq!(header.frame_type, FrameType::Settings);
1803 assert_eq!(header.flags, 0);
1804 assert_eq!(header.stream_id, 0);
1805 }
1806
1807 #[test]
1808 fn test_frame_header_data_basic() {
1809 let raw = build_frame_header(100, 0, 1, 1);
1810 let (_, header) =
1811 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1812 assert_eq!(header.payload_len, 100);
1813 assert_eq!(header.frame_type, FrameType::Data);
1814 assert_eq!(header.flags, 1);
1815 assert_eq!(header.stream_id, 1);
1816 }
1817
1818 #[test]
1819 fn test_frame_header_stream_id_reserved_bit_masked() {
1820 let raw = build_frame_header(5, 0, 0, 0x80000001);
1823 let (_, header) =
1824 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1825 assert_eq!(header.stream_id, 1, "reserved MSB must be masked off");
1826 }
1827
1828 #[test]
1831 fn test_parse_data_frame_end_stream() {
1832 let payload = b"hello";
1833 let raw = build_raw_frame(payload.len() as u32, 0, 0x01, 1, payload);
1834 let (remaining, header) =
1835 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1836 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1837 match f {
1838 Frame::Data(d) => {
1839 assert_eq!(d.stream_id, 1);
1840 assert!(d.end_stream);
1841 }
1842 other => panic!("expected Data, got {other:?}"),
1843 }
1844 }
1845
1846 #[test]
1847 fn test_parse_data_frame_no_end_stream() {
1848 let payload = b"data";
1849 let raw = build_raw_frame(payload.len() as u32, 0, 0x00, 3, payload);
1850 let (remaining, header) =
1851 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1852 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1853 match f {
1854 Frame::Data(d) => {
1855 assert_eq!(d.stream_id, 3);
1856 assert!(!d.end_stream);
1857 }
1858 other => panic!("expected Data, got {other:?}"),
1859 }
1860 }
1861
1862 #[test]
1863 fn test_parse_data_frame_with_padding() {
1864 let pad_length: u8 = 2;
1866 let actual_data = b"hello";
1867 let total_payload = 1 + actual_data.len() + pad_length as usize;
1868 let mut payload = Vec::new();
1869 payload.push(pad_length);
1870 payload.extend_from_slice(actual_data);
1871 payload.extend_from_slice(&[0x00; 2]);
1872
1873 let raw = build_raw_frame(total_payload as u32, 0, 0x08, 1, &payload);
1874 let (remaining, header) =
1875 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1876 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1877 match f {
1878 Frame::Data(d) => {
1879 assert_eq!(d.stream_id, 1);
1880 assert_eq!(d.payload.len, actual_data.len() as u32);
1881 }
1882 other => panic!("expected Data, got {other:?}"),
1883 }
1884 }
1885
1886 #[test]
1887 fn test_parse_data_frame_padding_exceeds_payload() {
1888 let mut payload = Vec::new();
1890 payload.push(10); payload.extend_from_slice(b"hello");
1892
1893 let raw = build_raw_frame(payload.len() as u32, 0, 0x08, 1, &payload);
1894 let (remaining, header) =
1895 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1896 let result = frame_body(remaining, &header);
1897 assert!(
1898 result.is_err(),
1899 "padding exceeding payload should be a protocol error"
1900 );
1901 }
1902
1903 #[test]
1906 fn test_parse_headers_frame_basic() {
1907 let hblock = b"\x82\x86";
1908 let raw = build_raw_frame(hblock.len() as u32, 1, 0x04, 1, hblock);
1909 let (remaining, header) =
1910 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1911 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1912 match f {
1913 Frame::Headers(h) => {
1914 assert_eq!(h.stream_id, 1);
1915 assert!(!h.end_stream);
1916 assert!(h.end_headers);
1917 assert!(h.priority.is_none());
1918 }
1919 other => panic!("expected Headers, got {other:?}"),
1920 }
1921 }
1922
1923 #[test]
1924 fn test_parse_headers_frame_end_stream_and_headers() {
1925 let hblock = b"\x82";
1926 let raw = build_raw_frame(hblock.len() as u32, 1, 0x05, 1, hblock);
1927 let (remaining, header) =
1928 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1929 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1930 match f {
1931 Frame::Headers(h) => {
1932 assert!(h.end_stream);
1933 assert!(h.end_headers);
1934 }
1935 other => panic!("expected Headers, got {other:?}"),
1936 }
1937 }
1938
1939 #[test]
1940 fn test_parse_headers_frame_with_priority() {
1941 let hblock = b"\x82";
1942 let payload_len = 5 + hblock.len(); let mut payload = Vec::new();
1944 payload.extend_from_slice(&[0x00, 0x00, 0x00, 0x01]);
1946 payload.push(15); payload.extend_from_slice(hblock);
1948
1949 let raw = build_raw_frame(payload_len as u32, 1, 0x24, 3, &payload);
1950 let (remaining, header) =
1951 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1952 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1953 match f {
1954 Frame::Headers(h) => {
1955 assert_eq!(h.stream_id, 3);
1956 let priority = h.priority.expect("should have priority");
1957 match priority {
1958 PriorityPart::Rfc7540 {
1959 stream_dependency,
1960 weight,
1961 } => {
1962 assert!(!stream_dependency.exclusive);
1963 assert_eq!(stream_dependency.stream_id, 1);
1964 assert_eq!(weight, 15);
1965 }
1966 other => panic!("expected Rfc7540, got {other:?}"),
1967 }
1968 }
1969 other => panic!("expected Headers, got {other:?}"),
1970 }
1971 }
1972
1973 #[test]
1974 fn test_parse_headers_frame_with_exclusive_priority() {
1975 let hblock = b"\x82\x86";
1976 let mut payload = Vec::new();
1977 let dep = 0x80000005u32;
1979 payload.extend_from_slice(&dep.to_be_bytes());
1980 payload.push(255); payload.extend_from_slice(hblock);
1982
1983 let payload_len = payload.len();
1984 let raw = build_raw_frame(payload_len as u32, 1, 0x24, 3, &payload);
1985 let (remaining, header) =
1986 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1987 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1988 match f {
1989 Frame::Headers(h) => {
1990 let priority = h.priority.expect("should have priority");
1991 match priority {
1992 PriorityPart::Rfc7540 {
1993 stream_dependency,
1994 weight,
1995 } => {
1996 assert!(stream_dependency.exclusive, "exclusive bit should be set");
1997 assert_eq!(stream_dependency.stream_id, 5);
1998 assert_eq!(weight, 255);
1999 }
2000 other => panic!("expected Rfc7540, got {other:?}"),
2001 }
2002 }
2003 other => panic!("expected Headers, got {other:?}"),
2004 }
2005 }
2006
2007 #[test]
2008 fn test_parse_headers_stream_id_zero_rejected() {
2009 let raw = build_raw_frame(2, 1, 0x04, 0, b"\x82\x86");
2010 let result = frame_header(&raw, DEFAULT_MAX_FRAME_SIZE);
2011 assert!(
2012 result.is_err(),
2013 "HEADERS with stream_id=0 should be rejected"
2014 );
2015 }
2016
2017 #[test]
2020 fn test_parse_rst_stream() {
2021 let error_code = 0x00000008u32; let raw = build_raw_frame(4, 3, 0, 1, &error_code.to_be_bytes());
2023 let (remaining, header) =
2024 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2025 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2026 match f {
2027 Frame::RstStream(rst) => {
2028 assert_eq!(rst.stream_id, 1);
2029 assert_eq!(rst.error_code, 0x08);
2030 }
2031 other => panic!("expected RstStream, got {other:?}"),
2032 }
2033 }
2034
2035 #[test]
2036 fn test_parse_rst_stream_stream_id_zero_rejected() {
2037 let raw = build_raw_frame(4, 3, 0, 0, &[0u8; 4]);
2038 let result = frame_header(&raw, DEFAULT_MAX_FRAME_SIZE);
2039 assert!(
2040 result.is_err(),
2041 "RST_STREAM with stream_id=0 should be rejected"
2042 );
2043 }
2044
2045 #[test]
2048 fn test_parse_settings_frame_with_values() {
2049 let mut payload = Vec::new();
2050 payload.extend_from_slice(&0x0001u16.to_be_bytes());
2052 payload.extend_from_slice(&4096u32.to_be_bytes());
2053 payload.extend_from_slice(&0x0003u16.to_be_bytes());
2055 payload.extend_from_slice(&100u32.to_be_bytes());
2056 payload.extend_from_slice(&0x0004u16.to_be_bytes());
2058 payload.extend_from_slice(&65535u32.to_be_bytes());
2059
2060 let raw = build_raw_frame(payload.len() as u32, 4, 0x0, 0, &payload);
2061 let (remaining, header) =
2062 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2063 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2064 match f {
2065 Frame::Settings(s) => {
2066 assert!(!s.ack);
2067 assert_eq!(s.settings.len(), 3);
2068 assert_eq!(s.settings[0].identifier, 0x0001);
2069 assert_eq!(s.settings[0].value, 4096);
2070 assert_eq!(s.settings[1].identifier, 0x0003);
2071 assert_eq!(s.settings[1].value, 100);
2072 assert_eq!(s.settings[2].identifier, 0x0004);
2073 assert_eq!(s.settings[2].value, 65535);
2074 }
2075 other => panic!("expected Settings, got {other:?}"),
2076 }
2077 }
2078
2079 #[test]
2082 fn test_parse_ping_frame() {
2083 let ping_payload = [1u8, 2, 3, 4, 5, 6, 7, 8];
2084 let raw = build_raw_frame(8, 6, 0, 0, &ping_payload);
2085 let (remaining, header) =
2086 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2087 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2088 match f {
2089 Frame::Ping(p) => {
2090 assert_eq!(p.payload, ping_payload);
2091 assert!(!p.ack);
2092 }
2093 other => panic!("expected Ping, got {other:?}"),
2094 }
2095 }
2096
2097 #[test]
2098 fn test_parse_ping_ack_preserves_payload() {
2099 let ping_payload = [0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE];
2100 let raw = build_raw_frame(8, 6, 0x01, 0, &ping_payload);
2101 let (remaining, header) =
2102 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2103 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2104 match f {
2105 Frame::Ping(p) => {
2106 assert_eq!(
2107 p.payload, ping_payload,
2108 "PING ACK must echo the exact payload"
2109 );
2110 assert!(p.ack);
2111 }
2112 other => panic!("expected Ping, got {other:?}"),
2113 }
2114 }
2115
2116 #[test]
2117 fn test_parse_ping_stream_id_nonzero_rejected() {
2118 let raw = build_raw_frame(8, 6, 0, 1, &[0u8; 8]);
2119 let result = frame_header(&raw, DEFAULT_MAX_FRAME_SIZE);
2120 assert!(result.is_err(), "PING with stream_id!=0 should be rejected");
2121 }
2122
2123 #[test]
2126 fn test_parse_window_update_connection_level() {
2127 let increment = 1000u32;
2128 let raw = build_raw_frame(4, 8, 0, 0, &increment.to_be_bytes());
2129 let (remaining, header) =
2130 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2131 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2132 match f {
2133 Frame::WindowUpdate(w) => {
2134 assert_eq!(w.stream_id, 0);
2135 assert_eq!(w.increment, 1000);
2136 }
2137 other => panic!("expected WindowUpdate, got {other:?}"),
2138 }
2139 }
2140
2141 #[test]
2142 fn test_parse_window_update_stream_level() {
2143 let increment = 65535u32;
2144 let raw = build_raw_frame(4, 8, 0, 5, &increment.to_be_bytes());
2145 let (remaining, header) =
2146 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2147 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2148 match f {
2149 Frame::WindowUpdate(w) => {
2150 assert_eq!(w.stream_id, 5);
2151 assert_eq!(w.increment, 65535);
2153 }
2154 other => panic!("expected WindowUpdate, got {other:?}"),
2155 }
2156 }
2157
2158 #[test]
2159 fn test_parse_window_update_wrong_size() {
2160 let raw = build_raw_frame(3, 8, 0, 0, &[0u8; 3]);
2161 let (remaining, header) =
2162 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2163 let result = frame_body(remaining, &header);
2164 assert!(
2165 result.is_err(),
2166 "WINDOW_UPDATE with payload != 4 should fail"
2167 );
2168 match result {
2169 Err(Err::Failure(e)) => {
2170 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
2171 }
2172 other => panic!("expected FrameSizeError, got {other:?}"),
2173 }
2174 }
2175
2176 #[test]
2179 fn test_parse_frame_at_max_frame_size() {
2180 let payload = vec![0u8; DEFAULT_MAX_FRAME_SIZE as usize];
2181 let raw = build_raw_frame(DEFAULT_MAX_FRAME_SIZE, 0, 0x0, 1, &payload);
2182 let (remaining, header) =
2183 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2184 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2185 match f {
2186 Frame::Data(d) => {
2187 assert_eq!(d.payload.len, DEFAULT_MAX_FRAME_SIZE);
2188 }
2189 other => panic!("expected Data, got {other:?}"),
2190 }
2191 }
2192
2193 #[test]
2194 fn test_parse_frame_with_custom_max_frame_size() {
2195 let custom_max = 32768u32;
2196 let payload = vec![0u8; 20000];
2197 let raw = build_raw_frame(20000, 0, 0x0, 1, &payload);
2198 let (remaining, header) =
2199 frame_header(&raw, custom_max).expect("frame header parses with custom max");
2200 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2201 match f {
2202 Frame::Data(d) => {
2203 assert_eq!(d.payload.len, 20000);
2204 }
2205 other => panic!("expected Data, got {other:?}"),
2206 }
2207 }
2208
2209 #[test]
2212 fn test_h2_error_try_from_valid() {
2213 assert_eq!(H2Error::try_from(0x0), Ok(H2Error::NoError));
2214 assert_eq!(H2Error::try_from(0x1), Ok(H2Error::ProtocolError));
2215 assert_eq!(H2Error::try_from(0x6), Ok(H2Error::FrameSizeError));
2216 assert_eq!(H2Error::try_from(0xd), Ok(H2Error::HTTP11Required));
2217 }
2218
2219 #[test]
2220 fn test_h2_error_try_from_invalid() {
2221 assert_eq!(H2Error::try_from(0x0e), Err(0x0e));
2222 assert_eq!(H2Error::try_from(0xFF), Err(0xFF));
2223 }
2224
2225 #[test]
2226 fn test_h2_error_from_str() {
2227 assert_eq!("NO_ERROR".parse::<H2Error>(), Ok(H2Error::NoError));
2228 assert_eq!(
2229 "PROTOCOL_ERROR".parse::<H2Error>(),
2230 Ok(H2Error::ProtocolError)
2231 );
2232 assert_eq!(
2233 "ENHANCE_YOUR_CALM".parse::<H2Error>(),
2234 Ok(H2Error::EnhanceYourCalm)
2235 );
2236 assert!("INVALID_ERROR".parse::<H2Error>().is_err());
2237 }
2238
2239 #[test]
2240 fn test_h2_error_as_str_roundtrip() {
2241 let errors = [
2242 H2Error::NoError,
2243 H2Error::ProtocolError,
2244 H2Error::InternalError,
2245 H2Error::FlowControlError,
2246 H2Error::SettingsTimeout,
2247 H2Error::StreamClosed,
2248 H2Error::FrameSizeError,
2249 H2Error::RefusedStream,
2250 H2Error::Cancel,
2251 H2Error::CompressionError,
2252 H2Error::ConnectError,
2253 H2Error::EnhanceYourCalm,
2254 H2Error::InadequateSecurity,
2255 H2Error::HTTP11Required,
2256 ];
2257
2258 for error in &errors {
2259 let s = error.as_str();
2260 let parsed: H2Error = s.parse().unwrap_or_else(|_| panic!("failed to parse {s}"));
2261 assert_eq!(*error, parsed, "roundtrip failed for {s}");
2262 }
2263 }
2264
2265 #[test]
2268 fn test_parse_priority_frame() {
2269 let mut payload = Vec::new();
2270 payload.extend_from_slice(&0x00000001u32.to_be_bytes());
2272 payload.push(15); assert_eq!(payload.len(), 5);
2274
2275 let raw = build_raw_frame(5, 2, 0, 3, &payload);
2276 let (remaining, header) =
2277 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2278 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2279 match f {
2280 Frame::Priority(p) => {
2281 assert_eq!(p.stream_id, 3);
2282 match p.inner {
2283 PriorityPart::Rfc7540 {
2284 stream_dependency,
2285 weight,
2286 } => {
2287 assert!(!stream_dependency.exclusive);
2288 assert_eq!(stream_dependency.stream_id, 1);
2289 assert_eq!(weight, 15);
2290 }
2291 other => panic!("expected Rfc7540, got {other:?}"),
2292 }
2293 }
2294 other => panic!("expected Priority, got {other:?}"),
2295 }
2296 }
2297
2298 #[test]
2299 fn test_parse_priority_wrong_size_rejected() {
2300 let raw = build_raw_frame(4, 2, 0, 1, &[0u8; 4]);
2301 let (remaining, header) =
2302 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2303 let result = frame_body(remaining, &header);
2304 assert!(
2305 result.is_err(),
2306 "PRIORITY with wrong payload size should fail"
2307 );
2308 }
2309
2310 #[test]
2317 fn test_headers_padded_priority_underflow_rejected() {
2318 let raw: [u8; 16] = [
2319 0x00, 0x00, 0x06, 0x01, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x00, 0x64, 0x6d, 0x6d,
2320 0x6d, 0x6d,
2321 ];
2322 let (remaining, header) =
2323 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2324 let result = frame_body(remaining, &header);
2325 assert!(
2326 result.is_err(),
2327 "PADDED+PRIORITY HEADERS with oversized pad_length must error, not panic"
2328 );
2329 }
2330
2331 #[test]
2339 fn test_strip_padding_all_padding_accepted() {
2340 let input = [
2344 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, ];
2351
2352 let (remaining, header) =
2353 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2354 let (_, frame) =
2355 frame_body(remaining, &header).expect("DATA with all-padding body must parse");
2356 match frame {
2357 Frame::Data(data) => {
2358 assert_eq!(data.stream_id, 1);
2359 assert_eq!(data.payload.len, 0);
2361 }
2362 other => panic!("expected Frame::Data, got {other:?}"),
2363 }
2364 }
2365
2366 #[test]
2367 fn test_strip_padding_pad_length_equals_payload_len_rejected() {
2368 let input = [
2372 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x01, ];
2378
2379 let (remaining, header) =
2380 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2381 let result = frame_body(remaining, &header);
2382 assert!(
2383 matches!(
2384 result,
2385 Err(nom::Err::Failure(ParserError {
2386 kind: ParserErrorKind::H2(H2Error::ProtocolError),
2387 ..
2388 }))
2389 ),
2390 "pad_length > remaining body must yield PROTOCOL_ERROR, got {result:?}"
2391 );
2392 }
2393
2394 #[test]
2400 fn test_goaway_short_payload_rejected() {
2401 let input = [
2402 0x00, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
2408
2409 let (remaining, header) =
2410 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2411 assert_eq!(header.frame_type, FrameType::GoAway);
2412 let result = frame_body(remaining, &header);
2413 assert!(
2414 matches!(
2415 result,
2416 Err(nom::Err::Failure(ParserError {
2417 kind: ParserErrorKind::H2(H2Error::FrameSizeError),
2418 ..
2419 }))
2420 ),
2421 "GOAWAY with payload_len < 8 must yield FRAME_SIZE_ERROR, got {result:?}"
2422 );
2423 }
2424
2425 #[test]
2426 fn test_goaway_minimum_payload_accepted() {
2427 let input = [
2428 0x00, 0x00, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, ];
2435
2436 let (remaining, header) =
2437 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2438 let (_, frame) = frame_body(remaining, &header).expect("minimal GOAWAY must parse cleanly");
2439 match frame {
2440 Frame::GoAway(goaway) => {
2441 assert_eq!(goaway.last_stream_id, 10);
2442 assert_eq!(goaway.error_code, 0);
2443 }
2444 other => panic!("expected Frame::GoAway, got {other:?}"),
2445 }
2446 }
2447
2448 #[test]
2456 fn test_push_promise_rejected_at_wire_layer() {
2457 let input = [
2458 0x00, 0x00, 0x08, 0x05, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, ];
2465
2466 let (remaining, header) =
2467 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2468 assert_eq!(header.frame_type, FrameType::PushPromise);
2469 let result = frame_body(remaining, &header);
2470 assert!(
2471 matches!(
2472 result,
2473 Err(nom::Err::Failure(ParserError {
2474 kind: ParserErrorKind::H2(H2Error::ProtocolError),
2475 ..
2476 }))
2477 ),
2478 "PUSH_PROMISE must be rejected at wire layer with PROTOCOL_ERROR, got {result:?}"
2479 );
2480 }
2481}