1use std::convert::From;
12
13use kawa::repr::Slice;
14use nom::{
15 Err, IResult,
16 bytes::complete::{tag, take},
17 combinator::{complete, map},
18 error::{ErrorKind, ParseError},
19 multi::many0,
20 number::complete::{be_u8, be_u16, be_u24, be_u32},
21 sequence::tuple,
22};
23use sozu_command::logging::ansi_palette;
24
25macro_rules! log_module_context {
30 () => {{
31 let (open, reset, _, _, _) = ansi_palette();
32 format!("{open}MUX-PARSER{reset}\t >>>", open = open, reset = reset)
33 }};
34}
35
36pub const FRAME_HEADER_SIZE: usize = 9;
40
41pub const STREAM_ID_MASK: u32 = 0x7FFFFFFF;
43
44pub const FLAG_END_STREAM: u8 = 0x1;
47pub const FLAG_END_HEADERS: u8 = 0x4;
49pub const FLAG_PADDED: u8 = 0x8;
51pub const FLAG_PRIORITY: u8 = 0x20;
53pub const FLAG_ACK: u8 = 0x1;
55
56pub const PRIORITY_PAYLOAD_SIZE: u32 = 5;
58pub const RST_STREAM_PAYLOAD_SIZE: u32 = 4;
59pub const SETTINGS_ENTRY_SIZE: u32 = 6;
60pub const PING_PAYLOAD_SIZE: u32 = 8;
61pub const WINDOW_UPDATE_PAYLOAD_SIZE: u32 = 4;
62pub const GOAWAY_PAYLOAD_SIZE: u32 = 8;
63
64pub const SETTINGS_HEADER_TABLE_SIZE: u16 = 1;
66pub const SETTINGS_ENABLE_PUSH: u16 = 2;
67pub const SETTINGS_MAX_CONCURRENT_STREAMS: u16 = 3;
68pub const SETTINGS_INITIAL_WINDOW_SIZE: u16 = 4;
69pub const SETTINGS_MAX_FRAME_SIZE: u16 = 5;
70pub const SETTINGS_MAX_HEADER_LIST_SIZE: u16 = 6;
71pub const SETTINGS_ENABLE_CONNECT_PROTOCOL: u16 = 8;
72pub const SETTINGS_NO_RFC7540_PRIORITIES: u16 = 9;
73pub const SETTINGS_COUNT: u32 = 8;
75
76#[derive(Clone, Debug, PartialEq)]
79pub struct FrameHeader {
80 pub payload_len: u32,
81 pub frame_type: FrameType,
82 pub flags: u8,
83 pub stream_id: u32,
84}
85
86#[derive(Clone, Debug, PartialEq)]
87pub enum FrameType {
88 Data,
89 Headers,
90 Priority,
91 RstStream,
92 Settings,
93 PushPromise,
94 Ping,
95 GoAway,
96 WindowUpdate,
97 Continuation,
98 PriorityUpdate,
102 Unknown(u8),
107}
108
109impl std::str::FromStr for H2Error {
110 type Err = ();
111
112 fn from_str(s: &str) -> Result<Self, ()> {
113 match s {
114 "NO_ERROR" => Ok(H2Error::NoError),
115 "PROTOCOL_ERROR" => Ok(H2Error::ProtocolError),
116 "INTERNAL_ERROR" => Ok(H2Error::InternalError),
117 "FLOW_CONTROL_ERROR" => Ok(H2Error::FlowControlError),
118 "SETTINGS_TIMEOUT" => Ok(H2Error::SettingsTimeout),
119 "STREAM_CLOSED" => Ok(H2Error::StreamClosed),
120 "FRAME_SIZE_ERROR" => Ok(H2Error::FrameSizeError),
121 "REFUSED_STREAM" => Ok(H2Error::RefusedStream),
122 "CANCEL" => Ok(H2Error::Cancel),
123 "COMPRESSION_ERROR" => Ok(H2Error::CompressionError),
124 "CONNECT_ERROR" => Ok(H2Error::ConnectError),
125 "ENHANCE_YOUR_CALM" => Ok(H2Error::EnhanceYourCalm),
126 "INADEQUATE_SECURITY" => Ok(H2Error::InadequateSecurity),
127 "HTTP_1_1_REQUIRED" => Ok(H2Error::HTTP11Required),
128 _ => Err(()),
129 }
130 }
131}
132
133#[derive(Clone, Debug, PartialEq)]
134pub struct ParserError<'a> {
135 pub input: &'a [u8],
136 pub kind: ParserErrorKind,
137}
138
139#[derive(Clone, Debug, PartialEq)]
140pub enum ParserErrorKind {
141 Nom(ErrorKind),
142 H2(H2Error),
143}
144
145#[derive(Clone, Copy, Debug, PartialEq)]
146#[repr(u32)]
147pub enum H2Error {
148 NoError = 0x0,
149 ProtocolError = 0x1,
150 InternalError = 0x2,
151 FlowControlError = 0x3,
152 SettingsTimeout = 0x4,
153 StreamClosed = 0x5,
154 FrameSizeError = 0x6,
155 RefusedStream = 0x7,
156 Cancel = 0x8,
157 CompressionError = 0x9,
158 ConnectError = 0xa,
159 EnhanceYourCalm = 0xb,
160 InadequateSecurity = 0xc,
161 HTTP11Required = 0xd,
162}
163
164impl TryFrom<u32> for H2Error {
165 type Error = u32;
166
167 fn try_from(code: u32) -> Result<Self, u32> {
168 match code {
169 0x0 => Ok(H2Error::NoError),
170 0x1 => Ok(H2Error::ProtocolError),
171 0x2 => Ok(H2Error::InternalError),
172 0x3 => Ok(H2Error::FlowControlError),
173 0x4 => Ok(H2Error::SettingsTimeout),
174 0x5 => Ok(H2Error::StreamClosed),
175 0x6 => Ok(H2Error::FrameSizeError),
176 0x7 => Ok(H2Error::RefusedStream),
177 0x8 => Ok(H2Error::Cancel),
178 0x9 => Ok(H2Error::CompressionError),
179 0xa => Ok(H2Error::ConnectError),
180 0xb => Ok(H2Error::EnhanceYourCalm),
181 0xc => Ok(H2Error::InadequateSecurity),
182 0xd => Ok(H2Error::HTTP11Required),
183 other => Err(other),
184 }
185 }
186}
187
188impl H2Error {
189 pub const fn as_str(&self) -> &'static str {
191 match self {
192 H2Error::NoError => "NO_ERROR",
193 H2Error::ProtocolError => "PROTOCOL_ERROR",
194 H2Error::InternalError => "INTERNAL_ERROR",
195 H2Error::FlowControlError => "FLOW_CONTROL_ERROR",
196 H2Error::SettingsTimeout => "SETTINGS_TIMEOUT",
197 H2Error::StreamClosed => "STREAM_CLOSED",
198 H2Error::FrameSizeError => "FRAME_SIZE_ERROR",
199 H2Error::RefusedStream => "REFUSED_STREAM",
200 H2Error::Cancel => "CANCEL",
201 H2Error::CompressionError => "COMPRESSION_ERROR",
202 H2Error::ConnectError => "CONNECT_ERROR",
203 H2Error::EnhanceYourCalm => "ENHANCE_YOUR_CALM",
204 H2Error::InadequateSecurity => "INADEQUATE_SECURITY",
205 H2Error::HTTP11Required => "HTTP_1_1_REQUIRED",
206 }
207 }
208}
209
210impl std::fmt::Display for H2Error {
211 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
212 f.write_str(self.as_str())
213 }
214}
215
216impl<'a> ParserError<'a> {
217 pub fn new(input: &'a [u8], error: ParserErrorKind) -> ParserError<'a> {
218 ParserError { input, kind: error }
219 }
220 pub fn new_h2(input: &'a [u8], error: H2Error) -> ParserError<'a> {
221 ParserError {
222 input,
223 kind: ParserErrorKind::H2(error),
224 }
225 }
226}
227
228impl<'a> ParseError<&'a [u8]> for ParserError<'a> {
229 fn from_error_kind(input: &'a [u8], kind: ErrorKind) -> Self {
230 ParserError {
231 input,
232 kind: ParserErrorKind::Nom(kind),
233 }
234 }
235
236 fn append(input: &'a [u8], kind: ErrorKind, _other: Self) -> Self {
237 ParserError {
238 input,
239 kind: ParserErrorKind::Nom(kind),
240 }
241 }
242}
243
244impl<'a> From<(&'a [u8], ErrorKind)> for ParserError<'a> {
245 fn from((input, kind): (&'a [u8], ErrorKind)) -> Self {
246 ParserError {
247 input,
248 kind: ParserErrorKind::Nom(kind),
249 }
250 }
251}
252
253pub fn preface(i: &[u8]) -> IResult<&[u8], &[u8]> {
254 tag(b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")(i)
255}
256
257macro_rules! ensure_frame_size {
265 ($input:expr, $cond:expr) => {
266 if !($cond) {
267 return Err(Err::Failure(ParserError::new_h2(
268 $input,
269 H2Error::FrameSizeError,
270 )));
271 }
272 };
273}
274
275pub fn frame_header(input: &[u8], max_frame_size: u32) -> IResult<&[u8], FrameHeader, ParserError> {
288 let (i, payload_len) = be_u24(input)?;
289 if payload_len > max_frame_size {
290 return Err(Err::Failure(ParserError::new_h2(
291 i,
292 H2Error::FrameSizeError,
293 )));
294 }
295
296 let (i, t) = be_u8(i)?;
297 let frame_type = convert_frame_type(t);
298 let (i, flags) = be_u8(i)?;
299 let (i, stream_id) = be_u32(i)?;
300 let stream_id = stream_id & STREAM_ID_MASK;
301
302 let valid_stream_id = match frame_type {
307 FrameType::Data
308 | FrameType::Headers
309 | FrameType::Priority
310 | FrameType::RstStream
311 | FrameType::PushPromise
312 | FrameType::Continuation => stream_id != 0,
313 FrameType::Settings | FrameType::Ping | FrameType::GoAway | FrameType::PriorityUpdate => {
316 stream_id == 0
317 }
318 FrameType::WindowUpdate | FrameType::Unknown(_) => true,
319 };
320 if !valid_stream_id {
321 error!("{} invalid stream_id: {}", log_module_context!(), stream_id);
322 return Err(Err::Failure(ParserError::new_h2(i, H2Error::ProtocolError)));
323 }
324
325 Ok((
326 i,
327 FrameHeader {
328 payload_len,
329 frame_type,
330 flags,
331 stream_id,
332 },
333 ))
334}
335
336fn convert_frame_type(t: u8) -> FrameType {
342 trace!("{} got frame type: {}", log_module_context!(), t);
343 match t {
344 0 => FrameType::Data,
345 1 => FrameType::Headers,
346 2 => FrameType::Priority,
347 3 => FrameType::RstStream,
348 4 => FrameType::Settings,
349 5 => FrameType::PushPromise,
350 6 => FrameType::Ping,
351 7 => FrameType::GoAway,
352 8 => FrameType::WindowUpdate,
353 9 => FrameType::Continuation,
354 0x10 => FrameType::PriorityUpdate,
356 other => FrameType::Unknown(other),
357 }
358}
359
360#[derive(Clone, Debug)]
361pub enum Frame {
362 Data(Data),
363 Headers(Headers),
364 Priority(Priority),
365 RstStream(RstStream),
366 Settings(Settings),
367 PushPromise(PushPromise),
368 Ping(Ping),
369 GoAway(GoAway),
370 WindowUpdate(WindowUpdate),
371 Continuation(Continuation),
372 PriorityUpdate(PriorityUpdate),
376 Unknown(u8),
379}
380
381#[derive(Clone, Debug, PartialEq)]
383pub struct PriorityUpdate {
384 pub prioritized_stream_id: u32,
388 pub priority_field_value: Vec<u8>,
392}
393
394pub fn frame_body<'a>(
395 i: &'a [u8],
396 header: &FrameHeader,
397) -> IResult<&'a [u8], Frame, ParserError<'a>> {
398 let f = match header.frame_type {
399 FrameType::Data => data_frame(i, header)?,
400 FrameType::Headers => headers_frame(i, header)?,
401 FrameType::Priority => {
402 ensure_frame_size!(i, header.payload_len == PRIORITY_PAYLOAD_SIZE);
403 priority_frame(i, header)?
404 }
405 FrameType::RstStream => {
406 ensure_frame_size!(i, header.payload_len == RST_STREAM_PAYLOAD_SIZE);
407 rst_stream_frame(i, header)?
408 }
409 FrameType::PushPromise => push_promise_frame(i, header)?,
410 FrameType::Continuation => continuation_frame(i, header)?,
411 FrameType::Settings => {
412 ensure_frame_size!(
414 i,
415 !(header.flags & FLAG_ACK != 0 && header.payload_len != 0)
416 );
417 ensure_frame_size!(i, header.payload_len % SETTINGS_ENTRY_SIZE == 0);
418 settings_frame(i, header)?
419 }
420 FrameType::Ping => {
421 ensure_frame_size!(i, header.payload_len == PING_PAYLOAD_SIZE);
422 ping_frame(i, header)?
423 }
424 FrameType::GoAway => {
425 ensure_frame_size!(i, header.payload_len >= GOAWAY_PAYLOAD_SIZE);
428 goaway_frame(i, header)?
429 }
430 FrameType::WindowUpdate => {
431 ensure_frame_size!(i, header.payload_len == WINDOW_UPDATE_PAYLOAD_SIZE);
432 window_update_frame(i, header)?
433 }
434 FrameType::PriorityUpdate => priority_update_frame(i, header)?,
436 FrameType::Unknown(_) => unknown_frame(i, header)?,
438 };
439
440 Ok(f)
441}
442
443#[derive(Clone, Debug)]
444pub struct Data {
445 pub stream_id: u32,
446 pub payload: Slice,
447 pub end_stream: bool,
448}
449
450fn strip_padding<'a>(
464 i: &'a [u8],
465 flags: u8,
466 error_input: &'a [u8],
467) -> IResult<&'a [u8], u8, ParserError<'a>> {
468 let (i, pad_length) = if flags & FLAG_PADDED != 0 {
469 let (i, pad_length) = be_u8(i)?;
470 (i, pad_length)
471 } else {
472 (i, 0)
473 };
474
475 if (pad_length as usize) > i.len() {
476 return Err(Err::Failure(ParserError::new_h2(
477 error_input,
478 H2Error::ProtocolError,
479 )));
480 }
481
482 Ok((i, pad_length))
483}
484
485fn unpad<'a>(
491 i: &'a [u8],
492 pad_length: u8,
493 error_input: &'a [u8],
494) -> Result<&'a [u8], Err<ParserError<'a>>> {
495 let content_len = i
496 .len()
497 .checked_sub(pad_length as usize)
498 .ok_or_else(|| Err::Failure(ParserError::new_h2(error_input, H2Error::ProtocolError)))?;
499 Ok(&i[..content_len])
500}
501
502pub fn data_frame<'a>(
503 input: &'a [u8],
504 header: &FrameHeader,
505) -> IResult<&'a [u8], Frame, ParserError<'a>> {
506 let (remaining, i) = take(header.payload_len)(input)?;
507
508 let (i, pad_length) = strip_padding(i, header.flags, input)?;
509 let payload = unpad(i, pad_length, input)?;
510
511 Ok((
512 remaining,
513 Frame::Data(Data {
514 stream_id: header.stream_id,
515 payload: Slice::new(input, payload),
516 end_stream: header.flags & FLAG_END_STREAM != 0,
517 }),
518 ))
519}
520
521#[derive(Clone, Debug)]
522pub struct Headers {
523 pub stream_id: u32,
524 pub priority: Option<PriorityPart>,
525 pub header_block_fragment: Slice,
526 pub end_stream: bool,
528 pub end_headers: bool,
529}
530
531#[derive(Clone, Debug, PartialEq)]
532pub struct StreamDependency {
533 pub exclusive: bool,
534 pub stream_id: u32,
535}
536
537fn stream_dependency(i: &[u8]) -> IResult<&[u8], StreamDependency, ParserError<'_>> {
538 let (i, stream) = map(be_u32, |i| StreamDependency {
539 exclusive: i & 0x80000000 != 0,
540 stream_id: i & STREAM_ID_MASK,
541 })(i)?;
542 Ok((i, stream))
543}
544
545pub fn headers_frame<'a>(
546 input: &'a [u8],
547 header: &FrameHeader,
548) -> IResult<&'a [u8], Frame, ParserError<'a>> {
549 let (remaining, i) = take(header.payload_len)(input)?;
550
551 let (i, pad_length) = strip_padding(i, header.flags, input)?;
552
553 let (i, priority) = if header.flags & FLAG_PRIORITY != 0 {
554 let (i, stream_dependency) = stream_dependency(i)?;
555 let (i, weight) = be_u8(i)?;
556 (
557 i,
558 Some(PriorityPart::Rfc7540 {
559 stream_dependency,
560 weight,
561 }),
562 )
563 } else {
564 (i, None)
565 };
566
567 let header_block_fragment = unpad(i, pad_length, input)?;
568
569 Ok((
570 remaining,
571 Frame::Headers(Headers {
572 stream_id: header.stream_id,
573 priority,
574 header_block_fragment: Slice::new(input, header_block_fragment),
575 end_stream: header.flags & FLAG_END_STREAM != 0,
576 end_headers: header.flags & FLAG_END_HEADERS != 0,
577 }),
578 ))
579}
580
581#[derive(Clone, Debug, PartialEq)]
582pub enum PriorityPart {
583 Rfc7540 {
584 stream_dependency: StreamDependency,
585 weight: u8,
586 },
587 Rfc9218 {
588 urgency: u8, incremental: bool,
590 },
591}
592
593#[derive(Clone, Debug, PartialEq)]
594pub struct Priority {
595 pub stream_id: u32,
596 pub inner: PriorityPart,
597}
598
599pub fn priority_frame<'a>(
600 input: &'a [u8],
601 header: &FrameHeader,
602) -> IResult<&'a [u8], Frame, ParserError<'a>> {
603 let (i, data) = take(header.payload_len)(input)?;
609 let (_, (stream_dependency, weight)) = tuple((stream_dependency, be_u8))(data)?;
610 Ok((
611 i,
612 Frame::Priority(Priority {
613 stream_id: header.stream_id,
614 inner: PriorityPart::Rfc7540 {
615 stream_dependency,
616 weight,
617 },
618 }),
619 ))
620}
621
622#[derive(Clone, Debug, PartialEq)]
623pub struct RstStream {
624 pub stream_id: u32,
625 pub error_code: u32,
626}
627
628pub fn rst_stream_frame<'a>(
629 input: &'a [u8],
630 header: &FrameHeader,
631) -> IResult<&'a [u8], Frame, ParserError<'a>> {
632 let (i, data) = take(header.payload_len)(input)?;
637 let (_, error_code) = be_u32(data)?;
638 Ok((
639 i,
640 Frame::RstStream(RstStream {
641 stream_id: header.stream_id,
642 error_code,
643 }),
644 ))
645}
646
647#[derive(Clone, Debug, PartialEq)]
648pub struct Settings {
649 pub settings: Vec<Setting>,
650 pub ack: bool,
651}
652
653#[derive(Clone, Debug, PartialEq)]
654pub struct Setting {
655 pub identifier: u16,
656 pub value: u32,
657}
658
659pub const MAX_SETTINGS_ENTRIES: usize = 64;
669
670pub fn settings_frame<'a>(
671 input: &'a [u8],
672 header: &FrameHeader,
673) -> IResult<&'a [u8], Frame, ParserError<'a>> {
674 if header.payload_len / SETTINGS_ENTRY_SIZE > MAX_SETTINGS_ENTRIES as u32 {
678 return Err(Err::Failure(ParserError::new_h2(
679 input,
680 H2Error::FrameSizeError,
681 )));
682 }
683
684 let (i, data) = take(header.payload_len)(input)?;
685
686 let (_, settings) = many0(map(
687 complete(tuple((be_u16, be_u32))),
688 |(identifier, value)| Setting { identifier, value },
689 ))(data)?;
690
691 Ok((
692 i,
693 Frame::Settings(Settings {
694 settings,
695 ack: header.flags & FLAG_ACK != 0,
696 }),
697 ))
698}
699
700#[derive(Clone, Debug)]
709pub struct PushPromise;
710
711pub fn push_promise_frame<'a>(
712 input: &'a [u8],
713 header: &FrameHeader,
714) -> IResult<&'a [u8], Frame, ParserError<'a>> {
715 let (_remaining, _payload) = take(header.payload_len)(input)?;
718 Err(Err::Failure(ParserError::new_h2(
719 input,
720 H2Error::ProtocolError,
721 )))
722}
723
724#[derive(Clone, Debug, PartialEq)]
725pub struct Ping {
726 pub payload: [u8; 8],
727 pub ack: bool,
728}
729
730pub fn ping_frame<'a>(
731 input: &'a [u8],
732 header: &FrameHeader,
733) -> IResult<&'a [u8], Frame, ParserError<'a>> {
734 let (i, data) = take(header.payload_len)(input)?;
738
739 let mut p = Ping {
740 payload: [0; 8],
741 ack: header.flags & FLAG_ACK != 0,
742 };
743 p.payload[..8].copy_from_slice(&data[..8]);
744
745 Ok((i, Frame::Ping(p)))
746}
747
748#[derive(Clone, Debug)]
749pub struct GoAway {
750 pub last_stream_id: u32,
751 pub error_code: u32,
752 pub additional_debug_data: Slice,
753}
754
755pub fn goaway_frame<'a>(
756 input: &'a [u8],
757 header: &FrameHeader,
758) -> IResult<&'a [u8], Frame, ParserError<'a>> {
759 let (remaining, i) = take(header.payload_len)(input)?;
760 let (i, raw_last_stream_id) = be_u32(i)?;
761 let last_stream_id = raw_last_stream_id & STREAM_ID_MASK;
763 let (additional_debug_data, error_code) = be_u32(i)?;
764 Ok((
765 remaining,
766 Frame::GoAway(GoAway {
767 last_stream_id,
768 error_code,
769 additional_debug_data: Slice::new(input, additional_debug_data),
770 }),
771 ))
772}
773
774#[derive(Clone, Debug, PartialEq)]
775pub struct WindowUpdate {
776 pub stream_id: u32,
777 pub increment: u32,
778}
779
780pub fn window_update_frame<'a>(
781 input: &'a [u8],
782 header: &FrameHeader,
783) -> IResult<&'a [u8], Frame, ParserError<'a>> {
784 let (i, data) = take(header.payload_len)(input)?;
788 let (_, increment) = be_u32(data)?;
789 let increment = increment & STREAM_ID_MASK;
790
791 Ok((
799 i,
800 Frame::WindowUpdate(WindowUpdate {
801 stream_id: header.stream_id,
802 increment,
803 }),
804 ))
805}
806
807#[derive(Clone, Debug)]
815pub struct Continuation;
816
817pub fn continuation_frame<'a>(
818 input: &'a [u8],
819 header: &FrameHeader,
820) -> IResult<&'a [u8], Frame, ParserError<'a>> {
821 let (remaining, _) = take(header.payload_len)(input)?;
823 Ok((remaining, Frame::Continuation(Continuation)))
824}
825
826pub fn unknown_frame<'a>(
831 input: &'a [u8],
832 header: &FrameHeader,
833) -> IResult<&'a [u8], Frame, ParserError<'a>> {
834 let (remaining, _payload) = take(header.payload_len)(input)?;
835 let raw = match header.frame_type {
836 FrameType::Unknown(t) => t,
837 _ => 0,
838 };
839 Ok((remaining, Frame::Unknown(raw)))
840}
841
842pub fn priority_update_frame<'a>(
859 input: &'a [u8],
860 header: &FrameHeader,
861) -> IResult<&'a [u8], Frame, ParserError<'a>> {
862 if header.payload_len < PRIORITY_UPDATE_MIN_PAYLOAD {
863 return Err(Err::Failure(ParserError::new_h2(
864 input,
865 H2Error::FrameSizeError,
866 )));
867 }
868 let value_len = (header.payload_len - PRIORITY_UPDATE_MIN_PAYLOAD) as usize;
877 if value_len > PRIORITY_UPDATE_MAX_VALUE {
878 return Err(Err::Failure(ParserError::new_h2(
879 input,
880 H2Error::ProtocolError,
881 )));
882 }
883 let (remaining, payload) = take(header.payload_len)(input)?;
884 let (raw_id_bytes, value_bytes) = payload.split_at(PRIORITY_UPDATE_MIN_PAYLOAD as usize);
885 let prioritized_stream_id = u32::from_be_bytes([
886 raw_id_bytes[0],
887 raw_id_bytes[1],
888 raw_id_bytes[2],
889 raw_id_bytes[3],
890 ]) & STREAM_ID_MASK;
891 Ok((
892 remaining,
893 Frame::PriorityUpdate(PriorityUpdate {
894 prioritized_stream_id,
895 priority_field_value: value_bytes.to_vec(),
896 }),
897 ))
898}
899
900pub const PRIORITY_UPDATE_MIN_PAYLOAD: u32 = 4;
904
905pub const PRIORITY_UPDATE_MAX_VALUE: usize = 1024;
913
914#[cfg(test)]
915mod tests {
916 use super::*;
917
918 const DEFAULT_MAX_FRAME_SIZE: u32 = 1 << 14;
920
921 #[test]
927 fn test_settings_ack_with_payload_rejected() {
928 let input = [
930 0x00, 0x00, 0x06, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64,
936 ];
937
938 let (remaining, header) =
939 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
940 assert_eq!(header.frame_type, FrameType::Settings);
941 assert_eq!(header.flags & FLAG_ACK, FLAG_ACK);
942 assert_eq!(header.payload_len, 6);
943
944 let result = frame_body(remaining, &header);
945 assert!(
946 result.is_err(),
947 "SETTINGS ACK with non-empty payload must be rejected"
948 );
949 match result {
950 Err(nom::Err::Failure(e)) => {
951 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
952 }
953 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
954 }
955 }
956
957 #[test]
963 fn test_settings_ack_empty_accepted() {
964 let input = [
965 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, ];
970
971 let (remaining, header) =
972 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
973 assert_eq!(header.frame_type, FrameType::Settings);
974 assert_eq!(header.flags & FLAG_ACK, FLAG_ACK);
975
976 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
977 match frame {
978 Frame::Settings(settings) => {
979 assert!(settings.ack, "ACK flag must be set");
980 assert!(
981 settings.settings.is_empty(),
982 "should have no settings entries"
983 );
984 }
985 other => panic!("expected Frame::Settings, got {other:?}"),
986 }
987 }
988
989 #[test]
994 fn test_window_update_max_increment() {
995 let input = [
996 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFF, ];
1002
1003 let (remaining, header) =
1004 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1005 assert_eq!(header.frame_type, FrameType::WindowUpdate);
1006 assert_eq!(header.stream_id, 1);
1007
1008 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
1009 match frame {
1010 Frame::WindowUpdate(wu) => {
1011 assert_eq!(wu.increment, 0x7FFFFFFF);
1012 assert_eq!(wu.stream_id, 1);
1013 }
1014 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1015 }
1016 }
1017
1018 #[test]
1024 fn test_window_update_zero_increment_parsed() {
1025 let input = [
1027 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
1033
1034 let (remaining, header) =
1035 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1036 assert_eq!(header.frame_type, FrameType::WindowUpdate);
1037
1038 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
1039 match frame {
1040 Frame::WindowUpdate(wu) => {
1041 assert_eq!(wu.stream_id, 0);
1042 assert_eq!(wu.increment, 0);
1043 }
1044 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1045 }
1046
1047 let input2 = [
1049 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, ];
1055
1056 let (remaining2, header2) =
1057 frame_header(&input2, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1058 let (_, frame2) =
1059 frame_body(remaining2, &header2).expect("second frame body parses cleanly");
1060 match frame2 {
1061 Frame::WindowUpdate(wu) => {
1062 assert_eq!(wu.stream_id, 3);
1063 assert_eq!(wu.increment, 0);
1064 }
1065 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1066 }
1067 }
1068
1069 #[test]
1077 fn test_unknown_frame_type_is_ignored() {
1078 let input = [
1079 0x00, 0x00, 0x04, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef, ];
1085
1086 let (remaining, header) = frame_header(&input, DEFAULT_MAX_FRAME_SIZE)
1087 .expect("unknown frame header must parse cleanly");
1088 assert!(matches!(header.frame_type, FrameType::Unknown(0xFF)));
1089 assert_eq!(header.payload_len, 4);
1090
1091 let (after, frame) =
1092 frame_body(remaining, &header).expect("unknown frame body must be consumed");
1093 assert!(after.is_empty(), "payload bytes must be consumed");
1094 match frame {
1095 Frame::Unknown(0xFF) => {}
1096 other => panic!("expected Frame::Unknown(0xFF), got {other:?}"),
1097 }
1098 }
1099
1100 #[test]
1105 fn test_priority_update_empty_field_parses() {
1106 let input = [
1107 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1113 ];
1114
1115 let (remaining, header) = frame_header(&input, DEFAULT_MAX_FRAME_SIZE)
1116 .expect("PRIORITY_UPDATE header must parse");
1117 assert!(matches!(header.frame_type, FrameType::PriorityUpdate));
1118 let (_, frame) = frame_body(remaining, &header).expect("body must be consumed");
1119 match frame {
1120 Frame::PriorityUpdate(PriorityUpdate {
1121 prioritized_stream_id,
1122 ref priority_field_value,
1123 }) => {
1124 assert_eq!(prioritized_stream_id, 1);
1125 assert!(priority_field_value.is_empty());
1126 }
1127 other => panic!("expected Frame::PriorityUpdate, got {other:?}"),
1128 }
1129 }
1130
1131 #[test]
1135 fn test_priority_update_with_priority_field_parses() {
1136 let value = b"u=0, i";
1137 let mut input = vec![
1138 0x00,
1139 0x00,
1140 0x04 + value.len() as u8, 0x10, 0x00, 0x00,
1144 0x00,
1145 0x00,
1146 0x00, 0x00,
1148 0x00,
1149 0x00,
1150 0x05, ];
1152 input.extend_from_slice(value);
1153
1154 let (remaining, header) =
1155 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("header parses");
1156 assert!(matches!(header.frame_type, FrameType::PriorityUpdate));
1157 let (_, frame) = frame_body(remaining, &header).expect("body parses");
1158 match frame {
1159 Frame::PriorityUpdate(PriorityUpdate {
1160 prioritized_stream_id,
1161 ref priority_field_value,
1162 }) => {
1163 assert_eq!(prioritized_stream_id, 5);
1164 assert_eq!(priority_field_value.as_slice(), value);
1165 }
1166 other => panic!("expected Frame::PriorityUpdate, got {other:?}"),
1167 }
1168 }
1169
1170 #[test]
1173 fn test_priority_update_payload_below_min_is_frame_size_error() {
1174 let input = [
1175 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1177 ];
1178 let (remaining, header) =
1179 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("header parses");
1180 let result = frame_body(remaining, &header);
1181 match result {
1182 Err(Err::Failure(e)) => {
1183 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1184 }
1185 other => panic!("expected FRAME_SIZE_ERROR, got {other:?}"),
1186 }
1187 }
1188
1189 #[test]
1195 fn test_priority_update_oversized_value_is_protocol_error() {
1196 let payload_len = (PRIORITY_UPDATE_MIN_PAYLOAD as usize) + PRIORITY_UPDATE_MAX_VALUE + 1;
1198 let mut input = Vec::with_capacity(9 + payload_len);
1199 input.push(((payload_len >> 16) & 0xff) as u8);
1201 input.push(((payload_len >> 8) & 0xff) as u8);
1202 input.push((payload_len & 0xff) as u8);
1203 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));
1208 let (remaining, header) =
1211 frame_header(&input, payload_len as u32 + 1).expect("header parses");
1212 match frame_body(remaining, &header) {
1213 Err(Err::Failure(e)) => {
1214 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1215 }
1216 other => {
1217 panic!("expected PROTOCOL_ERROR for oversized PRIORITY_UPDATE value, got {other:?}")
1218 }
1219 }
1220 }
1221
1222 #[test]
1225 fn test_priority_update_at_max_value_accepted() {
1226 let payload_len = (PRIORITY_UPDATE_MIN_PAYLOAD as usize) + PRIORITY_UPDATE_MAX_VALUE;
1227 let mut input = Vec::with_capacity(9 + payload_len);
1228 input.push(((payload_len >> 16) & 0xff) as u8);
1229 input.push(((payload_len >> 8) & 0xff) as u8);
1230 input.push((payload_len & 0xff) as u8);
1231 input.push(0x10);
1232 input.push(0x00);
1233 input.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]);
1234 input.extend_from_slice(&[0x00, 0x00, 0x00, 0x01]);
1235 input.extend(std::iter::repeat_n(b'a', PRIORITY_UPDATE_MAX_VALUE));
1236 let (remaining, header) =
1237 frame_header(&input, payload_len as u32 + 1).expect("header parses");
1238 match frame_body(remaining, &header) {
1239 Ok((_, Frame::PriorityUpdate(pu))) => {
1240 assert_eq!(pu.priority_field_value.len(), PRIORITY_UPDATE_MAX_VALUE);
1241 }
1242 other => panic!("expected Frame::PriorityUpdate at the cap boundary, got {other:?}"),
1243 }
1244 }
1245
1246 #[test]
1251 fn test_priority_update_on_non_zero_stream_is_protocol_error() {
1252 let input = [
1253 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, ];
1259 match frame_header(&input, DEFAULT_MAX_FRAME_SIZE) {
1260 Err(Err::Failure(e)) => {
1261 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1262 }
1263 other => panic!("expected PROTOCOL_ERROR, got {other:?}"),
1264 }
1265 }
1266
1267 #[test]
1272 fn test_settings_payload_not_multiple_of_6_rejected() {
1273 let input = [
1274 0x00, 0x00, 0x05, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, ];
1280
1281 let (remaining, header) =
1282 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1283 assert_eq!(header.frame_type, FrameType::Settings);
1284
1285 let result = frame_body(remaining, &header);
1286 assert!(
1287 result.is_err(),
1288 "odd-size SETTINGS payload must be rejected"
1289 );
1290 match result {
1291 Err(nom::Err::Failure(e)) => {
1292 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1293 }
1294 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1295 }
1296 }
1297
1298 #[test]
1303 fn test_settings_frame_over_cap_rejected() {
1304 let n_entries: u16 = (MAX_SETTINGS_ENTRIES as u16) + 1;
1306 let payload_len = u32::from(n_entries) * SETTINGS_ENTRY_SIZE;
1307 let mut input = Vec::with_capacity(9 + payload_len as usize);
1308 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 {
1313 input.extend_from_slice(&i.to_be_bytes()); input.extend_from_slice(&0u32.to_be_bytes()); }
1316
1317 let (remaining, header) =
1318 frame_header(&input, 16_777_215).expect("frame header parses cleanly");
1319 assert_eq!(header.frame_type, FrameType::Settings);
1320
1321 let result = frame_body(remaining, &header);
1322 assert!(
1323 result.is_err(),
1324 "SETTINGS frame over MAX_SETTINGS_ENTRIES must be rejected"
1325 );
1326 match result {
1327 Err(nom::Err::Failure(e)) => {
1328 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1329 }
1330 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1331 }
1332 }
1333
1334 #[test]
1336 fn test_settings_frame_at_cap_accepted() {
1337 let n_entries: u16 = MAX_SETTINGS_ENTRIES as u16;
1338 let payload_len = u32::from(n_entries) * SETTINGS_ENTRY_SIZE;
1339 let mut input = Vec::with_capacity(9 + payload_len as usize);
1340 input.extend_from_slice(&payload_len.to_be_bytes()[1..]);
1341 input.push(0x04);
1342 input.push(0x00);
1343 input.extend_from_slice(&[0, 0, 0, 0]);
1344 for _ in 0..n_entries {
1345 input.extend_from_slice(&0u16.to_be_bytes());
1346 input.extend_from_slice(&0u32.to_be_bytes());
1347 }
1348
1349 let (remaining, header) =
1350 frame_header(&input, 16_777_215).expect("frame header parses cleanly");
1351 let result = frame_body(remaining, &header);
1352 assert!(result.is_ok(), "exactly MAX_SETTINGS_ENTRIES must parse");
1353 }
1354
1355 #[test]
1359 fn test_rst_stream_wrong_payload_size_rejected() {
1360 let input = [
1362 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
1368
1369 let (remaining, header) =
1370 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1371 assert_eq!(header.frame_type, FrameType::RstStream);
1372
1373 let result = frame_body(remaining, &header);
1374 assert!(
1375 result.is_err(),
1376 "wrong RST_STREAM payload size must be rejected"
1377 );
1378 match result {
1379 Err(nom::Err::Failure(e)) => {
1380 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1381 }
1382 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1383 }
1384 }
1385
1386 #[test]
1390 fn test_ping_wrong_payload_size_rejected() {
1391 let input = [
1392 0x00, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, ];
1398
1399 let (remaining, header) =
1400 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1401 assert_eq!(header.frame_type, FrameType::Ping);
1402
1403 let result = frame_body(remaining, &header);
1404 assert!(result.is_err(), "wrong PING payload size must be rejected");
1405 match result {
1406 Err(nom::Err::Failure(e)) => {
1407 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1408 }
1409 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1410 }
1411 }
1412
1413 #[test]
1418 fn test_frame_exceeding_max_frame_size_rejected() {
1419 let input = [
1421 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, ];
1426
1427 let result = frame_header(&input, DEFAULT_MAX_FRAME_SIZE);
1428 assert!(result.is_err(), "oversized frame must be rejected");
1429 match result {
1430 Err(nom::Err::Failure(e)) => {
1431 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1432 }
1433 other => panic!("expected Failure(FrameSizeError), got {other:?}"),
1434 }
1435 }
1436
1437 #[test]
1441 fn test_settings_on_nonzero_stream_rejected() {
1442 let input = [
1443 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, ];
1448
1449 let result = frame_header(&input, DEFAULT_MAX_FRAME_SIZE);
1450 assert!(
1451 result.is_err(),
1452 "SETTINGS on non-zero stream must be rejected"
1453 );
1454 match result {
1455 Err(nom::Err::Failure(e)) => {
1456 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1457 }
1458 other => panic!("expected Failure(ProtocolError), got {other:?}"),
1459 }
1460 }
1461
1462 #[test]
1466 fn test_data_on_stream_zero_rejected() {
1467 let input = [
1468 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCA, 0xFE,
1473 ];
1474
1475 let result = frame_header(&input, DEFAULT_MAX_FRAME_SIZE);
1476 assert!(result.is_err(), "DATA on stream 0 must be rejected");
1477 match result {
1478 Err(nom::Err::Failure(e)) => {
1479 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::ProtocolError));
1480 }
1481 other => panic!("expected Failure(ProtocolError), got {other:?}"),
1482 }
1483 }
1484
1485 #[test]
1490 fn test_window_update_reserved_bit_masked() {
1491 let input = [
1492 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, ];
1498
1499 let (remaining, header) =
1500 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1501 let (_, frame) = frame_body(remaining, &header).expect("frame body parses cleanly");
1502 match frame {
1503 Frame::WindowUpdate(wu) => {
1504 assert_eq!(
1505 wu.increment, 1,
1506 "reserved bit must be masked to yield increment=1"
1507 );
1508 }
1509 other => panic!("expected Frame::WindowUpdate, got {other:?}"),
1510 }
1511 }
1512
1513 fn build_frame_header(payload_len: u32, frame_type: u8, flags: u8, stream_id: u32) -> Vec<u8> {
1517 vec![
1518 ((payload_len >> 16) & 0xFF) as u8,
1519 ((payload_len >> 8) & 0xFF) as u8,
1520 (payload_len & 0xFF) as u8,
1521 frame_type,
1522 flags,
1523 ((stream_id >> 24) & 0xFF) as u8,
1524 ((stream_id >> 16) & 0xFF) as u8,
1525 ((stream_id >> 8) & 0xFF) as u8,
1526 (stream_id & 0xFF) as u8,
1527 ]
1528 }
1529
1530 fn build_raw_frame(
1532 payload_len: u32,
1533 frame_type: u8,
1534 flags: u8,
1535 stream_id: u32,
1536 payload: &[u8],
1537 ) -> Vec<u8> {
1538 let mut raw = build_frame_header(payload_len, frame_type, flags, stream_id);
1539 raw.extend_from_slice(payload);
1540 raw
1541 }
1542
1543 #[test]
1546 fn test_preface_valid() {
1547 let input = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
1548 let (remaining, matched) = preface(input).expect("should parse preface");
1549 assert!(remaining.is_empty());
1550 assert_eq!(matched, input.as_slice());
1551 }
1552
1553 #[test]
1554 fn test_preface_invalid() {
1555 let input = b"GET / HTTP/1.1\r\n";
1556 let result = preface(input);
1557 assert!(result.is_err(), "invalid preface should fail");
1558 }
1559
1560 #[test]
1561 fn test_preface_with_trailing_data() {
1562 let mut input = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".to_vec();
1563 input.extend_from_slice(b"extra stuff");
1564 let (remaining, _) = preface(&input).expect("should parse preface");
1565 assert_eq!(remaining, b"extra stuff");
1566 }
1567
1568 #[test]
1571 fn test_frame_header_settings_basic() {
1572 let raw = build_frame_header(0, 4, 0, 0);
1573 let (remaining, header) =
1574 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1575 assert!(remaining.is_empty());
1576 assert_eq!(header.payload_len, 0);
1577 assert_eq!(header.frame_type, FrameType::Settings);
1578 assert_eq!(header.flags, 0);
1579 assert_eq!(header.stream_id, 0);
1580 }
1581
1582 #[test]
1583 fn test_frame_header_data_basic() {
1584 let raw = build_frame_header(100, 0, 1, 1);
1585 let (_, header) =
1586 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1587 assert_eq!(header.payload_len, 100);
1588 assert_eq!(header.frame_type, FrameType::Data);
1589 assert_eq!(header.flags, 1);
1590 assert_eq!(header.stream_id, 1);
1591 }
1592
1593 #[test]
1594 fn test_frame_header_stream_id_reserved_bit_masked() {
1595 let raw = build_frame_header(5, 0, 0, 0x80000001);
1598 let (_, header) =
1599 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1600 assert_eq!(header.stream_id, 1, "reserved MSB must be masked off");
1601 }
1602
1603 #[test]
1606 fn test_parse_data_frame_end_stream() {
1607 let payload = b"hello";
1608 let raw = build_raw_frame(payload.len() as u32, 0, 0x01, 1, payload);
1609 let (remaining, header) =
1610 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1611 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1612 match f {
1613 Frame::Data(d) => {
1614 assert_eq!(d.stream_id, 1);
1615 assert!(d.end_stream);
1616 }
1617 other => panic!("expected Data, got {other:?}"),
1618 }
1619 }
1620
1621 #[test]
1622 fn test_parse_data_frame_no_end_stream() {
1623 let payload = b"data";
1624 let raw = build_raw_frame(payload.len() as u32, 0, 0x00, 3, payload);
1625 let (remaining, header) =
1626 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1627 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1628 match f {
1629 Frame::Data(d) => {
1630 assert_eq!(d.stream_id, 3);
1631 assert!(!d.end_stream);
1632 }
1633 other => panic!("expected Data, got {other:?}"),
1634 }
1635 }
1636
1637 #[test]
1638 fn test_parse_data_frame_with_padding() {
1639 let pad_length: u8 = 2;
1641 let actual_data = b"hello";
1642 let total_payload = 1 + actual_data.len() + pad_length as usize;
1643 let mut payload = Vec::new();
1644 payload.push(pad_length);
1645 payload.extend_from_slice(actual_data);
1646 payload.extend_from_slice(&[0x00; 2]);
1647
1648 let raw = build_raw_frame(total_payload as u32, 0, 0x08, 1, &payload);
1649 let (remaining, header) =
1650 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1651 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1652 match f {
1653 Frame::Data(d) => {
1654 assert_eq!(d.stream_id, 1);
1655 assert_eq!(d.payload.len, actual_data.len() as u32);
1656 }
1657 other => panic!("expected Data, got {other:?}"),
1658 }
1659 }
1660
1661 #[test]
1662 fn test_parse_data_frame_padding_exceeds_payload() {
1663 let mut payload = Vec::new();
1665 payload.push(10); payload.extend_from_slice(b"hello");
1667
1668 let raw = build_raw_frame(payload.len() as u32, 0, 0x08, 1, &payload);
1669 let (remaining, header) =
1670 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1671 let result = frame_body(remaining, &header);
1672 assert!(
1673 result.is_err(),
1674 "padding exceeding payload should be a protocol error"
1675 );
1676 }
1677
1678 #[test]
1681 fn test_parse_headers_frame_basic() {
1682 let hblock = b"\x82\x86";
1683 let raw = build_raw_frame(hblock.len() as u32, 1, 0x04, 1, hblock);
1684 let (remaining, header) =
1685 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1686 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1687 match f {
1688 Frame::Headers(h) => {
1689 assert_eq!(h.stream_id, 1);
1690 assert!(!h.end_stream);
1691 assert!(h.end_headers);
1692 assert!(h.priority.is_none());
1693 }
1694 other => panic!("expected Headers, got {other:?}"),
1695 }
1696 }
1697
1698 #[test]
1699 fn test_parse_headers_frame_end_stream_and_headers() {
1700 let hblock = b"\x82";
1701 let raw = build_raw_frame(hblock.len() as u32, 1, 0x05, 1, hblock);
1702 let (remaining, header) =
1703 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1704 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1705 match f {
1706 Frame::Headers(h) => {
1707 assert!(h.end_stream);
1708 assert!(h.end_headers);
1709 }
1710 other => panic!("expected Headers, got {other:?}"),
1711 }
1712 }
1713
1714 #[test]
1715 fn test_parse_headers_frame_with_priority() {
1716 let hblock = b"\x82";
1717 let payload_len = 5 + hblock.len(); let mut payload = Vec::new();
1719 payload.extend_from_slice(&[0x00, 0x00, 0x00, 0x01]);
1721 payload.push(15); payload.extend_from_slice(hblock);
1723
1724 let raw = build_raw_frame(payload_len as u32, 1, 0x24, 3, &payload);
1725 let (remaining, header) =
1726 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1727 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1728 match f {
1729 Frame::Headers(h) => {
1730 assert_eq!(h.stream_id, 3);
1731 let priority = h.priority.expect("should have priority");
1732 match priority {
1733 PriorityPart::Rfc7540 {
1734 stream_dependency,
1735 weight,
1736 } => {
1737 assert!(!stream_dependency.exclusive);
1738 assert_eq!(stream_dependency.stream_id, 1);
1739 assert_eq!(weight, 15);
1740 }
1741 other => panic!("expected Rfc7540, got {other:?}"),
1742 }
1743 }
1744 other => panic!("expected Headers, got {other:?}"),
1745 }
1746 }
1747
1748 #[test]
1749 fn test_parse_headers_frame_with_exclusive_priority() {
1750 let hblock = b"\x82\x86";
1751 let mut payload = Vec::new();
1752 let dep = 0x80000005u32;
1754 payload.extend_from_slice(&dep.to_be_bytes());
1755 payload.push(255); payload.extend_from_slice(hblock);
1757
1758 let payload_len = payload.len();
1759 let raw = build_raw_frame(payload_len as u32, 1, 0x24, 3, &payload);
1760 let (remaining, header) =
1761 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1762 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1763 match f {
1764 Frame::Headers(h) => {
1765 let priority = h.priority.expect("should have priority");
1766 match priority {
1767 PriorityPart::Rfc7540 {
1768 stream_dependency,
1769 weight,
1770 } => {
1771 assert!(stream_dependency.exclusive, "exclusive bit should be set");
1772 assert_eq!(stream_dependency.stream_id, 5);
1773 assert_eq!(weight, 255);
1774 }
1775 other => panic!("expected Rfc7540, got {other:?}"),
1776 }
1777 }
1778 other => panic!("expected Headers, got {other:?}"),
1779 }
1780 }
1781
1782 #[test]
1783 fn test_parse_headers_stream_id_zero_rejected() {
1784 let raw = build_raw_frame(2, 1, 0x04, 0, b"\x82\x86");
1785 let result = frame_header(&raw, DEFAULT_MAX_FRAME_SIZE);
1786 assert!(
1787 result.is_err(),
1788 "HEADERS with stream_id=0 should be rejected"
1789 );
1790 }
1791
1792 #[test]
1795 fn test_parse_rst_stream() {
1796 let error_code = 0x00000008u32; let raw = build_raw_frame(4, 3, 0, 1, &error_code.to_be_bytes());
1798 let (remaining, header) =
1799 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1800 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1801 match f {
1802 Frame::RstStream(rst) => {
1803 assert_eq!(rst.stream_id, 1);
1804 assert_eq!(rst.error_code, 0x08);
1805 }
1806 other => panic!("expected RstStream, got {other:?}"),
1807 }
1808 }
1809
1810 #[test]
1811 fn test_parse_rst_stream_stream_id_zero_rejected() {
1812 let raw = build_raw_frame(4, 3, 0, 0, &[0u8; 4]);
1813 let result = frame_header(&raw, DEFAULT_MAX_FRAME_SIZE);
1814 assert!(
1815 result.is_err(),
1816 "RST_STREAM with stream_id=0 should be rejected"
1817 );
1818 }
1819
1820 #[test]
1823 fn test_parse_settings_frame_with_values() {
1824 let mut payload = Vec::new();
1825 payload.extend_from_slice(&0x0001u16.to_be_bytes());
1827 payload.extend_from_slice(&4096u32.to_be_bytes());
1828 payload.extend_from_slice(&0x0003u16.to_be_bytes());
1830 payload.extend_from_slice(&100u32.to_be_bytes());
1831 payload.extend_from_slice(&0x0004u16.to_be_bytes());
1833 payload.extend_from_slice(&65535u32.to_be_bytes());
1834
1835 let raw = build_raw_frame(payload.len() as u32, 4, 0x0, 0, &payload);
1836 let (remaining, header) =
1837 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1838 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1839 match f {
1840 Frame::Settings(s) => {
1841 assert!(!s.ack);
1842 assert_eq!(s.settings.len(), 3);
1843 assert_eq!(s.settings[0].identifier, 0x0001);
1844 assert_eq!(s.settings[0].value, 4096);
1845 assert_eq!(s.settings[1].identifier, 0x0003);
1846 assert_eq!(s.settings[1].value, 100);
1847 assert_eq!(s.settings[2].identifier, 0x0004);
1848 assert_eq!(s.settings[2].value, 65535);
1849 }
1850 other => panic!("expected Settings, got {other:?}"),
1851 }
1852 }
1853
1854 #[test]
1857 fn test_parse_ping_frame() {
1858 let ping_payload = [1u8, 2, 3, 4, 5, 6, 7, 8];
1859 let raw = build_raw_frame(8, 6, 0, 0, &ping_payload);
1860 let (remaining, header) =
1861 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1862 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1863 match f {
1864 Frame::Ping(p) => {
1865 assert_eq!(p.payload, ping_payload);
1866 assert!(!p.ack);
1867 }
1868 other => panic!("expected Ping, got {other:?}"),
1869 }
1870 }
1871
1872 #[test]
1873 fn test_parse_ping_ack_preserves_payload() {
1874 let ping_payload = [0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE];
1875 let raw = build_raw_frame(8, 6, 0x01, 0, &ping_payload);
1876 let (remaining, header) =
1877 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1878 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1879 match f {
1880 Frame::Ping(p) => {
1881 assert_eq!(
1882 p.payload, ping_payload,
1883 "PING ACK must echo the exact payload"
1884 );
1885 assert!(p.ack);
1886 }
1887 other => panic!("expected Ping, got {other:?}"),
1888 }
1889 }
1890
1891 #[test]
1892 fn test_parse_ping_stream_id_nonzero_rejected() {
1893 let raw = build_raw_frame(8, 6, 0, 1, &[0u8; 8]);
1894 let result = frame_header(&raw, DEFAULT_MAX_FRAME_SIZE);
1895 assert!(result.is_err(), "PING with stream_id!=0 should be rejected");
1896 }
1897
1898 #[test]
1901 fn test_parse_window_update_connection_level() {
1902 let increment = 1000u32;
1903 let raw = build_raw_frame(4, 8, 0, 0, &increment.to_be_bytes());
1904 let (remaining, header) =
1905 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1906 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1907 match f {
1908 Frame::WindowUpdate(w) => {
1909 assert_eq!(w.stream_id, 0);
1910 assert_eq!(w.increment, 1000);
1911 }
1912 other => panic!("expected WindowUpdate, got {other:?}"),
1913 }
1914 }
1915
1916 #[test]
1917 fn test_parse_window_update_stream_level() {
1918 let increment = 65535u32;
1919 let raw = build_raw_frame(4, 8, 0, 5, &increment.to_be_bytes());
1920 let (remaining, header) =
1921 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1922 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1923 match f {
1924 Frame::WindowUpdate(w) => {
1925 assert_eq!(w.stream_id, 5);
1926 assert_eq!(w.increment, 65535);
1928 }
1929 other => panic!("expected WindowUpdate, got {other:?}"),
1930 }
1931 }
1932
1933 #[test]
1934 fn test_parse_window_update_wrong_size() {
1935 let raw = build_raw_frame(3, 8, 0, 0, &[0u8; 3]);
1936 let (remaining, header) =
1937 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1938 let result = frame_body(remaining, &header);
1939 assert!(
1940 result.is_err(),
1941 "WINDOW_UPDATE with payload != 4 should fail"
1942 );
1943 match result {
1944 Err(Err::Failure(e)) => {
1945 assert_eq!(e.kind, ParserErrorKind::H2(H2Error::FrameSizeError));
1946 }
1947 other => panic!("expected FrameSizeError, got {other:?}"),
1948 }
1949 }
1950
1951 #[test]
1954 fn test_parse_frame_at_max_frame_size() {
1955 let payload = vec![0u8; DEFAULT_MAX_FRAME_SIZE as usize];
1956 let raw = build_raw_frame(DEFAULT_MAX_FRAME_SIZE, 0, 0x0, 1, &payload);
1957 let (remaining, header) =
1958 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
1959 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1960 match f {
1961 Frame::Data(d) => {
1962 assert_eq!(d.payload.len, DEFAULT_MAX_FRAME_SIZE);
1963 }
1964 other => panic!("expected Data, got {other:?}"),
1965 }
1966 }
1967
1968 #[test]
1969 fn test_parse_frame_with_custom_max_frame_size() {
1970 let custom_max = 32768u32;
1971 let payload = vec![0u8; 20000];
1972 let raw = build_raw_frame(20000, 0, 0x0, 1, &payload);
1973 let (remaining, header) =
1974 frame_header(&raw, custom_max).expect("frame header parses with custom max");
1975 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
1976 match f {
1977 Frame::Data(d) => {
1978 assert_eq!(d.payload.len, 20000);
1979 }
1980 other => panic!("expected Data, got {other:?}"),
1981 }
1982 }
1983
1984 #[test]
1987 fn test_h2_error_try_from_valid() {
1988 assert_eq!(H2Error::try_from(0x0), Ok(H2Error::NoError));
1989 assert_eq!(H2Error::try_from(0x1), Ok(H2Error::ProtocolError));
1990 assert_eq!(H2Error::try_from(0x6), Ok(H2Error::FrameSizeError));
1991 assert_eq!(H2Error::try_from(0xd), Ok(H2Error::HTTP11Required));
1992 }
1993
1994 #[test]
1995 fn test_h2_error_try_from_invalid() {
1996 assert_eq!(H2Error::try_from(0x0e), Err(0x0e));
1997 assert_eq!(H2Error::try_from(0xFF), Err(0xFF));
1998 }
1999
2000 #[test]
2001 fn test_h2_error_from_str() {
2002 assert_eq!("NO_ERROR".parse::<H2Error>(), Ok(H2Error::NoError));
2003 assert_eq!(
2004 "PROTOCOL_ERROR".parse::<H2Error>(),
2005 Ok(H2Error::ProtocolError)
2006 );
2007 assert_eq!(
2008 "ENHANCE_YOUR_CALM".parse::<H2Error>(),
2009 Ok(H2Error::EnhanceYourCalm)
2010 );
2011 assert!("INVALID_ERROR".parse::<H2Error>().is_err());
2012 }
2013
2014 #[test]
2015 fn test_h2_error_as_str_roundtrip() {
2016 let errors = [
2017 H2Error::NoError,
2018 H2Error::ProtocolError,
2019 H2Error::InternalError,
2020 H2Error::FlowControlError,
2021 H2Error::SettingsTimeout,
2022 H2Error::StreamClosed,
2023 H2Error::FrameSizeError,
2024 H2Error::RefusedStream,
2025 H2Error::Cancel,
2026 H2Error::CompressionError,
2027 H2Error::ConnectError,
2028 H2Error::EnhanceYourCalm,
2029 H2Error::InadequateSecurity,
2030 H2Error::HTTP11Required,
2031 ];
2032
2033 for error in &errors {
2034 let s = error.as_str();
2035 let parsed: H2Error = s.parse().unwrap_or_else(|_| panic!("failed to parse {s}"));
2036 assert_eq!(*error, parsed, "roundtrip failed for {s}");
2037 }
2038 }
2039
2040 #[test]
2043 fn test_parse_priority_frame() {
2044 let mut payload = Vec::new();
2045 payload.extend_from_slice(&0x00000001u32.to_be_bytes());
2047 payload.push(15); assert_eq!(payload.len(), 5);
2049
2050 let raw = build_raw_frame(5, 2, 0, 3, &payload);
2051 let (remaining, header) =
2052 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2053 let (_, f) = frame_body(remaining, &header).expect("frame body parses cleanly");
2054 match f {
2055 Frame::Priority(p) => {
2056 assert_eq!(p.stream_id, 3);
2057 match p.inner {
2058 PriorityPart::Rfc7540 {
2059 stream_dependency,
2060 weight,
2061 } => {
2062 assert!(!stream_dependency.exclusive);
2063 assert_eq!(stream_dependency.stream_id, 1);
2064 assert_eq!(weight, 15);
2065 }
2066 other => panic!("expected Rfc7540, got {other:?}"),
2067 }
2068 }
2069 other => panic!("expected Priority, got {other:?}"),
2070 }
2071 }
2072
2073 #[test]
2074 fn test_parse_priority_wrong_size_rejected() {
2075 let raw = build_raw_frame(4, 2, 0, 1, &[0u8; 4]);
2076 let (remaining, header) =
2077 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2078 let result = frame_body(remaining, &header);
2079 assert!(
2080 result.is_err(),
2081 "PRIORITY with wrong payload size should fail"
2082 );
2083 }
2084
2085 #[test]
2092 fn test_headers_padded_priority_underflow_rejected() {
2093 let raw: [u8; 16] = [
2094 0x00, 0x00, 0x06, 0x01, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x00, 0x64, 0x6d, 0x6d,
2095 0x6d, 0x6d,
2096 ];
2097 let (remaining, header) =
2098 frame_header(&raw, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2099 let result = frame_body(remaining, &header);
2100 assert!(
2101 result.is_err(),
2102 "PADDED+PRIORITY HEADERS with oversized pad_length must error, not panic"
2103 );
2104 }
2105
2106 #[test]
2114 fn test_strip_padding_all_padding_accepted() {
2115 let input = [
2119 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, ];
2126
2127 let (remaining, header) =
2128 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2129 let (_, frame) =
2130 frame_body(remaining, &header).expect("DATA with all-padding body must parse");
2131 match frame {
2132 Frame::Data(data) => {
2133 assert_eq!(data.stream_id, 1);
2134 assert_eq!(data.payload.len, 0);
2136 }
2137 other => panic!("expected Frame::Data, got {other:?}"),
2138 }
2139 }
2140
2141 #[test]
2142 fn test_strip_padding_pad_length_equals_payload_len_rejected() {
2143 let input = [
2147 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x01, ];
2153
2154 let (remaining, header) =
2155 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2156 let result = frame_body(remaining, &header);
2157 assert!(
2158 matches!(
2159 result,
2160 Err(nom::Err::Failure(ParserError {
2161 kind: ParserErrorKind::H2(H2Error::ProtocolError),
2162 ..
2163 }))
2164 ),
2165 "pad_length > remaining body must yield PROTOCOL_ERROR, got {result:?}"
2166 );
2167 }
2168
2169 #[test]
2175 fn test_goaway_short_payload_rejected() {
2176 let input = [
2177 0x00, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
2183
2184 let (remaining, header) =
2185 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2186 assert_eq!(header.frame_type, FrameType::GoAway);
2187 let result = frame_body(remaining, &header);
2188 assert!(
2189 matches!(
2190 result,
2191 Err(nom::Err::Failure(ParserError {
2192 kind: ParserErrorKind::H2(H2Error::FrameSizeError),
2193 ..
2194 }))
2195 ),
2196 "GOAWAY with payload_len < 8 must yield FRAME_SIZE_ERROR, got {result:?}"
2197 );
2198 }
2199
2200 #[test]
2201 fn test_goaway_minimum_payload_accepted() {
2202 let input = [
2203 0x00, 0x00, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, ];
2210
2211 let (remaining, header) =
2212 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2213 let (_, frame) = frame_body(remaining, &header).expect("minimal GOAWAY must parse cleanly");
2214 match frame {
2215 Frame::GoAway(goaway) => {
2216 assert_eq!(goaway.last_stream_id, 10);
2217 assert_eq!(goaway.error_code, 0);
2218 }
2219 other => panic!("expected Frame::GoAway, got {other:?}"),
2220 }
2221 }
2222
2223 #[test]
2231 fn test_push_promise_rejected_at_wire_layer() {
2232 let input = [
2233 0x00, 0x00, 0x08, 0x05, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, ];
2240
2241 let (remaining, header) =
2242 frame_header(&input, DEFAULT_MAX_FRAME_SIZE).expect("frame header parses cleanly");
2243 assert_eq!(header.frame_type, FrameType::PushPromise);
2244 let result = frame_body(remaining, &header);
2245 assert!(
2246 matches!(
2247 result,
2248 Err(nom::Err::Failure(ParserError {
2249 kind: ParserErrorKind::H2(H2Error::ProtocolError),
2250 ..
2251 }))
2252 ),
2253 "PUSH_PROMISE must be rejected at wire layer with PROTOCOL_ERROR, got {result:?}"
2254 );
2255 }
2256}