1use std::convert::From;
12
13use kawa::repr::Slice;
14use nom::{
15 Err, IResult,
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 sequence::tuple,
22};
23use sozu_command::logging::ansi_palette;
24
25macro_rules! log_module_context {
30 () => {{
31 let (open, reset, _, _, _) = ansi_palette();
32 format!("{open}MUX-PARSER{reset}\t >>>", open = open, reset = reset)
33 }};
34}
35
36pub const FRAME_HEADER_SIZE: usize = 9;
40
41pub const STREAM_ID_MASK: u32 = 0x7FFFFFFF;
43
44pub const FLAG_END_STREAM: u8 = 0x1;
47pub const FLAG_END_HEADERS: u8 = 0x4;
49pub const FLAG_PADDED: u8 = 0x8;
51pub const FLAG_PRIORITY: u8 = 0x20;
53pub const FLAG_ACK: u8 = 0x1;
55
56pub const PRIORITY_PAYLOAD_SIZE: u32 = 5;
58pub const RST_STREAM_PAYLOAD_SIZE: u32 = 4;
59pub const SETTINGS_ENTRY_SIZE: u32 = 6;
60pub const PING_PAYLOAD_SIZE: u32 = 8;
61pub const WINDOW_UPDATE_PAYLOAD_SIZE: u32 = 4;
62pub const GOAWAY_PAYLOAD_SIZE: u32 = 8;
63
64pub const SETTINGS_HEADER_TABLE_SIZE: u16 = 1;
66pub const SETTINGS_ENABLE_PUSH: u16 = 2;
67pub const SETTINGS_MAX_CONCURRENT_STREAMS: u16 = 3;
68pub const SETTINGS_INITIAL_WINDOW_SIZE: u16 = 4;
69pub const SETTINGS_MAX_FRAME_SIZE: u16 = 5;
70pub const SETTINGS_MAX_HEADER_LIST_SIZE: u16 = 6;
71pub const SETTINGS_ENABLE_CONNECT_PROTOCOL: u16 = 8;
72pub const SETTINGS_NO_RFC7540_PRIORITIES: u16 = 9;
73pub const SETTINGS_COUNT: u32 = 8;
75
76#[derive(Clone, Debug, PartialEq)]
79pub struct FrameHeader {
80 pub payload_len: u32,
81 pub frame_type: FrameType,
82 pub flags: u8,
83 pub stream_id: u32,
84}
85
86#[derive(Clone, Debug, PartialEq)]
87pub enum FrameType {
88 Data,
89 Headers,
90 Priority,
91 RstStream,
92 Settings,
93 PushPromise,
94 Ping,
95 GoAway,
96 WindowUpdate,
97 Continuation,
98 PriorityUpdate,
102 Unknown(u8),
107}
108
109impl std::str::FromStr for H2Error {
110 type Err = ();
111
112 fn from_str(s: &str) -> Result<Self, ()> {
113 match s {
114 "NO_ERROR" => Ok(H2Error::NoError),
115 "PROTOCOL_ERROR" => Ok(H2Error::ProtocolError),
116 "INTERNAL_ERROR" => Ok(H2Error::InternalError),
117 "FLOW_CONTROL_ERROR" => Ok(H2Error::FlowControlError),
118 "SETTINGS_TIMEOUT" => Ok(H2Error::SettingsTimeout),
119 "STREAM_CLOSED" => Ok(H2Error::StreamClosed),
120 "FRAME_SIZE_ERROR" => Ok(H2Error::FrameSizeError),
121 "REFUSED_STREAM" => Ok(H2Error::RefusedStream),
122 "CANCEL" => Ok(H2Error::Cancel),
123 "COMPRESSION_ERROR" => Ok(H2Error::CompressionError),
124 "CONNECT_ERROR" => Ok(H2Error::ConnectError),
125 "ENHANCE_YOUR_CALM" => Ok(H2Error::EnhanceYourCalm),
126 "INADEQUATE_SECURITY" => Ok(H2Error::InadequateSecurity),
127 "HTTP_1_1_REQUIRED" => Ok(H2Error::HTTP11Required),
128 _ => Err(()),
129 }
130 }
131}
132
133#[derive(Clone, Debug, PartialEq)]
134pub struct ParserError<'a> {
135 pub input: &'a [u8],
136 pub kind: ParserErrorKind,
137}
138
139#[derive(Clone, Debug, PartialEq)]
140pub enum ParserErrorKind {
141 Nom(ErrorKind),
142 H2(H2Error),
143}
144
145#[derive(Clone, Copy, Debug, PartialEq)]
146#[repr(u32)]
147pub enum H2Error {
148 NoError = 0x0,
149 ProtocolError = 0x1,
150 InternalError = 0x2,
151 FlowControlError = 0x3,
152 SettingsTimeout = 0x4,
153 StreamClosed = 0x5,
154 FrameSizeError = 0x6,
155 RefusedStream = 0x7,
156 Cancel = 0x8,
157 CompressionError = 0x9,
158 ConnectError = 0xa,
159 EnhanceYourCalm = 0xb,
160 InadequateSecurity = 0xc,
161 HTTP11Required = 0xd,
162}
163
164impl TryFrom<u32> for H2Error {
165 type Error = u32;
166
167 fn try_from(code: u32) -> Result<Self, u32> {
168 match code {
169 0x0 => Ok(H2Error::NoError),
170 0x1 => Ok(H2Error::ProtocolError),
171 0x2 => Ok(H2Error::InternalError),
172 0x3 => Ok(H2Error::FlowControlError),
173 0x4 => Ok(H2Error::SettingsTimeout),
174 0x5 => Ok(H2Error::StreamClosed),
175 0x6 => Ok(H2Error::FrameSizeError),
176 0x7 => Ok(H2Error::RefusedStream),
177 0x8 => Ok(H2Error::Cancel),
178 0x9 => Ok(H2Error::CompressionError),
179 0xa => Ok(H2Error::ConnectError),
180 0xb => Ok(H2Error::EnhanceYourCalm),
181 0xc => Ok(H2Error::InadequateSecurity),
182 0xd => Ok(H2Error::HTTP11Required),
183 other => Err(other),
184 }
185 }
186}
187
188impl H2Error {
189 pub const fn as_str(&self) -> &'static str {
191 match self {
192 H2Error::NoError => "NO_ERROR",
193 H2Error::ProtocolError => "PROTOCOL_ERROR",
194 H2Error::InternalError => "INTERNAL_ERROR",
195 H2Error::FlowControlError => "FLOW_CONTROL_ERROR",
196 H2Error::SettingsTimeout => "SETTINGS_TIMEOUT",
197 H2Error::StreamClosed => "STREAM_CLOSED",
198 H2Error::FrameSizeError => "FRAME_SIZE_ERROR",
199 H2Error::RefusedStream => "REFUSED_STREAM",
200 H2Error::Cancel => "CANCEL",
201 H2Error::CompressionError => "COMPRESSION_ERROR",
202 H2Error::ConnectError => "CONNECT_ERROR",
203 H2Error::EnhanceYourCalm => "ENHANCE_YOUR_CALM",
204 H2Error::InadequateSecurity => "INADEQUATE_SECURITY",
205 H2Error::HTTP11Required => "HTTP_1_1_REQUIRED",
206 }
207 }
208}
209
210impl std::fmt::Display for H2Error {
211 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
212 f.write_str(self.as_str())
213 }
214}
215
216impl<'a> ParserError<'a> {
217 pub fn new(input: &'a [u8], error: ParserErrorKind) -> ParserError<'a> {
218 ParserError { input, kind: error }
219 }
220 pub fn new_h2(input: &'a [u8], error: H2Error) -> ParserError<'a> {
221 ParserError {
222 input,
223 kind: ParserErrorKind::H2(error),
224 }
225 }
226}
227
228impl<'a> ParseError<&'a [u8]> for ParserError<'a> {
229 fn from_error_kind(input: &'a [u8], kind: ErrorKind) -> Self {
230 ParserError {
231 input,
232 kind: ParserErrorKind::Nom(kind),
233 }
234 }
235
236 fn append(input: &'a [u8], kind: ErrorKind, _other: Self) -> Self {
237 ParserError {
238 input,
239 kind: ParserErrorKind::Nom(kind),
240 }
241 }
242}
243
244impl<'a> From<(&'a [u8], ErrorKind)> for ParserError<'a> {
245 fn from((input, kind): (&'a [u8], ErrorKind)) -> Self {
246 ParserError {
247 input,
248 kind: ParserErrorKind::Nom(kind),
249 }
250 }
251}
252
253pub fn preface(i: &[u8]) -> IResult<&[u8], &[u8]> {
254 tag(b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")(i)
255}
256
257macro_rules! ensure_frame_size {
265 ($input:expr, $cond:expr) => {
266 if !($cond) {
267 return Err(Err::Failure(ParserError::new_h2(
268 $input,
269 H2Error::FrameSizeError,
270 )));
271 }
272 };
273}
274
275pub fn frame_header(input: &[u8], max_frame_size: u32) -> IResult<&[u8], FrameHeader, ParserError> {
288 let in_len = input.len();
289 let (i, payload_len) = be_u24(input)?;
290 if payload_len > max_frame_size {
291 return Err(Err::Failure(ParserError::new_h2(
292 i,
293 H2Error::FrameSizeError,
294 )));
295 }
296
297 let (i, t) = be_u8(i)?;
298 let frame_type = convert_frame_type(t);
299 let (i, flags) = be_u8(i)?;
300 let (i, raw_stream_id) = be_u32(i)?;
301 let stream_id = raw_stream_id & STREAM_ID_MASK;
302 debug_assert!(i.len() <= in_len, "parser must not grow its input");
307 debug_assert_eq!(
308 i.len(),
309 in_len - FRAME_HEADER_SIZE,
310 "frame_header must consume exactly the 9-byte header"
311 );
312 debug_assert!(
313 payload_len <= max_frame_size,
314 "frame_header must enforce the size bound it was given"
315 );
316 debug_assert_eq!(
317 stream_id & !STREAM_ID_MASK,
318 0,
319 "reserved high bit must be masked off the stream id"
320 );
321
322 let valid_stream_id = match frame_type {
327 FrameType::Data
328 | FrameType::Headers
329 | FrameType::Priority
330 | FrameType::RstStream
331 | FrameType::PushPromise
332 | FrameType::Continuation => stream_id != 0,
333 FrameType::Settings | FrameType::Ping | FrameType::GoAway | FrameType::PriorityUpdate => {
336 stream_id == 0
337 }
338 FrameType::WindowUpdate | FrameType::Unknown(_) => true,
339 };
340 if !valid_stream_id {
341 error!("{} invalid stream_id: {}", log_module_context!(), stream_id);
342 return Err(Err::Failure(ParserError::new_h2(i, H2Error::ProtocolError)));
343 }
344
345 Ok((
346 i,
347 FrameHeader {
348 payload_len,
349 frame_type,
350 flags,
351 stream_id,
352 },
353 ))
354}
355
356fn convert_frame_type(t: u8) -> FrameType {
362 trace!("{} got frame type: {}", log_module_context!(), t);
363 match t {
364 0 => FrameType::Data,
365 1 => FrameType::Headers,
366 2 => FrameType::Priority,
367 3 => FrameType::RstStream,
368 4 => FrameType::Settings,
369 5 => FrameType::PushPromise,
370 6 => FrameType::Ping,
371 7 => FrameType::GoAway,
372 8 => FrameType::WindowUpdate,
373 9 => FrameType::Continuation,
374 0x10 => FrameType::PriorityUpdate,
376 other => FrameType::Unknown(other),
377 }
378}
379
380#[derive(Clone, Debug)]
381pub enum Frame {
382 Data(Data),
383 Headers(Headers),
384 Priority(Priority),
385 RstStream(RstStream),
386 Settings(Settings),
387 PushPromise(PushPromise),
388 Ping(Ping),
389 GoAway(GoAway),
390 WindowUpdate(WindowUpdate),
391 Continuation(Continuation),
392 PriorityUpdate(PriorityUpdate),
396 Unknown(u8),
399}
400
401#[derive(Clone, Debug, PartialEq)]
403pub struct PriorityUpdate {
404 pub prioritized_stream_id: u32,
408 pub priority_field_value: Vec<u8>,
412}
413
414pub fn frame_body<'a>(
415 i: &'a [u8],
416 header: &FrameHeader,
417) -> IResult<&'a [u8], Frame, ParserError<'a>> {
418 let in_len = i.len();
419 let f = match header.frame_type {
420 FrameType::Data => data_frame(i, header)?,
421 FrameType::Headers => headers_frame(i, header)?,
422 FrameType::Priority => {
423 ensure_frame_size!(i, header.payload_len == PRIORITY_PAYLOAD_SIZE);
424 priority_frame(i, header)?
425 }
426 FrameType::RstStream => {
427 ensure_frame_size!(i, header.payload_len == RST_STREAM_PAYLOAD_SIZE);
428 rst_stream_frame(i, header)?
429 }
430 FrameType::PushPromise => push_promise_frame(i, header)?,
431 FrameType::Continuation => continuation_frame(i, header)?,
432 FrameType::Settings => {
433 ensure_frame_size!(
435 i,
436 !(header.flags & FLAG_ACK != 0 && header.payload_len != 0)
437 );
438 ensure_frame_size!(i, header.payload_len % SETTINGS_ENTRY_SIZE == 0);
439 settings_frame(i, header)?
440 }
441 FrameType::Ping => {
442 ensure_frame_size!(i, header.payload_len == PING_PAYLOAD_SIZE);
443 ping_frame(i, header)?
444 }
445 FrameType::GoAway => {
446 ensure_frame_size!(i, header.payload_len >= GOAWAY_PAYLOAD_SIZE);
449 goaway_frame(i, header)?
450 }
451 FrameType::WindowUpdate => {
452 ensure_frame_size!(i, header.payload_len == WINDOW_UPDATE_PAYLOAD_SIZE);
453 window_update_frame(i, header)?
454 }
455 FrameType::PriorityUpdate => priority_update_frame(i, header)?,
457 FrameType::Unknown(_) => unknown_frame(i, header)?,
459 };
460
461 debug_assert!(
464 f.0.len() <= in_len,
465 "frame body parser must not grow its input"
466 );
467 debug_assert!(
468 f.0.len() <= in_len.saturating_sub(header.payload_len as usize),
469 "frame body must consume at least the declared payload_len bytes"
470 );
471 Ok(f)
472}
473
474#[derive(Clone, Debug)]
475pub struct Data {
476 pub stream_id: u32,
477 pub payload: Slice,
478 pub end_stream: bool,
479}
480
481fn strip_padding<'a>(
495 i: &'a [u8],
496 flags: u8,
497 error_input: &'a [u8],
498) -> IResult<&'a [u8], u8, ParserError<'a>> {
499 let in_len = i.len();
500 let (i, pad_length) = if flags & FLAG_PADDED != 0 {
501 let (i, pad_length) = be_u8(i)?;
502 (i, pad_length)
503 } else {
504 (i, 0)
505 };
506 debug_assert_eq!(
509 i.len(),
510 in_len - (flags & FLAG_PADDED != 0) as usize,
511 "strip_padding consumes the pad-length byte iff PADDED is set"
512 );
513
514 if (pad_length as usize) > i.len() {
515 return Err(Err::Failure(ParserError::new_h2(
516 error_input,
517 H2Error::ProtocolError,
518 )));
519 }
520
521 debug_assert!(
524 pad_length as usize <= i.len(),
525 "strip_padding must reject pad_length larger than the remaining payload"
526 );
527 Ok((i, pad_length))
528}
529
530fn unpad<'a>(
536 i: &'a [u8],
537 pad_length: u8,
538 error_input: &'a [u8],
539) -> Result<&'a [u8], Err<ParserError<'a>>> {
540 let in_len = i.len();
541 let content_len = i
542 .len()
543 .checked_sub(pad_length as usize)
544 .ok_or_else(|| Err::Failure(ParserError::new_h2(error_input, H2Error::ProtocolError)))?;
545 debug_assert!(
548 content_len <= in_len,
549 "unpad must not grow the content slice"
550 );
551 debug_assert_eq!(
552 content_len + pad_length as usize,
553 in_len,
554 "content and padding must exactly partition the input"
555 );
556 Ok(&i[..content_len])
557}
558
559pub fn data_frame<'a>(
560 input: &'a [u8],
561 header: &FrameHeader,
562) -> IResult<&'a [u8], Frame, ParserError<'a>> {
563 let in_len = input.len();
564 let (remaining, i) = take(header.payload_len)(input)?;
565
566 let (i, pad_length) = strip_padding(i, header.flags, input)?;
567 let payload = unpad(i, pad_length, input)?;
568
569 debug_assert_eq!(
573 remaining.len(),
574 in_len - header.payload_len as usize,
575 "data_frame must consume exactly payload_len bytes"
576 );
577 debug_assert!(
578 payload.len() <= header.payload_len as usize,
579 "data payload must fit within the declared frame payload"
580 );
581 debug_assert!(
582 pad_length as usize <= header.payload_len as usize,
583 "padding must not exceed the frame payload"
584 );
585
586 Ok((
587 remaining,
588 Frame::Data(Data {
589 stream_id: header.stream_id,
590 payload: Slice::new(input, payload),
591 end_stream: header.flags & FLAG_END_STREAM != 0,
592 }),
593 ))
594}
595
596#[derive(Clone, Debug)]
597pub struct Headers {
598 pub stream_id: u32,
599 pub priority: Option<PriorityPart>,
600 pub header_block_fragment: Slice,
601 pub end_stream: bool,
603 pub end_headers: bool,
604}
605
606#[derive(Clone, Debug, PartialEq)]
607pub struct StreamDependency {
608 pub exclusive: bool,
609 pub stream_id: u32,
610}
611
612fn stream_dependency(i: &[u8]) -> IResult<&[u8], StreamDependency, ParserError<'_>> {
613 let (i, stream) = map(be_u32, |i| StreamDependency {
614 exclusive: i & 0x80000000 != 0,
615 stream_id: i & STREAM_ID_MASK,
616 })(i)?;
617 Ok((i, stream))
618}
619
620pub fn headers_frame<'a>(
621 input: &'a [u8],
622 header: &FrameHeader,
623) -> IResult<&'a [u8], Frame, ParserError<'a>> {
624 let in_len = input.len();
625 let (remaining, i) = take(header.payload_len)(input)?;
626
627 let (i, pad_length) = strip_padding(i, header.flags, input)?;
628
629 let (i, priority) = if header.flags & FLAG_PRIORITY != 0 {
630 let (i, stream_dependency) = stream_dependency(i)?;
631 let (i, weight) = be_u8(i)?;
632 (
633 i,
634 Some(PriorityPart::Rfc7540 {
635 stream_dependency,
636 weight,
637 }),
638 )
639 } else {
640 (i, None)
641 };
642
643 let header_block_fragment = unpad(i, pad_length, input)?;
644
645 debug_assert_eq!(
649 remaining.len(),
650 in_len - header.payload_len as usize,
651 "headers_frame must consume exactly payload_len bytes"
652 );
653 debug_assert!(
654 header_block_fragment.len() <= header.payload_len as usize,
655 "header block fragment must fit within the declared frame payload"
656 );
657
658 Ok((
659 remaining,
660 Frame::Headers(Headers {
661 stream_id: header.stream_id,
662 priority,
663 header_block_fragment: Slice::new(input, header_block_fragment),
664 end_stream: header.flags & FLAG_END_STREAM != 0,
665 end_headers: header.flags & FLAG_END_HEADERS != 0,
666 }),
667 ))
668}
669
670#[derive(Clone, Debug, PartialEq)]
671pub enum PriorityPart {
672 Rfc7540 {
673 stream_dependency: StreamDependency,
674 weight: u8,
675 },
676 Rfc9218 {
677 urgency: u8, incremental: bool,
679 },
680}
681
682#[derive(Clone, Debug, PartialEq)]
683pub struct Priority {
684 pub stream_id: u32,
685 pub inner: PriorityPart,
686}
687
688pub fn priority_frame<'a>(
689 input: &'a [u8],
690 header: &FrameHeader,
691) -> IResult<&'a [u8], Frame, ParserError<'a>> {
692 let in_len = input.len();
698 let (i, data) = take(header.payload_len)(input)?;
699 debug_assert_eq!(
702 i.len(),
703 in_len - header.payload_len as usize,
704 "priority_frame must consume exactly payload_len bytes"
705 );
706 debug_assert_eq!(
707 data.len(),
708 PRIORITY_PAYLOAD_SIZE as usize,
709 "PRIORITY payload must be exactly 5 bytes"
710 );
711 let (_, (stream_dependency, weight)) = tuple((stream_dependency, be_u8))(data)?;
712 Ok((
713 i,
714 Frame::Priority(Priority {
715 stream_id: header.stream_id,
716 inner: PriorityPart::Rfc7540 {
717 stream_dependency,
718 weight,
719 },
720 }),
721 ))
722}
723
724#[derive(Clone, Debug, PartialEq)]
725pub struct RstStream {
726 pub stream_id: u32,
727 pub error_code: u32,
728}
729
730pub fn rst_stream_frame<'a>(
731 input: &'a [u8],
732 header: &FrameHeader,
733) -> IResult<&'a [u8], Frame, ParserError<'a>> {
734 let in_len = input.len();
739 let (i, data) = take(header.payload_len)(input)?;
740 debug_assert_eq!(
743 i.len(),
744 in_len - header.payload_len as usize,
745 "rst_stream_frame must consume exactly payload_len bytes"
746 );
747 debug_assert_eq!(
748 data.len(),
749 RST_STREAM_PAYLOAD_SIZE as usize,
750 "RST_STREAM payload must be exactly 4 bytes"
751 );
752 let (_, error_code) = be_u32(data)?;
753 Ok((
754 i,
755 Frame::RstStream(RstStream {
756 stream_id: header.stream_id,
757 error_code,
758 }),
759 ))
760}
761
762#[derive(Clone, Debug, PartialEq)]
763pub struct Settings {
764 pub settings: Vec<Setting>,
765 pub ack: bool,
766}
767
768#[derive(Clone, Debug, PartialEq)]
769pub struct Setting {
770 pub identifier: u16,
771 pub value: u32,
772}
773
774pub const MAX_SETTINGS_ENTRIES: usize = 64;
784
785pub fn settings_frame<'a>(
786 input: &'a [u8],
787 header: &FrameHeader,
788) -> IResult<&'a [u8], Frame, ParserError<'a>> {
789 if header.payload_len / SETTINGS_ENTRY_SIZE > MAX_SETTINGS_ENTRIES as u32 {
793 return Err(Err::Failure(ParserError::new_h2(
794 input,
795 H2Error::FrameSizeError,
796 )));
797 }
798
799 let in_len = input.len();
800 let (i, data) = take(header.payload_len)(input)?;
801
802 let (_, settings) = many0(map(
803 complete(tuple((be_u16, be_u32))),
804 |(identifier, value)| Setting { identifier, value },
805 ))(data)?;
806
807 debug_assert_eq!(
811 i.len(),
812 in_len - header.payload_len as usize,
813 "settings_frame must consume exactly payload_len bytes"
814 );
815 debug_assert_eq!(
816 settings.len(),
817 header.payload_len as usize / SETTINGS_ENTRY_SIZE as usize,
818 "one SETTINGS entry decodes per 6 payload bytes"
819 );
820 debug_assert!(
821 settings.len() <= MAX_SETTINGS_ENTRIES,
822 "settings_frame must honour the MAX_SETTINGS_ENTRIES allocation cap"
823 );
824
825 Ok((
826 i,
827 Frame::Settings(Settings {
828 settings,
829 ack: header.flags & FLAG_ACK != 0,
830 }),
831 ))
832}
833
834#[derive(Clone, Debug)]
843pub struct PushPromise;
844
845pub fn push_promise_frame<'a>(
846 input: &'a [u8],
847 header: &FrameHeader,
848) -> IResult<&'a [u8], Frame, ParserError<'a>> {
849 let (_remaining, _payload) = take(header.payload_len)(input)?;
852 Err(Err::Failure(ParserError::new_h2(
853 input,
854 H2Error::ProtocolError,
855 )))
856}
857
858#[derive(Clone, Debug, PartialEq)]
859pub struct Ping {
860 pub payload: [u8; 8],
861 pub ack: bool,
862}
863
864pub fn ping_frame<'a>(
865 input: &'a [u8],
866 header: &FrameHeader,
867) -> IResult<&'a [u8], Frame, ParserError<'a>> {
868 let in_len = input.len();
872 let (i, data) = take(header.payload_len)(input)?;
873
874 debug_assert_eq!(
879 i.len(),
880 in_len - header.payload_len as usize,
881 "ping_frame must consume exactly payload_len bytes"
882 );
883 debug_assert_eq!(
884 data.len(),
885 PING_PAYLOAD_SIZE as usize,
886 "PING payload must be exactly 8 bytes for the opaque-data copy"
887 );
888
889 let mut p = Ping {
890 payload: [0; 8],
891 ack: header.flags & FLAG_ACK != 0,
892 };
893 p.payload[..8].copy_from_slice(&data[..8]);
894
895 Ok((i, Frame::Ping(p)))
896}
897
898#[derive(Clone, Debug)]
899pub struct GoAway {
900 pub last_stream_id: u32,
901 pub error_code: u32,
902 pub additional_debug_data: Slice,
903}
904
905pub fn goaway_frame<'a>(
906 input: &'a [u8],
907 header: &FrameHeader,
908) -> IResult<&'a [u8], Frame, ParserError<'a>> {
909 let in_len = input.len();
910 let (remaining, i) = take(header.payload_len)(input)?;
911 let (i, raw_last_stream_id) = be_u32(i)?;
912 let last_stream_id = raw_last_stream_id & STREAM_ID_MASK;
914 let (additional_debug_data, error_code) = be_u32(i)?;
915 debug_assert_eq!(
919 remaining.len(),
920 in_len - header.payload_len as usize,
921 "goaway_frame must consume exactly payload_len bytes"
922 );
923 debug_assert_eq!(
924 additional_debug_data.len(),
925 header.payload_len as usize - GOAWAY_PAYLOAD_SIZE as usize,
926 "GOAWAY debug data is payload_len minus the 8-byte fixed prefix"
927 );
928 debug_assert_eq!(
929 last_stream_id & !STREAM_ID_MASK,
930 0,
931 "GOAWAY last_stream_id reserved high bit must be masked"
932 );
933 Ok((
934 remaining,
935 Frame::GoAway(GoAway {
936 last_stream_id,
937 error_code,
938 additional_debug_data: Slice::new(input, additional_debug_data),
939 }),
940 ))
941}
942
943#[derive(Clone, Debug, PartialEq)]
944pub struct WindowUpdate {
945 pub stream_id: u32,
946 pub increment: u32,
947}
948
949pub fn window_update_frame<'a>(
950 input: &'a [u8],
951 header: &FrameHeader,
952) -> IResult<&'a [u8], Frame, ParserError<'a>> {
953 let in_len = input.len();
957 let (i, data) = take(header.payload_len)(input)?;
958 debug_assert_eq!(
961 i.len(),
962 in_len - header.payload_len as usize,
963 "window_update_frame must consume exactly payload_len bytes"
964 );
965 debug_assert_eq!(
966 data.len(),
967 WINDOW_UPDATE_PAYLOAD_SIZE as usize,
968 "WINDOW_UPDATE payload must be exactly 4 bytes"
969 );
970 let (_, increment) = be_u32(data)?;
971 let increment = increment & STREAM_ID_MASK;
972 debug_assert!(
974 increment <= STREAM_ID_MASK,
975 "window-size increment must be a 31-bit value"
976 );
977
978 Ok((
986 i,
987 Frame::WindowUpdate(WindowUpdate {
988 stream_id: header.stream_id,
989 increment,
990 }),
991 ))
992}
993
994#[derive(Clone, Debug)]
1002pub struct Continuation;
1003
1004pub fn continuation_frame<'a>(
1005 input: &'a [u8],
1006 header: &FrameHeader,
1007) -> IResult<&'a [u8], Frame, ParserError<'a>> {
1008 let in_len = input.len();
1010 let (remaining, _) = take(header.payload_len)(input)?;
1011 debug_assert_eq!(
1012 remaining.len(),
1013 in_len - header.payload_len as usize,
1014 "continuation_frame must consume exactly payload_len bytes"
1015 );
1016 Ok((remaining, Frame::Continuation(Continuation)))
1017}
1018
1019pub fn unknown_frame<'a>(
1024 input: &'a [u8],
1025 header: &FrameHeader,
1026) -> IResult<&'a [u8], Frame, ParserError<'a>> {
1027 let in_len = input.len();
1028 let (remaining, _payload) = take(header.payload_len)(input)?;
1029 debug_assert_eq!(
1030 remaining.len(),
1031 in_len - header.payload_len as usize,
1032 "unknown_frame must consume exactly payload_len bytes"
1033 );
1034 let raw = match header.frame_type {
1035 FrameType::Unknown(t) => t,
1036 _ => 0,
1037 };
1038 Ok((remaining, Frame::Unknown(raw)))
1039}
1040
1041pub fn priority_update_frame<'a>(
1058 input: &'a [u8],
1059 header: &FrameHeader,
1060) -> IResult<&'a [u8], Frame, ParserError<'a>> {
1061 if header.payload_len < PRIORITY_UPDATE_MIN_PAYLOAD {
1062 return Err(Err::Failure(ParserError::new_h2(
1063 input,
1064 H2Error::FrameSizeError,
1065 )));
1066 }
1067 let value_len = (header.payload_len - PRIORITY_UPDATE_MIN_PAYLOAD) as usize;
1076 if value_len > PRIORITY_UPDATE_MAX_VALUE {
1077 return Err(Err::Failure(ParserError::new_h2(
1078 input,
1079 H2Error::ProtocolError,
1080 )));
1081 }
1082 let in_len = input.len();
1083 let (remaining, payload) = take(header.payload_len)(input)?;
1084 let (raw_id_bytes, value_bytes) = payload.split_at(PRIORITY_UPDATE_MIN_PAYLOAD as usize);
1085 debug_assert_eq!(
1089 remaining.len(),
1090 in_len - header.payload_len as usize,
1091 "priority_update_frame must consume exactly payload_len bytes"
1092 );
1093 debug_assert_eq!(
1094 raw_id_bytes.len(),
1095 PRIORITY_UPDATE_MIN_PAYLOAD as usize,
1096 "PRIORITY_UPDATE stream-id prefix must be exactly 4 bytes"
1097 );
1098 debug_assert!(
1099 value_bytes.len() <= PRIORITY_UPDATE_MAX_VALUE,
1100 "priority field value must respect the PRIORITY_UPDATE_MAX_VALUE cap"
1101 );
1102 let prioritized_stream_id = u32::from_be_bytes([
1103 raw_id_bytes[0],
1104 raw_id_bytes[1],
1105 raw_id_bytes[2],
1106 raw_id_bytes[3],
1107 ]) & STREAM_ID_MASK;
1108 debug_assert_eq!(
1109 prioritized_stream_id & !STREAM_ID_MASK,
1110 0,
1111 "prioritized_stream_id reserved high bit must be masked"
1112 );
1113 Ok((
1114 remaining,
1115 Frame::PriorityUpdate(PriorityUpdate {
1116 prioritized_stream_id,
1117 priority_field_value: value_bytes.to_vec(),
1118 }),
1119 ))
1120}
1121
1122pub const PRIORITY_UPDATE_MIN_PAYLOAD: u32 = 4;
1126
1127pub const PRIORITY_UPDATE_MAX_VALUE: usize = 1024;
1135
1136#[cfg(test)]
1137mod tests {
1138 use super::*;
1139
1140 const DEFAULT_MAX_FRAME_SIZE: u32 = 1 << 14;
1142
1143 #[test]
1149 fn test_settings_ack_with_payload_rejected() {
1150 let input = [
1152 0x00, 0x00, 0x06, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64,
1158 ];
1159
1160 let (remaining, header) =
1161 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1162 assert_eq!(header.frame_type, FrameType::Settings);
1163 assert_eq!(header.flags & FLAG_ACK, FLAG_ACK);
1164 assert_eq!(header.payload_len, 6);
1165
1166 let result = frame_body(remaining, &header);
1167 assert!(
1168 result.is_err(),
1169 "SETTINGS ACK with non-empty payload must be rejected"
1170 );
1171 match result {
1172 Err(nom::Err::Failure(e)) => {
1173 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1174 }
1175 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1176 }
1177 }
1178
1179 #[test]
1185 fn test_settings_ack_empty_accepted() {
1186 let input = [
1187 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, ];
1192
1193 let (remaining, header) =
1194 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1195 assert_eq!(header.frame_type, FrameType::Settings);
1196 assert_eq!(header.flags & FLAG_ACK, FLAG_ACK);
1197
1198 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
1199 match frame {
1200 Frame::Settings(settings) => {
1201 assert!(settings.ack, "ACK flag must be set");
1202 assert!(
1203 settings.settings.is_empty(),
1204 "should have no settings entries"
1205 );
1206 }
1207 other => panic!("expected Frame::Settings, got {other:?}"),
1208 }
1209 }
1210
1211 #[test]
1216 fn test_window_update_max_increment() {
1217 let input = [
1218 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFF, ];
1224
1225 let (remaining, header) =
1226 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1227 assert_eq!(header.frame_type, FrameType::WindowUpdate);
1228 assert_eq!(header.stream_id, 1);
1229
1230 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
1231 match frame {
1232 Frame::WindowUpdate(wu) => {
1233 assert_eq!(wu.increment, 0x7FFFFFFF);
1234 assert_eq!(wu.stream_id, 1);
1235 }
1236 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1237 }
1238 }
1239
1240 #[test]
1246 fn test_window_update_zero_increment_parsed() {
1247 let input = [
1249 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
1255
1256 let (remaining, header) =
1257 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1258 assert_eq!(header.frame_type, FrameType::WindowUpdate);
1259
1260 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
1261 match frame {
1262 Frame::WindowUpdate(wu) => {
1263 assert_eq!(wu.stream_id, 0);
1264 assert_eq!(wu.increment, 0);
1265 }
1266 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1267 }
1268
1269 let input2 = [
1271 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, ];
1277
1278 let (remaining2, header2) =
1279 frame_header(&input2, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1280 let (_, frame2) =
1281 frame_body(remaining2, &header2).expect("second frame body parses cleanly");
1282 match frame2 {
1283 Frame::WindowUpdate(wu) => {
1284 assert_eq!(wu.stream_id, 3);
1285 assert_eq!(wu.increment, 0);
1286 }
1287 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1288 }
1289 }
1290
1291 #[test]
1299 fn test_unknown_frame_type_is_ignored() {
1300 let input = [
1301 0x00, 0x00, 0x04, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef, ];
1307
1308 let (remaining, header) = frame_header(&input, DEFAULT_MAX_FRAME_SIZE)
1309 .expect("unknown frame header must parse cleanly");
1310 assert!(matches!(header.frame_type, FrameType::Unknown(0xFF)));
1311 assert_eq!(header.payload_len, 4);
1312
1313 let (after, frame) =
1314 frame_body(remaining, &header).expect("unknown frame body must be consumed");
1315 assert!(after.is_empty(), "payload bytes must be consumed");
1316 match frame {
1317 Frame::Unknown(0xFF) => {}
1318 other => panic!("expected Frame::Unknown(0xFF), got {other:?}"),
1319 }
1320 }
1321
1322 #[test]
1327 fn test_priority_update_empty_field_parses() {
1328 let input = [
1329 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1335 ];
1336
1337 let (remaining, header) = frame_header(&input, DEFAULT_MAX_FRAME_SIZE)
1338 .expect("PRIORITY_UPDATE header must parse");
1339 assert!(matches!(header.frame_type, FrameType::PriorityUpdate));
1340 let (_, frame) = frame_body(remaining, &header).expect("body must be consumed");
1341 match frame {
1342 Frame::PriorityUpdate(PriorityUpdate {
1343 prioritized_stream_id,
1344 ref priority_field_value,
1345 }) => {
1346 assert_eq!(prioritized_stream_id, 1);
1347 assert!(priority_field_value.is_empty());
1348 }
1349 other => panic!("expected Frame::PriorityUpdate, got {other:?}"),
1350 }
1351 }
1352
1353 #[test]
1357 fn test_priority_update_with_priority_field_parses() {
1358 let value = b"u=0, i";
1359 let mut input = vec![
1360 0x00,
1361 0x00,
1362 0x04 + value.len() as u8, 0x10, 0x00, 0x00,
1366 0x00,
1367 0x00,
1368 0x00, 0x00,
1370 0x00,
1371 0x00,
1372 0x05, ];
1374 input.extend_from_slice(value);
1375
1376 let (remaining, header) =
1377 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("header parses");
1378 assert!(matches!(header.frame_type, FrameType::PriorityUpdate));
1379 let (_, frame) = frame_body(remaining, &header).expect("body parses");
1380 match frame {
1381 Frame::PriorityUpdate(PriorityUpdate {
1382 prioritized_stream_id,
1383 ref priority_field_value,
1384 }) => {
1385 assert_eq!(prioritized_stream_id, 5);
1386 assert_eq!(priority_field_value.as_slice(), value);
1387 }
1388 other => panic!("expected Frame::PriorityUpdate, got {other:?}"),
1389 }
1390 }
1391
1392 #[test]
1395 fn test_priority_update_payload_below_min_is_frame_size_error() {
1396 let input = [
1397 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1399 ];
1400 let (remaining, header) =
1401 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("header parses");
1402 let result = frame_body(remaining, &header);
1403 match result {
1404 Err(Err::Failure(e)) => {
1405 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1406 }
1407 other => panic!("expected FRAME_SIZE_ERROR, got {other:?}"),
1408 }
1409 }
1410
1411 #[test]
1417 fn test_priority_update_oversized_value_is_protocol_error() {
1418 let payload_len = (PRIORITY_UPDATE_MIN_PAYLOAD as usize) + PRIORITY_UPDATE_MAX_VALUE + 1;
1420 let mut input = Vec::with_capacity(9 + payload_len);
1421 input.push(((payload_len >> 16) & 0xff) as u8);
1423 input.push(((payload_len >> 8) & 0xff) as u8);
1424 input.push((payload_len & 0xff) as u8);
1425 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));
1430 let (remaining, header) =
1433 frame_header(&input, payload_len as u32 + 1).expect("header parses");
1434 match frame_body(remaining, &header) {
1435 Err(Err::Failure(e)) => {
1436 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1437 }
1438 other => {
1439 panic!("expected PROTOCOL_ERROR for oversized PRIORITY_UPDATE value, got {other:?}")
1440 }
1441 }
1442 }
1443
1444 #[test]
1447 fn test_priority_update_at_max_value_accepted() {
1448 let payload_len = (PRIORITY_UPDATE_MIN_PAYLOAD as usize) + PRIORITY_UPDATE_MAX_VALUE;
1449 let mut input = Vec::with_capacity(9 + payload_len);
1450 input.push(((payload_len >> 16) & 0xff) as u8);
1451 input.push(((payload_len >> 8) & 0xff) as u8);
1452 input.push((payload_len & 0xff) as u8);
1453 input.push(0x10);
1454 input.push(0x00);
1455 input.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]);
1456 input.extend_from_slice(&[0x00, 0x00, 0x00, 0x01]);
1457 input.extend(std::iter::repeat_n(b'a', PRIORITY_UPDATE_MAX_VALUE));
1458 let (remaining, header) =
1459 frame_header(&input, payload_len as u32 + 1).expect("header parses");
1460 match frame_body(remaining, &header) {
1461 Ok((_, Frame::PriorityUpdate(pu))) => {
1462 assert_eq!(pu.priority_field_value.len(), PRIORITY_UPDATE_MAX_VALUE);
1463 }
1464 other => panic!("expected Frame::PriorityUpdate at the cap boundary, got {other:?}"),
1465 }
1466 }
1467
1468 #[test]
1473 fn test_priority_update_on_non_zero_stream_is_protocol_error() {
1474 let input = [
1475 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, ];
1481 match frame_header(&input, DEFAULT_MAX_FRAME_SIZE) {
1482 Err(Err::Failure(e)) => {
1483 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1484 }
1485 other => panic!("expected PROTOCOL_ERROR, got {other:?}"),
1486 }
1487 }
1488
1489 #[test]
1494 fn test_settings_payload_not_multiple_of_6_rejected() {
1495 let input = [
1496 0x00, 0x00, 0x05, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, ];
1502
1503 let (remaining, header) =
1504 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1505 assert_eq!(header.frame_type, FrameType::Settings);
1506
1507 let result = frame_body(remaining, &header);
1508 assert!(
1509 result.is_err(),
1510 "odd-size SETTINGS payload must be rejected"
1511 );
1512 match result {
1513 Err(nom::Err::Failure(e)) => {
1514 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1515 }
1516 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1517 }
1518 }
1519
1520 #[test]
1525 fn test_settings_frame_over_cap_rejected() {
1526 let n_entries: u16 = (MAX_SETTINGS_ENTRIES as u16) + 1;
1528 let payload_len = u32::from(n_entries) * SETTINGS_ENTRY_SIZE;
1529 let mut input = Vec::with_capacity(9 + payload_len as usize);
1530 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 {
1535 input.extend_from_slice(&i.to_be_bytes()); input.extend_from_slice(&0u32.to_be_bytes()); }
1538
1539 let (remaining, header) =
1540 frame_header(&input, 16_777_215).expect("frame header parses cleanly");
1541 assert_eq!(header.frame_type, FrameType::Settings);
1542
1543 let result = frame_body(remaining, &header);
1544 assert!(
1545 result.is_err(),
1546 "SETTINGS frame over MAX_SETTINGS_ENTRIES must be rejected"
1547 );
1548 match result {
1549 Err(nom::Err::Failure(e)) => {
1550 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1551 }
1552 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1553 }
1554 }
1555
1556 #[test]
1558 fn test_settings_frame_at_cap_accepted() {
1559 let n_entries: u16 = MAX_SETTINGS_ENTRIES as u16;
1560 let payload_len = u32::from(n_entries) * SETTINGS_ENTRY_SIZE;
1561 let mut input = Vec::with_capacity(9 + payload_len as usize);
1562 input.extend_from_slice(&payload_len.to_be_bytes()[1..]);
1563 input.push(0x04);
1564 input.push(0x00);
1565 input.extend_from_slice(&[0, 0, 0, 0]);
1566 for _ in 0..n_entries {
1567 input.extend_from_slice(&0u16.to_be_bytes());
1568 input.extend_from_slice(&0u32.to_be_bytes());
1569 }
1570
1571 let (remaining, header) =
1572 frame_header(&input, 16_777_215).expect("frame header parses cleanly");
1573 let result = frame_body(remaining, &header);
1574 assert!(result.is_ok(), "exactly MAX_SETTINGS_ENTRIES must parse");
1575 }
1576
1577 #[test]
1581 fn test_rst_stream_wrong_payload_size_rejected() {
1582 let input = [
1584 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
1590
1591 let (remaining, header) =
1592 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1593 assert_eq!(header.frame_type, FrameType::RstStream);
1594
1595 let result = frame_body(remaining, &header);
1596 assert!(
1597 result.is_err(),
1598 "wrong RST_STREAM payload size must be rejected"
1599 );
1600 match result {
1601 Err(nom::Err::Failure(e)) => {
1602 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1603 }
1604 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1605 }
1606 }
1607
1608 #[test]
1612 fn test_ping_wrong_payload_size_rejected() {
1613 let input = [
1614 0x00, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, ];
1620
1621 let (remaining, header) =
1622 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1623 assert_eq!(header.frame_type, FrameType::Ping);
1624
1625 let result = frame_body(remaining, &header);
1626 assert!(result.is_err(), "wrong PING payload size must be rejected");
1627 match result {
1628 Err(nom::Err::Failure(e)) => {
1629 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1630 }
1631 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1632 }
1633 }
1634
1635 #[test]
1640 fn test_frame_exceeding_max_frame_size_rejected() {
1641 let input = [
1643 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, ];
1648
1649 let result = frame_header(&input, DEFAULT_MAX_FRAME_SIZE);
1650 assert!(result.is_err(), "oversized frame must be rejected");
1651 match result {
1652 Err(nom::Err::Failure(e)) => {
1653 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1654 }
1655 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1656 }
1657 }
1658
1659 #[test]
1663 fn test_settings_on_nonzero_stream_rejected() {
1664 let input = [
1665 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, ];
1670
1671 let result = frame_header(&input, DEFAULT_MAX_FRAME_SIZE);
1672 assert!(
1673 result.is_err(),
1674 "SETTINGS on non-zero stream must be rejected"
1675 );
1676 match result {
1677 Err(nom::Err::Failure(e)) => {
1678 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1679 }
1680 other => panic!("expected Failure(ProtocolError), got {other:?}"),
1681 }
1682 }
1683
1684 #[test]
1688 fn test_data_on_stream_zero_rejected() {
1689 let input = [
1690 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCA, 0xFE,
1695 ];
1696
1697 let result = frame_header(&input, DEFAULT_MAX_FRAME_SIZE);
1698 assert!(result.is_err(), "DATA on stream 0 must be rejected");
1699 match result {
1700 Err(nom::Err::Failure(e)) => {
1701 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1702 }
1703 other => panic!("expected Failure(ProtocolError), got {other:?}"),
1704 }
1705 }
1706
1707 #[test]
1712 fn test_window_update_reserved_bit_masked() {
1713 let input = [
1714 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, ];
1720
1721 let (remaining, header) =
1722 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1723 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
1724 match frame {
1725 Frame::WindowUpdate(wu) => {
1726 assert_eq!(
1727 wu.increment, 1,
1728 "reserved bit must be masked to yield increment=1"
1729 );
1730 }
1731 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1732 }
1733 }
1734
1735 fn build_frame_header(payload_len: u32, frame_type: u8, flags: u8, stream_id: u32) -> Vec<u8> {
1739 vec![
1740 ((payload_len >> 16) & 0xFF) as u8,
1741 ((payload_len >> 8) & 0xFF) as u8,
1742 (payload_len & 0xFF) as u8,
1743 frame_type,
1744 flags,
1745 ((stream_id >> 24) & 0xFF) as u8,
1746 ((stream_id >> 16) & 0xFF) as u8,
1747 ((stream_id >> 8) & 0xFF) as u8,
1748 (stream_id & 0xFF) as u8,
1749 ]
1750 }
1751
1752 fn build_raw_frame(
1754 payload_len: u32,
1755 frame_type: u8,
1756 flags: u8,
1757 stream_id: u32,
1758 payload: &[u8],
1759 ) -> Vec<u8> {
1760 let mut raw = build_frame_header(payload_len, frame_type, flags, stream_id);
1761 raw.extend_from_slice(payload);
1762 raw
1763 }
1764
1765 #[test]
1768 fn test_preface_valid() {
1769 let input = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
1770 let (remaining, matched) = preface(input).expect("should parse preface");
1771 assert!(remaining.is_empty());
1772 assert_eq!(matched, input.as_slice());
1773 }
1774
1775 #[test]
1776 fn test_preface_invalid() {
1777 let input = b"GET / HTTP/1.1\r\n";
1778 let result = preface(input);
1779 assert!(result.is_err(), "invalid preface should fail");
1780 }
1781
1782 #[test]
1783 fn test_preface_with_trailing_data() {
1784 let mut input = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".to_vec();
1785 input.extend_from_slice(b"extra stuff");
1786 let (remaining, _) = preface(&input).expect("should parse preface");
1787 assert_eq!(remaining, b"extra stuff");
1788 }
1789
1790 #[test]
1793 fn test_frame_header_settings_basic() {
1794 let raw = build_frame_header(0, 4, 0, 0);
1795 let (remaining, header) =
1796 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1797 assert!(remaining.is_empty());
1798 assert_eq!(header.payload_len, 0);
1799 assert_eq!(header.frame_type, FrameType::Settings);
1800 assert_eq!(header.flags, 0);
1801 assert_eq!(header.stream_id, 0);
1802 }
1803
1804 #[test]
1805 fn test_frame_header_data_basic() {
1806 let raw = build_frame_header(100, 0, 1, 1);
1807 let (_, header) =
1808 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1809 assert_eq!(header.payload_len, 100);
1810 assert_eq!(header.frame_type, FrameType::Data);
1811 assert_eq!(header.flags, 1);
1812 assert_eq!(header.stream_id, 1);
1813 }
1814
1815 #[test]
1816 fn test_frame_header_stream_id_reserved_bit_masked() {
1817 let raw = build_frame_header(5, 0, 0, 0x80000001);
1820 let (_, header) =
1821 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1822 assert_eq!(header.stream_id, 1, "reserved MSB must be masked off");
1823 }
1824
1825 #[test]
1828 fn test_parse_data_frame_end_stream() {
1829 let payload = b"hello";
1830 let raw = build_raw_frame(payload.len() as u32, 0, 0x01, 1, payload);
1831 let (remaining, header) =
1832 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1833 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1834 match f {
1835 Frame::Data(d) => {
1836 assert_eq!(d.stream_id, 1);
1837 assert!(d.end_stream);
1838 }
1839 other => panic!("expected Data, got {other:?}"),
1840 }
1841 }
1842
1843 #[test]
1844 fn test_parse_data_frame_no_end_stream() {
1845 let payload = b"data";
1846 let raw = build_raw_frame(payload.len() as u32, 0, 0x00, 3, payload);
1847 let (remaining, header) =
1848 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1849 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1850 match f {
1851 Frame::Data(d) => {
1852 assert_eq!(d.stream_id, 3);
1853 assert!(!d.end_stream);
1854 }
1855 other => panic!("expected Data, got {other:?}"),
1856 }
1857 }
1858
1859 #[test]
1860 fn test_parse_data_frame_with_padding() {
1861 let pad_length: u8 = 2;
1863 let actual_data = b"hello";
1864 let total_payload = 1 + actual_data.len() + pad_length as usize;
1865 let mut payload = Vec::new();
1866 payload.push(pad_length);
1867 payload.extend_from_slice(actual_data);
1868 payload.extend_from_slice(&[0x00; 2]);
1869
1870 let raw = build_raw_frame(total_payload as u32, 0, 0x08, 1, &payload);
1871 let (remaining, header) =
1872 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1873 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1874 match f {
1875 Frame::Data(d) => {
1876 assert_eq!(d.stream_id, 1);
1877 assert_eq!(d.payload.len, actual_data.len() as u32);
1878 }
1879 other => panic!("expected Data, got {other:?}"),
1880 }
1881 }
1882
1883 #[test]
1884 fn test_parse_data_frame_padding_exceeds_payload() {
1885 let mut payload = Vec::new();
1887 payload.push(10); payload.extend_from_slice(b"hello");
1889
1890 let raw = build_raw_frame(payload.len() as u32, 0, 0x08, 1, &payload);
1891 let (remaining, header) =
1892 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1893 let result = frame_body(remaining, &header);
1894 assert!(
1895 result.is_err(),
1896 "padding exceeding payload should be a protocol error"
1897 );
1898 }
1899
1900 #[test]
1903 fn test_parse_headers_frame_basic() {
1904 let hblock = b"\x82\x86";
1905 let raw = build_raw_frame(hblock.len() as u32, 1, 0x04, 1, hblock);
1906 let (remaining, header) =
1907 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1908 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1909 match f {
1910 Frame::Headers(h) => {
1911 assert_eq!(h.stream_id, 1);
1912 assert!(!h.end_stream);
1913 assert!(h.end_headers);
1914 assert!(h.priority.is_none());
1915 }
1916 other => panic!("expected Headers, got {other:?}"),
1917 }
1918 }
1919
1920 #[test]
1921 fn test_parse_headers_frame_end_stream_and_headers() {
1922 let hblock = b"\x82";
1923 let raw = build_raw_frame(hblock.len() as u32, 1, 0x05, 1, hblock);
1924 let (remaining, header) =
1925 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1926 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1927 match f {
1928 Frame::Headers(h) => {
1929 assert!(h.end_stream);
1930 assert!(h.end_headers);
1931 }
1932 other => panic!("expected Headers, got {other:?}"),
1933 }
1934 }
1935
1936 #[test]
1937 fn test_parse_headers_frame_with_priority() {
1938 let hblock = b"\x82";
1939 let payload_len = 5 + hblock.len(); let mut payload = Vec::new();
1941 payload.extend_from_slice(&[0x00, 0x00, 0x00, 0x01]);
1943 payload.push(15); payload.extend_from_slice(hblock);
1945
1946 let raw = build_raw_frame(payload_len as u32, 1, 0x24, 3, &payload);
1947 let (remaining, header) =
1948 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1949 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1950 match f {
1951 Frame::Headers(h) => {
1952 assert_eq!(h.stream_id, 3);
1953 let priority = h.priority.expect("should have priority");
1954 match priority {
1955 PriorityPart::Rfc7540 {
1956 stream_dependency,
1957 weight,
1958 } => {
1959 assert!(!stream_dependency.exclusive);
1960 assert_eq!(stream_dependency.stream_id, 1);
1961 assert_eq!(weight, 15);
1962 }
1963 other => panic!("expected Rfc7540, got {other:?}"),
1964 }
1965 }
1966 other => panic!("expected Headers, got {other:?}"),
1967 }
1968 }
1969
1970 #[test]
1971 fn test_parse_headers_frame_with_exclusive_priority() {
1972 let hblock = b"\x82\x86";
1973 let mut payload = Vec::new();
1974 let dep = 0x80000005u32;
1976 payload.extend_from_slice(&dep.to_be_bytes());
1977 payload.push(255); payload.extend_from_slice(hblock);
1979
1980 let payload_len = payload.len();
1981 let raw = build_raw_frame(payload_len as u32, 1, 0x24, 3, &payload);
1982 let (remaining, header) =
1983 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1984 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1985 match f {
1986 Frame::Headers(h) => {
1987 let priority = h.priority.expect("should have priority");
1988 match priority {
1989 PriorityPart::Rfc7540 {
1990 stream_dependency,
1991 weight,
1992 } => {
1993 assert!(stream_dependency.exclusive, "exclusive bit should be set");
1994 assert_eq!(stream_dependency.stream_id, 5);
1995 assert_eq!(weight, 255);
1996 }
1997 other => panic!("expected Rfc7540, got {other:?}"),
1998 }
1999 }
2000 other => panic!("expected Headers, got {other:?}"),
2001 }
2002 }
2003
2004 #[test]
2005 fn test_parse_headers_stream_id_zero_rejected() {
2006 let raw = build_raw_frame(2, 1, 0x04, 0, b"\x82\x86");
2007 let result = frame_header(&raw, DEFAULT_MAX_FRAME_SIZE);
2008 assert!(
2009 result.is_err(),
2010 "HEADERS with stream_id=0 should be rejected"
2011 );
2012 }
2013
2014 #[test]
2017 fn test_parse_rst_stream() {
2018 let error_code = 0x00000008u32; let raw = build_raw_frame(4, 3, 0, 1, &error_code.to_be_bytes());
2020 let (remaining, header) =
2021 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2022 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2023 match f {
2024 Frame::RstStream(rst) => {
2025 assert_eq!(rst.stream_id, 1);
2026 assert_eq!(rst.error_code, 0x08);
2027 }
2028 other => panic!("expected RstStream, got {other:?}"),
2029 }
2030 }
2031
2032 #[test]
2033 fn test_parse_rst_stream_stream_id_zero_rejected() {
2034 let raw = build_raw_frame(4, 3, 0, 0, &[0u8; 4]);
2035 let result = frame_header(&raw, DEFAULT_MAX_FRAME_SIZE);
2036 assert!(
2037 result.is_err(),
2038 "RST_STREAM with stream_id=0 should be rejected"
2039 );
2040 }
2041
2042 #[test]
2045 fn test_parse_settings_frame_with_values() {
2046 let mut payload = Vec::new();
2047 payload.extend_from_slice(&0x0001u16.to_be_bytes());
2049 payload.extend_from_slice(&4096u32.to_be_bytes());
2050 payload.extend_from_slice(&0x0003u16.to_be_bytes());
2052 payload.extend_from_slice(&100u32.to_be_bytes());
2053 payload.extend_from_slice(&0x0004u16.to_be_bytes());
2055 payload.extend_from_slice(&65535u32.to_be_bytes());
2056
2057 let raw = build_raw_frame(payload.len() as u32, 4, 0x0, 0, &payload);
2058 let (remaining, header) =
2059 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2060 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2061 match f {
2062 Frame::Settings(s) => {
2063 assert!(!s.ack);
2064 assert_eq!(s.settings.len(), 3);
2065 assert_eq!(s.settings[0].identifier, 0x0001);
2066 assert_eq!(s.settings[0].value, 4096);
2067 assert_eq!(s.settings[1].identifier, 0x0003);
2068 assert_eq!(s.settings[1].value, 100);
2069 assert_eq!(s.settings[2].identifier, 0x0004);
2070 assert_eq!(s.settings[2].value, 65535);
2071 }
2072 other => panic!("expected Settings, got {other:?}"),
2073 }
2074 }
2075
2076 #[test]
2079 fn test_parse_ping_frame() {
2080 let ping_payload = [1u8, 2, 3, 4, 5, 6, 7, 8];
2081 let raw = build_raw_frame(8, 6, 0, 0, &ping_payload);
2082 let (remaining, header) =
2083 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2084 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2085 match f {
2086 Frame::Ping(p) => {
2087 assert_eq!(p.payload, ping_payload);
2088 assert!(!p.ack);
2089 }
2090 other => panic!("expected Ping, got {other:?}"),
2091 }
2092 }
2093
2094 #[test]
2095 fn test_parse_ping_ack_preserves_payload() {
2096 let ping_payload = [0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE];
2097 let raw = build_raw_frame(8, 6, 0x01, 0, &ping_payload);
2098 let (remaining, header) =
2099 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2100 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2101 match f {
2102 Frame::Ping(p) => {
2103 assert_eq!(
2104 p.payload, ping_payload,
2105 "PING ACK must echo the exact payload"
2106 );
2107 assert!(p.ack);
2108 }
2109 other => panic!("expected Ping, got {other:?}"),
2110 }
2111 }
2112
2113 #[test]
2114 fn test_parse_ping_stream_id_nonzero_rejected() {
2115 let raw = build_raw_frame(8, 6, 0, 1, &[0u8; 8]);
2116 let result = frame_header(&raw, DEFAULT_MAX_FRAME_SIZE);
2117 assert!(result.is_err(), "PING with stream_id!=0 should be rejected");
2118 }
2119
2120 #[test]
2123 fn test_parse_window_update_connection_level() {
2124 let increment = 1000u32;
2125 let raw = build_raw_frame(4, 8, 0, 0, &increment.to_be_bytes());
2126 let (remaining, header) =
2127 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2128 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2129 match f {
2130 Frame::WindowUpdate(w) => {
2131 assert_eq!(w.stream_id, 0);
2132 assert_eq!(w.increment, 1000);
2133 }
2134 other => panic!("expected WindowUpdate, got {other:?}"),
2135 }
2136 }
2137
2138 #[test]
2139 fn test_parse_window_update_stream_level() {
2140 let increment = 65535u32;
2141 let raw = build_raw_frame(4, 8, 0, 5, &increment.to_be_bytes());
2142 let (remaining, header) =
2143 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2144 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2145 match f {
2146 Frame::WindowUpdate(w) => {
2147 assert_eq!(w.stream_id, 5);
2148 assert_eq!(w.increment, 65535);
2150 }
2151 other => panic!("expected WindowUpdate, got {other:?}"),
2152 }
2153 }
2154
2155 #[test]
2156 fn test_parse_window_update_wrong_size() {
2157 let raw = build_raw_frame(3, 8, 0, 0, &[0u8; 3]);
2158 let (remaining, header) =
2159 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2160 let result = frame_body(remaining, &header);
2161 assert!(
2162 result.is_err(),
2163 "WINDOW_UPDATE with payload != 4 should fail"
2164 );
2165 match result {
2166 Err(Err::Failure(e)) => {
2167 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
2168 }
2169 other => panic!("expected FrameSizeError, got {other:?}"),
2170 }
2171 }
2172
2173 #[test]
2176 fn test_parse_frame_at_max_frame_size() {
2177 let payload = vec![0u8; DEFAULT_MAX_FRAME_SIZE as usize];
2178 let raw = build_raw_frame(DEFAULT_MAX_FRAME_SIZE, 0, 0x0, 1, &payload);
2179 let (remaining, header) =
2180 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2181 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2182 match f {
2183 Frame::Data(d) => {
2184 assert_eq!(d.payload.len, DEFAULT_MAX_FRAME_SIZE);
2185 }
2186 other => panic!("expected Data, got {other:?}"),
2187 }
2188 }
2189
2190 #[test]
2191 fn test_parse_frame_with_custom_max_frame_size() {
2192 let custom_max = 32768u32;
2193 let payload = vec![0u8; 20000];
2194 let raw = build_raw_frame(20000, 0, 0x0, 1, &payload);
2195 let (remaining, header) =
2196 frame_header(&raw, custom_max).expect("frame header parses with custom max");
2197 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2198 match f {
2199 Frame::Data(d) => {
2200 assert_eq!(d.payload.len, 20000);
2201 }
2202 other => panic!("expected Data, got {other:?}"),
2203 }
2204 }
2205
2206 #[test]
2209 fn test_h2_error_try_from_valid() {
2210 assert_eq!(H2Error::try_from(0x0), Ok(H2Error::NoError));
2211 assert_eq!(H2Error::try_from(0x1), Ok(H2Error::ProtocolError));
2212 assert_eq!(H2Error::try_from(0x6), Ok(H2Error::FrameSizeError));
2213 assert_eq!(H2Error::try_from(0xd), Ok(H2Error::HTTP11Required));
2214 }
2215
2216 #[test]
2217 fn test_h2_error_try_from_invalid() {
2218 assert_eq!(H2Error::try_from(0x0e), Err(0x0e));
2219 assert_eq!(H2Error::try_from(0xFF), Err(0xFF));
2220 }
2221
2222 #[test]
2223 fn test_h2_error_from_str() {
2224 assert_eq!("NO_ERROR".parse::<H2Error>(), Ok(H2Error::NoError));
2225 assert_eq!(
2226 "PROTOCOL_ERROR".parse::<H2Error>(),
2227 Ok(H2Error::ProtocolError)
2228 );
2229 assert_eq!(
2230 "ENHANCE_YOUR_CALM".parse::<H2Error>(),
2231 Ok(H2Error::EnhanceYourCalm)
2232 );
2233 assert!("INVALID_ERROR".parse::<H2Error>().is_err());
2234 }
2235
2236 #[test]
2237 fn test_h2_error_as_str_roundtrip() {
2238 let errors = [
2239 H2Error::NoError,
2240 H2Error::ProtocolError,
2241 H2Error::InternalError,
2242 H2Error::FlowControlError,
2243 H2Error::SettingsTimeout,
2244 H2Error::StreamClosed,
2245 H2Error::FrameSizeError,
2246 H2Error::RefusedStream,
2247 H2Error::Cancel,
2248 H2Error::CompressionError,
2249 H2Error::ConnectError,
2250 H2Error::EnhanceYourCalm,
2251 H2Error::InadequateSecurity,
2252 H2Error::HTTP11Required,
2253 ];
2254
2255 for error in &errors {
2256 let s = error.as_str();
2257 let parsed: H2Error = s.parse().unwrap_or_else(|_| panic!("failed to parse {s}"));
2258 assert_eq!(*error, parsed, "roundtrip failed for {s}");
2259 }
2260 }
2261
2262 #[test]
2265 fn test_parse_priority_frame() {
2266 let mut payload = Vec::new();
2267 payload.extend_from_slice(&0x00000001u32.to_be_bytes());
2269 payload.push(15); assert_eq!(payload.len(), 5);
2271
2272 let raw = build_raw_frame(5, 2, 0, 3, &payload);
2273 let (remaining, header) =
2274 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2275 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2276 match f {
2277 Frame::Priority(p) => {
2278 assert_eq!(p.stream_id, 3);
2279 match p.inner {
2280 PriorityPart::Rfc7540 {
2281 stream_dependency,
2282 weight,
2283 } => {
2284 assert!(!stream_dependency.exclusive);
2285 assert_eq!(stream_dependency.stream_id, 1);
2286 assert_eq!(weight, 15);
2287 }
2288 other => panic!("expected Rfc7540, got {other:?}"),
2289 }
2290 }
2291 other => panic!("expected Priority, got {other:?}"),
2292 }
2293 }
2294
2295 #[test]
2296 fn test_parse_priority_wrong_size_rejected() {
2297 let raw = build_raw_frame(4, 2, 0, 1, &[0u8; 4]);
2298 let (remaining, header) =
2299 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2300 let result = frame_body(remaining, &header);
2301 assert!(
2302 result.is_err(),
2303 "PRIORITY with wrong payload size should fail"
2304 );
2305 }
2306
2307 #[test]
2314 fn test_headers_padded_priority_underflow_rejected() {
2315 let raw: [u8; 16] = [
2316 0x00, 0x00, 0x06, 0x01, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x00, 0x64, 0x6d, 0x6d,
2317 0x6d, 0x6d,
2318 ];
2319 let (remaining, header) =
2320 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2321 let result = frame_body(remaining, &header);
2322 assert!(
2323 result.is_err(),
2324 "PADDED+PRIORITY HEADERS with oversized pad_length must error, not panic"
2325 );
2326 }
2327
2328 #[test]
2336 fn test_strip_padding_all_padding_accepted() {
2337 let input = [
2341 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, ];
2348
2349 let (remaining, header) =
2350 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2351 let (_, frame) =
2352 frame_body(remaining, &header).expect("DATA with all-padding body must parse");
2353 match frame {
2354 Frame::Data(data) => {
2355 assert_eq!(data.stream_id, 1);
2356 assert_eq!(data.payload.len, 0);
2358 }
2359 other => panic!("expected Frame::Data, got {other:?}"),
2360 }
2361 }
2362
2363 #[test]
2364 fn test_strip_padding_pad_length_equals_payload_len_rejected() {
2365 let input = [
2369 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x01, ];
2375
2376 let (remaining, header) =
2377 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2378 let result = frame_body(remaining, &header);
2379 assert!(
2380 matches!(
2381 result,
2382 Err(nom::Err::Failure(ParserError {
2383 kind: ParserErrorKind::H2(H2Error::ProtocolError),
2384 ..
2385 }))
2386 ),
2387 "pad_length > remaining body must yield PROTOCOL_ERROR, got {result:?}"
2388 );
2389 }
2390
2391 #[test]
2397 fn test_goaway_short_payload_rejected() {
2398 let input = [
2399 0x00, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
2405
2406 let (remaining, header) =
2407 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2408 assert_eq!(header.frame_type, FrameType::GoAway);
2409 let result = frame_body(remaining, &header);
2410 assert!(
2411 matches!(
2412 result,
2413 Err(nom::Err::Failure(ParserError {
2414 kind: ParserErrorKind::H2(H2Error::FrameSizeError),
2415 ..
2416 }))
2417 ),
2418 "GOAWAY with payload_len < 8 must yield FRAME_SIZE_ERROR, got {result:?}"
2419 );
2420 }
2421
2422 #[test]
2423 fn test_goaway_minimum_payload_accepted() {
2424 let input = [
2425 0x00, 0x00, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, ];
2432
2433 let (remaining, header) =
2434 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2435 let (_, frame) = frame_body(remaining, &header).expect("minimal GOAWAY must parse cleanly");
2436 match frame {
2437 Frame::GoAway(goaway) => {
2438 assert_eq!(goaway.last_stream_id, 10);
2439 assert_eq!(goaway.error_code, 0);
2440 }
2441 other => panic!("expected Frame::GoAway, got {other:?}"),
2442 }
2443 }
2444
2445 #[test]
2453 fn test_push_promise_rejected_at_wire_layer() {
2454 let input = [
2455 0x00, 0x00, 0x08, 0x05, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, ];
2462
2463 let (remaining, header) =
2464 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2465 assert_eq!(header.frame_type, FrameType::PushPromise);
2466 let result = frame_body(remaining, &header);
2467 assert!(
2468 matches!(
2469 result,
2470 Err(nom::Err::Failure(ParserError {
2471 kind: ParserErrorKind::H2(H2Error::ProtocolError),
2472 ..
2473 }))
2474 ),
2475 "PUSH_PROMISE must be rejected at wire layer with PROTOCOL_ERROR, got {result:?}"
2476 );
2477 }
2478}