1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 use core::mem::take;
15
16 use crate::h2::error::ErrorCode;
17 use crate::h2::hpack::representation::{
18 Name, ReprDecStateHolder, ReprDecodeState, ReprDecoder, Representation,
19 };
20 use crate::h2::hpack::table::{DynamicTable, Header, TableSearcher};
21 use crate::h2::{H2Error, Parts};
22
23 // A structure used to store header lines and octets lengths of header lines.
24 struct HeaderLines {
25 parts: Parts,
26 header_size: usize,
27 }
28
29 /// Decoder implementation of [`HPACK`].
30 ///
31 /// [`HPACK`]: https://httpwg.org/specs/rfc7541.html
32 pub(crate) struct HpackDecoder {
33 header_list_size: usize,
34 table: DynamicTable,
35 lines: HeaderLines,
36 holder: ReprDecStateHolder,
37 }
38
39 impl HpackDecoder {
40 /// Creates a `HpackDecoder` with the given max size.
with_max_size(header_table_size: usize, max_header_list_size: usize) -> Self41 pub(crate) fn with_max_size(header_table_size: usize, max_header_list_size: usize) -> Self {
42 Self {
43 header_list_size: max_header_list_size,
44 table: DynamicTable::with_max_size(header_table_size),
45 lines: HeaderLines {
46 parts: Parts::new(),
47 header_size: 0,
48 },
49 holder: ReprDecStateHolder::new(),
50 }
51 }
52
53 /// Users can call `decode` multiple times to decode the byte stream in
54 /// segments.
decode(&mut self, buf: &[u8]) -> Result<(), H2Error>55 pub(crate) fn decode(&mut self, buf: &[u8]) -> Result<(), H2Error> {
56 // Initialize ReprDecoder.
57 let mut decoder = ReprDecoder::new(buf);
58 decoder.load(&mut self.holder);
59
60 let mut updater = Updater::new(&mut self.table, &mut self.lines, self.header_list_size);
61 loop {
62 match decoder.decode()? {
63 // If a `Repr` is decoded, the `Updater` updates it immediately.
64 Some(repr) => updater.update(repr)?,
65 // If no `Repr` is decoded at this time, the intermediate result
66 // needs to be saved.
67 None => {
68 decoder.save(&mut self.holder);
69 return Ok(());
70 }
71 }
72 }
73 }
74
75 /// Users call `finish` to stop decoding and get the result.
finish(&mut self) -> Result<Parts, H2Error>76 pub(crate) fn finish(&mut self) -> Result<Parts, H2Error> {
77 if !self.holder.is_empty() {
78 return Err(H2Error::ConnectionError(ErrorCode::CompressionError));
79 }
80 self.lines.header_size = 0;
81 Ok(take(&mut self.lines.parts))
82 }
83
84 /// Update the SETTING_HEADER_LIST_SIZE
update_header_list_size(&mut self, size: usize)85 pub(crate) fn update_header_list_size(&mut self, size: usize) {
86 self.header_list_size = size
87 }
88 }
89
90 /// `Updater` is used to update `DynamicTable` `PseudoHeaders` and
91 /// `HttpHeaderMap`.
92 struct Updater<'a> {
93 header_list_size: usize,
94 table: &'a mut DynamicTable,
95 lines: &'a mut HeaderLines,
96 }
97
98 impl<'a> Updater<'a> {
99 /// Creates a new `Updater`.
new( table: &'a mut DynamicTable, lines: &'a mut HeaderLines, header_list_size: usize, ) -> Self100 fn new(
101 table: &'a mut DynamicTable,
102 lines: &'a mut HeaderLines,
103 header_list_size: usize,
104 ) -> Self {
105 Self {
106 table,
107 lines,
108 header_list_size,
109 }
110 }
111
112 /// Updates the `DynamicTable` and `Parts`.
update(&mut self, repr: Representation) -> Result<(), H2Error>113 fn update(&mut self, repr: Representation) -> Result<(), H2Error> {
114 match repr {
115 Representation::Indexed { index } => self.update_indexed(index),
116 Representation::LiteralWithIndexing { name: n, value: v } => {
117 self.update_literal_with_indexing(n, v)
118 }
119 Representation::LiteralWithoutIndexing { name: n, value: v } => {
120 self.update_literal_without_indexing(n, v)
121 }
122 Representation::LiteralNeverIndexed { name: n, value: v } => {
123 self.update_literal_never_indexing(n, v)
124 }
125 Representation::SizeUpdate { max_size } => {
126 self.table.update_size(max_size);
127 Ok(())
128 }
129 }
130 }
131
update_indexed(&mut self, index: usize) -> Result<(), H2Error>132 fn update_indexed(&mut self, index: usize) -> Result<(), H2Error> {
133 let searcher = TableSearcher::new(self.table);
134 let (h, v) = searcher
135 .search_header(index)
136 .ok_or(H2Error::ConnectionError(ErrorCode::CompressionError))?;
137 self.check_header_list_size(&h, &v)?;
138 self.lines.parts.update(h, v);
139 Ok(())
140 }
141
update_literal_with_indexing(&mut self, name: Name, value: Vec<u8>) -> Result<(), H2Error>142 fn update_literal_with_indexing(&mut self, name: Name, value: Vec<u8>) -> Result<(), H2Error> {
143 let (h, v) = self.get_header_by_name_and_value(name, value)?;
144 self.check_header_list_size(&h, &v)?;
145 self.table.update(h.clone(), v.clone());
146 self.lines.parts.update(h, v);
147 Ok(())
148 }
149
update_literal_without_indexing( &mut self, name: Name, value: Vec<u8>, ) -> Result<(), H2Error>150 fn update_literal_without_indexing(
151 &mut self,
152 name: Name,
153 value: Vec<u8>,
154 ) -> Result<(), H2Error> {
155 let (h, v) = self.get_header_by_name_and_value(name, value)?;
156 self.check_header_list_size(&h, &v)?;
157 self.lines.parts.update(h, v);
158 Ok(())
159 }
160
161 // TODO: 支持 `LiteralNeverIndexed`.
update_literal_never_indexing(&mut self, name: Name, value: Vec<u8>) -> Result<(), H2Error>162 fn update_literal_never_indexing(&mut self, name: Name, value: Vec<u8>) -> Result<(), H2Error> {
163 self.update_literal_without_indexing(name, value)
164 }
165
check_header_list_size(&mut self, key: &Header, value: &String) -> Result<(), H2Error>166 fn check_header_list_size(&mut self, key: &Header, value: &String) -> Result<(), H2Error> {
167 let line_size = header_line_length(key.len(), value.len());
168 self.update_size(line_size);
169 if self.lines.header_size > self.header_list_size {
170 Err(H2Error::ConnectionError(ErrorCode::ConnectError))
171 } else {
172 Ok(())
173 }
174 }
175
update_size(&mut self, addition: usize)176 pub(crate) fn update_size(&mut self, addition: usize) {
177 self.lines.header_size += addition;
178 }
179
get_header_by_name_and_value( &self, name: Name, value: Vec<u8>, ) -> Result<(Header, String), H2Error>180 fn get_header_by_name_and_value(
181 &self,
182 name: Name,
183 value: Vec<u8>,
184 ) -> Result<(Header, String), H2Error> {
185 let h = match name {
186 Name::Index(index) => {
187 let searcher = TableSearcher::new(self.table);
188 searcher
189 .search_header_name(index)
190 .ok_or(H2Error::ConnectionError(ErrorCode::CompressionError))?
191 }
192 Name::Literal(octets) => Header::Other(
193 String::from_utf8(octets)
194 .map_err(|_| H2Error::ConnectionError(ErrorCode::CompressionError))?,
195 ),
196 };
197 let v = String::from_utf8(value)
198 .map_err(|_| H2Error::ConnectionError(ErrorCode::CompressionError))?;
199 Ok((h, v))
200 }
201 }
202
header_line_length(key_size: usize, value_size: usize) -> usize203 fn header_line_length(key_size: usize, value_size: usize) -> usize {
204 key_size + value_size + 32
205 }
206
207 #[cfg(test)]
208 mod ut_hpack_decoder {
209 use crate::h2::hpack::table::Header;
210 use crate::h2::hpack::HpackDecoder;
211 use crate::test_util::decode;
212
213 const MAX_HEADER_LIST_SIZE: usize = 16 << 20;
214
215 /// UT test cases for `HpackDecoder`.
216 ///
217 /// # Brief
218 /// 1. Creates a `HpackDecoder`.
219 /// 2. Calls `HpackDecoder::decode()` function, passing in the specified
220 /// parameters.
221 /// 3. Checks if the test results are correct.
222 #[test]
ut_hpack_decoder()223 fn ut_hpack_decoder() {
224 rfc7541_test_cases();
225 slices_test_cases();
226
227 macro_rules! check_pseudo {
228 (
229 $pseudo: expr,
230 { $a: expr, $m: expr, $p: expr, $sc: expr, $st: expr } $(,)?
231 ) => {
232 assert_eq!($pseudo.authority(), $a);
233 assert_eq!($pseudo.method(), $m);
234 assert_eq!($pseudo.path(), $p);
235 assert_eq!($pseudo.scheme(), $sc);
236 assert_eq!($pseudo.status(), $st);
237 };
238 }
239
240 macro_rules! check_map {
241 ($map: expr, { $($(,)? $k: literal => $v: literal)* } $(,)?) => {
242 $(
243 assert_eq!($map.get($k).unwrap().to_str().unwrap(), $v);
244 )*
245 }
246 }
247
248 macro_rules! check_table {
249 (
250 $hpack: expr, $size: expr,
251 { $($(,)? $($k: literal)? $($k2: ident)? => $v: literal)* } $(,)?
252 ) => {
253 assert_eq!($hpack.table.curr_size(), $size);
254 let mut _cnt = 0;
255 $(
256
257 $(
258 match $hpack.table.header(_cnt) {
259 Some((Header::Other(k), v)) if k == $k && v == $v => {},
260 _ => panic!("DynamicTable::header() failed! (branch 1)"),
261 }
262 )?
263 $(
264 match $hpack.table.header(_cnt) {
265 Some((Header::$k2, v)) if v == $v => {},
266 _ => panic!("DynamicTable::header() failed! (branch 2)"),
267 }
268 )?
269 _cnt += 1;
270 )*
271 }
272 }
273
274 macro_rules! get_parts {
275 ($hpack: expr $(, $input: literal)*) => {{
276 $(
277 let text = decode($input).unwrap();
278 assert!($hpack.decode(text.as_slice()).is_ok());
279 )*
280 match $hpack.finish() {
281 Ok(parts) => parts,
282 Err(_) => panic!("HpackDecoder::finish() failed!"),
283 }
284 }};
285 }
286
287 macro_rules! hpack_test_case {
288 (
289 $hpack: expr $(, $input: literal)*,
290 { $a: expr, $m: expr, $p: expr, $sc: expr, $st: expr },
291 { $size: expr $(, $($k2: literal)? $($k3: ident)? => $v2: literal)* } $(,)?
292 ) => {
293 let mut _hpack = $hpack;
294 let (pseudo, _) = get_parts!(_hpack $(, $input)*).into_parts();
295 check_pseudo!(pseudo, { $a, $m, $p, $sc, $st });
296 check_table!(_hpack, $size, { $($($k2)? $($k3)? => $v2)* });
297 };
298
299 (
300 $hpack: expr $(, $input: literal)*,
301 { $($(,)? $k1: literal => $v1: literal)* },
302 { $size: expr $(, $($k2: literal)? $($k3: ident)? => $v2: literal)* } $(,)?
303 ) => {
304 let mut _hpack = $hpack;
305 let (_, map) = get_parts!(_hpack $(, $input)*).into_parts();
306 check_map!(map, { $($k1 => $v1)* });
307 check_table!(_hpack, $size, { $($($k2)? $($k3)? => $v2)* });
308 };
309
310 (
311 $hpack: expr $(, $input: literal)*,
312 { $a: expr, $m: expr, $p: expr, $sc: expr, $st: expr },
313 { $($(,)? $k1: literal => $v1: literal)* },
314 { $size: expr $(, $($k2: literal)? $($k3: ident)? => $v2: literal)* } $(,)?
315 ) => {
316 let mut _hpack = $hpack;
317 let (pseudo, map) = get_parts!(_hpack $(, $input)*).into_parts();
318 check_pseudo!(pseudo, { $a, $m, $p, $sc, $st });
319 check_map!(map, { $($k1 => $v1)* });
320 check_table!(_hpack, $size, { $($($k2)? $($k3)? => $v2)* });
321 };
322 }
323
324 /// The following test cases are from RFC7541.
325 fn rfc7541_test_cases() {
326 // C.2.1. Literal Header Field with Indexing
327 hpack_test_case!(
328 HpackDecoder::with_max_size(4096, MAX_HEADER_LIST_SIZE),
329 "400a637573746f6d2d6b65790d637573746f6d2d686561646572",
330 { "custom-key" => "custom-header" },
331 { 55, "custom-key" => "custom-header" },
332 );
333
334 // C.2.2. Literal Header Field without Indexing
335 hpack_test_case!(
336 HpackDecoder::with_max_size(4096, MAX_HEADER_LIST_SIZE),
337 "040c2f73616d706c652f70617468",
338 { None, None, Some("/sample/path"), None, None },
339 { 0 }
340 );
341
342 // C.2.3. Literal Header Field Never Indexed
343 hpack_test_case!(
344 HpackDecoder::with_max_size(4096, MAX_HEADER_LIST_SIZE),
345 "100870617373776f726406736563726574",
346 { "password" => "secret" },
347 { 0 },
348 );
349
350 // C.2.4. Indexed Header Field
351 hpack_test_case!(
352 HpackDecoder::with_max_size(4096, MAX_HEADER_LIST_SIZE),
353 "82",
354 { None, Some("GET"), None, None, None },
355 { 0 }
356 );
357
358 // Request Examples without Huffman Coding.
359 {
360 let mut hpack_decoder = HpackDecoder::with_max_size(4096, MAX_HEADER_LIST_SIZE);
361 // C.3.1. First Request
362 hpack_test_case!(
363 &mut hpack_decoder,
364 "828684410f7777772e6578616d706c652e636f6d",
365 { Some("www.example.com"), Some("GET"), Some("/"), Some("http"), None },
366 { 57, Authority => "www.example.com" }
367 );
368
369 // C.3.2. Second Request
370 hpack_test_case!(
371 &mut hpack_decoder,
372 "828684be58086e6f2d6361636865",
373 { Some("www.example.com"), Some("GET"), Some("/"), Some("http"), None },
374 { "cache-control" => "no-cache" },
375 { 110, "cache-control" => "no-cache", Authority => "www.example.com" }
376 );
377
378 // C.3.3. Third Request
379 hpack_test_case!(
380 &mut hpack_decoder,
381 "828785bf400a637573746f6d2d6b65790c637573746f6d2d76616c7565",
382 { Some("www.example.com"), Some("GET"), Some("/index.html"), Some("https"), None },
383 { "custom-key" => "custom-value" },
384 { 164, "custom-key" => "custom-value", "cache-control" => "no-cache", Authority => "www.example.com" }
385 );
386 }
387
388 // C.4. Request Examples with Huffman Coding
389 {
390 let mut hpack_decoder = HpackDecoder::with_max_size(4096, MAX_HEADER_LIST_SIZE);
391 // C.4.1. First Request
392 hpack_test_case!(
393 &mut hpack_decoder,
394 "828684418cf1e3c2e5f23a6ba0ab90f4ff",
395 { Some("www.example.com"), Some("GET"), Some("/"), Some("http"), None },
396 { 57, Authority => "www.example.com" }
397 );
398
399 // C.4.2. Second Request
400 hpack_test_case!(
401 &mut hpack_decoder,
402 "828684be5886a8eb10649cbf",
403 { Some("www.example.com"), Some("GET"), Some("/"), Some("http"), None },
404 { "cache-control" => "no-cache" },
405 { 110, "cache-control" => "no-cache", Authority => "www.example.com" }
406 );
407
408 // C.4.3. Third Request
409 hpack_test_case!(
410 &mut hpack_decoder,
411 "828785bf408825a849e95ba97d7f8925a849e95bb8e8b4bf",
412 { Some("www.example.com"), Some("GET"), Some("/index.html"), Some("https"), None },
413 { "custom-key" => "custom-value" },
414 { 164, "custom-key" => "custom-value", "cache-control" => "no-cache", Authority => "www.example.com" }
415 );
416 }
417
418 // C.5. Response Examples without Huffman Coding
419 {
420 let mut hpack_decoder = HpackDecoder::with_max_size(256, MAX_HEADER_LIST_SIZE);
421 // C.5.1. First Response
422 hpack_test_case!(
423 &mut hpack_decoder,
424 "4803333032580770726976617465611d\
425 4d6f6e2c203231204f63742032303133\
426 2032303a31333a323120474d546e1768\
427 747470733a2f2f7777772e6578616d70\
428 6c652e636f6d",
429 { None, None, None, None, Some("302") },
430 {
431 "location" => "https://www.example.com",
432 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
433 "cache-control" => "private"
434 },
435 {
436 222,
437 "location" => "https://www.example.com",
438 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
439 "cache-control" => "private",
440 Status => "302"
441 }
442 );
443
444 // C.5.2. Second Response
445 hpack_test_case!(
446 &mut hpack_decoder,
447 "4803333037c1c0bf",
448 { None, None, None, None, Some("307") },
449 {
450 "cache-control" => "private",
451 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
452 "location" => "https://www.example.com"
453 },
454 {
455 222,
456 Status => "307",
457 "location" => "https://www.example.com",
458 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
459 "cache-control" => "private"
460 }
461 );
462
463 // C.5.3. Third Response
464 hpack_test_case!(
465 &mut hpack_decoder,
466 "88c1611d4d6f6e2c203231204f637420\
467 323031332032303a31333a323220474d\
468 54c05a04677a69707738666f6f3d4153\
469 444a4b48514b425a584f5157454f5049\
470 5541585157454f49553b206d61782d61\
471 67653d333630303b2076657273696f6e\
472 3d31",
473 { None, None, None, None, Some("200") },
474 {
475 "cache-control" => "private",
476 "date" => "Mon, 21 Oct 2013 20:13:22 GMT",
477 "location" => "https://www.example.com",
478 "content-encoding" => "gzip",
479 "set-cookie" => "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"
480 },
481 {
482 215,
483 "set-cookie" => "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
484 "content-encoding" => "gzip",
485 "date" => "Mon, 21 Oct 2013 20:13:22 GMT"
486 }
487 );
488 }
489
490 // C.6. Response Examples with Huffman Coding
491 {
492 let mut hpack_decoder = HpackDecoder::with_max_size(256, MAX_HEADER_LIST_SIZE);
493 // C.6.1. First Response
494 hpack_test_case!(
495 &mut hpack_decoder,
496 "488264025885aec3771a4b6196d07abe\
497 941054d444a8200595040b8166e082a6\
498 2d1bff6e919d29ad171863c78f0b97c8\
499 e9ae82ae43d3",
500 { None, None, None, None, Some("302") },
501 {
502 "location" => "https://www.example.com",
503 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
504 "cache-control" => "private"
505 },
506 {
507 222,
508 "location" => "https://www.example.com",
509 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
510 "cache-control" => "private",
511 Status => "302"
512 }
513 );
514
515 // C.6.2. Second Response
516 hpack_test_case!(
517 &mut hpack_decoder,
518 "4883640effc1c0bf",
519 { None, None, None, None, Some("307") },
520 {
521 "cache-control" => "private",
522 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
523 "location" => "https://www.example.com"
524 },
525 {
526 222,
527 Status => "307",
528 "location" => "https://www.example.com",
529 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
530 "cache-control" => "private"
531 }
532 );
533
534 // C.6.3. Third Response
535 hpack_test_case!(
536 &mut hpack_decoder,
537 "88c16196d07abe941054d444a8200595\
538 040b8166e084a62d1bffc05a839bd9ab\
539 77ad94e7821dd7f2e6c7b335dfdfcd5b\
540 3960d5af27087f3672c1ab270fb5291f\
541 9587316065c003ed4ee5b1063d5007",
542 { None, None, None, None, Some("200") },
543 {
544 "cache-control" => "private",
545 "date" => "Mon, 21 Oct 2013 20:13:22 GMT",
546 "location" => "https://www.example.com",
547 "content-encoding" => "gzip",
548 "set-cookie" => "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"
549 },
550 {
551 215,
552 "set-cookie" => "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
553 "content-encoding" => "gzip",
554 "date" => "Mon, 21 Oct 2013 20:13:22 GMT"
555 }
556 );
557 }
558 }
559
560 fn slices_test_cases() {
561 // C.2.1. Literal Header Field with Indexing
562 hpack_test_case!(
563 HpackDecoder::with_max_size(4096, MAX_HEADER_LIST_SIZE),
564 "04", "0c", "2f", "73", "61", "6d", "70", "6c", "65", "2f", "70", "61", "74", "68",
565 { None, None, Some("/sample/path"), None, None },
566 { 0 }
567 );
568
569 // C.6.1. First Response
570 hpack_test_case!(
571 HpackDecoder::with_max_size(256, MAX_HEADER_LIST_SIZE),
572 "488264025885aec3771a4b6196d07abe",
573 "941054d444a8200595040b8166e082a6",
574 "2d1bff6e919d29ad171863c78f0b97c8",
575 "e9ae82ae43d3",
576 { None, None, None, None, Some("302") },
577 {
578 "location" => "https://www.example.com",
579 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
580 "cache-control" => "private"
581 },
582 {
583 222,
584 "location" => "https://www.example.com",
585 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
586 "cache-control" => "private",
587 Status => "302"
588 }
589 );
590 }
591 }
592 }
593