• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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