1use super::{util, StreamDependency, StreamId};
2use crate::ext::Protocol;
3use crate::frame::{Error, Frame, Head, Kind};
4use crate::hpack::{self, BytesStr};
5
6use http::header::{self, HeaderName, HeaderValue};
7use http::{uri, HeaderMap, Method, Request, StatusCode, Uri};
8
9use bytes::{Buf, BufMut, BytesMut};
10
11use std::fmt;
12use std::io::Cursor;
13use std::ops::ControlFlow;
14
15type EncodeBuf<'a> = bytes::buf::Limit<&'a mut BytesMut>;
16
17const MAX_HEADER_LIST_ABUSE_MULTIPLIER: usize = 4;
18
19#[derive(Eq, PartialEq)]
23pub struct Headers {
24 stream_id: StreamId,
26
27 stream_dep: Option<StreamDependency>,
29
30 header_block: HeaderBlock,
32
33 flags: HeadersFlag,
35}
36
37#[derive(Copy, Clone, Eq, PartialEq)]
38pub struct HeadersFlag(u8);
39
40#[derive(Eq, PartialEq)]
41pub struct PushPromise {
42 stream_id: StreamId,
44
45 promised_id: StreamId,
47
48 header_block: HeaderBlock,
50
51 flags: PushPromiseFlag,
53}
54
55#[derive(Copy, Clone, Eq, PartialEq)]
56pub struct PushPromiseFlag(u8);
57
58#[derive(Debug)]
59pub struct Continuation {
60 stream_id: StreamId,
62
63 header_block: EncodingHeaderBlock,
64}
65
66#[derive(Debug, Default, Eq, PartialEq)]
68pub struct Pseudo {
69 pub method: Option<Method>,
71 pub scheme: Option<BytesStr>,
72 pub authority: Option<BytesStr>,
73 pub path: Option<BytesStr>,
74 pub protocol: Option<Protocol>,
75
76 pub status: Option<StatusCode>,
78}
79
80#[derive(Debug)]
81pub struct Iter {
82 pseudo: Option<Pseudo>,
84
85 fields: header::IntoIter<HeaderValue>,
87}
88
89#[derive(Debug, PartialEq, Eq)]
90struct HeaderBlock {
91 fields: HeaderMap,
93
94 field_size: usize,
96
97 is_over_size: bool,
99
100 pseudo: Pseudo,
103}
104
105#[derive(Debug)]
106struct EncodingHeaderBlock {
107 hpack: BytesMut,
108}
109
110const END_STREAM: u8 = 0x1;
111const END_HEADERS: u8 = 0x4;
112const PADDED: u8 = 0x8;
113const PRIORITY: u8 = 0x20;
114const ALL: u8 = END_STREAM | END_HEADERS | PADDED | PRIORITY;
115
116impl Headers {
119 pub fn new(stream_id: StreamId, pseudo: Pseudo, fields: HeaderMap) -> Self {
121 Headers {
122 stream_id,
123 stream_dep: None,
124 header_block: HeaderBlock {
125 field_size: calculate_headermap_size(&fields),
126 fields,
127 is_over_size: false,
128 pseudo,
129 },
130 flags: HeadersFlag::default(),
131 }
132 }
133
134 pub fn trailers(stream_id: StreamId, fields: HeaderMap) -> Self {
135 let mut flags = HeadersFlag::default();
136 flags.set_end_stream();
137
138 Headers {
139 stream_id,
140 stream_dep: None,
141 header_block: HeaderBlock {
142 field_size: calculate_headermap_size(&fields),
143 fields,
144 is_over_size: false,
145 pseudo: Pseudo::default(),
146 },
147 flags,
148 }
149 }
150
151 pub fn load(head: Head, mut src: BytesMut) -> Result<(Self, BytesMut), Error> {
155 let flags = HeadersFlag(head.flag());
156 let mut pad = 0;
157
158 tracing::trace!("loading headers; flags={:?}", flags);
159
160 if head.stream_id().is_zero() {
161 return Err(Error::InvalidStreamId);
162 }
163
164 if flags.is_padded() {
166 if src.is_empty() {
167 return Err(Error::MalformedMessage);
168 }
169 pad = src[0] as usize;
170
171 src.advance(1);
173 }
174
175 let stream_dep = if flags.is_priority() {
177 if src.len() < 5 {
178 return Err(Error::MalformedMessage);
179 }
180 let stream_dep = StreamDependency::load(&src[..5])?;
181
182 if stream_dep.dependency_id() == head.stream_id() {
183 return Err(Error::InvalidDependencyId);
184 }
185
186 src.advance(5);
188
189 Some(stream_dep)
190 } else {
191 None
192 };
193
194 if pad > 0 {
195 if pad > src.len() {
196 return Err(Error::TooMuchPadding);
197 }
198
199 let len = src.len() - pad;
200 src.truncate(len);
201 }
202
203 let headers = Headers {
204 stream_id: head.stream_id(),
205 stream_dep,
206 header_block: HeaderBlock {
207 fields: HeaderMap::new(),
208 field_size: 0,
209 is_over_size: false,
210 pseudo: Pseudo::default(),
211 },
212 flags,
213 };
214
215 Ok((headers, src))
216 }
217
218 pub fn load_hpack(
219 &mut self,
220 src: &mut BytesMut,
221 max_header_list_size: usize,
222 decoder: &mut hpack::Decoder,
223 ) -> Result<(), Error> {
224 self.header_block.load(src, max_header_list_size, decoder)
225 }
226
227 pub fn stream_id(&self) -> StreamId {
228 self.stream_id
229 }
230
231 pub fn is_end_headers(&self) -> bool {
232 self.flags.is_end_headers()
233 }
234
235 pub fn set_end_headers(&mut self) {
236 self.flags.set_end_headers();
237 }
238
239 pub fn is_end_stream(&self) -> bool {
240 self.flags.is_end_stream()
241 }
242
243 pub fn set_end_stream(&mut self) {
244 self.flags.set_end_stream()
245 }
246
247 pub fn is_over_size(&self) -> bool {
248 self.header_block.is_over_size
249 }
250
251 pub fn into_parts(self) -> (Pseudo, HeaderMap) {
252 (self.header_block.pseudo, self.header_block.fields)
253 }
254
255 #[cfg(feature = "unstable")]
256 pub fn pseudo_mut(&mut self) -> &mut Pseudo {
257 &mut self.header_block.pseudo
258 }
259
260 pub(crate) fn pseudo(&self) -> &Pseudo {
261 &self.header_block.pseudo
262 }
263
264 pub(crate) fn is_informational(&self) -> bool {
266 self.header_block.pseudo.is_informational()
267 }
268
269 pub fn fields(&self) -> &HeaderMap {
270 &self.header_block.fields
271 }
272
273 pub fn into_fields(self) -> HeaderMap {
274 self.header_block.fields
275 }
276
277 pub fn encode(
278 self,
279 encoder: &mut hpack::Encoder,
280 dst: &mut EncodeBuf<'_>,
281 ) -> Option<Continuation> {
282 debug_assert!(self.flags.is_end_headers());
284
285 let head = self.head();
287
288 self.header_block
289 .into_encoding(encoder)
290 .encode(&head, dst, Some(encoder), |_| {})
291 }
292
293 fn head(&self) -> Head {
294 Head::new(Kind::Headers, self.flags.into(), self.stream_id)
295 }
296}
297
298impl<T> From<Headers> for Frame<T> {
299 fn from(src: Headers) -> Self {
300 Frame::Headers(src)
301 }
302}
303
304impl fmt::Debug for Headers {
305 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
306 let mut builder = f.debug_struct("Headers");
307 builder
308 .field("stream_id", &self.stream_id)
309 .field("flags", &self.flags);
310
311 if let Some(ref protocol) = self.header_block.pseudo.protocol {
312 builder.field("protocol", protocol);
313 }
314
315 if let Some(ref dep) = self.stream_dep {
316 builder.field("stream_dep", dep);
317 }
318
319 builder.finish()
321 }
322}
323
324#[derive(Debug, PartialEq, Eq)]
327pub struct ParseU64Error;
328
329pub fn parse_u64(src: &[u8]) -> Result<u64, ParseU64Error> {
330 if src.len() > 19 {
331 return Err(ParseU64Error);
333 }
334
335 let mut ret = 0;
336
337 for &d in src {
338 if d < b'0' || d > b'9' {
339 return Err(ParseU64Error);
340 }
341
342 ret *= 10;
343 ret += (d - b'0') as u64;
344 }
345
346 Ok(ret)
347}
348
349#[derive(Debug)]
352pub enum PushPromiseHeaderError {
353 InvalidContentLength(Result<u64, ParseU64Error>),
354 NotSafeAndCacheable,
355}
356
357impl PushPromise {
358 pub fn new(
359 stream_id: StreamId,
360 promised_id: StreamId,
361 pseudo: Pseudo,
362 fields: HeaderMap,
363 ) -> Self {
364 PushPromise {
365 flags: PushPromiseFlag::default(),
366 header_block: HeaderBlock {
367 field_size: calculate_headermap_size(&fields),
368 fields,
369 is_over_size: false,
370 pseudo,
371 },
372 promised_id,
373 stream_id,
374 }
375 }
376
377 pub fn validate_request(req: &Request<()>) -> Result<(), PushPromiseHeaderError> {
378 use PushPromiseHeaderError::*;
379 if let Some(content_length) = req.headers().get(header::CONTENT_LENGTH) {
385 let parsed_length = parse_u64(content_length.as_bytes());
386 if parsed_length != Ok(0) {
387 return Err(InvalidContentLength(parsed_length));
388 }
389 }
390 if !Self::safe_and_cacheable(req.method()) {
393 return Err(NotSafeAndCacheable);
394 }
395
396 Ok(())
397 }
398
399 fn safe_and_cacheable(method: &Method) -> bool {
400 method == Method::GET || method == Method::HEAD
403 }
404
405 pub fn fields(&self) -> &HeaderMap {
406 &self.header_block.fields
407 }
408
409 #[cfg(feature = "unstable")]
410 pub fn into_fields(self) -> HeaderMap {
411 self.header_block.fields
412 }
413
414 pub fn load(head: Head, mut src: BytesMut) -> Result<(Self, BytesMut), Error> {
418 let flags = PushPromiseFlag(head.flag());
419 let mut pad = 0;
420
421 if head.stream_id().is_zero() {
422 return Err(Error::InvalidStreamId);
423 }
424
425 if flags.is_padded() {
427 if src.is_empty() {
428 return Err(Error::MalformedMessage);
429 }
430
431 pad = src[0] as usize;
433
434 src.advance(1);
436 }
437
438 if src.len() < 5 {
439 return Err(Error::MalformedMessage);
440 }
441
442 let (promised_id, _) = StreamId::parse(&src[..4]);
443 src.advance(4);
445
446 if pad > 0 {
447 if pad > src.len() {
448 return Err(Error::TooMuchPadding);
449 }
450
451 let len = src.len() - pad;
452 src.truncate(len);
453 }
454
455 let frame = PushPromise {
456 flags,
457 header_block: HeaderBlock {
458 fields: HeaderMap::new(),
459 field_size: 0,
460 is_over_size: false,
461 pseudo: Pseudo::default(),
462 },
463 promised_id,
464 stream_id: head.stream_id(),
465 };
466 Ok((frame, src))
467 }
468
469 pub fn load_hpack(
470 &mut self,
471 src: &mut BytesMut,
472 max_header_list_size: usize,
473 decoder: &mut hpack::Decoder,
474 ) -> Result<(), Error> {
475 self.header_block.load(src, max_header_list_size, decoder)
476 }
477
478 pub fn stream_id(&self) -> StreamId {
479 self.stream_id
480 }
481
482 pub fn promised_id(&self) -> StreamId {
483 self.promised_id
484 }
485
486 pub fn is_end_headers(&self) -> bool {
487 self.flags.is_end_headers()
488 }
489
490 pub fn set_end_headers(&mut self) {
491 self.flags.set_end_headers();
492 }
493
494 pub fn is_over_size(&self) -> bool {
495 self.header_block.is_over_size
496 }
497
498 pub fn encode(
499 self,
500 encoder: &mut hpack::Encoder,
501 dst: &mut EncodeBuf<'_>,
502 ) -> Option<Continuation> {
503 debug_assert!(self.flags.is_end_headers());
505
506 let head = self.head();
507 let promised_id = self.promised_id;
508
509 self.header_block
510 .into_encoding(encoder)
511 .encode(&head, dst, Some(encoder), |dst| {
512 dst.put_u32(promised_id.into());
513 })
514 }
515
516 fn head(&self) -> Head {
517 Head::new(Kind::PushPromise, self.flags.into(), self.stream_id)
518 }
519
520 pub fn into_parts(self) -> (Pseudo, HeaderMap) {
522 (self.header_block.pseudo, self.header_block.fields)
523 }
524}
525
526impl<T> From<PushPromise> for Frame<T> {
527 fn from(src: PushPromise) -> Self {
528 Frame::PushPromise(src)
529 }
530}
531
532impl fmt::Debug for PushPromise {
533 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
534 f.debug_struct("PushPromise")
535 .field("stream_id", &self.stream_id)
536 .field("promised_id", &self.promised_id)
537 .field("flags", &self.flags)
538 .finish()
540 }
541}
542
543impl Continuation {
546 fn head(&self) -> Head {
547 Head::new(Kind::Continuation, END_HEADERS, self.stream_id)
548 }
549
550 pub fn encode(self, dst: &mut EncodeBuf<'_>) -> Option<Continuation> {
551 let head = self.head();
553
554 self.header_block.encode(&head, dst, None, |_| {})
555 }
556}
557
558impl Pseudo {
561 pub fn request(method: Method, uri: Uri, protocol: Option<Protocol>) -> Self {
562 let parts = uri::Parts::from(uri);
563
564 let (scheme, path) = if method == Method::CONNECT && protocol.is_none() {
565 (None, None)
566 } else {
567 let path = parts
568 .path_and_query
569 .map(|v| BytesStr::from(v.as_str()))
570 .unwrap_or(BytesStr::from_static(""));
571
572 let path = if !path.is_empty() {
573 path
574 } else if method == Method::OPTIONS {
575 BytesStr::from_static("*")
576 } else {
577 BytesStr::from_static("/")
578 };
579
580 (parts.scheme, Some(path))
581 };
582
583 let mut pseudo = Pseudo {
584 method: Some(method),
585 scheme: None,
586 authority: None,
587 path,
588 protocol,
589 status: None,
590 };
591
592 if let Some(scheme) = scheme {
594 pseudo.set_scheme(scheme);
595 }
596
597 if let Some(authority) = parts.authority {
600 pseudo.set_authority(BytesStr::from(authority.as_str()));
601 }
602
603 pseudo
604 }
605
606 pub fn response(status: StatusCode) -> Self {
607 Pseudo {
608 method: None,
609 scheme: None,
610 authority: None,
611 path: None,
612 protocol: None,
613 status: Some(status),
614 }
615 }
616
617 #[cfg(feature = "unstable")]
618 pub fn set_status(&mut self, value: StatusCode) {
619 self.status = Some(value);
620 }
621
622 pub fn set_scheme(&mut self, scheme: uri::Scheme) {
623 let bytes_str = match scheme.as_str() {
624 "http" => BytesStr::from_static("http"),
625 "https" => BytesStr::from_static("https"),
626 s => BytesStr::from(s),
627 };
628 self.scheme = Some(bytes_str);
629 }
630
631 #[cfg(feature = "unstable")]
632 pub fn set_protocol(&mut self, protocol: Protocol) {
633 self.protocol = Some(protocol);
634 }
635
636 pub fn set_authority(&mut self, authority: BytesStr) {
637 self.authority = Some(authority);
638 }
639
640 pub(crate) fn is_informational(&self) -> bool {
642 self.status
643 .map_or(false, |status| status.is_informational())
644 }
645}
646
647impl EncodingHeaderBlock {
650 fn encode<F>(
651 mut self,
652 head: &Head,
653 dst: &mut EncodeBuf<'_>,
654 encoder: Option<&mut hpack::Encoder>,
655 f: F,
656 ) -> Option<Continuation>
657 where
658 F: FnOnce(&mut EncodeBuf<'_>),
659 {
660 let head_pos = dst.get_ref().len();
661
662 head.encode(0, dst);
666
667 let payload_pos = dst.get_ref().len();
668
669 f(dst);
670
671 let continuation = if self.hpack.len() > dst.remaining_mut() {
673 let head_part = self.hpack.split_to(dst.remaining_mut());
674 dst.put_slice(&head_part);
675
676 Some(Continuation {
677 stream_id: head.stream_id(),
678 header_block: self,
679 })
680 } else {
681 dst.put_slice(&self.hpack);
682 if let Some(encoder) = encoder {
685 encoder.return_scratch(self.hpack);
686 }
687
688 None
689 };
690
691 let payload_len = (dst.get_ref().len() - payload_pos) as u64;
693
694 let payload_len_be = payload_len.to_be_bytes();
696 assert!(payload_len_be[0..5].iter().all(|b| *b == 0));
697 (dst.get_mut()[head_pos..head_pos + 3]).copy_from_slice(&payload_len_be[5..]);
698
699 if continuation.is_some() {
700 debug_assert!(dst.get_ref()[head_pos + 4] & END_HEADERS == END_HEADERS);
703
704 dst.get_mut()[head_pos + 4] -= END_HEADERS;
705 }
706
707 continuation
708 }
709}
710
711impl Iterator for Iter {
714 type Item = hpack::Header<Option<HeaderName>>;
715
716 fn next(&mut self) -> Option<Self::Item> {
717 use crate::hpack::Header::*;
718
719 if let Some(ref mut pseudo) = self.pseudo {
720 if let Some(method) = pseudo.method.take() {
721 return Some(Method(method));
722 }
723
724 if let Some(scheme) = pseudo.scheme.take() {
725 return Some(Scheme(scheme));
726 }
727
728 if let Some(authority) = pseudo.authority.take() {
729 return Some(Authority(authority));
730 }
731
732 if let Some(path) = pseudo.path.take() {
733 return Some(Path(path));
734 }
735
736 if let Some(protocol) = pseudo.protocol.take() {
737 return Some(Protocol(protocol));
738 }
739
740 if let Some(status) = pseudo.status.take() {
741 return Some(Status(status));
742 }
743 }
744
745 self.pseudo = None;
746
747 self.fields
748 .next()
749 .map(|(name, value)| Field { name, value })
750 }
751}
752
753impl HeadersFlag {
756 pub fn empty() -> HeadersFlag {
757 HeadersFlag(0)
758 }
759
760 pub fn load(bits: u8) -> HeadersFlag {
761 HeadersFlag(bits & ALL)
762 }
763
764 pub fn is_end_stream(&self) -> bool {
765 self.0 & END_STREAM == END_STREAM
766 }
767
768 pub fn set_end_stream(&mut self) {
769 self.0 |= END_STREAM;
770 }
771
772 pub fn is_end_headers(&self) -> bool {
773 self.0 & END_HEADERS == END_HEADERS
774 }
775
776 pub fn set_end_headers(&mut self) {
777 self.0 |= END_HEADERS;
778 }
779
780 pub fn is_padded(&self) -> bool {
781 self.0 & PADDED == PADDED
782 }
783
784 pub fn is_priority(&self) -> bool {
785 self.0 & PRIORITY == PRIORITY
786 }
787}
788
789impl Default for HeadersFlag {
790 fn default() -> Self {
792 HeadersFlag(END_HEADERS)
793 }
794}
795
796impl From<HeadersFlag> for u8 {
797 fn from(src: HeadersFlag) -> u8 {
798 src.0
799 }
800}
801
802impl fmt::Debug for HeadersFlag {
803 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
804 util::debug_flags(fmt, self.0)
805 .flag_if(self.is_end_headers(), "END_HEADERS")
806 .flag_if(self.is_end_stream(), "END_STREAM")
807 .flag_if(self.is_padded(), "PADDED")
808 .flag_if(self.is_priority(), "PRIORITY")
809 .finish()
810 }
811}
812
813impl PushPromiseFlag {
816 pub fn empty() -> PushPromiseFlag {
817 PushPromiseFlag(0)
818 }
819
820 pub fn load(bits: u8) -> PushPromiseFlag {
821 PushPromiseFlag(bits & ALL)
822 }
823
824 pub fn is_end_headers(&self) -> bool {
825 self.0 & END_HEADERS == END_HEADERS
826 }
827
828 pub fn set_end_headers(&mut self) {
829 self.0 |= END_HEADERS;
830 }
831
832 pub fn is_padded(&self) -> bool {
833 self.0 & PADDED == PADDED
834 }
835}
836
837impl Default for PushPromiseFlag {
838 fn default() -> Self {
840 PushPromiseFlag(END_HEADERS)
841 }
842}
843
844impl From<PushPromiseFlag> for u8 {
845 fn from(src: PushPromiseFlag) -> u8 {
846 src.0
847 }
848}
849
850impl fmt::Debug for PushPromiseFlag {
851 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
852 util::debug_flags(fmt, self.0)
853 .flag_if(self.is_end_headers(), "END_HEADERS")
854 .flag_if(self.is_padded(), "PADDED")
855 .finish()
856 }
857}
858
859impl HeaderBlock {
862 fn load(
863 &mut self,
864 src: &mut BytesMut,
865 max_header_list_size: usize,
866 decoder: &mut hpack::Decoder,
867 ) -> Result<(), Error> {
868 let mut reg = !self.fields.is_empty();
869 let mut malformed = false;
870 let mut header_list_way_too_large = false;
871 let mut headers_size = self.calculate_header_list_size();
872 let max_header_list_abuse_size =
873 max_header_list_size.saturating_mul(MAX_HEADER_LIST_ABUSE_MULTIPLIER);
874
875 macro_rules! check_size {
876 () => {{
877 if headers_size > max_header_list_abuse_size {
878 tracing::trace!("load_hpack; header list size over abuse max");
879 header_list_way_too_large = true;
880 ControlFlow::Break(())
881 } else {
882 if headers_size >= max_header_list_size && !self.is_over_size {
883 tracing::trace!("load_hpack; header list size over max");
884 self.is_over_size = true;
885 }
886 ControlFlow::Continue(())
887 }
888 }};
889 }
890
891 macro_rules! set_pseudo {
892 ($field:ident, $val:expr) => {{
893 if reg {
894 tracing::trace!("load_hpack; header malformed -- pseudo not at head of block");
895 malformed = true;
896 } else if self.pseudo.$field.is_some() {
897 tracing::trace!("load_hpack; header malformed -- repeated pseudo");
898 malformed = true;
899 } else {
900 let __val = $val;
901 headers_size +=
902 decoded_header_size(stringify!($field).len() + 1, __val.as_str().len());
903 if check_size!().is_break() {
904 return ControlFlow::Break(());
905 }
906 if !self.is_over_size {
907 self.pseudo.$field = Some(__val);
908 }
909 }
910 }};
911 }
912
913 let mut cursor = Cursor::new(src);
914
915 let res = decoder.decode(&mut cursor, |header| {
920 use crate::hpack::Header::*;
921
922 match header {
923 Field { name, value } => {
924 if name == header::CONNECTION
928 || name == header::TRANSFER_ENCODING
929 || name == header::UPGRADE
930 || name == "keep-alive"
931 || name == "proxy-connection"
932 {
933 tracing::trace!("load_hpack; connection level header");
934 malformed = true;
935 } else if name == header::TE && value != "trailers" {
936 tracing::trace!(
937 "load_hpack; TE header not set to trailers; val={:?}",
938 value
939 );
940 malformed = true;
941 } else {
942 reg = true;
943
944 let header_size = decoded_header_size(name.as_str().len(), value.len());
945 headers_size += header_size;
946 if check_size!().is_break() {
947 return ControlFlow::Break(());
948 }
949 if !self.is_over_size {
950 self.field_size += header_size;
951 if let Err(_) = self.fields.try_append(name, value) {
952 self.is_over_size = true;
956 }
957 }
958 }
959 }
960 Authority(v) => set_pseudo!(authority, v),
961 Method(v) => set_pseudo!(method, v),
962 Scheme(v) => set_pseudo!(scheme, v),
963 Path(v) => set_pseudo!(path, v),
964 Protocol(v) => set_pseudo!(protocol, v),
965 Status(v) => set_pseudo!(status, v),
966 }
967
968 ControlFlow::Continue(())
969 });
970
971 match res {
972 Ok(()) => {}
973 Err(e) => {
974 tracing::trace!("hpack decoding error; err={:?}", e);
975 return Err(e.into());
976 }
977 }
978
979 if header_list_way_too_large {
980 tracing::trace!("header list way too large; aborting connection");
981 return Err(Error::HeaderListWayTooLarge);
982 }
983
984 if malformed {
985 tracing::trace!("malformed message");
986 return Err(Error::MalformedMessage);
987 }
988
989 Ok(())
990 }
991
992 fn into_encoding(self, encoder: &mut hpack::Encoder) -> EncodingHeaderBlock {
993 let mut hpack = encoder.take_scratch();
994 hpack.clear();
995 let headers = Iter {
996 pseudo: Some(self.pseudo),
997 fields: self.fields.into_iter(),
998 };
999
1000 encoder.encode(headers, &mut hpack);
1001
1002 EncodingHeaderBlock { hpack }
1003 }
1004
1005 fn calculate_header_list_size(&self) -> usize {
1013 macro_rules! pseudo_size {
1014 ($name:ident) => {{
1015 self.pseudo
1016 .$name
1017 .as_ref()
1018 .map(|m| decoded_header_size(stringify!($name).len() + 1, m.as_str().len()))
1019 .unwrap_or(0)
1020 }};
1021 }
1022
1023 pseudo_size!(method)
1024 + pseudo_size!(scheme)
1025 + pseudo_size!(status)
1026 + pseudo_size!(authority)
1027 + pseudo_size!(path)
1028 + self.field_size
1029 }
1030}
1031
1032fn calculate_headermap_size(map: &HeaderMap) -> usize {
1033 map.iter()
1034 .map(|(name, value)| decoded_header_size(name.as_str().len(), value.len()))
1035 .sum::<usize>()
1036}
1037
1038fn decoded_header_size(name: usize, value: usize) -> usize {
1039 name + value + 32
1040}
1041
1042#[cfg(test)]
1043mod test {
1044 use super::*;
1045 use crate::frame;
1046 use crate::hpack::{huffman, Encoder};
1047
1048 #[test]
1049 fn test_nameless_header_at_resume() {
1050 let mut encoder = Encoder::default();
1051 let mut dst = BytesMut::new();
1052
1053 let headers = Headers::new(
1054 StreamId::ZERO,
1055 Default::default(),
1056 HeaderMap::from_iter(vec![
1057 (
1058 HeaderName::from_static("hello"),
1059 HeaderValue::from_static("world"),
1060 ),
1061 (
1062 HeaderName::from_static("hello"),
1063 HeaderValue::from_static("zomg"),
1064 ),
1065 (
1066 HeaderName::from_static("hello"),
1067 HeaderValue::from_static("sup"),
1068 ),
1069 ]),
1070 );
1071
1072 let continuation = headers
1073 .encode(&mut encoder, &mut (&mut dst).limit(frame::HEADER_LEN + 8))
1074 .unwrap();
1075
1076 assert_eq!(17, dst.len());
1077 assert_eq!([0, 0, 8, 1, 0, 0, 0, 0, 0], &dst[0..9]);
1078 assert_eq!(&[0x40, 0x80 | 4], &dst[9..11]);
1079 assert_eq!("hello", huff_decode(&dst[11..15]));
1080 assert_eq!(0x80 | 4, dst[15]);
1081
1082 let mut world = dst[16..17].to_owned();
1083
1084 dst.clear();
1085
1086 assert!(continuation
1087 .encode(&mut (&mut dst).limit(frame::HEADER_LEN + 16))
1088 .is_none());
1089
1090 world.extend_from_slice(&dst[9..12]);
1091 assert_eq!("world", huff_decode(&world));
1092
1093 assert_eq!(24, dst.len());
1094 assert_eq!([0, 0, 15, 9, 4, 0, 0, 0, 0], &dst[0..9]);
1095
1096 assert_eq!(&[15, 47, 0x80 | 3], &dst[12..15]);
1098 assert_eq!("zomg", huff_decode(&dst[15..18]));
1099 assert_eq!(&[15, 47, 0x80 | 3], &dst[18..21]);
1100 assert_eq!("sup", huff_decode(&dst[21..]));
1101 }
1102
1103 fn huff_decode(src: &[u8]) -> BytesMut {
1104 let mut buf = BytesMut::new();
1105 huffman::decode(src, &mut buf).unwrap()
1106 }
1107
1108 #[test]
1109 fn test_connect_request_pseudo_headers_omits_path_and_scheme() {
1110 assert_eq!(
1114 Pseudo::request(
1115 Method::CONNECT,
1116 Uri::from_static("https://example.com:8443"),
1117 None
1118 ),
1119 Pseudo {
1120 method: Method::CONNECT.into(),
1121 authority: BytesStr::from_static("example.com:8443").into(),
1122 ..Default::default()
1123 }
1124 );
1125
1126 assert_eq!(
1127 Pseudo::request(
1128 Method::CONNECT,
1129 Uri::from_static("https://example.com/test"),
1130 None
1131 ),
1132 Pseudo {
1133 method: Method::CONNECT.into(),
1134 authority: BytesStr::from_static("example.com").into(),
1135 ..Default::default()
1136 }
1137 );
1138
1139 assert_eq!(
1140 Pseudo::request(Method::CONNECT, Uri::from_static("example.com:8443"), None),
1141 Pseudo {
1142 method: Method::CONNECT.into(),
1143 authority: BytesStr::from_static("example.com:8443").into(),
1144 ..Default::default()
1145 }
1146 );
1147 }
1148
1149 #[test]
1150 fn test_extended_connect_request_pseudo_headers_includes_path_and_scheme() {
1151 assert_eq!(
1157 Pseudo::request(
1158 Method::CONNECT,
1159 Uri::from_static("https://example.com:8443"),
1160 Protocol::from_static("the-bread-protocol").into()
1161 ),
1162 Pseudo {
1163 method: Method::CONNECT.into(),
1164 authority: BytesStr::from_static("example.com:8443").into(),
1165 scheme: BytesStr::from_static("https").into(),
1166 path: BytesStr::from_static("/").into(),
1167 protocol: Protocol::from_static("the-bread-protocol").into(),
1168 ..Default::default()
1169 }
1170 );
1171
1172 assert_eq!(
1173 Pseudo::request(
1174 Method::CONNECT,
1175 Uri::from_static("https://example.com:8443/test"),
1176 Protocol::from_static("the-bread-protocol").into()
1177 ),
1178 Pseudo {
1179 method: Method::CONNECT.into(),
1180 authority: BytesStr::from_static("example.com:8443").into(),
1181 scheme: BytesStr::from_static("https").into(),
1182 path: BytesStr::from_static("/test").into(),
1183 protocol: Protocol::from_static("the-bread-protocol").into(),
1184 ..Default::default()
1185 }
1186 );
1187
1188 assert_eq!(
1189 Pseudo::request(
1190 Method::CONNECT,
1191 Uri::from_static("http://example.com/a/b/c"),
1192 Protocol::from_static("the-bread-protocol").into()
1193 ),
1194 Pseudo {
1195 method: Method::CONNECT.into(),
1196 authority: BytesStr::from_static("example.com").into(),
1197 scheme: BytesStr::from_static("http").into(),
1198 path: BytesStr::from_static("/a/b/c").into(),
1199 protocol: Protocol::from_static("the-bread-protocol").into(),
1200 ..Default::default()
1201 }
1202 );
1203 }
1204
1205 #[test]
1206 fn test_options_request_with_empty_path_has_asterisk_as_pseudo_path() {
1207 assert_eq!(
1211 Pseudo::request(Method::OPTIONS, Uri::from_static("example.com:8080"), None,),
1212 Pseudo {
1213 method: Method::OPTIONS.into(),
1214 authority: BytesStr::from_static("example.com:8080").into(),
1215 path: BytesStr::from_static("*").into(),
1216 ..Default::default()
1217 }
1218 );
1219 }
1220
1221 #[test]
1222 fn test_try_append_prevents_panic_on_max_size_reached() {
1223 let num_headers = 25_000;
1246
1247 let mut hpack = Vec::new();
1249
1250 hpack.push(0x82u8); hpack.push(0x86); hpack.push(0x84); hpack.push(0x41); hpack.push(0x09); hpack.extend_from_slice(b"localhost");
1259
1260 for i in 0..num_headers {
1263 let name = format!("x-h-{i}");
1264 hpack.push(0x00u8); hpack.push(name.len() as u8);
1266 hpack.extend_from_slice(name.as_bytes());
1267 hpack.push(1u8); hpack.push(b'v');
1269 }
1270
1271 let payload_len = hpack.len();
1273 let mut frame = BytesMut::with_capacity(9 + payload_len);
1274
1275 frame.put_u8(((payload_len >> 16) & 0xFF) as u8);
1277 frame.put_u8(((payload_len >> 8) & 0xFF) as u8);
1278 frame.put_u8((payload_len & 0xFF) as u8);
1279 frame.put_u8(0x01); frame.put_u8(0x04); frame.put_u32(1); frame.extend_from_slice(&hpack);
1284
1285 let head = Head::parse(&frame[..9]);
1287 let payload = BytesMut::from(&frame[9..]);
1288 let (mut headers, mut hpack_data) = Headers::load(head, payload).unwrap();
1289 let mut decoder = hpack::Decoder::new(4096);
1293 const DEFAULT_MAX_HEADER_LIST_SIZE: usize = 16 << 20; headers
1295 .load_hpack(&mut hpack_data, DEFAULT_MAX_HEADER_LIST_SIZE, &mut decoder)
1296 .expect("load_hpack should return Ok");
1297
1298 assert!(
1300 headers.is_over_size(),
1301 "is_over_size should be true when HeaderMap capacity is exceeded"
1302 );
1303 }
1304
1305 #[test]
1306 fn test_non_option_and_non_connect_requests_include_path_and_scheme() {
1307 let methods = [
1308 Method::GET,
1309 Method::POST,
1310 Method::PUT,
1311 Method::DELETE,
1312 Method::HEAD,
1313 Method::PATCH,
1314 Method::TRACE,
1315 ];
1316
1317 for method in methods {
1318 assert_eq!(
1319 Pseudo::request(
1320 method.clone(),
1321 Uri::from_static("http://example.com:8080"),
1322 None,
1323 ),
1324 Pseudo {
1325 method: method.clone().into(),
1326 authority: BytesStr::from_static("example.com:8080").into(),
1327 scheme: BytesStr::from_static("http").into(),
1328 path: BytesStr::from_static("/").into(),
1329 ..Default::default()
1330 }
1331 );
1332 assert_eq!(
1333 Pseudo::request(
1334 method.clone(),
1335 Uri::from_static("https://example.com/a/b/c"),
1336 None,
1337 ),
1338 Pseudo {
1339 method: method.into(),
1340 authority: BytesStr::from_static("example.com").into(),
1341 scheme: BytesStr::from_static("https").into(),
1342 path: BytesStr::from_static("/a/b/c").into(),
1343 ..Default::default()
1344 }
1345 );
1346 }
1347 }
1348}