1 use super::{util, StreamDependency, StreamId};
2 use frame::{Error, Frame, Head, Kind};
3 use hpack;
4
5 use http::{uri, HeaderMap, Method, StatusCode, Uri};
6 use http::header::{self, HeaderName, HeaderValue};
7
8 use byteorder::{BigEndian, ByteOrder};
9 use bytes::{Bytes, BytesMut};
10 use string::String;
11
12 use std::fmt;
13 use std::io::Cursor;
14
15 // Minimum MAX_FRAME_SIZE is 16kb, so save some arbitrary space for frame
16 // head and other header bits.
17 const MAX_HEADER_LENGTH: usize = 1024 * 16 - 100;
18
19 /// Header frame
20 ///
21 /// This could be either a request or a response.
22 #[derive(Eq, PartialEq)]
23 pub struct Headers {
24 /// The ID of the stream with which this frame is associated.
25 stream_id: StreamId,
26
27 /// The stream dependency information, if any.
28 stream_dep: Option<StreamDependency>,
29
30 /// The header block fragment
31 header_block: HeaderBlock,
32
33 /// The associated flags
34 flags: HeadersFlag,
35 }
36
37 #[derive(Copy, Clone, Eq, PartialEq)]
38 pub struct HeadersFlag(u8);
39
40 #[derive(Eq, PartialEq)]
41 pub struct PushPromise {
42 /// The ID of the stream with which this frame is associated.
43 stream_id: StreamId,
44
45 /// The ID of the stream being reserved by this PushPromise.
46 promised_id: StreamId,
47
48 /// The header block fragment
49 header_block: HeaderBlock,
50
51 /// The associated flags
52 flags: PushPromiseFlag,
53 }
54
55 #[derive(Copy, Clone, Eq, PartialEq)]
56 pub struct PushPromiseFlag(u8);
57
58 #[derive(Debug)]
59 pub struct Continuation {
60 /// Stream ID of continuation frame
61 stream_id: StreamId,
62
63 header_block: EncodingHeaderBlock,
64 }
65
66 // TODO: These fields shouldn't be `pub`
67 #[derive(Debug, Default, Eq, PartialEq)]
68 pub struct Pseudo {
69 // Request
70 pub method: Option<Method>,
71 pub scheme: Option<String<Bytes>>,
72 pub authority: Option<String<Bytes>>,
73 pub path: Option<String<Bytes>>,
74
75 // Response
76 pub status: Option<StatusCode>,
77 }
78
79 #[derive(Debug)]
80 pub struct Iter {
81 /// Pseudo headers
82 pseudo: Option<Pseudo>,
83
84 /// Header fields
85 fields: header::IntoIter<HeaderValue>,
86 }
87
88 #[derive(Debug, PartialEq, Eq)]
89 struct HeaderBlock {
90 /// The decoded header fields
91 fields: HeaderMap,
92
93 /// Set to true if decoding went over the max header list size.
94 is_over_size: bool,
95
96 /// Pseudo headers, these are broken out as they must be sent as part of the
97 /// headers frame.
98 pseudo: Pseudo,
99 }
100
101 #[derive(Debug)]
102 struct EncodingHeaderBlock {
103 /// Argument to pass to the HPACK encoder to resume encoding
104 hpack: Option<hpack::EncodeState>,
105
106 /// remaining headers to encode
107 headers: Iter,
108 }
109
110 const END_STREAM: u8 = 0x1;
111 const END_HEADERS: u8 = 0x4;
112 const PADDED: u8 = 0x8;
113 const PRIORITY: u8 = 0x20;
114 const ALL: u8 = END_STREAM | END_HEADERS | PADDED | PRIORITY;
115
116 // ===== impl Headers =====
117
118 impl Headers {
119 /// Create a new HEADERS frame
new(stream_id: StreamId, pseudo: Pseudo, fields: HeaderMap) -> Self120 pub fn new(stream_id: StreamId, pseudo: Pseudo, fields: HeaderMap) -> Self {
121 Headers {
122 stream_id: stream_id,
123 stream_dep: None,
124 header_block: HeaderBlock {
125 fields: fields,
126 is_over_size: false,
127 pseudo: pseudo,
128 },
129 flags: HeadersFlag::default(),
130 }
131 }
132
trailers(stream_id: StreamId, fields: HeaderMap) -> Self133 pub fn trailers(stream_id: StreamId, fields: HeaderMap) -> Self {
134 let mut flags = HeadersFlag::default();
135 flags.set_end_stream();
136
137 Headers {
138 stream_id,
139 stream_dep: None,
140 header_block: HeaderBlock {
141 fields: fields,
142 is_over_size: false,
143 pseudo: Pseudo::default(),
144 },
145 flags: flags,
146 }
147 }
148
149 /// Loads the header frame but doesn't actually do HPACK decoding.
150 ///
151 /// HPACK decoding is done in the `load_hpack` step.
load(head: Head, mut src: BytesMut) -> Result<(Self, BytesMut), Error>152 pub fn load(head: Head, mut src: BytesMut) -> Result<(Self, BytesMut), Error> {
153 let flags = HeadersFlag(head.flag());
154 let mut pad = 0;
155
156 trace!("loading headers; flags={:?}", flags);
157
158 // Read the padding length
159 if flags.is_padded() {
160 if src.len() < 1 {
161 return Err(Error::MalformedMessage);
162 }
163 pad = src[0] as usize;
164
165 // Drop the padding
166 let _ = src.split_to(1);
167 }
168
169 // Read the stream dependency
170 let stream_dep = if flags.is_priority() {
171 if src.len() < 5 {
172 return Err(Error::MalformedMessage);
173 }
174 let stream_dep = StreamDependency::load(&src[..5])?;
175
176 if stream_dep.dependency_id() == head.stream_id() {
177 return Err(Error::InvalidDependencyId);
178 }
179
180 // Drop the next 5 bytes
181 let _ = src.split_to(5);
182
183 Some(stream_dep)
184 } else {
185 None
186 };
187
188 if pad > 0 {
189 if pad > src.len() {
190 return Err(Error::TooMuchPadding);
191 }
192
193 let len = src.len() - pad;
194 src.truncate(len);
195 }
196
197 let headers = Headers {
198 stream_id: head.stream_id(),
199 stream_dep: stream_dep,
200 header_block: HeaderBlock {
201 fields: HeaderMap::new(),
202 is_over_size: false,
203 pseudo: Pseudo::default(),
204 },
205 flags: flags,
206 };
207
208 Ok((headers, src))
209 }
210
load_hpack(&mut self, src: &mut BytesMut, max_header_list_size: usize, decoder: &mut hpack::Decoder) -> Result<(), Error>211 pub fn load_hpack(&mut self, src: &mut BytesMut, max_header_list_size: usize, decoder: &mut hpack::Decoder) -> Result<(), Error> {
212 self.header_block.load(src, max_header_list_size, decoder)
213 }
214
stream_id(&self) -> StreamId215 pub fn stream_id(&self) -> StreamId {
216 self.stream_id
217 }
218
is_end_headers(&self) -> bool219 pub fn is_end_headers(&self) -> bool {
220 self.flags.is_end_headers()
221 }
222
set_end_headers(&mut self)223 pub fn set_end_headers(&mut self) {
224 self.flags.set_end_headers();
225 }
226
is_end_stream(&self) -> bool227 pub fn is_end_stream(&self) -> bool {
228 self.flags.is_end_stream()
229 }
230
set_end_stream(&mut self)231 pub fn set_end_stream(&mut self) {
232 self.flags.set_end_stream()
233 }
234
is_over_size(&self) -> bool235 pub fn is_over_size(&self) -> bool {
236 self.header_block.is_over_size
237 }
238
has_too_big_field(&self) -> bool239 pub(crate) fn has_too_big_field(&self) -> bool {
240 self.header_block.has_too_big_field()
241 }
242
into_parts(self) -> (Pseudo, HeaderMap)243 pub fn into_parts(self) -> (Pseudo, HeaderMap) {
244 (self.header_block.pseudo, self.header_block.fields)
245 }
246
247 #[cfg(feature = "unstable")]
pseudo_mut(&mut self) -> &mut Pseudo248 pub fn pseudo_mut(&mut self) -> &mut Pseudo {
249 &mut self.header_block.pseudo
250 }
251
fields(&self) -> &HeaderMap252 pub fn fields(&self) -> &HeaderMap {
253 &self.header_block.fields
254 }
255
into_fields(self) -> HeaderMap256 pub fn into_fields(self) -> HeaderMap {
257 self.header_block.fields
258 }
259
encode(self, encoder: &mut hpack::Encoder, dst: &mut BytesMut) -> Option<Continuation>260 pub fn encode(self, encoder: &mut hpack::Encoder, dst: &mut BytesMut) -> Option<Continuation> {
261 // At this point, the `is_end_headers` flag should always be set
262 debug_assert!(self.flags.is_end_headers());
263
264 // Get the HEADERS frame head
265 let head = self.head();
266
267 self.header_block.into_encoding()
268 .encode(&head, encoder, dst, |_| {
269 })
270 }
271
head(&self) -> Head272 fn head(&self) -> Head {
273 Head::new(Kind::Headers, self.flags.into(), self.stream_id)
274 }
275 }
276
277 impl<T> From<Headers> for Frame<T> {
from(src: Headers) -> Self278 fn from(src: Headers) -> Self {
279 Frame::Headers(src)
280 }
281 }
282
283 impl fmt::Debug for Headers {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result284 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
285 let mut builder = f.debug_struct("Headers");
286 builder
287 .field("stream_id", &self.stream_id)
288 .field("flags", &self.flags);
289
290 if let Some(ref dep) = self.stream_dep {
291 builder.field("stream_dep", dep);
292 }
293
294 // `fields` and `pseudo` purposefully not included
295 builder.finish()
296 }
297 }
298
299 // ===== impl PushPromise =====
300
301 impl PushPromise {
302 /// Loads the push promise frame but doesn't actually do HPACK decoding.
303 ///
304 /// HPACK decoding is done in the `load_hpack` step.
load(head: Head, mut src: BytesMut) -> Result<(Self, BytesMut), Error>305 pub fn load(head: Head, mut src: BytesMut) -> Result<(Self, BytesMut), Error> {
306 let flags = PushPromiseFlag(head.flag());
307 let mut pad = 0;
308
309 // Read the padding length
310 if flags.is_padded() {
311 if src.len() < 1 {
312 return Err(Error::MalformedMessage);
313 }
314
315 // TODO: Ensure payload is sized correctly
316 pad = src[0] as usize;
317
318 // Drop the padding
319 let _ = src.split_to(1);
320 }
321
322 if src.len() < 5 {
323 return Err(Error::MalformedMessage);
324 }
325
326 let (promised_id, _) = StreamId::parse(&src[..4]);
327 // Drop promised_id bytes
328 let _ = src.split_to(4);
329
330 if pad > 0 {
331 if pad > src.len() {
332 return Err(Error::TooMuchPadding);
333 }
334
335 let len = src.len() - pad;
336 src.truncate(len);
337 }
338
339 let frame = PushPromise {
340 flags: flags,
341 header_block: HeaderBlock {
342 fields: HeaderMap::new(),
343 is_over_size: false,
344 pseudo: Pseudo::default(),
345 },
346 promised_id: promised_id,
347 stream_id: head.stream_id(),
348 };
349 Ok((frame, src))
350 }
351
load_hpack(&mut self, src: &mut BytesMut, max_header_list_size: usize, decoder: &mut hpack::Decoder) -> Result<(), Error>352 pub fn load_hpack(&mut self, src: &mut BytesMut, max_header_list_size: usize, decoder: &mut hpack::Decoder) -> Result<(), Error> {
353 self.header_block.load(src, max_header_list_size, decoder)
354 }
355
stream_id(&self) -> StreamId356 pub fn stream_id(&self) -> StreamId {
357 self.stream_id
358 }
359
promised_id(&self) -> StreamId360 pub fn promised_id(&self) -> StreamId {
361 self.promised_id
362 }
363
is_end_headers(&self) -> bool364 pub fn is_end_headers(&self) -> bool {
365 self.flags.is_end_headers()
366 }
367
set_end_headers(&mut self)368 pub fn set_end_headers(&mut self) {
369 self.flags.set_end_headers();
370 }
371
is_over_size(&self) -> bool372 pub fn is_over_size(&self) -> bool {
373 self.header_block.is_over_size
374 }
375
encode(self, encoder: &mut hpack::Encoder, dst: &mut BytesMut) -> Option<Continuation>376 pub fn encode(self, encoder: &mut hpack::Encoder, dst: &mut BytesMut) -> Option<Continuation> {
377 use bytes::BufMut;
378
379 // At this point, the `is_end_headers` flag should always be set
380 debug_assert!(self.flags.is_end_headers());
381
382 let head = self.head();
383 let promised_id = self.promised_id;
384
385 self.header_block.into_encoding()
386 .encode(&head, encoder, dst, |dst| {
387 dst.put_u32_be(promised_id.into());
388 })
389 }
390
head(&self) -> Head391 fn head(&self) -> Head {
392 Head::new(Kind::PushPromise, self.flags.into(), self.stream_id)
393 }
394 }
395
396 impl PushPromise {
397 /// Consume `self`, returning the parts of the frame
into_parts(self) -> (Pseudo, HeaderMap)398 pub fn into_parts(self) -> (Pseudo, HeaderMap) {
399 (self.header_block.pseudo, self.header_block.fields)
400 }
401 }
402
403 #[cfg(feature = "unstable")]
404 impl PushPromise {
new( stream_id: StreamId, promised_id: StreamId, pseudo: Pseudo, fields: HeaderMap, ) -> Self405 pub fn new(
406 stream_id: StreamId,
407 promised_id: StreamId,
408 pseudo: Pseudo,
409 fields: HeaderMap,
410 ) -> Self {
411 PushPromise {
412 flags: PushPromiseFlag::default(),
413 header_block: HeaderBlock {
414 fields,
415 is_over_size: false,
416 pseudo,
417 },
418 promised_id,
419 stream_id,
420 }
421 }
422
fields(&self) -> &HeaderMap423 pub fn fields(&self) -> &HeaderMap {
424 &self.header_block.fields
425 }
426
into_fields(self) -> HeaderMap427 pub fn into_fields(self) -> HeaderMap {
428 self.header_block.fields
429 }
430 }
431
432 impl<T> From<PushPromise> for Frame<T> {
from(src: PushPromise) -> Self433 fn from(src: PushPromise) -> Self {
434 Frame::PushPromise(src)
435 }
436 }
437
438 impl fmt::Debug for PushPromise {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result439 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
440 f.debug_struct("PushPromise")
441 .field("stream_id", &self.stream_id)
442 .field("promised_id", &self.promised_id)
443 .field("flags", &self.flags)
444 // `fields` and `pseudo` purposefully not included
445 .finish()
446 }
447 }
448
449 // ===== impl Continuation =====
450
451 impl Continuation {
head(&self) -> Head452 fn head(&self) -> Head {
453 Head::new(Kind::Continuation, END_HEADERS, self.stream_id)
454 }
455
encode(self, encoder: &mut hpack::Encoder, dst: &mut BytesMut) -> Option<Continuation>456 pub fn encode(self, encoder: &mut hpack::Encoder, dst: &mut BytesMut) -> Option<Continuation> {
457 // Get the CONTINUATION frame head
458 let head = self.head();
459
460 self.header_block
461 .encode(&head, encoder, dst, |_| {
462 })
463 }
464 }
465
466 // ===== impl Pseudo =====
467
468 impl Pseudo {
request(method: Method, uri: Uri) -> Self469 pub fn request(method: Method, uri: Uri) -> Self {
470 let parts = uri::Parts::from(uri);
471
472 let mut path = parts
473 .path_and_query
474 .map(|v| v.into())
475 .unwrap_or_else(|| Bytes::new());
476
477 if path.is_empty() && method != Method::OPTIONS {
478 path = Bytes::from_static(b"/");
479 }
480
481 let mut pseudo = Pseudo {
482 method: Some(method),
483 scheme: None,
484 authority: None,
485 path: Some(to_string(path)),
486 status: None,
487 };
488
489 // If the URI includes a scheme component, add it to the pseudo headers
490 //
491 // TODO: Scheme must be set...
492 if let Some(scheme) = parts.scheme {
493 pseudo.set_scheme(scheme);
494 }
495
496 // If the URI includes an authority component, add it to the pseudo
497 // headers
498 if let Some(authority) = parts.authority {
499 pseudo.set_authority(to_string(authority.into()));
500 }
501
502 pseudo
503 }
504
response(status: StatusCode) -> Self505 pub fn response(status: StatusCode) -> Self {
506 Pseudo {
507 method: None,
508 scheme: None,
509 authority: None,
510 path: None,
511 status: Some(status),
512 }
513 }
514
set_scheme(&mut self, scheme: uri::Scheme)515 pub fn set_scheme(&mut self, scheme: uri::Scheme) {
516 self.scheme = Some(to_string(scheme.into()));
517 }
518
set_authority(&mut self, authority: String<Bytes>)519 pub fn set_authority(&mut self, authority: String<Bytes>) {
520 self.authority = Some(authority);
521 }
522 }
523
to_string(src: Bytes) -> String<Bytes>524 fn to_string(src: Bytes) -> String<Bytes> {
525 unsafe { String::from_utf8_unchecked(src) }
526 }
527
528 // ===== impl EncodingHeaderBlock =====
529
530 impl EncodingHeaderBlock {
encode<F>(mut self, head: &Head, encoder: &mut hpack::Encoder, dst: &mut BytesMut, f: F) -> Option<Continuation> where F: FnOnce(&mut BytesMut),531 fn encode<F>(mut self,
532 head: &Head,
533 encoder: &mut hpack::Encoder,
534 dst: &mut BytesMut,
535 f: F)
536 -> Option<Continuation>
537 where F: FnOnce(&mut BytesMut),
538 {
539 let head_pos = dst.len();
540
541 // At this point, we don't know how big the h2 frame will be.
542 // So, we write the head with length 0, then write the body, and
543 // finally write the length once we know the size.
544 head.encode(0, dst);
545
546 let payload_pos = dst.len();
547
548 f(dst);
549
550 // Now, encode the header payload
551 let continuation = match encoder.encode(self.hpack, &mut self.headers, dst) {
552 hpack::Encode::Full => None,
553 hpack::Encode::Partial(state) => Some(Continuation {
554 stream_id: head.stream_id(),
555 header_block: EncodingHeaderBlock {
556 hpack: Some(state),
557 headers: self.headers,
558 },
559 }),
560 };
561
562 // Compute the header block length
563 let payload_len = (dst.len() - payload_pos) as u64;
564
565 // Write the frame length
566 BigEndian::write_uint(&mut dst[head_pos..head_pos + 3], payload_len, 3);
567
568 if continuation.is_some() {
569 // There will be continuation frames, so the `is_end_headers` flag
570 // must be unset
571 debug_assert!(dst[head_pos + 4] & END_HEADERS == END_HEADERS);
572
573 dst[head_pos + 4] -= END_HEADERS;
574 }
575
576 continuation
577 }
578 }
579
580 // ===== impl Iter =====
581
582 impl Iterator for Iter {
583 type Item = hpack::Header<Option<HeaderName>>;
584
next(&mut self) -> Option<Self::Item>585 fn next(&mut self) -> Option<Self::Item> {
586 use hpack::Header::*;
587
588 if let Some(ref mut pseudo) = self.pseudo {
589 if let Some(method) = pseudo.method.take() {
590 return Some(Method(method));
591 }
592
593 if let Some(scheme) = pseudo.scheme.take() {
594 return Some(Scheme(scheme));
595 }
596
597 if let Some(authority) = pseudo.authority.take() {
598 return Some(Authority(authority));
599 }
600
601 if let Some(path) = pseudo.path.take() {
602 return Some(Path(path));
603 }
604
605 if let Some(status) = pseudo.status.take() {
606 return Some(Status(status));
607 }
608 }
609
610 self.pseudo = None;
611
612 self.fields.next().map(|(name, value)| {
613 Field {
614 name: name,
615 value: value,
616 }
617 })
618 }
619 }
620
621 // ===== impl HeadersFlag =====
622
623 impl HeadersFlag {
empty() -> HeadersFlag624 pub fn empty() -> HeadersFlag {
625 HeadersFlag(0)
626 }
627
load(bits: u8) -> HeadersFlag628 pub fn load(bits: u8) -> HeadersFlag {
629 HeadersFlag(bits & ALL)
630 }
631
is_end_stream(&self) -> bool632 pub fn is_end_stream(&self) -> bool {
633 self.0 & END_STREAM == END_STREAM
634 }
635
set_end_stream(&mut self)636 pub fn set_end_stream(&mut self) {
637 self.0 |= END_STREAM;
638 }
639
is_end_headers(&self) -> bool640 pub fn is_end_headers(&self) -> bool {
641 self.0 & END_HEADERS == END_HEADERS
642 }
643
set_end_headers(&mut self)644 pub fn set_end_headers(&mut self) {
645 self.0 |= END_HEADERS;
646 }
647
is_padded(&self) -> bool648 pub fn is_padded(&self) -> bool {
649 self.0 & PADDED == PADDED
650 }
651
is_priority(&self) -> bool652 pub fn is_priority(&self) -> bool {
653 self.0 & PRIORITY == PRIORITY
654 }
655 }
656
657 impl Default for HeadersFlag {
658 /// Returns a `HeadersFlag` value with `END_HEADERS` set.
default() -> Self659 fn default() -> Self {
660 HeadersFlag(END_HEADERS)
661 }
662 }
663
664 impl From<HeadersFlag> for u8 {
from(src: HeadersFlag) -> u8665 fn from(src: HeadersFlag) -> u8 {
666 src.0
667 }
668 }
669
670 impl fmt::Debug for HeadersFlag {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result671 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
672 util::debug_flags(fmt, self.0)
673 .flag_if(self.is_end_headers(), "END_HEADERS")
674 .flag_if(self.is_end_stream(), "END_STREAM")
675 .flag_if(self.is_padded(), "PADDED")
676 .flag_if(self.is_priority(), "PRIORITY")
677 .finish()
678 }
679 }
680
681 // ===== impl PushPromiseFlag =====
682
683 impl PushPromiseFlag {
empty() -> PushPromiseFlag684 pub fn empty() -> PushPromiseFlag {
685 PushPromiseFlag(0)
686 }
687
load(bits: u8) -> PushPromiseFlag688 pub fn load(bits: u8) -> PushPromiseFlag {
689 PushPromiseFlag(bits & ALL)
690 }
691
is_end_headers(&self) -> bool692 pub fn is_end_headers(&self) -> bool {
693 self.0 & END_HEADERS == END_HEADERS
694 }
695
set_end_headers(&mut self)696 pub fn set_end_headers(&mut self) {
697 self.0 |= END_HEADERS;
698 }
699
is_padded(&self) -> bool700 pub fn is_padded(&self) -> bool {
701 self.0 & PADDED == PADDED
702 }
703 }
704
705 impl Default for PushPromiseFlag {
706 /// Returns a `PushPromiseFlag` value with `END_HEADERS` set.
default() -> Self707 fn default() -> Self {
708 PushPromiseFlag(END_HEADERS)
709 }
710 }
711
712 impl From<PushPromiseFlag> for u8 {
from(src: PushPromiseFlag) -> u8713 fn from(src: PushPromiseFlag) -> u8 {
714 src.0
715 }
716 }
717
718 impl fmt::Debug for PushPromiseFlag {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result719 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
720 util::debug_flags(fmt, self.0)
721 .flag_if(self.is_end_headers(), "END_HEADERS")
722 .flag_if(self.is_padded(), "PADDED")
723 .finish()
724 }
725 }
726
727 // ===== HeaderBlock =====
728
729
730 impl HeaderBlock {
load(&mut self, src: &mut BytesMut, max_header_list_size: usize, decoder: &mut hpack::Decoder) -> Result<(), Error>731 fn load(&mut self, src: &mut BytesMut, max_header_list_size: usize, decoder: &mut hpack::Decoder) -> Result<(), Error> {
732 let mut reg = !self.fields.is_empty();
733 let mut malformed = false;
734 let mut headers_size = self.calculate_header_list_size();
735
736 macro_rules! set_pseudo {
737 ($field:ident, $val:expr) => {{
738 if reg {
739 trace!("load_hpack; header malformed -- pseudo not at head of block");
740 malformed = true;
741 } else if self.pseudo.$field.is_some() {
742 trace!("load_hpack; header malformed -- repeated pseudo");
743 malformed = true;
744 } else {
745 let __val = $val;
746 headers_size += decoded_header_size(stringify!($ident).len() + 1, __val.as_str().len());
747 if headers_size < max_header_list_size {
748 self.pseudo.$field = Some(__val);
749 } else if !self.is_over_size {
750 trace!("load_hpack; header list size over max");
751 self.is_over_size = true;
752 }
753 }
754 }}
755 }
756
757 let mut cursor = Cursor::new(src);
758
759 // If the header frame is malformed, we still have to continue decoding
760 // the headers. A malformed header frame is a stream level error, but
761 // the hpack state is connection level. In order to maintain correct
762 // state for other streams, the hpack decoding process must complete.
763 let res = decoder.decode(&mut cursor, |header| {
764 use hpack::Header::*;
765
766 match header {
767 Field {
768 name,
769 value,
770 } => {
771 // Connection level header fields are not supported and must
772 // result in a protocol error.
773
774 if name == header::CONNECTION
775 || name == header::TRANSFER_ENCODING
776 || name == header::UPGRADE
777 || name == "keep-alive"
778 || name == "proxy-connection"
779 {
780 trace!("load_hpack; connection level header");
781 malformed = true;
782 } else if name == header::TE && value != "trailers" {
783 trace!("load_hpack; TE header not set to trailers; val={:?}", value);
784 malformed = true;
785 } else {
786 reg = true;
787
788 headers_size += decoded_header_size(name.as_str().len(), value.len());
789 if headers_size < max_header_list_size {
790 self.fields.append(name, value);
791 } else if !self.is_over_size {
792 trace!("load_hpack; header list size over max");
793 self.is_over_size = true;
794 }
795 }
796 },
797 Authority(v) => set_pseudo!(authority, v),
798 Method(v) => set_pseudo!(method, v),
799 Scheme(v) => set_pseudo!(scheme, v),
800 Path(v) => set_pseudo!(path, v),
801 Status(v) => set_pseudo!(status, v),
802 }
803 });
804
805 if let Err(e) = res {
806 trace!("hpack decoding error; err={:?}", e);
807 return Err(e.into());
808 }
809
810 if malformed {
811 trace!("malformed message");
812 return Err(Error::MalformedMessage.into());
813 }
814
815 Ok(())
816 }
817
into_encoding(self) -> EncodingHeaderBlock818 fn into_encoding(self) -> EncodingHeaderBlock {
819 EncodingHeaderBlock {
820 hpack: None,
821 headers: Iter {
822 pseudo: Some(self.pseudo),
823 fields: self.fields.into_iter(),
824 },
825 }
826 }
827
828 /// Calculates the size of the currently decoded header list.
829 ///
830 /// According to http://httpwg.org/specs/rfc7540.html#SETTINGS_MAX_HEADER_LIST_SIZE
831 ///
832 /// > The value is based on the uncompressed size of header fields,
833 /// > including the length of the name and value in octets plus an
834 /// > overhead of 32 octets for each header field.
calculate_header_list_size(&self) -> usize835 fn calculate_header_list_size(&self) -> usize {
836 macro_rules! pseudo_size {
837 ($name:ident) => ({
838 self.pseudo
839 .$name
840 .as_ref()
841 .map(|m| decoded_header_size(stringify!($name).len() + 1, m.as_str().len()))
842 .unwrap_or(0)
843 });
844 }
845
846 pseudo_size!(method) +
847 pseudo_size!(scheme) +
848 pseudo_size!(status) +
849 pseudo_size!(authority) +
850 pseudo_size!(path) +
851 self.fields.iter()
852 .map(|(name, value)| decoded_header_size(name.as_str().len(), value.len()))
853 .sum::<usize>()
854 }
855
856 /// Iterate over all pseudos and headers to see if any individual pair
857 /// would be too large to encode.
has_too_big_field(&self) -> bool858 pub(crate) fn has_too_big_field(&self) -> bool {
859 macro_rules! pseudo_size {
860 ($name:ident) => ({
861 self.pseudo
862 .$name
863 .as_ref()
864 .map(|m| decoded_header_size(stringify!($name).len() + 1, m.as_str().len()))
865 .unwrap_or(0)
866 });
867 }
868
869 if pseudo_size!(method) > MAX_HEADER_LENGTH {
870 return true;
871 }
872
873 if pseudo_size!(scheme) > MAX_HEADER_LENGTH {
874 return true;
875 }
876
877 if pseudo_size!(authority) > MAX_HEADER_LENGTH {
878 return true;
879 }
880
881 if pseudo_size!(path) > MAX_HEADER_LENGTH {
882 return true;
883 }
884
885 // skip :status, its never going to be too big
886
887 for (name, value) in &self.fields {
888 if decoded_header_size(name.as_str().len(), value.len()) > MAX_HEADER_LENGTH {
889 return true;
890 }
891 }
892
893 false
894 }
895 }
896
decoded_header_size(name: usize, value: usize) -> usize897 fn decoded_header_size(name: usize, value: usize) -> usize {
898 name + value + 32
899 }
900
901 // Stupid hack to make the set_pseudo! macro happy, since all other values
902 // have a method `as_str` except for `String<Bytes>`.
903 trait AsStr {
as_str(&self) -> &str904 fn as_str(&self) -> &str;
905 }
906
907 impl AsStr for String<Bytes> {
as_str(&self) -> &str908 fn as_str(&self) -> &str {
909 self
910 }
911 }
912