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, Copy, 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 const CLIENT_PREFACE_MAGIC: &[u8; 24] = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
258
259pub fn preface(i: &[u8]) -> IResult<&[u8], &[u8]> {
260 tag(&CLIENT_PREFACE_MAGIC[..])(i)
261}
262
263macro_rules! ensure_frame_size {
271 ($input:expr, $cond:expr) => {
272 if !($cond) {
273 return Err(Err::Failure(ParserError::new_h2(
274 $input,
275 H2Error::FrameSizeError,
276 )));
277 }
278 };
279}
280
281pub fn frame_header(
294 input: &[u8],
295 max_frame_size: u32,
296) -> IResult<&[u8], FrameHeader, ParserError<'_>> {
297 let in_len = input.len();
298 let (i, payload_len) = be_u24(input)?;
299 if payload_len > max_frame_size {
300 return Err(Err::Failure(ParserError::new_h2(
301 i,
302 H2Error::FrameSizeError,
303 )));
304 }
305
306 let (i, t) = be_u8(i)?;
307 let frame_type = convert_frame_type(t);
308 let (i, flags) = be_u8(i)?;
309 let (i, raw_stream_id) = be_u32(i)?;
310 let stream_id = raw_stream_id & STREAM_ID_MASK;
311 debug_assert!(i.len() <= in_len, "parser must not grow its input");
316 debug_assert_eq!(
317 i.len(),
318 in_len - FRAME_HEADER_SIZE,
319 "frame_header must consume exactly the 9-byte header"
320 );
321 debug_assert!(
322 payload_len <= max_frame_size,
323 "frame_header must enforce the size bound it was given"
324 );
325 debug_assert_eq!(
326 stream_id & !STREAM_ID_MASK,
327 0,
328 "reserved high bit must be masked off the stream id"
329 );
330
331 let valid_stream_id = match frame_type {
336 FrameType::Data
337 | FrameType::Headers
338 | FrameType::Priority
339 | FrameType::RstStream
340 | FrameType::PushPromise
341 | FrameType::Continuation => stream_id != 0,
342 FrameType::Settings | FrameType::Ping | FrameType::GoAway | FrameType::PriorityUpdate => {
345 stream_id == 0
346 }
347 FrameType::WindowUpdate | FrameType::Unknown(_) => true,
348 };
349 if !valid_stream_id {
350 error!("{} invalid stream_id: {}", log_module_context!(), stream_id);
351 return Err(Err::Failure(ParserError::new_h2(i, H2Error::ProtocolError)));
352 }
353
354 Ok((
355 i,
356 FrameHeader {
357 payload_len,
358 frame_type,
359 flags,
360 stream_id,
361 },
362 ))
363}
364
365fn convert_frame_type(t: u8) -> FrameType {
371 trace!("{} got frame type: {}", log_module_context!(), t);
372 match t {
373 0 => FrameType::Data,
374 1 => FrameType::Headers,
375 2 => FrameType::Priority,
376 3 => FrameType::RstStream,
377 4 => FrameType::Settings,
378 5 => FrameType::PushPromise,
379 6 => FrameType::Ping,
380 7 => FrameType::GoAway,
381 8 => FrameType::WindowUpdate,
382 9 => FrameType::Continuation,
383 0x10 => FrameType::PriorityUpdate,
385 other => FrameType::Unknown(other),
386 }
387}
388
389#[derive(Clone, Debug)]
390pub enum Frame {
391 Data(Data),
392 Headers(Headers),
393 Priority(Priority),
394 RstStream(RstStream),
395 Settings(Settings),
396 PushPromise(PushPromise),
397 Ping(Ping),
398 GoAway(GoAway),
399 WindowUpdate(WindowUpdate),
400 Continuation(Continuation),
401 PriorityUpdate(PriorityUpdate),
405 Unknown(u8),
408}
409
410impl Frame {
411 pub fn frame_type(&self) -> FrameType {
418 match self {
419 Frame::Data(_) => FrameType::Data,
420 Frame::Headers(_) => FrameType::Headers,
421 Frame::Priority(_) => FrameType::Priority,
422 Frame::RstStream(_) => FrameType::RstStream,
423 Frame::Settings(_) => FrameType::Settings,
424 Frame::PushPromise(_) => FrameType::PushPromise,
425 Frame::Ping(_) => FrameType::Ping,
426 Frame::GoAway(_) => FrameType::GoAway,
427 Frame::WindowUpdate(_) => FrameType::WindowUpdate,
428 Frame::Continuation(_) => FrameType::Continuation,
429 Frame::PriorityUpdate(_) => FrameType::PriorityUpdate,
430 Frame::Unknown(raw) => FrameType::Unknown(*raw),
431 }
432 }
433}
434
435#[derive(Clone, Debug, PartialEq)]
437pub struct PriorityUpdate {
438 pub prioritized_stream_id: u32,
442 pub priority_field_value: Vec<u8>,
446}
447
448pub fn frame_body<'a>(
449 i: &'a [u8],
450 header: &FrameHeader,
451) -> IResult<&'a [u8], Frame, ParserError<'a>> {
452 let in_len = i.len();
453 let f = match header.frame_type {
454 FrameType::Data => data_frame(i, header)?,
455 FrameType::Headers => headers_frame(i, header)?,
456 FrameType::Priority => {
457 ensure_frame_size!(i, header.payload_len == PRIORITY_PAYLOAD_SIZE);
458 priority_frame(i, header)?
459 }
460 FrameType::RstStream => {
461 ensure_frame_size!(i, header.payload_len == RST_STREAM_PAYLOAD_SIZE);
462 rst_stream_frame(i, header)?
463 }
464 FrameType::PushPromise => push_promise_frame(i, header)?,
465 FrameType::Continuation => continuation_frame(i, header)?,
466 FrameType::Settings => {
467 ensure_frame_size!(
469 i,
470 !(header.flags & FLAG_ACK != 0 && header.payload_len != 0)
471 );
472 ensure_frame_size!(i, header.payload_len.is_multiple_of(SETTINGS_ENTRY_SIZE));
473 settings_frame(i, header)?
474 }
475 FrameType::Ping => {
476 ensure_frame_size!(i, header.payload_len == PING_PAYLOAD_SIZE);
477 ping_frame(i, header)?
478 }
479 FrameType::GoAway => {
480 ensure_frame_size!(i, header.payload_len >= GOAWAY_PAYLOAD_SIZE);
483 goaway_frame(i, header)?
484 }
485 FrameType::WindowUpdate => {
486 ensure_frame_size!(i, header.payload_len == WINDOW_UPDATE_PAYLOAD_SIZE);
487 window_update_frame(i, header)?
488 }
489 FrameType::PriorityUpdate => priority_update_frame(i, header)?,
491 FrameType::Unknown(_) => unknown_frame(i, header)?,
493 };
494
495 debug_assert!(
498 f.0.len() <= in_len,
499 "frame body parser must not grow its input"
500 );
501 debug_assert!(
502 f.0.len() <= in_len.saturating_sub(header.payload_len as usize),
503 "frame body must consume at least the declared payload_len bytes"
504 );
505 Ok(f)
506}
507
508#[derive(Clone, Debug)]
509pub struct Data {
510 pub stream_id: u32,
511 pub payload: Slice,
512 pub end_stream: bool,
513}
514
515fn strip_padding<'a>(
529 i: &'a [u8],
530 flags: u8,
531 error_input: &'a [u8],
532) -> IResult<&'a [u8], u8, ParserError<'a>> {
533 let in_len = i.len();
534 let (i, pad_length) = if flags & FLAG_PADDED != 0 {
535 let (i, pad_length) = be_u8(i)?;
536 (i, pad_length)
537 } else {
538 (i, 0)
539 };
540 debug_assert_eq!(
543 i.len(),
544 in_len - (flags & FLAG_PADDED != 0) as usize,
545 "strip_padding consumes the pad-length byte iff PADDED is set"
546 );
547
548 if (pad_length as usize) > i.len() {
549 return Err(Err::Failure(ParserError::new_h2(
550 error_input,
551 H2Error::ProtocolError,
552 )));
553 }
554
555 debug_assert!(
558 pad_length as usize <= i.len(),
559 "strip_padding must reject pad_length larger than the remaining payload"
560 );
561 Ok((i, pad_length))
562}
563
564fn unpad<'a>(
570 i: &'a [u8],
571 pad_length: u8,
572 error_input: &'a [u8],
573) -> Result<&'a [u8], Err<ParserError<'a>>> {
574 let in_len = i.len();
575 let content_len = i
576 .len()
577 .checked_sub(pad_length as usize)
578 .ok_or_else(|| Err::Failure(ParserError::new_h2(error_input, H2Error::ProtocolError)))?;
579 debug_assert!(
582 content_len <= in_len,
583 "unpad must not grow the content slice"
584 );
585 debug_assert_eq!(
586 content_len + pad_length as usize,
587 in_len,
588 "content and padding must exactly partition the input"
589 );
590 Ok(&i[..content_len])
591}
592
593pub fn data_frame<'a>(
594 input: &'a [u8],
595 header: &FrameHeader,
596) -> IResult<&'a [u8], Frame, ParserError<'a>> {
597 let in_len = input.len();
598 let (remaining, i) = take(header.payload_len)(input)?;
599
600 let (i, pad_length) = strip_padding(i, header.flags, input)?;
601 let payload = unpad(i, pad_length, input)?;
602
603 debug_assert_eq!(
607 remaining.len(),
608 in_len - header.payload_len as usize,
609 "data_frame must consume exactly payload_len bytes"
610 );
611 debug_assert!(
612 payload.len() <= header.payload_len as usize,
613 "data payload must fit within the declared frame payload"
614 );
615 debug_assert!(
616 pad_length as usize <= header.payload_len as usize,
617 "padding must not exceed the frame payload"
618 );
619
620 Ok((
621 remaining,
622 Frame::Data(Data {
623 stream_id: header.stream_id,
624 payload: Slice::new(input, payload),
625 end_stream: header.flags & FLAG_END_STREAM != 0,
626 }),
627 ))
628}
629
630#[derive(Clone, Debug)]
631pub struct Headers {
632 pub stream_id: u32,
633 pub priority: Option<PriorityPart>,
634 pub header_block_fragment: Slice,
635 pub end_stream: bool,
637 pub end_headers: bool,
638}
639
640#[derive(Clone, Debug, PartialEq)]
641pub struct StreamDependency {
642 pub exclusive: bool,
643 pub stream_id: u32,
644}
645
646fn stream_dependency(i: &[u8]) -> IResult<&[u8], StreamDependency, ParserError<'_>> {
647 let (i, stream) = map(be_u32, |i| StreamDependency {
648 exclusive: i & 0x80000000 != 0,
649 stream_id: i & STREAM_ID_MASK,
650 })
651 .parse(i)?;
652 Ok((i, stream))
653}
654
655pub fn headers_frame<'a>(
656 input: &'a [u8],
657 header: &FrameHeader,
658) -> IResult<&'a [u8], Frame, ParserError<'a>> {
659 let in_len = input.len();
660 let (remaining, i) = take(header.payload_len)(input)?;
661
662 let (i, pad_length) = strip_padding(i, header.flags, input)?;
663
664 let (i, priority) = if header.flags & FLAG_PRIORITY != 0 {
665 let (i, stream_dependency) = stream_dependency(i)?;
666 let (i, weight) = be_u8(i)?;
667 (
668 i,
669 Some(PriorityPart::Rfc7540 {
670 stream_dependency,
671 weight,
672 }),
673 )
674 } else {
675 (i, None)
676 };
677
678 let header_block_fragment = unpad(i, pad_length, input)?;
679
680 debug_assert_eq!(
684 remaining.len(),
685 in_len - header.payload_len as usize,
686 "headers_frame must consume exactly payload_len bytes"
687 );
688 debug_assert!(
689 header_block_fragment.len() <= header.payload_len as usize,
690 "header block fragment must fit within the declared frame payload"
691 );
692
693 Ok((
694 remaining,
695 Frame::Headers(Headers {
696 stream_id: header.stream_id,
697 priority,
698 header_block_fragment: Slice::new(input, header_block_fragment),
699 end_stream: header.flags & FLAG_END_STREAM != 0,
700 end_headers: header.flags & FLAG_END_HEADERS != 0,
701 }),
702 ))
703}
704
705#[derive(Clone, Debug, PartialEq)]
706pub enum PriorityPart {
707 Rfc7540 {
708 stream_dependency: StreamDependency,
709 weight: u8,
710 },
711 Rfc9218 {
712 urgency: u8, incremental: bool,
714 },
715}
716
717#[derive(Clone, Debug, PartialEq)]
718pub struct Priority {
719 pub stream_id: u32,
720 pub inner: PriorityPart,
721}
722
723pub fn priority_frame<'a>(
724 input: &'a [u8],
725 header: &FrameHeader,
726) -> IResult<&'a [u8], Frame, ParserError<'a>> {
727 let in_len = input.len();
733 let (i, data) = take(header.payload_len)(input)?;
734 debug_assert_eq!(
737 i.len(),
738 in_len - header.payload_len as usize,
739 "priority_frame must consume exactly payload_len bytes"
740 );
741 debug_assert_eq!(
742 data.len(),
743 PRIORITY_PAYLOAD_SIZE as usize,
744 "PRIORITY payload must be exactly 5 bytes"
745 );
746 let (_, (stream_dependency, weight)) = (stream_dependency, be_u8).parse(data)?;
747 Ok((
748 i,
749 Frame::Priority(Priority {
750 stream_id: header.stream_id,
751 inner: PriorityPart::Rfc7540 {
752 stream_dependency,
753 weight,
754 },
755 }),
756 ))
757}
758
759#[derive(Clone, Debug, PartialEq)]
760pub struct RstStream {
761 pub stream_id: u32,
762 pub error_code: u32,
763}
764
765pub fn rst_stream_frame<'a>(
766 input: &'a [u8],
767 header: &FrameHeader,
768) -> IResult<&'a [u8], Frame, ParserError<'a>> {
769 let in_len = input.len();
774 let (i, data) = take(header.payload_len)(input)?;
775 debug_assert_eq!(
778 i.len(),
779 in_len - header.payload_len as usize,
780 "rst_stream_frame must consume exactly payload_len bytes"
781 );
782 debug_assert_eq!(
783 data.len(),
784 RST_STREAM_PAYLOAD_SIZE as usize,
785 "RST_STREAM payload must be exactly 4 bytes"
786 );
787 let (_, error_code) = be_u32(data)?;
788 Ok((
789 i,
790 Frame::RstStream(RstStream {
791 stream_id: header.stream_id,
792 error_code,
793 }),
794 ))
795}
796
797#[derive(Clone, Debug, PartialEq)]
798pub struct Settings {
799 pub settings: Vec<Setting>,
800 pub ack: bool,
801}
802
803#[derive(Clone, Debug, PartialEq)]
804pub struct Setting {
805 pub identifier: u16,
806 pub value: u32,
807}
808
809pub const MAX_SETTINGS_ENTRIES: usize = 64;
819
820pub fn settings_frame<'a>(
821 input: &'a [u8],
822 header: &FrameHeader,
823) -> IResult<&'a [u8], Frame, ParserError<'a>> {
824 if header.payload_len / SETTINGS_ENTRY_SIZE > MAX_SETTINGS_ENTRIES as u32 {
828 return Err(Err::Failure(ParserError::new_h2(
829 input,
830 H2Error::FrameSizeError,
831 )));
832 }
833
834 let in_len = input.len();
835 let (i, data) = take(header.payload_len)(input)?;
836
837 let (_, settings) = many0(map(complete((be_u16, be_u32)), |(identifier, value)| {
838 Setting { identifier, value }
839 }))
840 .parse(data)?;
841
842 debug_assert_eq!(
846 i.len(),
847 in_len - header.payload_len as usize,
848 "settings_frame must consume exactly payload_len bytes"
849 );
850 debug_assert_eq!(
851 settings.len(),
852 header.payload_len as usize / SETTINGS_ENTRY_SIZE as usize,
853 "one SETTINGS entry decodes per 6 payload bytes"
854 );
855 debug_assert!(
856 settings.len() <= MAX_SETTINGS_ENTRIES,
857 "settings_frame must honour the MAX_SETTINGS_ENTRIES allocation cap"
858 );
859
860 Ok((
861 i,
862 Frame::Settings(Settings {
863 settings,
864 ack: header.flags & FLAG_ACK != 0,
865 }),
866 ))
867}
868
869#[derive(Clone, Debug)]
878pub struct PushPromise;
879
880pub fn push_promise_frame<'a>(
881 input: &'a [u8],
882 header: &FrameHeader,
883) -> IResult<&'a [u8], Frame, ParserError<'a>> {
884 let (_remaining, _payload) = take(header.payload_len)(input)?;
887 Err(Err::Failure(ParserError::new_h2(
888 input,
889 H2Error::ProtocolError,
890 )))
891}
892
893#[derive(Clone, Debug, PartialEq)]
894pub struct Ping {
895 pub payload: [u8; 8],
896 pub ack: bool,
897}
898
899pub fn ping_frame<'a>(
900 input: &'a [u8],
901 header: &FrameHeader,
902) -> IResult<&'a [u8], Frame, ParserError<'a>> {
903 let in_len = input.len();
907 let (i, data) = take(header.payload_len)(input)?;
908
909 debug_assert_eq!(
914 i.len(),
915 in_len - header.payload_len as usize,
916 "ping_frame must consume exactly payload_len bytes"
917 );
918 debug_assert_eq!(
919 data.len(),
920 PING_PAYLOAD_SIZE as usize,
921 "PING payload must be exactly 8 bytes for the opaque-data copy"
922 );
923
924 let mut p = Ping {
925 payload: [0; 8],
926 ack: header.flags & FLAG_ACK != 0,
927 };
928 p.payload[..8].copy_from_slice(&data[..8]);
929
930 Ok((i, Frame::Ping(p)))
931}
932
933#[derive(Clone, Debug)]
934pub struct GoAway {
935 pub last_stream_id: u32,
936 pub error_code: u32,
937 pub additional_debug_data: Slice,
938}
939
940pub fn goaway_frame<'a>(
941 input: &'a [u8],
942 header: &FrameHeader,
943) -> IResult<&'a [u8], Frame, ParserError<'a>> {
944 let in_len = input.len();
945 let (remaining, i) = take(header.payload_len)(input)?;
946 let (i, raw_last_stream_id) = be_u32(i)?;
947 let last_stream_id = raw_last_stream_id & STREAM_ID_MASK;
949 let (additional_debug_data, error_code) = be_u32(i)?;
950 debug_assert_eq!(
954 remaining.len(),
955 in_len - header.payload_len as usize,
956 "goaway_frame must consume exactly payload_len bytes"
957 );
958 debug_assert_eq!(
959 additional_debug_data.len(),
960 header.payload_len as usize - GOAWAY_PAYLOAD_SIZE as usize,
961 "GOAWAY debug data is payload_len minus the 8-byte fixed prefix"
962 );
963 debug_assert_eq!(
964 last_stream_id & !STREAM_ID_MASK,
965 0,
966 "GOAWAY last_stream_id reserved high bit must be masked"
967 );
968 Ok((
969 remaining,
970 Frame::GoAway(GoAway {
971 last_stream_id,
972 error_code,
973 additional_debug_data: Slice::new(input, additional_debug_data),
974 }),
975 ))
976}
977
978#[derive(Clone, Debug, PartialEq)]
979pub struct WindowUpdate {
980 pub stream_id: u32,
981 pub increment: u32,
982}
983
984pub fn window_update_frame<'a>(
985 input: &'a [u8],
986 header: &FrameHeader,
987) -> IResult<&'a [u8], Frame, ParserError<'a>> {
988 let in_len = input.len();
992 let (i, data) = take(header.payload_len)(input)?;
993 debug_assert_eq!(
996 i.len(),
997 in_len - header.payload_len as usize,
998 "window_update_frame must consume exactly payload_len bytes"
999 );
1000 debug_assert_eq!(
1001 data.len(),
1002 WINDOW_UPDATE_PAYLOAD_SIZE as usize,
1003 "WINDOW_UPDATE payload must be exactly 4 bytes"
1004 );
1005 let (_, increment) = be_u32(data)?;
1006 let increment = increment & STREAM_ID_MASK;
1007 debug_assert!(
1009 increment <= STREAM_ID_MASK,
1010 "window-size increment must be a 31-bit value"
1011 );
1012
1013 Ok((
1021 i,
1022 Frame::WindowUpdate(WindowUpdate {
1023 stream_id: header.stream_id,
1024 increment,
1025 }),
1026 ))
1027}
1028
1029#[derive(Clone, Debug)]
1037pub struct Continuation;
1038
1039pub fn continuation_frame<'a>(
1040 input: &'a [u8],
1041 header: &FrameHeader,
1042) -> IResult<&'a [u8], Frame, ParserError<'a>> {
1043 let in_len = input.len();
1045 let (remaining, _) = take(header.payload_len)(input)?;
1046 debug_assert_eq!(
1047 remaining.len(),
1048 in_len - header.payload_len as usize,
1049 "continuation_frame must consume exactly payload_len bytes"
1050 );
1051 Ok((remaining, Frame::Continuation(Continuation)))
1052}
1053
1054pub fn unknown_frame<'a>(
1059 input: &'a [u8],
1060 header: &FrameHeader,
1061) -> IResult<&'a [u8], Frame, ParserError<'a>> {
1062 let in_len = input.len();
1063 let (remaining, _payload) = take(header.payload_len)(input)?;
1064 debug_assert_eq!(
1065 remaining.len(),
1066 in_len - header.payload_len as usize,
1067 "unknown_frame must consume exactly payload_len bytes"
1068 );
1069 let raw = match header.frame_type {
1070 FrameType::Unknown(t) => t,
1071 _ => 0,
1072 };
1073 Ok((remaining, Frame::Unknown(raw)))
1074}
1075
1076pub fn priority_update_frame<'a>(
1093 input: &'a [u8],
1094 header: &FrameHeader,
1095) -> IResult<&'a [u8], Frame, ParserError<'a>> {
1096 if header.payload_len < PRIORITY_UPDATE_MIN_PAYLOAD {
1097 return Err(Err::Failure(ParserError::new_h2(
1098 input,
1099 H2Error::FrameSizeError,
1100 )));
1101 }
1102 let value_len = (header.payload_len - PRIORITY_UPDATE_MIN_PAYLOAD) as usize;
1111 if value_len > PRIORITY_UPDATE_MAX_VALUE {
1112 return Err(Err::Failure(ParserError::new_h2(
1113 input,
1114 H2Error::ProtocolError,
1115 )));
1116 }
1117 let in_len = input.len();
1118 let (remaining, payload) = take(header.payload_len)(input)?;
1119 let (raw_id_bytes, value_bytes) = payload.split_at(PRIORITY_UPDATE_MIN_PAYLOAD as usize);
1120 debug_assert_eq!(
1124 remaining.len(),
1125 in_len - header.payload_len as usize,
1126 "priority_update_frame must consume exactly payload_len bytes"
1127 );
1128 debug_assert_eq!(
1129 raw_id_bytes.len(),
1130 PRIORITY_UPDATE_MIN_PAYLOAD as usize,
1131 "PRIORITY_UPDATE stream-id prefix must be exactly 4 bytes"
1132 );
1133 debug_assert!(
1134 value_bytes.len() <= PRIORITY_UPDATE_MAX_VALUE,
1135 "priority field value must respect the PRIORITY_UPDATE_MAX_VALUE cap"
1136 );
1137 let prioritized_stream_id = u32::from_be_bytes([
1138 raw_id_bytes[0],
1139 raw_id_bytes[1],
1140 raw_id_bytes[2],
1141 raw_id_bytes[3],
1142 ]) & STREAM_ID_MASK;
1143 debug_assert_eq!(
1144 prioritized_stream_id & !STREAM_ID_MASK,
1145 0,
1146 "prioritized_stream_id reserved high bit must be masked"
1147 );
1148 Ok((
1149 remaining,
1150 Frame::PriorityUpdate(PriorityUpdate {
1151 prioritized_stream_id,
1152 priority_field_value: value_bytes.to_vec(),
1153 }),
1154 ))
1155}
1156
1157pub const PRIORITY_UPDATE_MIN_PAYLOAD: u32 = 4;
1161
1162pub const PRIORITY_UPDATE_MAX_VALUE: usize = 1024;
1170
1171#[cfg(test)]
1172mod tests {
1173 use super::*;
1174
1175 const DEFAULT_MAX_FRAME_SIZE: u32 = 1 << 14;
1177
1178 #[test]
1184 fn test_settings_ack_with_payload_rejected() {
1185 let input = [
1187 0x00, 0x00, 0x06, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64,
1193 ];
1194
1195 let (remaining, header) =
1196 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1197 assert_eq!(header.frame_type, FrameType::Settings);
1198 assert_eq!(header.flags & FLAG_ACK, FLAG_ACK);
1199 assert_eq!(header.payload_len, 6);
1200
1201 let result = frame_body(remaining, &header);
1202 assert!(
1203 result.is_err(),
1204 "SETTINGS ACK with non-empty payload must be rejected"
1205 );
1206 match result {
1207 Err(nom::Err::Failure(e)) => {
1208 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1209 }
1210 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1211 }
1212 }
1213
1214 #[test]
1220 fn test_settings_ack_empty_accepted() {
1221 let input = [
1222 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, ];
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::Settings);
1231 assert_eq!(header.flags & FLAG_ACK, FLAG_ACK);
1232
1233 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
1234 match frame {
1235 Frame::Settings(settings) => {
1236 assert!(settings.ack, "ACK flag must be set");
1237 assert!(
1238 settings.settings.is_empty(),
1239 "should have no settings entries"
1240 );
1241 }
1242 other => panic!("expected Frame::Settings, got {other:?}"),
1243 }
1244 }
1245
1246 #[test]
1251 fn test_window_update_max_increment() {
1252 let input = [
1253 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFF, ];
1259
1260 let (remaining, header) =
1261 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1262 assert_eq!(header.frame_type, FrameType::WindowUpdate);
1263 assert_eq!(header.stream_id, 1);
1264
1265 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
1266 match frame {
1267 Frame::WindowUpdate(wu) => {
1268 assert_eq!(wu.increment, 0x7FFFFFFF);
1269 assert_eq!(wu.stream_id, 1);
1270 }
1271 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1272 }
1273 }
1274
1275 #[test]
1281 fn test_window_update_zero_increment_parsed() {
1282 let input = [
1284 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
1290
1291 let (remaining, header) =
1292 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1293 assert_eq!(header.frame_type, FrameType::WindowUpdate);
1294
1295 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
1296 match frame {
1297 Frame::WindowUpdate(wu) => {
1298 assert_eq!(wu.stream_id, 0);
1299 assert_eq!(wu.increment, 0);
1300 }
1301 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1302 }
1303
1304 let input2 = [
1306 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, ];
1312
1313 let (remaining2, header2) =
1314 frame_header(&input2, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1315 let (_, frame2) =
1316 frame_body(remaining2, &header2).expect("second frame body parses cleanly");
1317 match frame2 {
1318 Frame::WindowUpdate(wu) => {
1319 assert_eq!(wu.stream_id, 3);
1320 assert_eq!(wu.increment, 0);
1321 }
1322 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1323 }
1324 }
1325
1326 #[test]
1334 fn test_unknown_frame_type_is_ignored() {
1335 let input = [
1336 0x00, 0x00, 0x04, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef, ];
1342
1343 let (remaining, header) = frame_header(&input, DEFAULT_MAX_FRAME_SIZE)
1344 .expect("unknown frame header must parse cleanly");
1345 assert!(matches!(header.frame_type, FrameType::Unknown(0xFF)));
1346 assert_eq!(header.payload_len, 4);
1347
1348 let (after, frame) =
1349 frame_body(remaining, &header).expect("unknown frame body must be consumed");
1350 assert!(after.is_empty(), "payload bytes must be consumed");
1351 match frame {
1352 Frame::Unknown(0xFF) => {}
1353 other => panic!("expected Frame::Unknown(0xFF), got {other:?}"),
1354 }
1355 }
1356
1357 #[test]
1362 fn test_priority_update_empty_field_parses() {
1363 let input = [
1364 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1370 ];
1371
1372 let (remaining, header) = frame_header(&input, DEFAULT_MAX_FRAME_SIZE)
1373 .expect("PRIORITY_UPDATE header must parse");
1374 assert!(matches!(header.frame_type, FrameType::PriorityUpdate));
1375 let (_, frame) = frame_body(remaining, &header).expect("body must be consumed");
1376 match frame {
1377 Frame::PriorityUpdate(PriorityUpdate {
1378 prioritized_stream_id,
1379 ref priority_field_value,
1380 }) => {
1381 assert_eq!(prioritized_stream_id, 1);
1382 assert!(priority_field_value.is_empty());
1383 }
1384 other => panic!("expected Frame::PriorityUpdate, got {other:?}"),
1385 }
1386 }
1387
1388 #[test]
1392 fn test_priority_update_with_priority_field_parses() {
1393 let value = b"u=0, i";
1394 let mut input = vec![
1395 0x00,
1396 0x00,
1397 0x04 + value.len() as u8, 0x10, 0x00, 0x00,
1401 0x00,
1402 0x00,
1403 0x00, 0x00,
1405 0x00,
1406 0x00,
1407 0x05, ];
1409 input.extend_from_slice(value);
1410
1411 let (remaining, header) =
1412 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("header parses");
1413 assert!(matches!(header.frame_type, FrameType::PriorityUpdate));
1414 let (_, frame) = frame_body(remaining, &header).expect("body parses");
1415 match frame {
1416 Frame::PriorityUpdate(PriorityUpdate {
1417 prioritized_stream_id,
1418 ref priority_field_value,
1419 }) => {
1420 assert_eq!(prioritized_stream_id, 5);
1421 assert_eq!(priority_field_value.as_slice(), value);
1422 }
1423 other => panic!("expected Frame::PriorityUpdate, got {other:?}"),
1424 }
1425 }
1426
1427 #[test]
1430 fn test_priority_update_payload_below_min_is_frame_size_error() {
1431 let input = [
1432 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1434 ];
1435 let (remaining, header) =
1436 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("header parses");
1437 let result = frame_body(remaining, &header);
1438 match result {
1439 Err(Err::Failure(e)) => {
1440 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1441 }
1442 other => panic!("expected FRAME_SIZE_ERROR, got {other:?}"),
1443 }
1444 }
1445
1446 #[test]
1452 fn test_priority_update_oversized_value_is_protocol_error() {
1453 let payload_len = (PRIORITY_UPDATE_MIN_PAYLOAD as usize) + PRIORITY_UPDATE_MAX_VALUE + 1;
1455 let mut input = Vec::with_capacity(9 + payload_len);
1456 input.push(((payload_len >> 16) & 0xff) as u8);
1458 input.push(((payload_len >> 8) & 0xff) as u8);
1459 input.push((payload_len & 0xff) as u8);
1460 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));
1465 let (remaining, header) =
1468 frame_header(&input, payload_len as u32 + 1).expect("header parses");
1469 match frame_body(remaining, &header) {
1470 Err(Err::Failure(e)) => {
1471 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1472 }
1473 other => {
1474 panic!("expected PROTOCOL_ERROR for oversized PRIORITY_UPDATE value, got {other:?}")
1475 }
1476 }
1477 }
1478
1479 #[test]
1482 fn test_priority_update_at_max_value_accepted() {
1483 let payload_len = (PRIORITY_UPDATE_MIN_PAYLOAD as usize) + PRIORITY_UPDATE_MAX_VALUE;
1484 let mut input = Vec::with_capacity(9 + payload_len);
1485 input.push(((payload_len >> 16) & 0xff) as u8);
1486 input.push(((payload_len >> 8) & 0xff) as u8);
1487 input.push((payload_len & 0xff) as u8);
1488 input.push(0x10);
1489 input.push(0x00);
1490 input.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]);
1491 input.extend_from_slice(&[0x00, 0x00, 0x00, 0x01]);
1492 input.extend(std::iter::repeat_n(b'a', PRIORITY_UPDATE_MAX_VALUE));
1493 let (remaining, header) =
1494 frame_header(&input, payload_len as u32 + 1).expect("header parses");
1495 match frame_body(remaining, &header) {
1496 Ok((_, Frame::PriorityUpdate(pu))) => {
1497 assert_eq!(pu.priority_field_value.len(), PRIORITY_UPDATE_MAX_VALUE);
1498 }
1499 other => panic!("expected Frame::PriorityUpdate at the cap boundary, got {other:?}"),
1500 }
1501 }
1502
1503 #[test]
1508 fn test_priority_update_on_non_zero_stream_is_protocol_error() {
1509 let input = [
1510 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, ];
1516 match frame_header(&input, DEFAULT_MAX_FRAME_SIZE) {
1517 Err(Err::Failure(e)) => {
1518 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1519 }
1520 other => panic!("expected PROTOCOL_ERROR, got {other:?}"),
1521 }
1522 }
1523
1524 #[test]
1529 fn test_settings_payload_not_multiple_of_6_rejected() {
1530 let input = [
1531 0x00, 0x00, 0x05, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, ];
1537
1538 let (remaining, header) =
1539 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1540 assert_eq!(header.frame_type, FrameType::Settings);
1541
1542 let result = frame_body(remaining, &header);
1543 assert!(
1544 result.is_err(),
1545 "odd-size SETTINGS payload must be rejected"
1546 );
1547 match result {
1548 Err(nom::Err::Failure(e)) => {
1549 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1550 }
1551 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1552 }
1553 }
1554
1555 #[test]
1560 fn test_settings_frame_over_cap_rejected() {
1561 let n_entries: u16 = (MAX_SETTINGS_ENTRIES as u16) + 1;
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..]); input.push(0x04); input.push(0x00); input.extend_from_slice(&[0, 0, 0, 0]); for i in 0..n_entries {
1570 input.extend_from_slice(&i.to_be_bytes()); input.extend_from_slice(&0u32.to_be_bytes()); }
1573
1574 let (remaining, header) =
1575 frame_header(&input, 16_777_215).expect("frame header parses cleanly");
1576 assert_eq!(header.frame_type, FrameType::Settings);
1577
1578 let result = frame_body(remaining, &header);
1579 assert!(
1580 result.is_err(),
1581 "SETTINGS frame over MAX_SETTINGS_ENTRIES must be rejected"
1582 );
1583 match result {
1584 Err(nom::Err::Failure(e)) => {
1585 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1586 }
1587 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1588 }
1589 }
1590
1591 #[test]
1593 fn test_settings_frame_at_cap_accepted() {
1594 let n_entries: u16 = MAX_SETTINGS_ENTRIES as u16;
1595 let payload_len = u32::from(n_entries) * SETTINGS_ENTRY_SIZE;
1596 let mut input = Vec::with_capacity(9 + payload_len as usize);
1597 input.extend_from_slice(&payload_len.to_be_bytes()[1..]);
1598 input.push(0x04);
1599 input.push(0x00);
1600 input.extend_from_slice(&[0, 0, 0, 0]);
1601 for _ in 0..n_entries {
1602 input.extend_from_slice(&0u16.to_be_bytes());
1603 input.extend_from_slice(&0u32.to_be_bytes());
1604 }
1605
1606 let (remaining, header) =
1607 frame_header(&input, 16_777_215).expect("frame header parses cleanly");
1608 let result = frame_body(remaining, &header);
1609 assert!(result.is_ok(), "exactly MAX_SETTINGS_ENTRIES must parse");
1610 }
1611
1612 #[test]
1616 fn test_rst_stream_wrong_payload_size_rejected() {
1617 let input = [
1619 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
1625
1626 let (remaining, header) =
1627 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1628 assert_eq!(header.frame_type, FrameType::RstStream);
1629
1630 let result = frame_body(remaining, &header);
1631 assert!(
1632 result.is_err(),
1633 "wrong RST_STREAM payload size must be rejected"
1634 );
1635 match result {
1636 Err(nom::Err::Failure(e)) => {
1637 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1638 }
1639 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1640 }
1641 }
1642
1643 #[test]
1647 fn test_ping_wrong_payload_size_rejected() {
1648 let input = [
1649 0x00, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, ];
1655
1656 let (remaining, header) =
1657 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1658 assert_eq!(header.frame_type, FrameType::Ping);
1659
1660 let result = frame_body(remaining, &header);
1661 assert!(result.is_err(), "wrong PING payload size must be rejected");
1662 match result {
1663 Err(nom::Err::Failure(e)) => {
1664 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1665 }
1666 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1667 }
1668 }
1669
1670 #[test]
1675 fn test_frame_exceeding_max_frame_size_rejected() {
1676 let input = [
1678 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, ];
1683
1684 let result = frame_header(&input, DEFAULT_MAX_FRAME_SIZE);
1685 assert!(result.is_err(), "oversized frame must be rejected");
1686 match result {
1687 Err(nom::Err::Failure(e)) => {
1688 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1689 }
1690 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1691 }
1692 }
1693
1694 #[test]
1698 fn test_settings_on_nonzero_stream_rejected() {
1699 let input = [
1700 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, ];
1705
1706 let result = frame_header(&input, DEFAULT_MAX_FRAME_SIZE);
1707 assert!(
1708 result.is_err(),
1709 "SETTINGS on non-zero stream must be rejected"
1710 );
1711 match result {
1712 Err(nom::Err::Failure(e)) => {
1713 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1714 }
1715 other => panic!("expected Failure(ProtocolError), got {other:?}"),
1716 }
1717 }
1718
1719 #[test]
1723 fn test_data_on_stream_zero_rejected() {
1724 let input = [
1725 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCA, 0xFE,
1730 ];
1731
1732 let result = frame_header(&input, DEFAULT_MAX_FRAME_SIZE);
1733 assert!(result.is_err(), "DATA on stream 0 must be rejected");
1734 match result {
1735 Err(nom::Err::Failure(e)) => {
1736 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1737 }
1738 other => panic!("expected Failure(ProtocolError), got {other:?}"),
1739 }
1740 }
1741
1742 #[test]
1747 fn test_window_update_reserved_bit_masked() {
1748 let input = [
1749 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, ];
1755
1756 let (remaining, header) =
1757 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1758 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
1759 match frame {
1760 Frame::WindowUpdate(wu) => {
1761 assert_eq!(
1762 wu.increment, 1,
1763 "reserved bit must be masked to yield increment=1"
1764 );
1765 }
1766 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1767 }
1768 }
1769
1770 fn build_frame_header(payload_len: u32, frame_type: u8, flags: u8, stream_id: u32) -> Vec<u8> {
1774 vec![
1775 ((payload_len >> 16) & 0xFF) as u8,
1776 ((payload_len >> 8) & 0xFF) as u8,
1777 (payload_len & 0xFF) as u8,
1778 frame_type,
1779 flags,
1780 ((stream_id >> 24) & 0xFF) as u8,
1781 ((stream_id >> 16) & 0xFF) as u8,
1782 ((stream_id >> 8) & 0xFF) as u8,
1783 (stream_id & 0xFF) as u8,
1784 ]
1785 }
1786
1787 fn build_raw_frame(
1789 payload_len: u32,
1790 frame_type: u8,
1791 flags: u8,
1792 stream_id: u32,
1793 payload: &[u8],
1794 ) -> Vec<u8> {
1795 let mut raw = build_frame_header(payload_len, frame_type, flags, stream_id);
1796 raw.extend_from_slice(payload);
1797 raw
1798 }
1799
1800 #[test]
1803 fn test_preface_valid() {
1804 let input = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
1805 let (remaining, matched) = preface(input).expect("should parse preface");
1806 assert!(remaining.is_empty());
1807 assert_eq!(matched, input.as_slice());
1808 }
1809
1810 #[test]
1811 fn test_preface_invalid() {
1812 let input = b"GET / HTTP/1.1\r\n";
1813 let result = preface(input);
1814 assert!(result.is_err(), "invalid preface should fail");
1815 }
1816
1817 #[test]
1818 fn test_preface_with_trailing_data() {
1819 let mut input = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".to_vec();
1820 input.extend_from_slice(b"extra stuff");
1821 let (remaining, _) = preface(&input).expect("should parse preface");
1822 assert_eq!(remaining, b"extra stuff");
1823 }
1824
1825 #[test]
1828 fn test_frame_header_settings_basic() {
1829 let raw = build_frame_header(0, 4, 0, 0);
1830 let (remaining, header) =
1831 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1832 assert!(remaining.is_empty());
1833 assert_eq!(header.payload_len, 0);
1834 assert_eq!(header.frame_type, FrameType::Settings);
1835 assert_eq!(header.flags, 0);
1836 assert_eq!(header.stream_id, 0);
1837 }
1838
1839 #[test]
1840 fn test_frame_header_data_basic() {
1841 let raw = build_frame_header(100, 0, 1, 1);
1842 let (_, header) =
1843 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1844 assert_eq!(header.payload_len, 100);
1845 assert_eq!(header.frame_type, FrameType::Data);
1846 assert_eq!(header.flags, 1);
1847 assert_eq!(header.stream_id, 1);
1848 }
1849
1850 #[test]
1851 fn test_frame_header_stream_id_reserved_bit_masked() {
1852 let raw = build_frame_header(5, 0, 0, 0x80000001);
1855 let (_, header) =
1856 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1857 assert_eq!(header.stream_id, 1, "reserved MSB must be masked off");
1858 }
1859
1860 #[test]
1863 fn test_parse_data_frame_end_stream() {
1864 let payload = b"hello";
1865 let raw = build_raw_frame(payload.len() as u32, 0, 0x01, 1, payload);
1866 let (remaining, header) =
1867 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1868 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1869 match f {
1870 Frame::Data(d) => {
1871 assert_eq!(d.stream_id, 1);
1872 assert!(d.end_stream);
1873 }
1874 other => panic!("expected Data, got {other:?}"),
1875 }
1876 }
1877
1878 #[test]
1879 fn test_parse_data_frame_no_end_stream() {
1880 let payload = b"data";
1881 let raw = build_raw_frame(payload.len() as u32, 0, 0x00, 3, payload);
1882 let (remaining, header) =
1883 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1884 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1885 match f {
1886 Frame::Data(d) => {
1887 assert_eq!(d.stream_id, 3);
1888 assert!(!d.end_stream);
1889 }
1890 other => panic!("expected Data, got {other:?}"),
1891 }
1892 }
1893
1894 #[test]
1895 fn test_parse_data_frame_with_padding() {
1896 let pad_length: u8 = 2;
1898 let actual_data = b"hello";
1899 let total_payload = 1 + actual_data.len() + pad_length as usize;
1900 let mut payload = Vec::new();
1901 payload.push(pad_length);
1902 payload.extend_from_slice(actual_data);
1903 payload.extend_from_slice(&[0x00; 2]);
1904
1905 let raw = build_raw_frame(total_payload as u32, 0, 0x08, 1, &payload);
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::Data(d) => {
1911 assert_eq!(d.stream_id, 1);
1912 assert_eq!(d.payload.len, actual_data.len() as u32);
1913 }
1914 other => panic!("expected Data, got {other:?}"),
1915 }
1916 }
1917
1918 #[test]
1919 fn test_parse_data_frame_padding_exceeds_payload() {
1920 let mut payload = Vec::new();
1922 payload.push(10); payload.extend_from_slice(b"hello");
1924
1925 let raw = build_raw_frame(payload.len() as u32, 0, 0x08, 1, &payload);
1926 let (remaining, header) =
1927 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1928 let result = frame_body(remaining, &header);
1929 assert!(
1930 result.is_err(),
1931 "padding exceeding payload should be a protocol error"
1932 );
1933 }
1934
1935 #[test]
1938 fn test_parse_headers_frame_basic() {
1939 let hblock = b"\x82\x86";
1940 let raw = build_raw_frame(hblock.len() as u32, 1, 0x04, 1, hblock);
1941 let (remaining, header) =
1942 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1943 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1944 match f {
1945 Frame::Headers(h) => {
1946 assert_eq!(h.stream_id, 1);
1947 assert!(!h.end_stream);
1948 assert!(h.end_headers);
1949 assert!(h.priority.is_none());
1950 }
1951 other => panic!("expected Headers, got {other:?}"),
1952 }
1953 }
1954
1955 #[test]
1956 fn test_parse_headers_frame_end_stream_and_headers() {
1957 let hblock = b"\x82";
1958 let raw = build_raw_frame(hblock.len() as u32, 1, 0x05, 1, hblock);
1959 let (remaining, header) =
1960 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1961 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1962 match f {
1963 Frame::Headers(h) => {
1964 assert!(h.end_stream);
1965 assert!(h.end_headers);
1966 }
1967 other => panic!("expected Headers, got {other:?}"),
1968 }
1969 }
1970
1971 #[test]
1972 fn test_parse_headers_frame_with_priority() {
1973 let hblock = b"\x82";
1974 let payload_len = 5 + hblock.len(); let mut payload = Vec::new();
1976 payload.extend_from_slice(&[0x00, 0x00, 0x00, 0x01]);
1978 payload.push(15); payload.extend_from_slice(hblock);
1980
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 assert_eq!(h.stream_id, 3);
1988 let priority = h.priority.expect("should have priority");
1989 match priority {
1990 PriorityPart::Rfc7540 {
1991 stream_dependency,
1992 weight,
1993 } => {
1994 assert!(!stream_dependency.exclusive);
1995 assert_eq!(stream_dependency.stream_id, 1);
1996 assert_eq!(weight, 15);
1997 }
1998 other => panic!("expected Rfc7540, got {other:?}"),
1999 }
2000 }
2001 other => panic!("expected Headers, got {other:?}"),
2002 }
2003 }
2004
2005 #[test]
2006 fn test_parse_headers_frame_with_exclusive_priority() {
2007 let hblock = b"\x82\x86";
2008 let mut payload = Vec::new();
2009 let dep = 0x80000005u32;
2011 payload.extend_from_slice(&dep.to_be_bytes());
2012 payload.push(255); payload.extend_from_slice(hblock);
2014
2015 let payload_len = payload.len();
2016 let raw = build_raw_frame(payload_len as u32, 1, 0x24, 3, &payload);
2017 let (remaining, header) =
2018 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2019 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2020 match f {
2021 Frame::Headers(h) => {
2022 let priority = h.priority.expect("should have priority");
2023 match priority {
2024 PriorityPart::Rfc7540 {
2025 stream_dependency,
2026 weight,
2027 } => {
2028 assert!(stream_dependency.exclusive, "exclusive bit should be set");
2029 assert_eq!(stream_dependency.stream_id, 5);
2030 assert_eq!(weight, 255);
2031 }
2032 other => panic!("expected Rfc7540, got {other:?}"),
2033 }
2034 }
2035 other => panic!("expected Headers, got {other:?}"),
2036 }
2037 }
2038
2039 #[test]
2040 fn test_parse_headers_stream_id_zero_rejected() {
2041 let raw = build_raw_frame(2, 1, 0x04, 0, b"\x82\x86");
2042 let result = frame_header(&raw, DEFAULT_MAX_FRAME_SIZE);
2043 assert!(
2044 result.is_err(),
2045 "HEADERS with stream_id=0 should be rejected"
2046 );
2047 }
2048
2049 #[test]
2052 fn test_parse_rst_stream() {
2053 let error_code = 0x00000008u32; let raw = build_raw_frame(4, 3, 0, 1, &error_code.to_be_bytes());
2055 let (remaining, header) =
2056 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2057 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2058 match f {
2059 Frame::RstStream(rst) => {
2060 assert_eq!(rst.stream_id, 1);
2061 assert_eq!(rst.error_code, 0x08);
2062 }
2063 other => panic!("expected RstStream, got {other:?}"),
2064 }
2065 }
2066
2067 #[test]
2068 fn test_parse_rst_stream_stream_id_zero_rejected() {
2069 let raw = build_raw_frame(4, 3, 0, 0, &[0u8; 4]);
2070 let result = frame_header(&raw, DEFAULT_MAX_FRAME_SIZE);
2071 assert!(
2072 result.is_err(),
2073 "RST_STREAM with stream_id=0 should be rejected"
2074 );
2075 }
2076
2077 #[test]
2080 fn test_parse_settings_frame_with_values() {
2081 let mut payload = Vec::new();
2082 payload.extend_from_slice(&0x0001u16.to_be_bytes());
2084 payload.extend_from_slice(&4096u32.to_be_bytes());
2085 payload.extend_from_slice(&0x0003u16.to_be_bytes());
2087 payload.extend_from_slice(&100u32.to_be_bytes());
2088 payload.extend_from_slice(&0x0004u16.to_be_bytes());
2090 payload.extend_from_slice(&65535u32.to_be_bytes());
2091
2092 let raw = build_raw_frame(payload.len() as u32, 4, 0x0, 0, &payload);
2093 let (remaining, header) =
2094 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2095 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2096 match f {
2097 Frame::Settings(s) => {
2098 assert!(!s.ack);
2099 assert_eq!(s.settings.len(), 3);
2100 assert_eq!(s.settings[0].identifier, 0x0001);
2101 assert_eq!(s.settings[0].value, 4096);
2102 assert_eq!(s.settings[1].identifier, 0x0003);
2103 assert_eq!(s.settings[1].value, 100);
2104 assert_eq!(s.settings[2].identifier, 0x0004);
2105 assert_eq!(s.settings[2].value, 65535);
2106 }
2107 other => panic!("expected Settings, got {other:?}"),
2108 }
2109 }
2110
2111 #[test]
2114 fn test_parse_ping_frame() {
2115 let ping_payload = [1u8, 2, 3, 4, 5, 6, 7, 8];
2116 let raw = build_raw_frame(8, 6, 0, 0, &ping_payload);
2117 let (remaining, header) =
2118 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2119 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2120 match f {
2121 Frame::Ping(p) => {
2122 assert_eq!(p.payload, ping_payload);
2123 assert!(!p.ack);
2124 }
2125 other => panic!("expected Ping, got {other:?}"),
2126 }
2127 }
2128
2129 #[test]
2130 fn test_parse_ping_ack_preserves_payload() {
2131 let ping_payload = [0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE];
2132 let raw = build_raw_frame(8, 6, 0x01, 0, &ping_payload);
2133 let (remaining, header) =
2134 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2135 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2136 match f {
2137 Frame::Ping(p) => {
2138 assert_eq!(
2139 p.payload, ping_payload,
2140 "PING ACK must echo the exact payload"
2141 );
2142 assert!(p.ack);
2143 }
2144 other => panic!("expected Ping, got {other:?}"),
2145 }
2146 }
2147
2148 #[test]
2149 fn test_parse_ping_stream_id_nonzero_rejected() {
2150 let raw = build_raw_frame(8, 6, 0, 1, &[0u8; 8]);
2151 let result = frame_header(&raw, DEFAULT_MAX_FRAME_SIZE);
2152 assert!(result.is_err(), "PING with stream_id!=0 should be rejected");
2153 }
2154
2155 #[test]
2158 fn test_parse_window_update_connection_level() {
2159 let increment = 1000u32;
2160 let raw = build_raw_frame(4, 8, 0, 0, &increment.to_be_bytes());
2161 let (remaining, header) =
2162 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2163 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2164 match f {
2165 Frame::WindowUpdate(w) => {
2166 assert_eq!(w.stream_id, 0);
2167 assert_eq!(w.increment, 1000);
2168 }
2169 other => panic!("expected WindowUpdate, got {other:?}"),
2170 }
2171 }
2172
2173 #[test]
2174 fn test_parse_window_update_stream_level() {
2175 let increment = 65535u32;
2176 let raw = build_raw_frame(4, 8, 0, 5, &increment.to_be_bytes());
2177 let (remaining, header) =
2178 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2179 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2180 match f {
2181 Frame::WindowUpdate(w) => {
2182 assert_eq!(w.stream_id, 5);
2183 assert_eq!(w.increment, 65535);
2185 }
2186 other => panic!("expected WindowUpdate, got {other:?}"),
2187 }
2188 }
2189
2190 #[test]
2191 fn test_parse_window_update_wrong_size() {
2192 let raw = build_raw_frame(3, 8, 0, 0, &[0u8; 3]);
2193 let (remaining, header) =
2194 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2195 let result = frame_body(remaining, &header);
2196 assert!(
2197 result.is_err(),
2198 "WINDOW_UPDATE with payload != 4 should fail"
2199 );
2200 match result {
2201 Err(Err::Failure(e)) => {
2202 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
2203 }
2204 other => panic!("expected FrameSizeError, got {other:?}"),
2205 }
2206 }
2207
2208 #[test]
2211 fn test_parse_frame_at_max_frame_size() {
2212 let payload = vec![0u8; DEFAULT_MAX_FRAME_SIZE as usize];
2213 let raw = build_raw_frame(DEFAULT_MAX_FRAME_SIZE, 0, 0x0, 1, &payload);
2214 let (remaining, header) =
2215 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2216 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2217 match f {
2218 Frame::Data(d) => {
2219 assert_eq!(d.payload.len, DEFAULT_MAX_FRAME_SIZE);
2220 }
2221 other => panic!("expected Data, got {other:?}"),
2222 }
2223 }
2224
2225 #[test]
2226 fn test_parse_frame_with_custom_max_frame_size() {
2227 let custom_max = 32768u32;
2228 let payload = vec![0u8; 20000];
2229 let raw = build_raw_frame(20000, 0, 0x0, 1, &payload);
2230 let (remaining, header) =
2231 frame_header(&raw, custom_max).expect("frame header parses with custom max");
2232 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2233 match f {
2234 Frame::Data(d) => {
2235 assert_eq!(d.payload.len, 20000);
2236 }
2237 other => panic!("expected Data, got {other:?}"),
2238 }
2239 }
2240
2241 #[test]
2244 fn test_h2_error_try_from_valid() {
2245 assert_eq!(H2Error::try_from(0x0), Ok(H2Error::NoError));
2246 assert_eq!(H2Error::try_from(0x1), Ok(H2Error::ProtocolError));
2247 assert_eq!(H2Error::try_from(0x6), Ok(H2Error::FrameSizeError));
2248 assert_eq!(H2Error::try_from(0xd), Ok(H2Error::HTTP11Required));
2249 }
2250
2251 #[test]
2252 fn test_h2_error_try_from_invalid() {
2253 assert_eq!(H2Error::try_from(0x0e), Err(0x0e));
2254 assert_eq!(H2Error::try_from(0xFF), Err(0xFF));
2255 }
2256
2257 #[test]
2258 fn test_h2_error_from_str() {
2259 assert_eq!("NO_ERROR".parse::<H2Error>(), Ok(H2Error::NoError));
2260 assert_eq!(
2261 "PROTOCOL_ERROR".parse::<H2Error>(),
2262 Ok(H2Error::ProtocolError)
2263 );
2264 assert_eq!(
2265 "ENHANCE_YOUR_CALM".parse::<H2Error>(),
2266 Ok(H2Error::EnhanceYourCalm)
2267 );
2268 assert!("INVALID_ERROR".parse::<H2Error>().is_err());
2269 }
2270
2271 #[test]
2272 fn test_h2_error_as_str_roundtrip() {
2273 let errors = [
2274 H2Error::NoError,
2275 H2Error::ProtocolError,
2276 H2Error::InternalError,
2277 H2Error::FlowControlError,
2278 H2Error::SettingsTimeout,
2279 H2Error::StreamClosed,
2280 H2Error::FrameSizeError,
2281 H2Error::RefusedStream,
2282 H2Error::Cancel,
2283 H2Error::CompressionError,
2284 H2Error::ConnectError,
2285 H2Error::EnhanceYourCalm,
2286 H2Error::InadequateSecurity,
2287 H2Error::HTTP11Required,
2288 ];
2289
2290 for error in &errors {
2291 let s = error.as_str();
2292 let parsed: H2Error = s.parse().unwrap_or_else(|_| panic!("failed to parse {s}"));
2293 assert_eq!(*error, parsed, "roundtrip failed for {s}");
2294 }
2295 }
2296
2297 #[test]
2300 fn test_parse_priority_frame() {
2301 let mut payload = Vec::new();
2302 payload.extend_from_slice(&0x00000001u32.to_be_bytes());
2304 payload.push(15); assert_eq!(payload.len(), 5);
2306
2307 let raw = build_raw_frame(5, 2, 0, 3, &payload);
2308 let (remaining, header) =
2309 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2310 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2311 match f {
2312 Frame::Priority(p) => {
2313 assert_eq!(p.stream_id, 3);
2314 match p.inner {
2315 PriorityPart::Rfc7540 {
2316 stream_dependency,
2317 weight,
2318 } => {
2319 assert!(!stream_dependency.exclusive);
2320 assert_eq!(stream_dependency.stream_id, 1);
2321 assert_eq!(weight, 15);
2322 }
2323 other => panic!("expected Rfc7540, got {other:?}"),
2324 }
2325 }
2326 other => panic!("expected Priority, got {other:?}"),
2327 }
2328 }
2329
2330 #[test]
2331 fn test_parse_priority_wrong_size_rejected() {
2332 let raw = build_raw_frame(4, 2, 0, 1, &[0u8; 4]);
2333 let (remaining, header) =
2334 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2335 let result = frame_body(remaining, &header);
2336 assert!(
2337 result.is_err(),
2338 "PRIORITY with wrong payload size should fail"
2339 );
2340 }
2341
2342 #[test]
2349 fn test_headers_padded_priority_underflow_rejected() {
2350 let raw: [u8; 16] = [
2351 0x00, 0x00, 0x06, 0x01, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x00, 0x64, 0x6d, 0x6d,
2352 0x6d, 0x6d,
2353 ];
2354 let (remaining, header) =
2355 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2356 let result = frame_body(remaining, &header);
2357 assert!(
2358 result.is_err(),
2359 "PADDED+PRIORITY HEADERS with oversized pad_length must error, not panic"
2360 );
2361 }
2362
2363 #[test]
2371 fn test_strip_padding_all_padding_accepted() {
2372 let input = [
2376 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, ];
2383
2384 let (remaining, header) =
2385 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2386 let (_, frame) =
2387 frame_body(remaining, &header).expect("DATA with all-padding body must parse");
2388 match frame {
2389 Frame::Data(data) => {
2390 assert_eq!(data.stream_id, 1);
2391 assert_eq!(data.payload.len, 0);
2393 }
2394 other => panic!("expected Frame::Data, got {other:?}"),
2395 }
2396 }
2397
2398 #[test]
2399 fn test_strip_padding_pad_length_equals_payload_len_rejected() {
2400 let input = [
2404 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x01, ];
2410
2411 let (remaining, header) =
2412 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2413 let result = frame_body(remaining, &header);
2414 assert!(
2415 matches!(
2416 result,
2417 Err(nom::Err::Failure(ParserError {
2418 kind: ParserErrorKind::H2(H2Error::ProtocolError),
2419 ..
2420 }))
2421 ),
2422 "pad_length > remaining body must yield PROTOCOL_ERROR, got {result:?}"
2423 );
2424 }
2425
2426 #[test]
2432 fn test_goaway_short_payload_rejected() {
2433 let input = [
2434 0x00, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
2440
2441 let (remaining, header) =
2442 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2443 assert_eq!(header.frame_type, FrameType::GoAway);
2444 let result = frame_body(remaining, &header);
2445 assert!(
2446 matches!(
2447 result,
2448 Err(nom::Err::Failure(ParserError {
2449 kind: ParserErrorKind::H2(H2Error::FrameSizeError),
2450 ..
2451 }))
2452 ),
2453 "GOAWAY with payload_len < 8 must yield FRAME_SIZE_ERROR, got {result:?}"
2454 );
2455 }
2456
2457 #[test]
2458 fn test_goaway_minimum_payload_accepted() {
2459 let input = [
2460 0x00, 0x00, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, ];
2467
2468 let (remaining, header) =
2469 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2470 let (_, frame) = frame_body(remaining, &header).expect("minimal GOAWAY must parse cleanly");
2471 match frame {
2472 Frame::GoAway(goaway) => {
2473 assert_eq!(goaway.last_stream_id, 10);
2474 assert_eq!(goaway.error_code, 0);
2475 }
2476 other => panic!("expected Frame::GoAway, got {other:?}"),
2477 }
2478 }
2479
2480 #[test]
2488 fn test_push_promise_rejected_at_wire_layer() {
2489 let input = [
2490 0x00, 0x00, 0x08, 0x05, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, ];
2497
2498 let (remaining, header) =
2499 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2500 assert_eq!(header.frame_type, FrameType::PushPromise);
2501 let result = frame_body(remaining, &header);
2502 assert!(
2503 matches!(
2504 result,
2505 Err(nom::Err::Failure(ParserError {
2506 kind: ParserErrorKind::H2(H2Error::ProtocolError),
2507 ..
2508 }))
2509 ),
2510 "PUSH_PROMISE must be rejected at wire layer with PROTOCOL_ERROR, got {result:?}"
2511 );
2512 }
2513}