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 fn preface(i: &[u8]) -> IResult<&[u8], &[u8]> {
253 tag(&b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"[..])(i)
254}
255
256macro_rules! ensure_frame_size {
264 ($input:expr, $cond:expr) => {
265 if !($cond) {
266 return Err(Err::Failure(ParserError::new_h2(
267 $input,
268 H2Error::FrameSizeError,
269 )));
270 }
271 };
272}
273
274pub fn frame_header(
287 input: &[u8],
288 max_frame_size: u32,
289) -> IResult<&[u8], FrameHeader, ParserError<'_>> {
290 let in_len = input.len();
291 let (i, payload_len) = be_u24(input)?;
292 if payload_len > max_frame_size {
293 return Err(Err::Failure(ParserError::new_h2(
294 i,
295 H2Error::FrameSizeError,
296 )));
297 }
298
299 let (i, t) = be_u8(i)?;
300 let frame_type = convert_frame_type(t);
301 let (i, flags) = be_u8(i)?;
302 let (i, raw_stream_id) = be_u32(i)?;
303 let stream_id = raw_stream_id & STREAM_ID_MASK;
304 debug_assert!(i.len() <= in_len, "parser must not grow its input");
309 debug_assert_eq!(
310 i.len(),
311 in_len - FRAME_HEADER_SIZE,
312 "frame_header must consume exactly the 9-byte header"
313 );
314 debug_assert!(
315 payload_len <= max_frame_size,
316 "frame_header must enforce the size bound it was given"
317 );
318 debug_assert_eq!(
319 stream_id & !STREAM_ID_MASK,
320 0,
321 "reserved high bit must be masked off the stream id"
322 );
323
324 let valid_stream_id = match frame_type {
329 FrameType::Data
330 | FrameType::Headers
331 | FrameType::Priority
332 | FrameType::RstStream
333 | FrameType::PushPromise
334 | FrameType::Continuation => stream_id != 0,
335 FrameType::Settings | FrameType::Ping | FrameType::GoAway | FrameType::PriorityUpdate => {
338 stream_id == 0
339 }
340 FrameType::WindowUpdate | FrameType::Unknown(_) => true,
341 };
342 if !valid_stream_id {
343 error!("{} invalid stream_id: {}", log_module_context!(), stream_id);
344 return Err(Err::Failure(ParserError::new_h2(i, H2Error::ProtocolError)));
345 }
346
347 Ok((
348 i,
349 FrameHeader {
350 payload_len,
351 frame_type,
352 flags,
353 stream_id,
354 },
355 ))
356}
357
358fn convert_frame_type(t: u8) -> FrameType {
364 trace!("{} got frame type: {}", log_module_context!(), t);
365 match t {
366 0 => FrameType::Data,
367 1 => FrameType::Headers,
368 2 => FrameType::Priority,
369 3 => FrameType::RstStream,
370 4 => FrameType::Settings,
371 5 => FrameType::PushPromise,
372 6 => FrameType::Ping,
373 7 => FrameType::GoAway,
374 8 => FrameType::WindowUpdate,
375 9 => FrameType::Continuation,
376 0x10 => FrameType::PriorityUpdate,
378 other => FrameType::Unknown(other),
379 }
380}
381
382#[derive(Clone, Debug)]
383pub enum Frame {
384 Data(Data),
385 Headers(Headers),
386 Priority(Priority),
387 RstStream(RstStream),
388 Settings(Settings),
389 PushPromise(PushPromise),
390 Ping(Ping),
391 GoAway(GoAway),
392 WindowUpdate(WindowUpdate),
393 Continuation(Continuation),
394 PriorityUpdate(PriorityUpdate),
398 Unknown(u8),
401}
402
403impl Frame {
404 pub fn frame_type(&self) -> FrameType {
411 match self {
412 Frame::Data(_) => FrameType::Data,
413 Frame::Headers(_) => FrameType::Headers,
414 Frame::Priority(_) => FrameType::Priority,
415 Frame::RstStream(_) => FrameType::RstStream,
416 Frame::Settings(_) => FrameType::Settings,
417 Frame::PushPromise(_) => FrameType::PushPromise,
418 Frame::Ping(_) => FrameType::Ping,
419 Frame::GoAway(_) => FrameType::GoAway,
420 Frame::WindowUpdate(_) => FrameType::WindowUpdate,
421 Frame::Continuation(_) => FrameType::Continuation,
422 Frame::PriorityUpdate(_) => FrameType::PriorityUpdate,
423 Frame::Unknown(raw) => FrameType::Unknown(*raw),
424 }
425 }
426}
427
428#[derive(Clone, Debug, PartialEq)]
430pub struct PriorityUpdate {
431 pub prioritized_stream_id: u32,
435 pub priority_field_value: Vec<u8>,
439}
440
441pub fn frame_body<'a>(
442 i: &'a [u8],
443 header: &FrameHeader,
444) -> IResult<&'a [u8], Frame, ParserError<'a>> {
445 let in_len = i.len();
446 let f = match header.frame_type {
447 FrameType::Data => data_frame(i, header)?,
448 FrameType::Headers => headers_frame(i, header)?,
449 FrameType::Priority => {
450 ensure_frame_size!(i, header.payload_len == PRIORITY_PAYLOAD_SIZE);
451 priority_frame(i, header)?
452 }
453 FrameType::RstStream => {
454 ensure_frame_size!(i, header.payload_len == RST_STREAM_PAYLOAD_SIZE);
455 rst_stream_frame(i, header)?
456 }
457 FrameType::PushPromise => push_promise_frame(i, header)?,
458 FrameType::Continuation => continuation_frame(i, header)?,
459 FrameType::Settings => {
460 ensure_frame_size!(
462 i,
463 !(header.flags & FLAG_ACK != 0 && header.payload_len != 0)
464 );
465 ensure_frame_size!(i, header.payload_len.is_multiple_of(SETTINGS_ENTRY_SIZE));
466 settings_frame(i, header)?
467 }
468 FrameType::Ping => {
469 ensure_frame_size!(i, header.payload_len == PING_PAYLOAD_SIZE);
470 ping_frame(i, header)?
471 }
472 FrameType::GoAway => {
473 ensure_frame_size!(i, header.payload_len >= GOAWAY_PAYLOAD_SIZE);
476 goaway_frame(i, header)?
477 }
478 FrameType::WindowUpdate => {
479 ensure_frame_size!(i, header.payload_len == WINDOW_UPDATE_PAYLOAD_SIZE);
480 window_update_frame(i, header)?
481 }
482 FrameType::PriorityUpdate => priority_update_frame(i, header)?,
484 FrameType::Unknown(_) => unknown_frame(i, header)?,
486 };
487
488 debug_assert!(
491 f.0.len() <= in_len,
492 "frame body parser must not grow its input"
493 );
494 debug_assert!(
495 f.0.len() <= in_len.saturating_sub(header.payload_len as usize),
496 "frame body must consume at least the declared payload_len bytes"
497 );
498 Ok(f)
499}
500
501#[derive(Clone, Debug)]
502pub struct Data {
503 pub stream_id: u32,
504 pub payload: Slice,
505 pub end_stream: bool,
506}
507
508fn strip_padding<'a>(
522 i: &'a [u8],
523 flags: u8,
524 error_input: &'a [u8],
525) -> IResult<&'a [u8], u8, ParserError<'a>> {
526 let in_len = i.len();
527 let (i, pad_length) = if flags & FLAG_PADDED != 0 {
528 let (i, pad_length) = be_u8(i)?;
529 (i, pad_length)
530 } else {
531 (i, 0)
532 };
533 debug_assert_eq!(
536 i.len(),
537 in_len - (flags & FLAG_PADDED != 0) as usize,
538 "strip_padding consumes the pad-length byte iff PADDED is set"
539 );
540
541 if (pad_length as usize) > i.len() {
542 return Err(Err::Failure(ParserError::new_h2(
543 error_input,
544 H2Error::ProtocolError,
545 )));
546 }
547
548 debug_assert!(
551 pad_length as usize <= i.len(),
552 "strip_padding must reject pad_length larger than the remaining payload"
553 );
554 Ok((i, pad_length))
555}
556
557fn unpad<'a>(
563 i: &'a [u8],
564 pad_length: u8,
565 error_input: &'a [u8],
566) -> Result<&'a [u8], Err<ParserError<'a>>> {
567 let in_len = i.len();
568 let content_len = i
569 .len()
570 .checked_sub(pad_length as usize)
571 .ok_or_else(|| Err::Failure(ParserError::new_h2(error_input, H2Error::ProtocolError)))?;
572 debug_assert!(
575 content_len <= in_len,
576 "unpad must not grow the content slice"
577 );
578 debug_assert_eq!(
579 content_len + pad_length as usize,
580 in_len,
581 "content and padding must exactly partition the input"
582 );
583 Ok(&i[..content_len])
584}
585
586pub fn data_frame<'a>(
587 input: &'a [u8],
588 header: &FrameHeader,
589) -> IResult<&'a [u8], Frame, ParserError<'a>> {
590 let in_len = input.len();
591 let (remaining, i) = take(header.payload_len)(input)?;
592
593 let (i, pad_length) = strip_padding(i, header.flags, input)?;
594 let payload = unpad(i, pad_length, input)?;
595
596 debug_assert_eq!(
600 remaining.len(),
601 in_len - header.payload_len as usize,
602 "data_frame must consume exactly payload_len bytes"
603 );
604 debug_assert!(
605 payload.len() <= header.payload_len as usize,
606 "data payload must fit within the declared frame payload"
607 );
608 debug_assert!(
609 pad_length as usize <= header.payload_len as usize,
610 "padding must not exceed the frame payload"
611 );
612
613 Ok((
614 remaining,
615 Frame::Data(Data {
616 stream_id: header.stream_id,
617 payload: Slice::new(input, payload),
618 end_stream: header.flags & FLAG_END_STREAM != 0,
619 }),
620 ))
621}
622
623#[derive(Clone, Debug)]
624pub struct Headers {
625 pub stream_id: u32,
626 pub priority: Option<PriorityPart>,
627 pub header_block_fragment: Slice,
628 pub end_stream: bool,
630 pub end_headers: bool,
631}
632
633#[derive(Clone, Debug, PartialEq)]
634pub struct StreamDependency {
635 pub exclusive: bool,
636 pub stream_id: u32,
637}
638
639fn stream_dependency(i: &[u8]) -> IResult<&[u8], StreamDependency, ParserError<'_>> {
640 let (i, stream) = map(be_u32, |i| StreamDependency {
641 exclusive: i & 0x80000000 != 0,
642 stream_id: i & STREAM_ID_MASK,
643 })
644 .parse(i)?;
645 Ok((i, stream))
646}
647
648pub fn headers_frame<'a>(
649 input: &'a [u8],
650 header: &FrameHeader,
651) -> IResult<&'a [u8], Frame, ParserError<'a>> {
652 let in_len = input.len();
653 let (remaining, i) = take(header.payload_len)(input)?;
654
655 let (i, pad_length) = strip_padding(i, header.flags, input)?;
656
657 let (i, priority) = if header.flags & FLAG_PRIORITY != 0 {
658 let (i, stream_dependency) = stream_dependency(i)?;
659 let (i, weight) = be_u8(i)?;
660 (
661 i,
662 Some(PriorityPart::Rfc7540 {
663 stream_dependency,
664 weight,
665 }),
666 )
667 } else {
668 (i, None)
669 };
670
671 let header_block_fragment = unpad(i, pad_length, input)?;
672
673 debug_assert_eq!(
677 remaining.len(),
678 in_len - header.payload_len as usize,
679 "headers_frame must consume exactly payload_len bytes"
680 );
681 debug_assert!(
682 header_block_fragment.len() <= header.payload_len as usize,
683 "header block fragment must fit within the declared frame payload"
684 );
685
686 Ok((
687 remaining,
688 Frame::Headers(Headers {
689 stream_id: header.stream_id,
690 priority,
691 header_block_fragment: Slice::new(input, header_block_fragment),
692 end_stream: header.flags & FLAG_END_STREAM != 0,
693 end_headers: header.flags & FLAG_END_HEADERS != 0,
694 }),
695 ))
696}
697
698#[derive(Clone, Debug, PartialEq)]
699pub enum PriorityPart {
700 Rfc7540 {
701 stream_dependency: StreamDependency,
702 weight: u8,
703 },
704 Rfc9218 {
705 urgency: u8, incremental: bool,
707 },
708}
709
710#[derive(Clone, Debug, PartialEq)]
711pub struct Priority {
712 pub stream_id: u32,
713 pub inner: PriorityPart,
714}
715
716pub fn priority_frame<'a>(
717 input: &'a [u8],
718 header: &FrameHeader,
719) -> IResult<&'a [u8], Frame, ParserError<'a>> {
720 let in_len = input.len();
726 let (i, data) = take(header.payload_len)(input)?;
727 debug_assert_eq!(
730 i.len(),
731 in_len - header.payload_len as usize,
732 "priority_frame must consume exactly payload_len bytes"
733 );
734 debug_assert_eq!(
735 data.len(),
736 PRIORITY_PAYLOAD_SIZE as usize,
737 "PRIORITY payload must be exactly 5 bytes"
738 );
739 let (_, (stream_dependency, weight)) = (stream_dependency, be_u8).parse(data)?;
740 Ok((
741 i,
742 Frame::Priority(Priority {
743 stream_id: header.stream_id,
744 inner: PriorityPart::Rfc7540 {
745 stream_dependency,
746 weight,
747 },
748 }),
749 ))
750}
751
752#[derive(Clone, Debug, PartialEq)]
753pub struct RstStream {
754 pub stream_id: u32,
755 pub error_code: u32,
756}
757
758pub fn rst_stream_frame<'a>(
759 input: &'a [u8],
760 header: &FrameHeader,
761) -> IResult<&'a [u8], Frame, ParserError<'a>> {
762 let in_len = input.len();
767 let (i, data) = take(header.payload_len)(input)?;
768 debug_assert_eq!(
771 i.len(),
772 in_len - header.payload_len as usize,
773 "rst_stream_frame must consume exactly payload_len bytes"
774 );
775 debug_assert_eq!(
776 data.len(),
777 RST_STREAM_PAYLOAD_SIZE as usize,
778 "RST_STREAM payload must be exactly 4 bytes"
779 );
780 let (_, error_code) = be_u32(data)?;
781 Ok((
782 i,
783 Frame::RstStream(RstStream {
784 stream_id: header.stream_id,
785 error_code,
786 }),
787 ))
788}
789
790#[derive(Clone, Debug, PartialEq)]
791pub struct Settings {
792 pub settings: Vec<Setting>,
793 pub ack: bool,
794}
795
796#[derive(Clone, Debug, PartialEq)]
797pub struct Setting {
798 pub identifier: u16,
799 pub value: u32,
800}
801
802pub const MAX_SETTINGS_ENTRIES: usize = 64;
812
813pub fn settings_frame<'a>(
814 input: &'a [u8],
815 header: &FrameHeader,
816) -> IResult<&'a [u8], Frame, ParserError<'a>> {
817 if header.payload_len / SETTINGS_ENTRY_SIZE > MAX_SETTINGS_ENTRIES as u32 {
821 return Err(Err::Failure(ParserError::new_h2(
822 input,
823 H2Error::FrameSizeError,
824 )));
825 }
826
827 let in_len = input.len();
828 let (i, data) = take(header.payload_len)(input)?;
829
830 let (_, settings) = many0(map(complete((be_u16, be_u32)), |(identifier, value)| {
831 Setting { identifier, value }
832 }))
833 .parse(data)?;
834
835 debug_assert_eq!(
839 i.len(),
840 in_len - header.payload_len as usize,
841 "settings_frame must consume exactly payload_len bytes"
842 );
843 debug_assert_eq!(
844 settings.len(),
845 header.payload_len as usize / SETTINGS_ENTRY_SIZE as usize,
846 "one SETTINGS entry decodes per 6 payload bytes"
847 );
848 debug_assert!(
849 settings.len() <= MAX_SETTINGS_ENTRIES,
850 "settings_frame must honour the MAX_SETTINGS_ENTRIES allocation cap"
851 );
852
853 Ok((
854 i,
855 Frame::Settings(Settings {
856 settings,
857 ack: header.flags & FLAG_ACK != 0,
858 }),
859 ))
860}
861
862#[derive(Clone, Debug)]
871pub struct PushPromise;
872
873pub fn push_promise_frame<'a>(
874 input: &'a [u8],
875 header: &FrameHeader,
876) -> IResult<&'a [u8], Frame, ParserError<'a>> {
877 let (_remaining, _payload) = take(header.payload_len)(input)?;
880 Err(Err::Failure(ParserError::new_h2(
881 input,
882 H2Error::ProtocolError,
883 )))
884}
885
886#[derive(Clone, Debug, PartialEq)]
887pub struct Ping {
888 pub payload: [u8; 8],
889 pub ack: bool,
890}
891
892pub fn ping_frame<'a>(
893 input: &'a [u8],
894 header: &FrameHeader,
895) -> IResult<&'a [u8], Frame, ParserError<'a>> {
896 let in_len = input.len();
900 let (i, data) = take(header.payload_len)(input)?;
901
902 debug_assert_eq!(
907 i.len(),
908 in_len - header.payload_len as usize,
909 "ping_frame must consume exactly payload_len bytes"
910 );
911 debug_assert_eq!(
912 data.len(),
913 PING_PAYLOAD_SIZE as usize,
914 "PING payload must be exactly 8 bytes for the opaque-data copy"
915 );
916
917 let mut p = Ping {
918 payload: [0; 8],
919 ack: header.flags & FLAG_ACK != 0,
920 };
921 p.payload[..8].copy_from_slice(&data[..8]);
922
923 Ok((i, Frame::Ping(p)))
924}
925
926#[derive(Clone, Debug)]
927pub struct GoAway {
928 pub last_stream_id: u32,
929 pub error_code: u32,
930 pub additional_debug_data: Slice,
931}
932
933pub fn goaway_frame<'a>(
934 input: &'a [u8],
935 header: &FrameHeader,
936) -> IResult<&'a [u8], Frame, ParserError<'a>> {
937 let in_len = input.len();
938 let (remaining, i) = take(header.payload_len)(input)?;
939 let (i, raw_last_stream_id) = be_u32(i)?;
940 let last_stream_id = raw_last_stream_id & STREAM_ID_MASK;
942 let (additional_debug_data, error_code) = be_u32(i)?;
943 debug_assert_eq!(
947 remaining.len(),
948 in_len - header.payload_len as usize,
949 "goaway_frame must consume exactly payload_len bytes"
950 );
951 debug_assert_eq!(
952 additional_debug_data.len(),
953 header.payload_len as usize - GOAWAY_PAYLOAD_SIZE as usize,
954 "GOAWAY debug data is payload_len minus the 8-byte fixed prefix"
955 );
956 debug_assert_eq!(
957 last_stream_id & !STREAM_ID_MASK,
958 0,
959 "GOAWAY last_stream_id reserved high bit must be masked"
960 );
961 Ok((
962 remaining,
963 Frame::GoAway(GoAway {
964 last_stream_id,
965 error_code,
966 additional_debug_data: Slice::new(input, additional_debug_data),
967 }),
968 ))
969}
970
971#[derive(Clone, Debug, PartialEq)]
972pub struct WindowUpdate {
973 pub stream_id: u32,
974 pub increment: u32,
975}
976
977pub fn window_update_frame<'a>(
978 input: &'a [u8],
979 header: &FrameHeader,
980) -> IResult<&'a [u8], Frame, ParserError<'a>> {
981 let in_len = input.len();
985 let (i, data) = take(header.payload_len)(input)?;
986 debug_assert_eq!(
989 i.len(),
990 in_len - header.payload_len as usize,
991 "window_update_frame must consume exactly payload_len bytes"
992 );
993 debug_assert_eq!(
994 data.len(),
995 WINDOW_UPDATE_PAYLOAD_SIZE as usize,
996 "WINDOW_UPDATE payload must be exactly 4 bytes"
997 );
998 let (_, increment) = be_u32(data)?;
999 let increment = increment & STREAM_ID_MASK;
1000 debug_assert!(
1002 increment <= STREAM_ID_MASK,
1003 "window-size increment must be a 31-bit value"
1004 );
1005
1006 Ok((
1014 i,
1015 Frame::WindowUpdate(WindowUpdate {
1016 stream_id: header.stream_id,
1017 increment,
1018 }),
1019 ))
1020}
1021
1022#[derive(Clone, Debug)]
1030pub struct Continuation;
1031
1032pub fn continuation_frame<'a>(
1033 input: &'a [u8],
1034 header: &FrameHeader,
1035) -> IResult<&'a [u8], Frame, ParserError<'a>> {
1036 let in_len = input.len();
1038 let (remaining, _) = take(header.payload_len)(input)?;
1039 debug_assert_eq!(
1040 remaining.len(),
1041 in_len - header.payload_len as usize,
1042 "continuation_frame must consume exactly payload_len bytes"
1043 );
1044 Ok((remaining, Frame::Continuation(Continuation)))
1045}
1046
1047pub fn unknown_frame<'a>(
1052 input: &'a [u8],
1053 header: &FrameHeader,
1054) -> IResult<&'a [u8], Frame, ParserError<'a>> {
1055 let in_len = input.len();
1056 let (remaining, _payload) = take(header.payload_len)(input)?;
1057 debug_assert_eq!(
1058 remaining.len(),
1059 in_len - header.payload_len as usize,
1060 "unknown_frame must consume exactly payload_len bytes"
1061 );
1062 let raw = match header.frame_type {
1063 FrameType::Unknown(t) => t,
1064 _ => 0,
1065 };
1066 Ok((remaining, Frame::Unknown(raw)))
1067}
1068
1069pub fn priority_update_frame<'a>(
1086 input: &'a [u8],
1087 header: &FrameHeader,
1088) -> IResult<&'a [u8], Frame, ParserError<'a>> {
1089 if header.payload_len < PRIORITY_UPDATE_MIN_PAYLOAD {
1090 return Err(Err::Failure(ParserError::new_h2(
1091 input,
1092 H2Error::FrameSizeError,
1093 )));
1094 }
1095 let value_len = (header.payload_len - PRIORITY_UPDATE_MIN_PAYLOAD) as usize;
1104 if value_len > PRIORITY_UPDATE_MAX_VALUE {
1105 return Err(Err::Failure(ParserError::new_h2(
1106 input,
1107 H2Error::ProtocolError,
1108 )));
1109 }
1110 let in_len = input.len();
1111 let (remaining, payload) = take(header.payload_len)(input)?;
1112 let (raw_id_bytes, value_bytes) = payload.split_at(PRIORITY_UPDATE_MIN_PAYLOAD as usize);
1113 debug_assert_eq!(
1117 remaining.len(),
1118 in_len - header.payload_len as usize,
1119 "priority_update_frame must consume exactly payload_len bytes"
1120 );
1121 debug_assert_eq!(
1122 raw_id_bytes.len(),
1123 PRIORITY_UPDATE_MIN_PAYLOAD as usize,
1124 "PRIORITY_UPDATE stream-id prefix must be exactly 4 bytes"
1125 );
1126 debug_assert!(
1127 value_bytes.len() <= PRIORITY_UPDATE_MAX_VALUE,
1128 "priority field value must respect the PRIORITY_UPDATE_MAX_VALUE cap"
1129 );
1130 let prioritized_stream_id = u32::from_be_bytes([
1131 raw_id_bytes[0],
1132 raw_id_bytes[1],
1133 raw_id_bytes[2],
1134 raw_id_bytes[3],
1135 ]) & STREAM_ID_MASK;
1136 debug_assert_eq!(
1137 prioritized_stream_id & !STREAM_ID_MASK,
1138 0,
1139 "prioritized_stream_id reserved high bit must be masked"
1140 );
1141 Ok((
1142 remaining,
1143 Frame::PriorityUpdate(PriorityUpdate {
1144 prioritized_stream_id,
1145 priority_field_value: value_bytes.to_vec(),
1146 }),
1147 ))
1148}
1149
1150pub const PRIORITY_UPDATE_MIN_PAYLOAD: u32 = 4;
1154
1155pub const PRIORITY_UPDATE_MAX_VALUE: usize = 1024;
1163
1164#[cfg(test)]
1165mod tests {
1166 use super::*;
1167
1168 const DEFAULT_MAX_FRAME_SIZE: u32 = 1 << 14;
1170
1171 #[test]
1177 fn test_settings_ack_with_payload_rejected() {
1178 let input = [
1180 0x00, 0x00, 0x06, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64,
1186 ];
1187
1188 let (remaining, header) =
1189 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1190 assert_eq!(header.frame_type, FrameType::Settings);
1191 assert_eq!(header.flags & FLAG_ACK, FLAG_ACK);
1192 assert_eq!(header.payload_len, 6);
1193
1194 let result = frame_body(remaining, &header);
1195 assert!(
1196 result.is_err(),
1197 "SETTINGS ACK with non-empty payload must be rejected"
1198 );
1199 match result {
1200 Err(nom::Err::Failure(e)) => {
1201 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1202 }
1203 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1204 }
1205 }
1206
1207 #[test]
1213 fn test_settings_ack_empty_accepted() {
1214 let input = [
1215 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, ];
1220
1221 let (remaining, header) =
1222 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1223 assert_eq!(header.frame_type, FrameType::Settings);
1224 assert_eq!(header.flags & FLAG_ACK, FLAG_ACK);
1225
1226 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
1227 match frame {
1228 Frame::Settings(settings) => {
1229 assert!(settings.ack, "ACK flag must be set");
1230 assert!(
1231 settings.settings.is_empty(),
1232 "should have no settings entries"
1233 );
1234 }
1235 other => panic!("expected Frame::Settings, got {other:?}"),
1236 }
1237 }
1238
1239 #[test]
1244 fn test_window_update_max_increment() {
1245 let input = [
1246 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFF, ];
1252
1253 let (remaining, header) =
1254 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1255 assert_eq!(header.frame_type, FrameType::WindowUpdate);
1256 assert_eq!(header.stream_id, 1);
1257
1258 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
1259 match frame {
1260 Frame::WindowUpdate(wu) => {
1261 assert_eq!(wu.increment, 0x7FFFFFFF);
1262 assert_eq!(wu.stream_id, 1);
1263 }
1264 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1265 }
1266 }
1267
1268 #[test]
1274 fn test_window_update_zero_increment_parsed() {
1275 let input = [
1277 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
1283
1284 let (remaining, header) =
1285 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1286 assert_eq!(header.frame_type, FrameType::WindowUpdate);
1287
1288 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
1289 match frame {
1290 Frame::WindowUpdate(wu) => {
1291 assert_eq!(wu.stream_id, 0);
1292 assert_eq!(wu.increment, 0);
1293 }
1294 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1295 }
1296
1297 let input2 = [
1299 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, ];
1305
1306 let (remaining2, header2) =
1307 frame_header(&input2, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1308 let (_, frame2) =
1309 frame_body(remaining2, &header2).expect("second frame body parses cleanly");
1310 match frame2 {
1311 Frame::WindowUpdate(wu) => {
1312 assert_eq!(wu.stream_id, 3);
1313 assert_eq!(wu.increment, 0);
1314 }
1315 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1316 }
1317 }
1318
1319 #[test]
1327 fn test_unknown_frame_type_is_ignored() {
1328 let input = [
1329 0x00, 0x00, 0x04, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef, ];
1335
1336 let (remaining, header) = frame_header(&input, DEFAULT_MAX_FRAME_SIZE)
1337 .expect("unknown frame header must parse cleanly");
1338 assert!(matches!(header.frame_type, FrameType::Unknown(0xFF)));
1339 assert_eq!(header.payload_len, 4);
1340
1341 let (after, frame) =
1342 frame_body(remaining, &header).expect("unknown frame body must be consumed");
1343 assert!(after.is_empty(), "payload bytes must be consumed");
1344 match frame {
1345 Frame::Unknown(0xFF) => {}
1346 other => panic!("expected Frame::Unknown(0xFF), got {other:?}"),
1347 }
1348 }
1349
1350 #[test]
1355 fn test_priority_update_empty_field_parses() {
1356 let input = [
1357 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1363 ];
1364
1365 let (remaining, header) = frame_header(&input, DEFAULT_MAX_FRAME_SIZE)
1366 .expect("PRIORITY_UPDATE header must parse");
1367 assert!(matches!(header.frame_type, FrameType::PriorityUpdate));
1368 let (_, frame) = frame_body(remaining, &header).expect("body must be consumed");
1369 match frame {
1370 Frame::PriorityUpdate(PriorityUpdate {
1371 prioritized_stream_id,
1372 ref priority_field_value,
1373 }) => {
1374 assert_eq!(prioritized_stream_id, 1);
1375 assert!(priority_field_value.is_empty());
1376 }
1377 other => panic!("expected Frame::PriorityUpdate, got {other:?}"),
1378 }
1379 }
1380
1381 #[test]
1385 fn test_priority_update_with_priority_field_parses() {
1386 let value = b"u=0, i";
1387 let mut input = vec![
1388 0x00,
1389 0x00,
1390 0x04 + value.len() as u8, 0x10, 0x00, 0x00,
1394 0x00,
1395 0x00,
1396 0x00, 0x00,
1398 0x00,
1399 0x00,
1400 0x05, ];
1402 input.extend_from_slice(value);
1403
1404 let (remaining, header) =
1405 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("header parses");
1406 assert!(matches!(header.frame_type, FrameType::PriorityUpdate));
1407 let (_, frame) = frame_body(remaining, &header).expect("body parses");
1408 match frame {
1409 Frame::PriorityUpdate(PriorityUpdate {
1410 prioritized_stream_id,
1411 ref priority_field_value,
1412 }) => {
1413 assert_eq!(prioritized_stream_id, 5);
1414 assert_eq!(priority_field_value.as_slice(), value);
1415 }
1416 other => panic!("expected Frame::PriorityUpdate, got {other:?}"),
1417 }
1418 }
1419
1420 #[test]
1423 fn test_priority_update_payload_below_min_is_frame_size_error() {
1424 let input = [
1425 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1427 ];
1428 let (remaining, header) =
1429 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("header parses");
1430 let result = frame_body(remaining, &header);
1431 match result {
1432 Err(Err::Failure(e)) => {
1433 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1434 }
1435 other => panic!("expected FRAME_SIZE_ERROR, got {other:?}"),
1436 }
1437 }
1438
1439 #[test]
1445 fn test_priority_update_oversized_value_is_protocol_error() {
1446 let payload_len = (PRIORITY_UPDATE_MIN_PAYLOAD as usize) + PRIORITY_UPDATE_MAX_VALUE + 1;
1448 let mut input = Vec::with_capacity(9 + payload_len);
1449 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); 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));
1458 let (remaining, header) =
1461 frame_header(&input, payload_len as u32 + 1).expect("header parses");
1462 match frame_body(remaining, &header) {
1463 Err(Err::Failure(e)) => {
1464 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1465 }
1466 other => {
1467 panic!("expected PROTOCOL_ERROR for oversized PRIORITY_UPDATE value, got {other:?}")
1468 }
1469 }
1470 }
1471
1472 #[test]
1475 fn test_priority_update_at_max_value_accepted() {
1476 let payload_len = (PRIORITY_UPDATE_MIN_PAYLOAD as usize) + PRIORITY_UPDATE_MAX_VALUE;
1477 let mut input = Vec::with_capacity(9 + payload_len);
1478 input.push(((payload_len >> 16) & 0xff) as u8);
1479 input.push(((payload_len >> 8) & 0xff) as u8);
1480 input.push((payload_len & 0xff) as u8);
1481 input.push(0x10);
1482 input.push(0x00);
1483 input.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]);
1484 input.extend_from_slice(&[0x00, 0x00, 0x00, 0x01]);
1485 input.extend(std::iter::repeat_n(b'a', PRIORITY_UPDATE_MAX_VALUE));
1486 let (remaining, header) =
1487 frame_header(&input, payload_len as u32 + 1).expect("header parses");
1488 match frame_body(remaining, &header) {
1489 Ok((_, Frame::PriorityUpdate(pu))) => {
1490 assert_eq!(pu.priority_field_value.len(), PRIORITY_UPDATE_MAX_VALUE);
1491 }
1492 other => panic!("expected Frame::PriorityUpdate at the cap boundary, got {other:?}"),
1493 }
1494 }
1495
1496 #[test]
1501 fn test_priority_update_on_non_zero_stream_is_protocol_error() {
1502 let input = [
1503 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, ];
1509 match frame_header(&input, DEFAULT_MAX_FRAME_SIZE) {
1510 Err(Err::Failure(e)) => {
1511 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1512 }
1513 other => panic!("expected PROTOCOL_ERROR, got {other:?}"),
1514 }
1515 }
1516
1517 #[test]
1522 fn test_settings_payload_not_multiple_of_6_rejected() {
1523 let input = [
1524 0x00, 0x00, 0x05, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, ];
1530
1531 let (remaining, header) =
1532 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1533 assert_eq!(header.frame_type, FrameType::Settings);
1534
1535 let result = frame_body(remaining, &header);
1536 assert!(
1537 result.is_err(),
1538 "odd-size SETTINGS payload must be rejected"
1539 );
1540 match result {
1541 Err(nom::Err::Failure(e)) => {
1542 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1543 }
1544 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1545 }
1546 }
1547
1548 #[test]
1553 fn test_settings_frame_over_cap_rejected() {
1554 let n_entries: u16 = (MAX_SETTINGS_ENTRIES as u16) + 1;
1556 let payload_len = u32::from(n_entries) * SETTINGS_ENTRY_SIZE;
1557 let mut input = Vec::with_capacity(9 + payload_len as usize);
1558 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 {
1563 input.extend_from_slice(&i.to_be_bytes()); input.extend_from_slice(&0u32.to_be_bytes()); }
1566
1567 let (remaining, header) =
1568 frame_header(&input, 16_777_215).expect("frame header parses cleanly");
1569 assert_eq!(header.frame_type, FrameType::Settings);
1570
1571 let result = frame_body(remaining, &header);
1572 assert!(
1573 result.is_err(),
1574 "SETTINGS frame over MAX_SETTINGS_ENTRIES must be rejected"
1575 );
1576 match result {
1577 Err(nom::Err::Failure(e)) => {
1578 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1579 }
1580 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1581 }
1582 }
1583
1584 #[test]
1586 fn test_settings_frame_at_cap_accepted() {
1587 let n_entries: u16 = MAX_SETTINGS_ENTRIES as u16;
1588 let payload_len = u32::from(n_entries) * SETTINGS_ENTRY_SIZE;
1589 let mut input = Vec::with_capacity(9 + payload_len as usize);
1590 input.extend_from_slice(&payload_len.to_be_bytes()[1..]);
1591 input.push(0x04);
1592 input.push(0x00);
1593 input.extend_from_slice(&[0, 0, 0, 0]);
1594 for _ in 0..n_entries {
1595 input.extend_from_slice(&0u16.to_be_bytes());
1596 input.extend_from_slice(&0u32.to_be_bytes());
1597 }
1598
1599 let (remaining, header) =
1600 frame_header(&input, 16_777_215).expect("frame header parses cleanly");
1601 let result = frame_body(remaining, &header);
1602 assert!(result.is_ok(), "exactly MAX_SETTINGS_ENTRIES must parse");
1603 }
1604
1605 #[test]
1609 fn test_rst_stream_wrong_payload_size_rejected() {
1610 let input = [
1612 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
1618
1619 let (remaining, header) =
1620 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1621 assert_eq!(header.frame_type, FrameType::RstStream);
1622
1623 let result = frame_body(remaining, &header);
1624 assert!(
1625 result.is_err(),
1626 "wrong RST_STREAM payload size must be rejected"
1627 );
1628 match result {
1629 Err(nom::Err::Failure(e)) => {
1630 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1631 }
1632 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1633 }
1634 }
1635
1636 #[test]
1640 fn test_ping_wrong_payload_size_rejected() {
1641 let input = [
1642 0x00, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, ];
1648
1649 let (remaining, header) =
1650 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1651 assert_eq!(header.frame_type, FrameType::Ping);
1652
1653 let result = frame_body(remaining, &header);
1654 assert!(result.is_err(), "wrong PING payload size must be rejected");
1655 match result {
1656 Err(nom::Err::Failure(e)) => {
1657 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1658 }
1659 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1660 }
1661 }
1662
1663 #[test]
1668 fn test_frame_exceeding_max_frame_size_rejected() {
1669 let input = [
1671 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, ];
1676
1677 let result = frame_header(&input, DEFAULT_MAX_FRAME_SIZE);
1678 assert!(result.is_err(), "oversized frame must be rejected");
1679 match result {
1680 Err(nom::Err::Failure(e)) => {
1681 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1682 }
1683 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1684 }
1685 }
1686
1687 #[test]
1691 fn test_settings_on_nonzero_stream_rejected() {
1692 let input = [
1693 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, ];
1698
1699 let result = frame_header(&input, DEFAULT_MAX_FRAME_SIZE);
1700 assert!(
1701 result.is_err(),
1702 "SETTINGS on non-zero stream must be rejected"
1703 );
1704 match result {
1705 Err(nom::Err::Failure(e)) => {
1706 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1707 }
1708 other => panic!("expected Failure(ProtocolError), got {other:?}"),
1709 }
1710 }
1711
1712 #[test]
1716 fn test_data_on_stream_zero_rejected() {
1717 let input = [
1718 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCA, 0xFE,
1723 ];
1724
1725 let result = frame_header(&input, DEFAULT_MAX_FRAME_SIZE);
1726 assert!(result.is_err(), "DATA on stream 0 must be rejected");
1727 match result {
1728 Err(nom::Err::Failure(e)) => {
1729 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1730 }
1731 other => panic!("expected Failure(ProtocolError), got {other:?}"),
1732 }
1733 }
1734
1735 #[test]
1740 fn test_window_update_reserved_bit_masked() {
1741 let input = [
1742 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, ];
1748
1749 let (remaining, header) =
1750 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1751 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
1752 match frame {
1753 Frame::WindowUpdate(wu) => {
1754 assert_eq!(
1755 wu.increment, 1,
1756 "reserved bit must be masked to yield increment=1"
1757 );
1758 }
1759 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1760 }
1761 }
1762
1763 fn build_frame_header(payload_len: u32, frame_type: u8, flags: u8, stream_id: u32) -> Vec<u8> {
1767 vec![
1768 ((payload_len >> 16) & 0xFF) as u8,
1769 ((payload_len >> 8) & 0xFF) as u8,
1770 (payload_len & 0xFF) as u8,
1771 frame_type,
1772 flags,
1773 ((stream_id >> 24) & 0xFF) as u8,
1774 ((stream_id >> 16) & 0xFF) as u8,
1775 ((stream_id >> 8) & 0xFF) as u8,
1776 (stream_id & 0xFF) as u8,
1777 ]
1778 }
1779
1780 fn build_raw_frame(
1782 payload_len: u32,
1783 frame_type: u8,
1784 flags: u8,
1785 stream_id: u32,
1786 payload: &[u8],
1787 ) -> Vec<u8> {
1788 let mut raw = build_frame_header(payload_len, frame_type, flags, stream_id);
1789 raw.extend_from_slice(payload);
1790 raw
1791 }
1792
1793 #[test]
1796 fn test_preface_valid() {
1797 let input = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
1798 let (remaining, matched) = preface(input).expect("should parse preface");
1799 assert!(remaining.is_empty());
1800 assert_eq!(matched, input.as_slice());
1801 }
1802
1803 #[test]
1804 fn test_preface_invalid() {
1805 let input = b"GET / HTTP/1.1\r\n";
1806 let result = preface(input);
1807 assert!(result.is_err(), "invalid preface should fail");
1808 }
1809
1810 #[test]
1811 fn test_preface_with_trailing_data() {
1812 let mut input = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".to_vec();
1813 input.extend_from_slice(b"extra stuff");
1814 let (remaining, _) = preface(&input).expect("should parse preface");
1815 assert_eq!(remaining, b"extra stuff");
1816 }
1817
1818 #[test]
1821 fn test_frame_header_settings_basic() {
1822 let raw = build_frame_header(0, 4, 0, 0);
1823 let (remaining, header) =
1824 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1825 assert!(remaining.is_empty());
1826 assert_eq!(header.payload_len, 0);
1827 assert_eq!(header.frame_type, FrameType::Settings);
1828 assert_eq!(header.flags, 0);
1829 assert_eq!(header.stream_id, 0);
1830 }
1831
1832 #[test]
1833 fn test_frame_header_data_basic() {
1834 let raw = build_frame_header(100, 0, 1, 1);
1835 let (_, header) =
1836 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1837 assert_eq!(header.payload_len, 100);
1838 assert_eq!(header.frame_type, FrameType::Data);
1839 assert_eq!(header.flags, 1);
1840 assert_eq!(header.stream_id, 1);
1841 }
1842
1843 #[test]
1844 fn test_frame_header_stream_id_reserved_bit_masked() {
1845 let raw = build_frame_header(5, 0, 0, 0x80000001);
1848 let (_, header) =
1849 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1850 assert_eq!(header.stream_id, 1, "reserved MSB must be masked off");
1851 }
1852
1853 #[test]
1856 fn test_parse_data_frame_end_stream() {
1857 let payload = b"hello";
1858 let raw = build_raw_frame(payload.len() as u32, 0, 0x01, 1, payload);
1859 let (remaining, header) =
1860 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1861 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1862 match f {
1863 Frame::Data(d) => {
1864 assert_eq!(d.stream_id, 1);
1865 assert!(d.end_stream);
1866 }
1867 other => panic!("expected Data, got {other:?}"),
1868 }
1869 }
1870
1871 #[test]
1872 fn test_parse_data_frame_no_end_stream() {
1873 let payload = b"data";
1874 let raw = build_raw_frame(payload.len() as u32, 0, 0x00, 3, payload);
1875 let (remaining, header) =
1876 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1877 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1878 match f {
1879 Frame::Data(d) => {
1880 assert_eq!(d.stream_id, 3);
1881 assert!(!d.end_stream);
1882 }
1883 other => panic!("expected Data, got {other:?}"),
1884 }
1885 }
1886
1887 #[test]
1888 fn test_parse_data_frame_with_padding() {
1889 let pad_length: u8 = 2;
1891 let actual_data = b"hello";
1892 let total_payload = 1 + actual_data.len() + pad_length as usize;
1893 let mut payload = Vec::new();
1894 payload.push(pad_length);
1895 payload.extend_from_slice(actual_data);
1896 payload.extend_from_slice(&[0x00; 2]);
1897
1898 let raw = build_raw_frame(total_payload as u32, 0, 0x08, 1, &payload);
1899 let (remaining, header) =
1900 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1901 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1902 match f {
1903 Frame::Data(d) => {
1904 assert_eq!(d.stream_id, 1);
1905 assert_eq!(d.payload.len, actual_data.len() as u32);
1906 }
1907 other => panic!("expected Data, got {other:?}"),
1908 }
1909 }
1910
1911 #[test]
1912 fn test_parse_data_frame_padding_exceeds_payload() {
1913 let mut payload = Vec::new();
1915 payload.push(10); payload.extend_from_slice(b"hello");
1917
1918 let raw = build_raw_frame(payload.len() as u32, 0, 0x08, 1, &payload);
1919 let (remaining, header) =
1920 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1921 let result = frame_body(remaining, &header);
1922 assert!(
1923 result.is_err(),
1924 "padding exceeding payload should be a protocol error"
1925 );
1926 }
1927
1928 #[test]
1931 fn test_parse_headers_frame_basic() {
1932 let hblock = b"\x82\x86";
1933 let raw = build_raw_frame(hblock.len() as u32, 1, 0x04, 1, hblock);
1934 let (remaining, header) =
1935 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1936 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1937 match f {
1938 Frame::Headers(h) => {
1939 assert_eq!(h.stream_id, 1);
1940 assert!(!h.end_stream);
1941 assert!(h.end_headers);
1942 assert!(h.priority.is_none());
1943 }
1944 other => panic!("expected Headers, got {other:?}"),
1945 }
1946 }
1947
1948 #[test]
1949 fn test_parse_headers_frame_end_stream_and_headers() {
1950 let hblock = b"\x82";
1951 let raw = build_raw_frame(hblock.len() as u32, 1, 0x05, 1, hblock);
1952 let (remaining, header) =
1953 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1954 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1955 match f {
1956 Frame::Headers(h) => {
1957 assert!(h.end_stream);
1958 assert!(h.end_headers);
1959 }
1960 other => panic!("expected Headers, got {other:?}"),
1961 }
1962 }
1963
1964 #[test]
1965 fn test_parse_headers_frame_with_priority() {
1966 let hblock = b"\x82";
1967 let payload_len = 5 + hblock.len(); let mut payload = Vec::new();
1969 payload.extend_from_slice(&[0x00, 0x00, 0x00, 0x01]);
1971 payload.push(15); payload.extend_from_slice(hblock);
1973
1974 let raw = build_raw_frame(payload_len as u32, 1, 0x24, 3, &payload);
1975 let (remaining, header) =
1976 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1977 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1978 match f {
1979 Frame::Headers(h) => {
1980 assert_eq!(h.stream_id, 3);
1981 let priority = h.priority.expect("should have priority");
1982 match priority {
1983 PriorityPart::Rfc7540 {
1984 stream_dependency,
1985 weight,
1986 } => {
1987 assert!(!stream_dependency.exclusive);
1988 assert_eq!(stream_dependency.stream_id, 1);
1989 assert_eq!(weight, 15);
1990 }
1991 other => panic!("expected Rfc7540, got {other:?}"),
1992 }
1993 }
1994 other => panic!("expected Headers, got {other:?}"),
1995 }
1996 }
1997
1998 #[test]
1999 fn test_parse_headers_frame_with_exclusive_priority() {
2000 let hblock = b"\x82\x86";
2001 let mut payload = Vec::new();
2002 let dep = 0x80000005u32;
2004 payload.extend_from_slice(&dep.to_be_bytes());
2005 payload.push(255); payload.extend_from_slice(hblock);
2007
2008 let payload_len = payload.len();
2009 let raw = build_raw_frame(payload_len as u32, 1, 0x24, 3, &payload);
2010 let (remaining, header) =
2011 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2012 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2013 match f {
2014 Frame::Headers(h) => {
2015 let priority = h.priority.expect("should have priority");
2016 match priority {
2017 PriorityPart::Rfc7540 {
2018 stream_dependency,
2019 weight,
2020 } => {
2021 assert!(stream_dependency.exclusive, "exclusive bit should be set");
2022 assert_eq!(stream_dependency.stream_id, 5);
2023 assert_eq!(weight, 255);
2024 }
2025 other => panic!("expected Rfc7540, got {other:?}"),
2026 }
2027 }
2028 other => panic!("expected Headers, got {other:?}"),
2029 }
2030 }
2031
2032 #[test]
2033 fn test_parse_headers_stream_id_zero_rejected() {
2034 let raw = build_raw_frame(2, 1, 0x04, 0, b"\x82\x86");
2035 let result = frame_header(&raw, DEFAULT_MAX_FRAME_SIZE);
2036 assert!(
2037 result.is_err(),
2038 "HEADERS with stream_id=0 should be rejected"
2039 );
2040 }
2041
2042 #[test]
2045 fn test_parse_rst_stream() {
2046 let error_code = 0x00000008u32; let raw = build_raw_frame(4, 3, 0, 1, &error_code.to_be_bytes());
2048 let (remaining, header) =
2049 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2050 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2051 match f {
2052 Frame::RstStream(rst) => {
2053 assert_eq!(rst.stream_id, 1);
2054 assert_eq!(rst.error_code, 0x08);
2055 }
2056 other => panic!("expected RstStream, got {other:?}"),
2057 }
2058 }
2059
2060 #[test]
2061 fn test_parse_rst_stream_stream_id_zero_rejected() {
2062 let raw = build_raw_frame(4, 3, 0, 0, &[0u8; 4]);
2063 let result = frame_header(&raw, DEFAULT_MAX_FRAME_SIZE);
2064 assert!(
2065 result.is_err(),
2066 "RST_STREAM with stream_id=0 should be rejected"
2067 );
2068 }
2069
2070 #[test]
2073 fn test_parse_settings_frame_with_values() {
2074 let mut payload = Vec::new();
2075 payload.extend_from_slice(&0x0001u16.to_be_bytes());
2077 payload.extend_from_slice(&4096u32.to_be_bytes());
2078 payload.extend_from_slice(&0x0003u16.to_be_bytes());
2080 payload.extend_from_slice(&100u32.to_be_bytes());
2081 payload.extend_from_slice(&0x0004u16.to_be_bytes());
2083 payload.extend_from_slice(&65535u32.to_be_bytes());
2084
2085 let raw = build_raw_frame(payload.len() as u32, 4, 0x0, 0, &payload);
2086 let (remaining, header) =
2087 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2088 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2089 match f {
2090 Frame::Settings(s) => {
2091 assert!(!s.ack);
2092 assert_eq!(s.settings.len(), 3);
2093 assert_eq!(s.settings[0].identifier, 0x0001);
2094 assert_eq!(s.settings[0].value, 4096);
2095 assert_eq!(s.settings[1].identifier, 0x0003);
2096 assert_eq!(s.settings[1].value, 100);
2097 assert_eq!(s.settings[2].identifier, 0x0004);
2098 assert_eq!(s.settings[2].value, 65535);
2099 }
2100 other => panic!("expected Settings, got {other:?}"),
2101 }
2102 }
2103
2104 #[test]
2107 fn test_parse_ping_frame() {
2108 let ping_payload = [1u8, 2, 3, 4, 5, 6, 7, 8];
2109 let raw = build_raw_frame(8, 6, 0, 0, &ping_payload);
2110 let (remaining, header) =
2111 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2112 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2113 match f {
2114 Frame::Ping(p) => {
2115 assert_eq!(p.payload, ping_payload);
2116 assert!(!p.ack);
2117 }
2118 other => panic!("expected Ping, got {other:?}"),
2119 }
2120 }
2121
2122 #[test]
2123 fn test_parse_ping_ack_preserves_payload() {
2124 let ping_payload = [0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE];
2125 let raw = build_raw_frame(8, 6, 0x01, 0, &ping_payload);
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::Ping(p) => {
2131 assert_eq!(
2132 p.payload, ping_payload,
2133 "PING ACK must echo the exact payload"
2134 );
2135 assert!(p.ack);
2136 }
2137 other => panic!("expected Ping, got {other:?}"),
2138 }
2139 }
2140
2141 #[test]
2142 fn test_parse_ping_stream_id_nonzero_rejected() {
2143 let raw = build_raw_frame(8, 6, 0, 1, &[0u8; 8]);
2144 let result = frame_header(&raw, DEFAULT_MAX_FRAME_SIZE);
2145 assert!(result.is_err(), "PING with stream_id!=0 should be rejected");
2146 }
2147
2148 #[test]
2151 fn test_parse_window_update_connection_level() {
2152 let increment = 1000u32;
2153 let raw = build_raw_frame(4, 8, 0, 0, &increment.to_be_bytes());
2154 let (remaining, header) =
2155 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2156 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2157 match f {
2158 Frame::WindowUpdate(w) => {
2159 assert_eq!(w.stream_id, 0);
2160 assert_eq!(w.increment, 1000);
2161 }
2162 other => panic!("expected WindowUpdate, got {other:?}"),
2163 }
2164 }
2165
2166 #[test]
2167 fn test_parse_window_update_stream_level() {
2168 let increment = 65535u32;
2169 let raw = build_raw_frame(4, 8, 0, 5, &increment.to_be_bytes());
2170 let (remaining, header) =
2171 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2172 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2173 match f {
2174 Frame::WindowUpdate(w) => {
2175 assert_eq!(w.stream_id, 5);
2176 assert_eq!(w.increment, 65535);
2178 }
2179 other => panic!("expected WindowUpdate, got {other:?}"),
2180 }
2181 }
2182
2183 #[test]
2184 fn test_parse_window_update_wrong_size() {
2185 let raw = build_raw_frame(3, 8, 0, 0, &[0u8; 3]);
2186 let (remaining, header) =
2187 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2188 let result = frame_body(remaining, &header);
2189 assert!(
2190 result.is_err(),
2191 "WINDOW_UPDATE with payload != 4 should fail"
2192 );
2193 match result {
2194 Err(Err::Failure(e)) => {
2195 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
2196 }
2197 other => panic!("expected FrameSizeError, got {other:?}"),
2198 }
2199 }
2200
2201 #[test]
2204 fn test_parse_frame_at_max_frame_size() {
2205 let payload = vec![0u8; DEFAULT_MAX_FRAME_SIZE as usize];
2206 let raw = build_raw_frame(DEFAULT_MAX_FRAME_SIZE, 0, 0x0, 1, &payload);
2207 let (remaining, header) =
2208 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2209 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2210 match f {
2211 Frame::Data(d) => {
2212 assert_eq!(d.payload.len, DEFAULT_MAX_FRAME_SIZE);
2213 }
2214 other => panic!("expected Data, got {other:?}"),
2215 }
2216 }
2217
2218 #[test]
2219 fn test_parse_frame_with_custom_max_frame_size() {
2220 let custom_max = 32768u32;
2221 let payload = vec![0u8; 20000];
2222 let raw = build_raw_frame(20000, 0, 0x0, 1, &payload);
2223 let (remaining, header) =
2224 frame_header(&raw, custom_max).expect("frame header parses with custom max");
2225 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2226 match f {
2227 Frame::Data(d) => {
2228 assert_eq!(d.payload.len, 20000);
2229 }
2230 other => panic!("expected Data, got {other:?}"),
2231 }
2232 }
2233
2234 #[test]
2237 fn test_h2_error_try_from_valid() {
2238 assert_eq!(H2Error::try_from(0x0), Ok(H2Error::NoError));
2239 assert_eq!(H2Error::try_from(0x1), Ok(H2Error::ProtocolError));
2240 assert_eq!(H2Error::try_from(0x6), Ok(H2Error::FrameSizeError));
2241 assert_eq!(H2Error::try_from(0xd), Ok(H2Error::HTTP11Required));
2242 }
2243
2244 #[test]
2245 fn test_h2_error_try_from_invalid() {
2246 assert_eq!(H2Error::try_from(0x0e), Err(0x0e));
2247 assert_eq!(H2Error::try_from(0xFF), Err(0xFF));
2248 }
2249
2250 #[test]
2251 fn test_h2_error_from_str() {
2252 assert_eq!("NO_ERROR".parse::<H2Error>(), Ok(H2Error::NoError));
2253 assert_eq!(
2254 "PROTOCOL_ERROR".parse::<H2Error>(),
2255 Ok(H2Error::ProtocolError)
2256 );
2257 assert_eq!(
2258 "ENHANCE_YOUR_CALM".parse::<H2Error>(),
2259 Ok(H2Error::EnhanceYourCalm)
2260 );
2261 assert!("INVALID_ERROR".parse::<H2Error>().is_err());
2262 }
2263
2264 #[test]
2265 fn test_h2_error_as_str_roundtrip() {
2266 let errors = [
2267 H2Error::NoError,
2268 H2Error::ProtocolError,
2269 H2Error::InternalError,
2270 H2Error::FlowControlError,
2271 H2Error::SettingsTimeout,
2272 H2Error::StreamClosed,
2273 H2Error::FrameSizeError,
2274 H2Error::RefusedStream,
2275 H2Error::Cancel,
2276 H2Error::CompressionError,
2277 H2Error::ConnectError,
2278 H2Error::EnhanceYourCalm,
2279 H2Error::InadequateSecurity,
2280 H2Error::HTTP11Required,
2281 ];
2282
2283 for error in &errors {
2284 let s = error.as_str();
2285 let parsed: H2Error = s.parse().unwrap_or_else(|_| panic!("failed to parse {s}"));
2286 assert_eq!(*error, parsed, "roundtrip failed for {s}");
2287 }
2288 }
2289
2290 #[test]
2293 fn test_parse_priority_frame() {
2294 let mut payload = Vec::new();
2295 payload.extend_from_slice(&0x00000001u32.to_be_bytes());
2297 payload.push(15); assert_eq!(payload.len(), 5);
2299
2300 let raw = build_raw_frame(5, 2, 0, 3, &payload);
2301 let (remaining, header) =
2302 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2303 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2304 match f {
2305 Frame::Priority(p) => {
2306 assert_eq!(p.stream_id, 3);
2307 match p.inner {
2308 PriorityPart::Rfc7540 {
2309 stream_dependency,
2310 weight,
2311 } => {
2312 assert!(!stream_dependency.exclusive);
2313 assert_eq!(stream_dependency.stream_id, 1);
2314 assert_eq!(weight, 15);
2315 }
2316 other => panic!("expected Rfc7540, got {other:?}"),
2317 }
2318 }
2319 other => panic!("expected Priority, got {other:?}"),
2320 }
2321 }
2322
2323 #[test]
2324 fn test_parse_priority_wrong_size_rejected() {
2325 let raw = build_raw_frame(4, 2, 0, 1, &[0u8; 4]);
2326 let (remaining, header) =
2327 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2328 let result = frame_body(remaining, &header);
2329 assert!(
2330 result.is_err(),
2331 "PRIORITY with wrong payload size should fail"
2332 );
2333 }
2334
2335 #[test]
2342 fn test_headers_padded_priority_underflow_rejected() {
2343 let raw: [u8; 16] = [
2344 0x00, 0x00, 0x06, 0x01, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x00, 0x64, 0x6d, 0x6d,
2345 0x6d, 0x6d,
2346 ];
2347 let (remaining, header) =
2348 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2349 let result = frame_body(remaining, &header);
2350 assert!(
2351 result.is_err(),
2352 "PADDED+PRIORITY HEADERS with oversized pad_length must error, not panic"
2353 );
2354 }
2355
2356 #[test]
2364 fn test_strip_padding_all_padding_accepted() {
2365 let input = [
2369 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, ];
2376
2377 let (remaining, header) =
2378 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2379 let (_, frame) =
2380 frame_body(remaining, &header).expect("DATA with all-padding body must parse");
2381 match frame {
2382 Frame::Data(data) => {
2383 assert_eq!(data.stream_id, 1);
2384 assert_eq!(data.payload.len, 0);
2386 }
2387 other => panic!("expected Frame::Data, got {other:?}"),
2388 }
2389 }
2390
2391 #[test]
2392 fn test_strip_padding_pad_length_equals_payload_len_rejected() {
2393 let input = [
2397 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x01, ];
2403
2404 let (remaining, header) =
2405 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2406 let result = frame_body(remaining, &header);
2407 assert!(
2408 matches!(
2409 result,
2410 Err(nom::Err::Failure(ParserError {
2411 kind: ParserErrorKind::H2(H2Error::ProtocolError),
2412 ..
2413 }))
2414 ),
2415 "pad_length > remaining body must yield PROTOCOL_ERROR, got {result:?}"
2416 );
2417 }
2418
2419 #[test]
2425 fn test_goaway_short_payload_rejected() {
2426 let input = [
2427 0x00, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
2433
2434 let (remaining, header) =
2435 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2436 assert_eq!(header.frame_type, FrameType::GoAway);
2437 let result = frame_body(remaining, &header);
2438 assert!(
2439 matches!(
2440 result,
2441 Err(nom::Err::Failure(ParserError {
2442 kind: ParserErrorKind::H2(H2Error::FrameSizeError),
2443 ..
2444 }))
2445 ),
2446 "GOAWAY with payload_len < 8 must yield FRAME_SIZE_ERROR, got {result:?}"
2447 );
2448 }
2449
2450 #[test]
2451 fn test_goaway_minimum_payload_accepted() {
2452 let input = [
2453 0x00, 0x00, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, ];
2460
2461 let (remaining, header) =
2462 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2463 let (_, frame) = frame_body(remaining, &header).expect("minimal GOAWAY must parse cleanly");
2464 match frame {
2465 Frame::GoAway(goaway) => {
2466 assert_eq!(goaway.last_stream_id, 10);
2467 assert_eq!(goaway.error_code, 0);
2468 }
2469 other => panic!("expected Frame::GoAway, got {other:?}"),
2470 }
2471 }
2472
2473 #[test]
2481 fn test_push_promise_rejected_at_wire_layer() {
2482 let input = [
2483 0x00, 0x00, 0x08, 0x05, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, ];
2490
2491 let (remaining, header) =
2492 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2493 assert_eq!(header.frame_type, FrameType::PushPromise);
2494 let result = frame_body(remaining, &header);
2495 assert!(
2496 matches!(
2497 result,
2498 Err(nom::Err::Failure(ParserError {
2499 kind: ParserErrorKind::H2(H2Error::ProtocolError),
2500 ..
2501 }))
2502 ),
2503 "PUSH_PROMISE must be rejected at wire layer with PROTOCOL_ERROR, got {result:?}"
2504 );
2505 }
2506}