1use super::{
8 integer, string,
9 table::{Header, Table},
10 HpackError,
11};
12use bytes::Bytes;
13
14const INDEXED: u8 = 0b1000_0000;
16const LITERAL_WITH_INDEXING: u8 = 0b0100_0000;
17const LITERAL_WITHOUT_INDEXING: u8 = 0b1111_0000;
18const LITERAL_NEVER_INDEXED: u8 = 0b0001_0000;
19const SIZE_UPDATE_MASK: u8 = 0b1110_0000;
20const SIZE_UPDATE: u8 = 0b0010_0000;
21
22#[derive(Debug)]
24pub struct Decoder {
25 table: Table,
27 max_table_size: usize,
31 queued_size_update: Option<usize>,
34 max_header_list_size: usize,
37}
38
39impl Decoder {
40 #[inline]
43 pub fn new(max_table_size: usize) -> Self {
44 Decoder {
45 table: Table::with_max_size(max_table_size),
46 max_table_size,
47 queued_size_update: None,
48 max_header_list_size: usize::MAX,
49 }
50 }
51
52 #[inline]
55 pub fn queue_size_update(&mut self, size: usize) {
56 self.queued_size_update = Some(match self.queued_size_update {
57 Some(current) => current.max(size),
58 None => size,
59 });
60 }
61
62 #[inline]
65 pub fn set_max_header_list_size(&mut self, size: usize) {
66 self.max_header_list_size = size;
67 }
68
69 #[cfg(test)]
70 #[inline]
71 pub(crate) fn table(&self) -> &Table {
72 &self.table
73 }
74
75 #[inline]
78 pub fn decode(&mut self, buf: &[u8], list_size: &mut usize) -> Result<Vec<Header>, HpackError> {
79 if let Some(size) = self.queued_size_update.take() {
80 self.max_table_size = size;
81 }
85
86 let mut off = 0usize;
87 let mut headers = Vec::new();
88 let mut can_resize = true;
91
92 while off < buf.len() {
93 let byte = buf[off];
94 off += 1;
97 let rep = Representation::load(byte)?;
98 match rep {
99 Representation::Indexed => {
100 can_resize = false;
101 let index = integer::decode(buf, &mut off, 7, byte)? as usize;
102 let entry = self.table.get(index).ok_or(HpackError::InvalidIndex)?;
103 *list_size += entry.name().len() + entry.value().len();
104 if *list_size > self.max_header_list_size {
105 return Err(HpackError::HeaderListTooLarge);
106 }
107 headers.push(entry);
108 }
109 Representation::LiteralWithIndexing
110 | Representation::LiteralWithoutIndexing
111 | Representation::LiteralNeverIndexed => {
112 can_resize = false;
113 let index = integer::decode(
114 buf,
115 &mut off,
116 if rep == Representation::LiteralWithIndexing {
117 6
118 } else {
119 4
120 },
121 byte,
122 )? as usize;
123
124 let name = if index == 0 {
126 let (_, name) = string::decode(buf, &mut off, self.max_header_list_size)?;
127 Bytes::from(name)
128 } else {
129 let entry = self.table.get(index).ok_or(HpackError::InvalidIndex)?;
130 Bytes::copy_from_slice(entry.name())
131 };
132
133 let (_, value) = string::decode(buf, &mut off, self.max_header_list_size)?;
134
135 *list_size += name.len() + value.len();
136 if *list_size > self.max_header_list_size {
137 return Err(HpackError::HeaderListTooLarge);
138 }
139
140 let header = Header::new(name, value);
141 if rep == Representation::LiteralWithIndexing {
142 self.table.add(header.clone());
143 }
144 headers.push(header);
145 }
146 Representation::SizeUpdate => {
147 if !can_resize {
148 return Err(HpackError::InvalidMaxSize);
149 }
150 let size = integer::decode(buf, &mut off, 5, byte)? as usize;
151 if size > self.max_table_size {
152 return Err(HpackError::InvalidMaxSize);
153 }
154 self.table.set_max_size(size);
155 }
156 }
157 }
158
159 Ok(headers)
160 }
161}
162
163impl Default for Decoder {
164 #[inline]
165 fn default() -> Self {
166 Decoder::new(4096)
167 }
168}
169
170#[derive(Debug, Clone, Copy, PartialEq, Eq)]
171enum Representation {
172 Indexed,
173 LiteralWithIndexing,
174 LiteralWithoutIndexing,
175 LiteralNeverIndexed,
176 SizeUpdate,
177}
178
179impl Representation {
180 #[inline]
181 fn load(byte: u8) -> Result<Representation, HpackError> {
182 if byte & INDEXED == INDEXED {
183 Ok(Representation::Indexed)
184 } else if byte & LITERAL_WITH_INDEXING == LITERAL_WITH_INDEXING {
185 Ok(Representation::LiteralWithIndexing)
186 } else if byte & LITERAL_WITHOUT_INDEXING == 0 {
187 Ok(Representation::LiteralWithoutIndexing)
188 } else if byte & LITERAL_WITHOUT_INDEXING == LITERAL_NEVER_INDEXED {
189 Ok(Representation::LiteralNeverIndexed)
190 } else if byte & SIZE_UPDATE_MASK == SIZE_UPDATE {
191 Ok(Representation::SizeUpdate)
192 } else {
193 Err(HpackError::InvalidRepresentation)
194 }
195 }
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201
202 #[inline]
203 fn decode_one(wire: &[u8]) -> Vec<(String, String)> {
204 let mut decoder = Decoder::new(4096);
205 decoder
206 .decode(wire, &mut 0)
207 .unwrap()
208 .into_iter()
209 .map(|h| {
210 (
211 String::from_utf8(h.name().to_vec()).unwrap(),
212 String::from_utf8(h.value().to_vec()).unwrap(),
213 )
214 })
215 .collect()
216 }
217
218 #[test]
220 fn literal_new_name_indexed() {
221 let wire = [
222 0x40, 0x0a, b'c', b'u', b's', b't', b'o', b'm', b'-', b'k', b'e', b'y', 0x0d, b'c',
223 b'u', b's', b't', b'o', b'm', b'-', b'h', b'e', b'a', b'd', b'e', b'r',
224 ];
225 assert_eq!(
226 decode_one(&wire),
227 vec![("custom-key".into(), "custom-header".into())]
228 );
229 }
230
231 #[test]
233 fn literal_without_indexing_indexed_name() {
234 let wire = [
235 0x04, 0x0c, b'/', b's', b'a', b'm', b'p', b'l', b'e', b'/', b'p', b'a', b't', b'h',
236 ];
237 assert_eq!(
238 decode_one(&wire),
239 vec![(":path".into(), "/sample/path".into())]
240 );
241 }
242
243 #[test]
245 fn literal_never_indexed() {
246 let wire = [
247 0x10, 0x08, b'p', b'a', b's', b's', b'w', b'o', b'r', b'd', 0x06, b's', b'e', b'c',
248 b'r', b'e', b't',
249 ];
250 assert_eq!(
251 decode_one(&wire),
252 vec![("password".into(), "secret".into())]
253 );
254 }
255
256 #[test]
258 fn indexed() {
259 assert_eq!(decode_one(&[0x82]), vec![(":method".into(), "GET".into())]);
260 }
261
262 #[test]
264 fn table_state_after_representations() {
265 let mut decoder = Decoder::new(4096);
266 let _ = decoder.decode(&[0x82], &mut 0).unwrap();
267 assert_eq!(decoder.table().dynamic_len(), 0);
268 let wire = [
270 0x40, 0x0a, b'c', b'u', b's', b't', b'o', b'm', b'-', b'k', b'e', b'y', 0x0d, b'c',
271 b'u', b's', b't', b'o', b'm', b'-', b'h', b'e', b'a', b'd', b'e', b'r',
272 ];
273 let _ = decoder.decode(&wire, &mut 0).unwrap();
274 assert_eq!(decoder.table().dynamic_len(), 1);
275 assert_eq!(decoder.table().get(62).unwrap().name(), b"custom-key");
276 }
277
278 #[test]
280 fn c3_1_request_without_huffman() {
281 let wire = hex_to_bytes("828684410f7777772e6578616d706c652e636f6d");
283 assert_eq!(
284 decode_one(&wire),
285 vec![
286 (":method".into(), "GET".into()),
287 (":scheme".into(), "http".into()),
288 (":path".into(), "/".into()),
289 (":authority".into(), "www.example.com".into()),
290 ]
291 );
292 }
293
294 #[test]
296 fn c4_1_request_with_huffman() {
297 let wire = hex_to_bytes("828684418cf1e3c2e5f23a6ba0ab90f4ff");
298 assert_eq!(
299 decode_one(&wire),
300 vec![
301 (":method".into(), "GET".into()),
302 (":scheme".into(), "http".into()),
303 (":path".into(), "/".into()),
304 (":authority".into(), "www.example.com".into()),
305 ]
306 );
307 }
308
309 #[test]
313 fn c3_c4_sequential_requests() {
314 let block = |d: &mut Decoder, wire: &str| {
315 d.decode(&hex_to_bytes(wire), &mut 0)
316 .unwrap()
317 .into_iter()
318 .map(|h| {
319 (
320 String::from_utf8(h.name().to_vec()).unwrap(),
321 String::from_utf8(h.value().to_vec()).unwrap(),
322 )
323 })
324 .collect::<Vec<_>>()
325 };
326
327 let mut decoder = Decoder::new(4096);
328 let _ = block(&mut decoder, "828684410f7777772e6578616d706c652e636f6d");
329
330 assert_eq!(
332 block(&mut decoder, "828684be58086e6f2d6361636865"),
333 vec![
334 (":method".into(), "GET".into()),
335 (":scheme".into(), "http".into()),
336 (":path".into(), "/".into()),
337 (":authority".into(), "www.example.com".into()),
338 ("cache-control".into(), "no-cache".into()),
339 ]
340 );
341
342 assert_eq!(
345 block(
346 &mut decoder,
347 "828785bf400a637573746f6d2d6b65790c637573746f6d2d76616c7565",
348 ),
349 vec![
350 (":method".into(), "GET".into()),
351 (":scheme".into(), "https".into()),
352 (":path".into(), "/index.html".into()),
353 (":authority".into(), "www.example.com".into()),
354 ("custom-key".into(), "custom-value".into()),
355 ]
356 );
357
358 let mut decoder = Decoder::new(4096);
359 let _ = block(&mut decoder, "828684418cf1e3c2e5f23a6ba0ab90f4ff");
360
361 assert_eq!(
363 block(&mut decoder, "828684be5886a8eb10649cbf"),
364 vec![
365 (":method".into(), "GET".into()),
366 (":scheme".into(), "http".into()),
367 (":path".into(), "/".into()),
368 (":authority".into(), "www.example.com".into()),
369 ("cache-control".into(), "no-cache".into()),
370 ]
371 );
372
373 assert_eq!(
375 block(
376 &mut decoder,
377 "828785bf408825a849e95ba97d7f8925a849e95bb8e8b4bf"
378 ),
379 vec![
380 (":method".into(), "GET".into()),
381 (":scheme".into(), "https".into()),
382 (":path".into(), "/index.html".into()),
383 (":authority".into(), "www.example.com".into()),
384 ("custom-key".into(), "custom-value".into()),
385 ]
386 );
387 }
388
389 #[test]
392 fn c5_response_walkthrough() {
393 let mut decoder = Decoder::new(256);
394 let block = |d: &mut Decoder, wire: &str| {
395 d.decode(&hex_to_bytes(wire), &mut 0)
396 .unwrap()
397 .into_iter()
398 .map(|h| {
399 (
400 String::from_utf8(h.name().to_vec()).unwrap(),
401 String::from_utf8(h.value().to_vec()).unwrap(),
402 )
403 })
404 .collect::<Vec<_>>()
405 };
406
407 let first = vec![
409 (":status".into(), "302".into()),
410 ("cache-control".into(), "private".into()),
411 ("date".into(), "Mon, 21 Oct 2013 20:13:21 GMT".into()),
412 ("location".into(), "https://www.example.com".into()),
413 ];
414 assert_eq!(
415 block(&mut decoder, "4803333032580770726976617465611d4d6f6e2c203231204f637420323031332032303a31333a323120474d546e1768747470733a2f2f7777772e6578616d706c652e636f6d"),
416 first
417 );
418 assert_eq!(decoder.table().dynamic_len(), 4);
419
420 let second = vec![
422 (":status".into(), "307".into()),
423 ("cache-control".into(), "private".into()),
424 ("date".into(), "Mon, 21 Oct 2013 20:13:21 GMT".into()),
425 ("location".into(), "https://www.example.com".into()),
426 ];
427 assert_eq!(block(&mut decoder, "4803333037c1c0bf"), second);
428 assert_eq!(decoder.table().dynamic_len(), 4);
429
430 let third = vec![
432 (":status".into(), "200".into()),
433 ("cache-control".into(), "private".into()),
434 ("date".into(), "Mon, 21 Oct 2013 20:13:22 GMT".into()),
435 ("location".into(), "https://www.example.com".into()),
436 ("content-encoding".into(), "gzip".into()),
437 (
438 "set-cookie".into(),
439 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1".into(),
440 ),
441 ];
442 assert_eq!(
443 block(
444 &mut decoder,
445 "88c1611d4d6f6e2c203231204f637420323031332032303a31333a323220474d54c05a04677a69707738666f6f3d4153444a4b48514b425a584f5157454f50495541585157454f49553b206d61782d6167653d333630303b2076657273696f6e3d31",
446 ),
447 third
448 );
449 assert_eq!(decoder.table().dynamic_len(), 3);
450 }
451
452 #[test]
455 fn c6_response_walkthrough() {
456 let mut decoder = Decoder::new(256);
457 let block = |d: &mut Decoder, wire: &str| {
458 d.decode(&hex_to_bytes(wire), &mut 0)
459 .unwrap()
460 .into_iter()
461 .map(|h| {
462 (
463 String::from_utf8(h.name().to_vec()).unwrap(),
464 String::from_utf8(h.value().to_vec()).unwrap(),
465 )
466 })
467 .collect::<Vec<_>>()
468 };
469
470 let first = vec![
471 (":status".into(), "302".into()),
472 ("cache-control".into(), "private".into()),
473 ("date".into(), "Mon, 21 Oct 2013 20:13:21 GMT".into()),
474 ("location".into(), "https://www.example.com".into()),
475 ];
476 assert_eq!(
477 block(&mut decoder, "488264025885aec3771a4b6196d07abe941054d444a8200595040b8166e082a62d1bff6e919d29ad171863c78f0b97c8e9ae82ae43d3"),
478 first
479 );
480 assert_eq!(decoder.table().dynamic_len(), 4);
481
482 let second = vec![
483 (":status".into(), "307".into()),
484 ("cache-control".into(), "private".into()),
485 ("date".into(), "Mon, 21 Oct 2013 20:13:21 GMT".into()),
486 ("location".into(), "https://www.example.com".into()),
487 ];
488 assert_eq!(block(&mut decoder, "4883640effc1c0bf"), second);
489 assert_eq!(decoder.table().dynamic_len(), 4);
490
491 let third = vec![
492 (":status".into(), "200".into()),
493 ("cache-control".into(), "private".into()),
494 ("date".into(), "Mon, 21 Oct 2013 20:13:22 GMT".into()),
495 ("location".into(), "https://www.example.com".into()),
496 ("content-encoding".into(), "gzip".into()),
497 (
498 "set-cookie".into(),
499 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1".into(),
500 ),
501 ];
502 assert_eq!(
503 block(
504 &mut decoder,
505 "88c16196d07abe941054d444a8200595040b8166e084a62d1bffc05a839bd9ab77ad94e7821dd7f2e6c7b335dfdfcd5b3960d5af27087f3672c1ab270fb5291f9587316065c003ed4ee5b1063d5007",
506 ),
507 third
508 );
509 assert_eq!(decoder.table().dynamic_len(), 3);
510 }
511
512 #[test]
513 fn size_update_at_start() {
514 let mut decoder = Decoder::new(4096);
515 let wire = [0x3f, 0xe1, 0x1f, 0x82];
517 let out = decoder.decode(&wire, &mut 0).unwrap();
518 assert_eq!(out.len(), 1);
519 assert_eq!(decoder.table().max_size(), 4096);
520 }
521
522 #[test]
523 fn size_update_after_field_rejected() {
524 let mut decoder = Decoder::new(4096);
525 assert!(matches!(
527 decoder.decode(&[0x82, 0x20], &mut 0),
528 Err(HpackError::InvalidMaxSize)
529 ));
530 }
531
532 #[test]
533 fn size_update_over_protocol_max_rejected() {
534 let mut decoder = Decoder::new(128);
535 assert!(matches!(
537 decoder.decode(&[0x3f, 0xe1, 0x1f], &mut 0),
538 Err(HpackError::InvalidMaxSize)
539 ));
540 }
541
542 #[test]
543 fn invalid_table_index_rejected() {
544 assert!(matches!(decode(&[0x80]), Err(HpackError::InvalidIndex)));
546 }
547
548 #[test]
549 fn index_out_of_range_rejected() {
550 let mut decoder = Decoder::new(4096);
551 assert!(matches!(
553 decoder.decode(&[0x7f, 0x49], &mut 0),
554 Err(HpackError::InvalidIndex)
555 ));
556 }
557
558 #[test]
559 fn header_list_size_capped() {
560 let mut decoder = Decoder::new(4096);
561 decoder.set_max_header_list_size(10);
562 let wire = [
565 0x40, 0x01, b'x', 0x0a, b'y', b'y', b'y', b'y', b'y', b'y', b'y', b'y', b'y', b'y',
566 ];
567 assert!(matches!(
568 decoder.decode(&wire, &mut 0),
569 Err(HpackError::HeaderListTooLarge)
570 ));
571 }
572
573 #[test]
574 fn small_size_update_ok() {
575 let mut decoder = Decoder::new(4096);
579 decoder.decode(&[0x30], &mut 0).unwrap();
580 assert_eq!(decoder.table().max_size(), 16);
581 }
582
583 fn decode(wire: &[u8]) -> Result<Vec<Header>, HpackError> {
584 let mut decoder = Decoder::new(4096);
585 decoder.decode(wire, &mut 0)
586 }
587
588 fn hex_to_bytes(hex: &str) -> Vec<u8> {
589 hex.as_bytes()
590 .chunks_exact(2)
591 .map(|pair| {
592 let hi = (pair[0] as char).to_digit(16).unwrap() as u8;
593 let lo = (pair[1] as char).to_digit(16).unwrap() as u8;
594 (hi << 4) | lo
595 })
596 .collect()
597 }
598}