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: &str) -> Result<(), H2Error>166 fn check_header_list_size(&mut self, key: &Header, value: &str) -> 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(unsafe { String::from_utf8_unchecked(octets) }),
193 };
194 let v = unsafe { String::from_utf8_unchecked(value) };
195 Ok((h, v))
196 }
197 }
198
header_line_length(key_size: usize, value_size: usize) -> usize199 fn header_line_length(key_size: usize, value_size: usize) -> usize {
200 key_size + value_size + 32
201 }
202
203 #[cfg(test)]
204 mod ut_hpack_decoder {
205 use crate::h2::hpack::table::Header;
206 use crate::h2::hpack::HpackDecoder;
207 use crate::util::test_util::decode;
208
209 const MAX_HEADER_LIST_SIZE: usize = 16 << 20;
210
211 /// UT test cases for `HpackDecoder`.
212 ///
213 /// # Brief
214 /// 1. Creates a `HpackDecoder`.
215 /// 2. Calls `HpackDecoder::decode()` function, passing in the specified
216 /// parameters.
217 /// 3. Checks if the test results are correct.
218 #[test]
ut_hpack_decoder()219 fn ut_hpack_decoder() {
220 rfc7541_test_cases();
221 slices_test_cases();
222
223 macro_rules! check_pseudo {
224 (
225 $pseudo: expr,
226 { $a: expr, $m: expr, $p: expr, $sc: expr, $st: expr } $(,)?
227 ) => {
228 assert_eq!($pseudo.authority(), $a);
229 assert_eq!($pseudo.method(), $m);
230 assert_eq!($pseudo.path(), $p);
231 assert_eq!($pseudo.scheme(), $sc);
232 assert_eq!($pseudo.status(), $st);
233 };
234 }
235
236 macro_rules! check_map {
237 ($map: expr, { $($(,)? $k: literal => $v: literal)* } $(,)?) => {
238 $(
239 assert_eq!($map.get($k).unwrap().to_string().unwrap(), $v);
240 )*
241 }
242 }
243
244 macro_rules! check_table {
245 (
246 $hpack: expr, $size: expr,
247 { $($(,)? $($k: literal)? $($k2: ident)? => $v: literal)* } $(,)?
248 ) => {
249 assert_eq!($hpack.table.curr_size(), $size);
250 let mut _cnt = 0;
251 $(
252
253 $(
254 match $hpack.table.header(_cnt) {
255 Some((Header::Other(k), v)) if k == $k && v == $v => {},
256 _ => panic!("DynamicTable::header() failed! (branch 1)"),
257 }
258 )?
259 $(
260 match $hpack.table.header(_cnt) {
261 Some((Header::$k2, v)) if v == $v => {},
262 _ => panic!("DynamicTable::header() failed! (branch 2)"),
263 }
264 )?
265 _cnt += 1;
266 )*
267 }
268 }
269
270 macro_rules! get_parts {
271 ($hpack: expr $(, $input: literal)*) => {{
272 $(
273 let text = decode($input).unwrap();
274 assert!($hpack.decode(text.as_slice()).is_ok());
275 )*
276 match $hpack.finish() {
277 Ok(parts) => parts,
278 Err(_) => panic!("HpackDecoder::finish() failed!"),
279 }
280 }};
281 }
282
283 macro_rules! hpack_test_case {
284 (
285 $hpack: expr $(, $input: literal)*,
286 { $a: expr, $m: expr, $p: expr, $sc: expr, $st: expr },
287 { $size: expr $(, $($k2: literal)? $($k3: ident)? => $v2: literal)* } $(,)?
288 ) => {
289 let mut _hpack = $hpack;
290 let (pseudo, _) = get_parts!(_hpack $(, $input)*).into_parts();
291 check_pseudo!(pseudo, { $a, $m, $p, $sc, $st });
292 check_table!(_hpack, $size, { $($($k2)? $($k3)? => $v2)* });
293 };
294
295 (
296 $hpack: expr $(, $input: literal)*,
297 { $($(,)? $k1: literal => $v1: literal)* },
298 { $size: expr $(, $($k2: literal)? $($k3: ident)? => $v2: literal)* } $(,)?
299 ) => {
300 let mut _hpack = $hpack;
301 let (_, map) = get_parts!(_hpack $(, $input)*).into_parts();
302 check_map!(map, { $($k1 => $v1)* });
303 check_table!(_hpack, $size, { $($($k2)? $($k3)? => $v2)* });
304 };
305
306 (
307 $hpack: expr $(, $input: literal)*,
308 { $a: expr, $m: expr, $p: expr, $sc: expr, $st: expr },
309 { $($(,)? $k1: literal => $v1: literal)* },
310 { $size: expr $(, $($k2: literal)? $($k3: ident)? => $v2: literal)* } $(,)?
311 ) => {
312 let mut _hpack = $hpack;
313 let (pseudo, map) = get_parts!(_hpack $(, $input)*).into_parts();
314 check_pseudo!(pseudo, { $a, $m, $p, $sc, $st });
315 check_map!(map, { $($k1 => $v1)* });
316 check_table!(_hpack, $size, { $($($k2)? $($k3)? => $v2)* });
317 };
318 }
319
320 /// The following test cases are from RFC7541.
321 fn rfc7541_test_cases() {
322 // C.2.1. Literal Header Field with Indexing
323 hpack_test_case!(
324 HpackDecoder::with_max_size(4096, MAX_HEADER_LIST_SIZE),
325 "400a637573746f6d2d6b65790d637573746f6d2d686561646572",
326 { "custom-key" => "custom-header" },
327 { 55, "custom-key" => "custom-header" },
328 );
329
330 // C.2.2. Literal Header Field without Indexing
331 hpack_test_case!(
332 HpackDecoder::with_max_size(4096, MAX_HEADER_LIST_SIZE),
333 "040c2f73616d706c652f70617468",
334 { None, None, Some("/sample/path"), None, None },
335 { 0 }
336 );
337
338 // C.2.3. Literal Header Field Never Indexed
339 hpack_test_case!(
340 HpackDecoder::with_max_size(4096, MAX_HEADER_LIST_SIZE),
341 "100870617373776f726406736563726574",
342 { "password" => "secret" },
343 { 0 },
344 );
345
346 // C.2.4. Indexed Header Field
347 hpack_test_case!(
348 HpackDecoder::with_max_size(4096, MAX_HEADER_LIST_SIZE),
349 "82",
350 { None, Some("GET"), None, None, None },
351 { 0 }
352 );
353
354 // Request Examples without Huffman Coding.
355 {
356 let mut hpack_decoder = HpackDecoder::with_max_size(4096, MAX_HEADER_LIST_SIZE);
357 // C.3.1. First Request
358 hpack_test_case!(
359 &mut hpack_decoder,
360 "828684410f7777772e6578616d706c652e636f6d",
361 { Some("www.example.com"), Some("GET"), Some("/"), Some("http"), None },
362 { 57, Authority => "www.example.com" }
363 );
364
365 // C.3.2. Second Request
366 hpack_test_case!(
367 &mut hpack_decoder,
368 "828684be58086e6f2d6361636865",
369 { Some("www.example.com"), Some("GET"), Some("/"), Some("http"), None },
370 { "cache-control" => "no-cache" },
371 { 110, "cache-control" => "no-cache", Authority => "www.example.com" }
372 );
373
374 // C.3.3. Third Request
375 hpack_test_case!(
376 &mut hpack_decoder,
377 "828785bf400a637573746f6d2d6b65790c637573746f6d2d76616c7565",
378 { Some("www.example.com"), Some("GET"), Some("/index.html"), Some("https"), None },
379 { "custom-key" => "custom-value" },
380 { 164, "custom-key" => "custom-value", "cache-control" => "no-cache", Authority => "www.example.com" }
381 );
382 }
383
384 // C.4. Request Examples with Huffman Coding
385 {
386 let mut hpack_decoder = HpackDecoder::with_max_size(4096, MAX_HEADER_LIST_SIZE);
387 // C.4.1. First Request
388 hpack_test_case!(
389 &mut hpack_decoder,
390 "828684418cf1e3c2e5f23a6ba0ab90f4ff",
391 { Some("www.example.com"), Some("GET"), Some("/"), Some("http"), None },
392 { 57, Authority => "www.example.com" }
393 );
394
395 // C.4.2. Second Request
396 hpack_test_case!(
397 &mut hpack_decoder,
398 "828684be5886a8eb10649cbf",
399 { Some("www.example.com"), Some("GET"), Some("/"), Some("http"), None },
400 { "cache-control" => "no-cache" },
401 { 110, "cache-control" => "no-cache", Authority => "www.example.com" }
402 );
403
404 // C.4.3. Third Request
405 hpack_test_case!(
406 &mut hpack_decoder,
407 "828785bf408825a849e95ba97d7f8925a849e95bb8e8b4bf",
408 { Some("www.example.com"), Some("GET"), Some("/index.html"), Some("https"), None },
409 { "custom-key" => "custom-value" },
410 { 164, "custom-key" => "custom-value", "cache-control" => "no-cache", Authority => "www.example.com" }
411 );
412 }
413
414 // C.5. Response Examples without Huffman Coding
415 {
416 let mut hpack_decoder = HpackDecoder::with_max_size(256, MAX_HEADER_LIST_SIZE);
417 // C.5.1. First Response
418 hpack_test_case!(
419 &mut hpack_decoder,
420 "4803333032580770726976617465611d\
421 4d6f6e2c203231204f63742032303133\
422 2032303a31333a323120474d546e1768\
423 747470733a2f2f7777772e6578616d70\
424 6c652e636f6d",
425 { None, None, None, None, Some("302") },
426 {
427 "location" => "https://www.example.com",
428 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
429 "cache-control" => "private"
430 },
431 {
432 222,
433 "location" => "https://www.example.com",
434 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
435 "cache-control" => "private",
436 Status => "302"
437 }
438 );
439
440 // C.5.2. Second Response
441 hpack_test_case!(
442 &mut hpack_decoder,
443 "4803333037c1c0bf",
444 { None, None, None, None, Some("307") },
445 {
446 "cache-control" => "private",
447 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
448 "location" => "https://www.example.com"
449 },
450 {
451 222,
452 Status => "307",
453 "location" => "https://www.example.com",
454 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
455 "cache-control" => "private"
456 }
457 );
458
459 // C.5.3. Third Response
460 hpack_test_case!(
461 &mut hpack_decoder,
462 "88c1611d4d6f6e2c203231204f637420\
463 323031332032303a31333a323220474d\
464 54c05a04677a69707738666f6f3d4153\
465 444a4b48514b425a584f5157454f5049\
466 5541585157454f49553b206d61782d61\
467 67653d333630303b2076657273696f6e\
468 3d31",
469 { None, None, None, None, Some("200") },
470 {
471 "cache-control" => "private",
472 "date" => "Mon, 21 Oct 2013 20:13:22 GMT",
473 "location" => "https://www.example.com",
474 "content-encoding" => "gzip",
475 "set-cookie" => "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"
476 },
477 {
478 215,
479 "set-cookie" => "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
480 "content-encoding" => "gzip",
481 "date" => "Mon, 21 Oct 2013 20:13:22 GMT"
482 }
483 );
484 }
485
486 // C.6. Response Examples with Huffman Coding
487 {
488 let mut hpack_decoder = HpackDecoder::with_max_size(256, MAX_HEADER_LIST_SIZE);
489 // C.6.1. First Response
490 hpack_test_case!(
491 &mut hpack_decoder,
492 "488264025885aec3771a4b6196d07abe\
493 941054d444a8200595040b8166e082a6\
494 2d1bff6e919d29ad171863c78f0b97c8\
495 e9ae82ae43d3",
496 { None, None, None, None, Some("302") },
497 {
498 "location" => "https://www.example.com",
499 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
500 "cache-control" => "private"
501 },
502 {
503 222,
504 "location" => "https://www.example.com",
505 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
506 "cache-control" => "private",
507 Status => "302"
508 }
509 );
510
511 // C.6.2. Second Response
512 hpack_test_case!(
513 &mut hpack_decoder,
514 "4883640effc1c0bf",
515 { None, None, None, None, Some("307") },
516 {
517 "cache-control" => "private",
518 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
519 "location" => "https://www.example.com"
520 },
521 {
522 222,
523 Status => "307",
524 "location" => "https://www.example.com",
525 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
526 "cache-control" => "private"
527 }
528 );
529
530 // C.6.3. Third Response
531 hpack_test_case!(
532 &mut hpack_decoder,
533 "88c16196d07abe941054d444a8200595\
534 040b8166e084a62d1bffc05a839bd9ab\
535 77ad94e7821dd7f2e6c7b335dfdfcd5b\
536 3960d5af27087f3672c1ab270fb5291f\
537 9587316065c003ed4ee5b1063d5007",
538 { None, None, None, None, Some("200") },
539 {
540 "cache-control" => "private",
541 "date" => "Mon, 21 Oct 2013 20:13:22 GMT",
542 "location" => "https://www.example.com",
543 "content-encoding" => "gzip",
544 "set-cookie" => "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"
545 },
546 {
547 215,
548 "set-cookie" => "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
549 "content-encoding" => "gzip",
550 "date" => "Mon, 21 Oct 2013 20:13:22 GMT"
551 }
552 );
553 }
554 }
555
556 fn slices_test_cases() {
557 // C.2.1. Literal Header Field with Indexing
558 hpack_test_case!(
559 HpackDecoder::with_max_size(4096, MAX_HEADER_LIST_SIZE),
560 "04", "0c", "2f", "73", "61", "6d", "70", "6c", "65", "2f", "70", "61", "74", "68",
561 { None, None, Some("/sample/path"), None, None },
562 { 0 }
563 );
564
565 // C.6.1. First Response
566 hpack_test_case!(
567 HpackDecoder::with_max_size(256, MAX_HEADER_LIST_SIZE),
568 "488264025885aec3771a4b6196d07abe",
569 "941054d444a8200595040b8166e082a6",
570 "2d1bff6e919d29ad171863c78f0b97c8",
571 "e9ae82ae43d3",
572 { None, None, None, None, Some("302") },
573 {
574 "location" => "https://www.example.com",
575 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
576 "cache-control" => "private"
577 },
578 {
579 222,
580 "location" => "https://www.example.com",
581 "date" => "Mon, 21 Oct 2013 20:13:21 GMT",
582 "cache-control" => "private",
583 Status => "302"
584 }
585 );
586 }
587 }
588
589 /// UT test cases for `HpackDecoder`.
590 ///
591 /// # Brief
592 /// 1. Creates a header buf with non-utf8 bytes `0xE5, 0xBB, 0x6F`.
593 /// 2. Calls `HpackDecoder::decode()` function, passing in the specified
594 /// parameters.
595 /// 3. Checks if the test results are correct.
596 #[test]
ut_decode_literal_non_utf8_header_value()597 fn ut_decode_literal_non_utf8_header_value() {
598 let mut decoder = HpackDecoder::with_max_size(1000, 2000);
599 let buf: [u8; 73] = [
600 0x0, 0x8D, 0x21, 0xEA, 0x49, 0x6A, 0x4A, 0xD2, 0x19, 0x15, 0x9D, 0x6, 0x49, 0x8F, 0x57,
601 0x39, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6D, 0x65, 0x6E, 0x74, 0x3B, 0x66, 0x69,
602 0x6C, 0x65, 0x4E, 0x61, 0x6D, 0x65, 0x3D, 0x54, 0x65, 0x73, 0x74, 0x5F, 0xE6, 0x96,
603 0xB0, 0xE5, 0xBB, 0x6F, 0x20, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74,
604 0x20, 0x57, 0x6F, 0x72, 0x64, 0x20, 0xE6, 0x96, 0x87, 0xE6, 0xA1, 0xA3, 0x2E, 0x64,
605 0x6F, 0x63,
606 ];
607 let res = decoder.decode(&buf);
608 assert!(res.is_ok());
609 }
610 }
611