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 #![rustfmt::skip]
15 
16 use crate::h3::parts::Parts;
17 use crate::h3::qpack::error::ErrorCode::{DecompressionFailed, EncoderStreamError};
18 use crate::h3::qpack::error::H3errorQpack;
19 use crate::h3::qpack::{
20     DeltaBase, EncoderInstPrefixBit, EncoderInstruction, MidBit, ReprPrefixBit, Representation,
21     RequireInsertCount,
22 };
23 use std::mem::take;
24 
25 use crate::h3::qpack::format::decoder::{
26     EncInstDecoder, InstDecodeState, Name, ReprDecodeState, ReprDecoder,
27 };
28 use crate::h3::qpack::integer::Integer;
29 use crate::h3::qpack::table::Field::Path;
30 use crate::h3::qpack::table::{DynamicTable, Field, TableSearcher};
31 
32 /// An decoder is used to de-compress field in a compression format for efficiently representing
33 /// HTTP fields that is to be used in HTTP/3. This is a variation of HPACK compression that seeks
34 /// to reduce head-of-line blocking.
35 ///
36 /// # Examples(not run)
37 // ```no_run
38 // use crate::ylong_http::h3::qpack::table::{DynamicTable, Field};
39 // use crate::ylong_http::h3::qpack::decoder::QpackDecoder;
40 // use crate::ylong_http::test_util::decode;
41 // const MAX_HEADER_LIST_SIZE: usize = 16 << 20;
42 //
43 // // Required content:
44 // let mut dynamic_table = DynamicTable::with_empty();
45 // let mut decoder = QpackDecoder::new(MAX_HEADER_LIST_SIZE, &mut dynamic_table);
46 //
47 // //decode instruction
48 // // convert hex string to dec-array
49 // let mut inst = decode("3fbd01c00f7777772e6578616d706c652e636f6dc10c2f73616d706c652f70617468").unwrap().as_slice().to_vec();
50 // decoder.decode_ins(&mut inst);
51 //
52 // //decode field section
53 // // convert hex string to dec-array
54 // let mut repr = decode("03811011").unwrap().as_slice().to_vec();
55 // decoder.decode_repr(&mut repr);
56 //
57 // ```
58 
59 pub(crate) struct FiledLines {
60     parts: Parts,
61     header_size: usize,
62 }
63 
64 pub struct QpackDecoder<'a> {
65     field_list_size: usize,
66     // max header list size
67     table: &'a mut DynamicTable,
68     // dynamic table
69     repr_state: Option<ReprDecodeState>,
70     // field decode state
71     inst_state: Option<InstDecodeState>,
72     // instruction decode state
73     lines: FiledLines,
74     // field lines, which is used to store the decoded field lines
75     base: usize,
76     // RFC required, got from field section prefix
77     require_insert_count: usize, // RFC required, got from field section prefix
78 }
79 
80 impl<'a> QpackDecoder<'a> {
81 
82     /// create a new decoder
83     /// # Examples(not run)
84     ///
85 //     ```no_run
86 //     use crate::ylong_http::h3::qpack::table::{DynamicTable, Field};
87 //     use crate::ylong_http::h3::qpack::decoder::QpackDecoder;
88 //     use crate::ylong_http::test_util::decode;
89 //     const MAX_HEADER_LIST_SIZE: usize = 16 << 20;
90 //     // Required content:
91 //     let mut dynamic_table = DynamicTable::with_empty();
92 //     let mut decoder = QpackDecoder::new(MAX_HEADER_LIST_SIZE, &mut dynamic_table);
93 //     ```
new(field_list_size: usize, table: &'a mut DynamicTable) -> Self94     pub fn new(field_list_size: usize, table: &'a mut DynamicTable) -> Self {
95         Self {
96             field_list_size,
97             table,
98             repr_state: None,
99             inst_state: None,
100             lines: FiledLines {
101                 parts: Parts::new(),
102                 header_size: 0,
103             },
104             base: 0,
105             require_insert_count: 0,
106         }
107     }
108 
109     /// Users can call `decode_ins` multiple times to decode decoder instructions.
110     /// # Examples(not run)
111 //     ```no_run
112 //     use crate::ylong_http::h3::qpack::table::{DynamicTable, Field};
113 //     use crate::ylong_http::h3::qpack::decoder::QpackDecoder;
114 //     use crate::ylong_http::test_util::decode;
115 //     const MAX_HEADER_LIST_SIZE: usize = 16 << 20;
116 //     // Required content:
117 //     let mut dynamic_table = DynamicTable::with_empty();
118 //     let mut decoder = QpackDecoder::new(MAX_HEADER_LIST_SIZE, &mut dynamic_table);
119 //     //decode instruction
120 //     // convert hex string to dec-array
121 //     let mut inst = decode("3fbd01c00f7777772e6578616d706c652e636f6dc10c2f73616d706c652f70617468").unwrap().as_slice().to_vec();
122 //     decoder.decode_ins(&mut inst);
123 //     ```
decode_ins(&mut self, buf: &[u8]) -> Result<(), H3errorQpack>124     pub fn decode_ins(&mut self, buf: &[u8]) -> Result<(), H3errorQpack> {
125         let mut decoder = EncInstDecoder::new();
126         let mut updater = Updater::new(self.table);
127         let mut cnt = 0;
128         loop {
129             match decoder.decode(&buf[cnt..], &mut self.inst_state)? {
130                 Some(inst) => match inst {
131                     (offset, EncoderInstruction::SetCap { capacity }) => {
132                         println!("set cap");
133                         cnt += offset;
134                         updater.update_capacity(capacity)?;
135                     }
136                     (
137                         offset,
138                         EncoderInstruction::InsertWithIndex {
139                             mid_bit,
140                             name,
141                             value,
142                         },
143                     ) => {
144                         cnt += offset;
145                         updater.update_table(mid_bit, name, value)?;
146                     }
147                     (
148                         offset,
149                         EncoderInstruction::InsertWithLiteral {
150                             mid_bit,
151                             name,
152                             value,
153                         },
154                     ) => {
155                         cnt += offset;
156                         updater.update_table(mid_bit, name, value)?;
157                     }
158                     (offset, EncoderInstruction::Duplicate { index }) => {
159                         cnt += offset;
160                         updater.duplicate(index)?;
161                     }
162                 },
163                 None => return Result::Ok(()),
164             }
165         }
166     }
167 
168     /// User call `decoder_repr` once for decoding a complete field section, which start with the `field section prefix`:
169     ///  0   1   2   3   4   5   6   7
170     /// +---+---+---+---+---+---+---+---+
171     /// |   Required Insert Count (8+)  |
172     /// +---+---------------------------+
173     /// | S |      Delta Base (7+)      |
174     /// +---+---------------------------+
175     /// |      Encoded Field Lines    ...
176     /// +-------------------------------+
177     /// # Examples(not run)
178 //     ```no_run
179 //     use crate::ylong_http::h3::qpack::table::{DynamicTable, Field};
180 //     use crate::ylong_http::h3::qpack::decoder::QpackDecoder;
181 //     use crate::ylong_http::test_util::decode;
182 //     const MAX_HEADER_LIST_SIZE: usize = 16 << 20;
183 //     // Required content:
184 //     let mut dynamic_table = DynamicTable::with_empty();
185 //     let mut decoder = QpackDecoder::new(MAX_HEADER_LIST_SIZE, &mut dynamic_table);
186 //     //decode field section
187 //     // convert hex string to dec-array
188 //     let mut repr = decode("03811011").unwrap().as_slice().to_vec();
189 //     decoder.decode_repr(&mut repr);
190 //     ```
decode_repr(&mut self, buf: &[u8]) -> Result<(), H3errorQpack>191     pub fn decode_repr(&mut self, buf: &[u8]) -> Result<(), H3errorQpack> {
192         let mut decoder = ReprDecoder::new();
193         let mut searcher = Searcher::new(self.field_list_size, self.table, &mut self.lines);
194         let mut cnt = 0;
195         loop {
196             match decoder.decode(&buf[cnt..], &mut self.repr_state)? {
197                 Some((
198                     offset,
199                     Representation::FieldSectionPrefix {
200                         require_insert_count,
201                         signal,
202                         delta_base,
203                     },
204                 )) => {
205                     cnt += offset;
206                     if require_insert_count.0 == 0 {
207                         self.require_insert_count = 0;
208                     } else {
209                         let max_entries = self.table.max_entries();
210                         let full_range = 2 * max_entries;
211                         let max_value = self.table.insert_count + max_entries;
212                         let max_wrapped = (max_value / full_range) * full_range;
213                         self.require_insert_count = max_wrapped + require_insert_count.0 - 1;
214                         if self.require_insert_count > max_value {
215                             self.require_insert_count -= full_range;
216                         }
217                     }
218                     if signal {
219                         self.base = self.require_insert_count - delta_base.0 - 1;
220                     } else {
221                         self.base = self.require_insert_count + delta_base.0;
222                     }
223                     searcher.base = self.base;
224                     if self.require_insert_count > self.table.insert_count {
225                         //todo:block
226                     }
227                 }
228                 Some((offset, Representation::Indexed { mid_bit, index })) => {
229                     cnt += offset;
230                     searcher.search(Representation::Indexed { mid_bit, index })?;
231                 }
232                 Some((offset, Representation::IndexedWithPostIndex { index })) => {
233                     cnt += offset;
234                     searcher.search(Representation::IndexedWithPostIndex { index })?;
235                 }
236                 Some((
237                     offset,
238                     Representation::LiteralWithIndexing {
239                         mid_bit,
240                         name,
241                         value,
242                     },
243                 )) => {
244                     println!("offset:{}", offset);
245                     cnt += offset;
246                     searcher.search_literal_with_indexing(mid_bit, name, value)?;
247                 }
248                 Some((
249                     offset,
250                     Representation::LiteralWithPostIndexing {
251                         mid_bit,
252                         name,
253                         value,
254                     },
255                 )) => {
256                     cnt += offset;
257                     searcher.search_literal_with_post_indexing(mid_bit, name, value)?;
258                 }
259                 Some((
260                     offset,
261                     Representation::LiteralWithLiteralName {
262                         mid_bit,
263                         name,
264                         value,
265                     },
266                 )) => {
267                     cnt += offset;
268                     searcher.search_listeral_with_literal(mid_bit, name, value)?;
269                 }
270 
271                 None => {
272                     return Result::Ok(());
273                 }
274             }
275         }
276     }
277 
278     /// Users call `finish` to stop decoding a field section. And send an `Section Acknowledgment` to encoder:
279     /// After processing an encoded field section whose declared Required Insert Count is not zero,
280     /// the decoder emits a Section Acknowledgment instruction. The instruction starts with the
281     /// '1' 1-bit pattern, followed by the field section's associated stream ID encoded as
282     /// a 7-bit prefix integer
283     ///  0   1   2   3   4   5   6   7
284     /// +---+---+---+---+---+---+---+---+
285     /// | 1 |      Stream ID (7+)       |
286     /// +---+---------------------------+
287     /// # Examples(not run)
288 //     ```no_run
289 //     use crate::ylong_http::h3::qpack::table::{DynamicTable, Field};
290 //     use crate::ylong_http::h3::qpack::decoder::QpackDecoder;
291 //     use crate::ylong_http::test_util::decode;
292 //     const MAX_HEADER_LIST_SIZE: usize = 16 << 20;
293 //     // Required content:
294 //     let mut dynamic_table = DynamicTable::with_empty();
295 //     let mut decoder = QpackDecoder::new(MAX_HEADER_LIST_SIZE, &mut dynamic_table);
296 //     //decode field section
297 //     // convert hex string to dec-array
298 //     let mut repr = decode("03811011").unwrap().as_slice().to_vec();
299 //     decoder.decode_repr(&mut repr);
300 //     //finish
301 //     let mut qpack_decoder_buf = [0u8;20];
302 //     decoder.finish(1,&mut qpack_decoder_buf);
303 //     ```
finish( &mut self, stream_id: usize, buf: &mut [u8], ) -> Result<(Parts, Option<usize>), H3errorQpack>304     pub fn finish(
305         &mut self,
306         stream_id: usize,
307         buf: &mut [u8],
308     ) -> Result<(Parts, Option<usize>), H3errorQpack> {
309         if self.repr_state.is_some() {
310             return Err(H3errorQpack::ConnectionError(DecompressionFailed));
311         }
312         self.lines.header_size = 0;
313         if self.require_insert_count > 0 {
314             let ack = Integer::index(0x80, stream_id, 0x7f);
315             let size = ack.encode(buf);
316             if let Ok(size) = size {
317                 return Ok((take(&mut self.lines.parts), Some(size)));
318             }
319         }
320         Ok((take(&mut self.lines.parts), None))
321     }
322 
323     /// Users call `stream_cancel` to stop cancel a stream. And send an `Stream Cancellation` to encoder:
324     /// When a stream is reset or reading is abandoned, the decoder emits a Stream Cancellation
325     /// instruction. The instruction starts with the '01' 2-bit pattern,
326     /// followed by the stream ID of the affected stream encoded as a 6-bit prefix integer.
327     ///  0   1   2   3   4   5   6   7
328     /// +---+---+---+---+---+---+---+---+
329     /// | 0 | 1 |     Stream ID (6+)    |
330     /// +---+---+-----------------------+
331     /// # Examples(not run)
332 //     ```no_run
333 //     use crate::ylong_http::h3::qpack::table::{DynamicTable, Field};
334 //     use crate::ylong_http::h3::qpack::decoder::QpackDecoder;
335 //     use crate::ylong_http::test_util::decode;
336 //     const MAX_HEADER_LIST_SIZE: usize = 16 << 20;
337 //     // Required content:
338 //     let mut dynamic_table = DynamicTable::with_empty();
339 //     let mut decoder = QpackDecoder::new(MAX_HEADER_LIST_SIZE, &mut dynamic_table);
340 //     //decode field section
341 //     // convert hex string to dec-array
342 //     let mut repr = decode("03811011").unwrap().as_slice().to_vec();
343 //     decoder.decode_repr(&mut repr);
344 //     //stream_cancel
345 //     let mut qpack_decoder_buf = [0u8;20];
346 //     decoder.stream_cancel(1,&mut qpack_decoder_buf);
347 //     ```
stream_cancel( &mut self, stream_id: usize, buf: &mut [u8], ) -> Result<usize, H3errorQpack>348     pub fn stream_cancel(
349         &mut self,
350         stream_id: usize,
351         buf: &mut [u8],
352     ) -> Result<usize, H3errorQpack> {
353         let ack = Integer::index(0x40, stream_id, 0x3f);
354         let size = ack.encode(buf);
355         if let Ok(size) = size {
356             return Ok(size);
357         }
358         Err(H3errorQpack::ConnectionError(DecompressionFailed))
359     }
360 }
361 
362 struct Updater<'a> {
363     table: &'a mut DynamicTable,
364 }
365 
366 impl<'a> Updater<'a> {
new(table: &'a mut DynamicTable) -> Self367     fn new(table: &'a mut DynamicTable) -> Self {
368         Self { table }
369     }
370 
update_capacity(&mut self, capacity: usize) -> Result<(), H3errorQpack>371     fn update_capacity(&mut self, capacity: usize) -> Result<(), H3errorQpack> {
372         self.table.update_size(capacity);
373         Ok(())
374     }
375 
update_table( &mut self, mid_bit: MidBit, name: Name, value: Vec<u8>, ) -> Result<(), H3errorQpack>376     fn update_table(
377         &mut self,
378         mid_bit: MidBit,
379         name: Name,
380         value: Vec<u8>,
381     ) -> Result<(), H3errorQpack> {
382         let (f, v) =
383             self.get_field_by_name_and_value(mid_bit, name, value, self.table.insert_count)?;
384         self.table.update(f, v);
385         Ok(())
386     }
387 
duplicate(&mut self, index: usize) -> Result<(), H3errorQpack>388     fn duplicate(&mut self, index: usize) -> Result<(), H3errorQpack> {
389         let table_searcher = TableSearcher::new(self.table);
390         let (f, v) = table_searcher
391             .find_field_dynamic(self.table.insert_count - index - 1)
392             .ok_or(H3errorQpack::ConnectionError(EncoderStreamError))?;
393         self.table.update(f, v);
394         Ok(())
395     }
396 
get_field_by_name_and_value( &self, mid_bit: MidBit, name: Name, value: Vec<u8>, insert_count: usize, ) -> Result<(Field, String), H3errorQpack>397     fn get_field_by_name_and_value(
398         &self,
399         mid_bit: MidBit,
400         name: Name,
401         value: Vec<u8>,
402         insert_count: usize,
403     ) -> Result<(Field, String), H3errorQpack> {
404         let h = match name {
405             Name::Index(index) => {
406                 let searcher = TableSearcher::new(self.table);
407                 if let Some(true) = mid_bit.t {
408                     searcher
409                         .find_field_name_static(index)
410                         .ok_or(H3errorQpack::ConnectionError(EncoderStreamError))?
411                 } else {
412                     searcher
413                         .find_field_name_dynamic(insert_count - index - 1)
414                         .ok_or(H3errorQpack::ConnectionError(EncoderStreamError))?
415                 }
416             }
417             Name::Literal(octets) => Field::Other(
418                 String::from_utf8(octets)
419                     .map_err(|_| H3errorQpack::ConnectionError(EncoderStreamError))?,
420             ),
421         };
422         let v = String::from_utf8(value)
423             .map_err(|_| H3errorQpack::ConnectionError(EncoderStreamError))?;
424         Ok((h, v))
425     }
426 }
427 
428 struct Searcher<'a> {
429     field_list_size: usize,
430     table: &'a DynamicTable,
431     lines: &'a mut FiledLines,
432     base: usize,
433 }
434 
435 impl<'a> Searcher<'a> {
new(field_list_size: usize, table: &'a DynamicTable, lines: &'a mut FiledLines) -> Self436     fn new(field_list_size: usize, table: &'a DynamicTable, lines: &'a mut FiledLines) -> Self {
437         Self {
438             field_list_size,
439             table,
440             lines,
441             base: 0,
442         }
443     }
444 
search(&mut self, repr: Representation) -> Result<(), H3errorQpack>445     fn search(&mut self, repr: Representation) -> Result<(), H3errorQpack> {
446         match repr {
447             Representation::Indexed { mid_bit, index } => self.search_indexed(mid_bit, index),
448             Representation::IndexedWithPostIndex { index } => self.search_post_indexed(index),
449             _ => Ok(()),
450         }
451     }
452 
search_indexed(&mut self, mid_bit: MidBit, index: usize) -> Result<(), H3errorQpack>453     fn search_indexed(&mut self, mid_bit: MidBit, index: usize) -> Result<(), H3errorQpack> {
454         let table_searcher = TableSearcher::new(self.table);
455         if let Some(true) = mid_bit.t {
456             let (f, v) = table_searcher
457                 .find_field_static(index)
458                 .ok_or(H3errorQpack::ConnectionError(DecompressionFailed))?;
459 
460             self.lines.parts.update(f, v);
461             Ok(())
462         } else {
463             let (f, v) = table_searcher
464                 .find_field_dynamic(self.base - index - 1)
465                 .ok_or(H3errorQpack::ConnectionError(DecompressionFailed))?;
466 
467             self.lines.parts.update(f, v);
468             Ok(())
469         }
470     }
471 
search_post_indexed(&mut self, index: usize) -> Result<(), H3errorQpack>472     fn search_post_indexed(&mut self, index: usize) -> Result<(), H3errorQpack> {
473         let table_searcher = TableSearcher::new(self.table);
474         let (f, v) = table_searcher
475             .find_field_dynamic(self.base + index)
476             .ok_or(H3errorQpack::ConnectionError(DecompressionFailed))?;
477         self.check_field_list_size(&f, &v)?;
478         self.lines.parts.update(f, v);
479         Ok(())
480     }
481 
search_literal_with_indexing( &mut self, mid_bit: MidBit, name: Name, value: Vec<u8>, ) -> Result<(), H3errorQpack>482     fn search_literal_with_indexing(
483         &mut self,
484         mid_bit: MidBit,
485         name: Name,
486         value: Vec<u8>,
487     ) -> Result<(), H3errorQpack> {
488         let (f, v) = self.get_field_by_name_and_value(
489             mid_bit,
490             name,
491             value,
492             ReprPrefixBit::LITERALWITHINDEXING,
493         )?;
494         self.check_field_list_size(&f, &v)?;
495         self.lines.parts.update(f, v);
496         Ok(())
497     }
498 
search_literal_with_post_indexing( &mut self, mid_bit: MidBit, name: Name, value: Vec<u8>, ) -> Result<(), H3errorQpack>499     fn search_literal_with_post_indexing(
500         &mut self,
501         mid_bit: MidBit,
502         name: Name,
503         value: Vec<u8>,
504     ) -> Result<(), H3errorQpack> {
505         let (f, v) = self.get_field_by_name_and_value(
506             mid_bit,
507             name,
508             value,
509             ReprPrefixBit::LITERALWITHPOSTINDEXING,
510         )?;
511         self.check_field_list_size(&f, &v)?;
512         self.lines.parts.update(f, v);
513         Ok(())
514     }
515 
search_listeral_with_literal( &mut self, mid_bit: MidBit, name: Name, value: Vec<u8>, ) -> Result<(), H3errorQpack>516     fn search_listeral_with_literal(
517         &mut self,
518         mid_bit: MidBit,
519         name: Name,
520         value: Vec<u8>,
521     ) -> Result<(), H3errorQpack> {
522         let (h, v) = self.get_field_by_name_and_value(
523             mid_bit,
524             name,
525             value,
526             ReprPrefixBit::LITERALWITHLITERALNAME,
527         )?;
528         self.check_field_list_size(&h, &v)?;
529         self.lines.parts.update(h, v);
530         Ok(())
531     }
532 
get_field_by_name_and_value( &self, mid_bit: MidBit, name: Name, value: Vec<u8>, repr: ReprPrefixBit, ) -> Result<(Field, String), H3errorQpack>533     fn get_field_by_name_and_value(
534         &self,
535         mid_bit: MidBit,
536         name: Name,
537         value: Vec<u8>,
538         repr: ReprPrefixBit,
539     ) -> Result<(Field, String), H3errorQpack> {
540         let h = match name {
541             Name::Index(index) => {
542                 if repr == ReprPrefixBit::LITERALWITHINDEXING {
543                     let searcher = TableSearcher::new(self.table);
544                     if let Some(true) = mid_bit.t {
545                         searcher
546                             .find_field_name_static(index)
547                             .ok_or(H3errorQpack::ConnectionError(DecompressionFailed))?
548                     } else {
549                         searcher
550                             .find_field_name_dynamic(self.base - index - 1)
551                             .ok_or(H3errorQpack::ConnectionError(DecompressionFailed))?
552                     }
553                 } else {
554                     let searcher = TableSearcher::new(self.table);
555                     searcher
556                         .find_field_name_dynamic(self.base + index)
557                         .ok_or(H3errorQpack::ConnectionError(DecompressionFailed))?
558                 }
559             }
560             Name::Literal(octets) => Field::Other(
561                 String::from_utf8(octets)
562                     .map_err(|_| H3errorQpack::ConnectionError(DecompressionFailed))?,
563             ),
564         };
565         let v = String::from_utf8(value)
566             .map_err(|_| H3errorQpack::ConnectionError(DecompressionFailed))?;
567         Ok((h, v))
568     }
update_size(&mut self, addition: usize)569     pub(crate) fn update_size(&mut self, addition: usize) {
570         self.lines.header_size += addition;
571     }
check_field_list_size(&mut self, key: &Field, value: &String) -> Result<(), H3errorQpack>572     fn check_field_list_size(&mut self, key: &Field, value: &String) -> Result<(), H3errorQpack> {
573         let line_size = field_line_length(key.len(), value.len());
574         self.update_size(line_size);
575         if self.lines.header_size > self.field_list_size {
576             Err(H3errorQpack::ConnectionError(DecompressionFailed))
577         } else {
578             Ok(())
579         }
580     }
581 }
582 
field_line_length(key_size: usize, value_size: usize) -> usize583 fn field_line_length(key_size: usize, value_size: usize) -> usize {
584     key_size + value_size + 32
585 }
586 
587 #[cfg(test)]
588 mod ut_qpack_decoder {
589     use crate::h3::qpack::format::decoder::ReprDecodeState;
590     use crate::h3::qpack::table::{DynamicTable, Field};
591     use crate::h3::qpack::QpackDecoder;
592     use crate::util::test_util::decode;
593 
594     const MAX_HEADER_LIST_SIZE: usize = 16 << 20;
595 
596     #[test]
ut_qpack_decoder()597     fn ut_qpack_decoder() {
598         rfc9204_test_cases();
599         test_need_more();
600         test_indexed_static();
601         test_indexed_dynamic();
602         test_post_indexed_dynamic();
603         test_literal_indexing_static();
604         test_literal_indexing_dynamic();
605         test_literal_post_indexing_dynamic();
606         test_literal_with_literal_name();
607         test_setcap();
608         decode_long_field();
609 
610         fn get_state(state: &Option<ReprDecodeState>) {
611             match state {
612                 Some(ReprDecodeState::FiledSectionPrefix(_)) => {
613                     println!("FiledSectionPrefix");
614                 }
615                 Some(ReprDecodeState::ReprIndex(_)) => {
616                     println!("Indexed");
617                 }
618                 Some(ReprDecodeState::ReprValueString(_)) => {
619                     println!("ReprValueString");
620                 }
621                 Some(ReprDecodeState::ReprNameAndValue(_)) => {
622                     println!("ReprNameAndValue");
623                 }
624                 None => {
625                     println!("None");
626                 }
627             }
628         }
629         macro_rules! check_pseudo {
630             (
631                 $pseudo: expr,
632                 { $a: expr, $m: expr, $p: expr, $sc: expr, $st: expr } $(,)?
633             ) => {
634                 assert_eq!($pseudo.authority(), $a);
635                 assert_eq!($pseudo.method(), $m);
636                 assert_eq!($pseudo.path(), $p);
637                 assert_eq!($pseudo.scheme(), $sc);
638                 assert_eq!($pseudo.status(), $st);
639             };
640         }
641 
642         macro_rules! get_parts {
643             ($qpack: expr $(, $input: literal)*) => {{
644                 $(
645                     let text = decode($input).unwrap().as_slice().to_vec();
646                     assert!($qpack.decode_repr(&text).is_ok());
647                 )*
648                 let mut ack = [0u8; 20];
649                 match $qpack.finish(1,&mut ack) {
650                     Ok((parts,_)) => parts,
651                     Err(_) => panic!("QpackDecoder::finish() failed!"),
652                 }
653             }};
654         }
655         macro_rules! check_map {
656             ($map: expr, { $($(,)? $k: literal => $v: literal)* } $(,)?) => {
657                 $(
658                     assert_eq!($map.get($k).unwrap().to_string().unwrap(), $v);
659                 )*
660             }
661         }
662         macro_rules! qpack_test_case {
663             (
664                 $qpack: expr $(, $input: literal)*,
665                 { $a: expr, $m: expr, $p: expr, $sc: expr, $st: expr },
666                 { $size: expr $(, $($k2: literal)? $($k3: ident)? => $v2: literal)* } $(,)?
667             ) => {
668                 let mut _qpack = $qpack;
669                 let (pseudo, _) = get_parts!(_qpack $(, $input)*).into_parts();
670                 check_pseudo!(pseudo, { $a, $m, $p, $sc, $st });
671             };
672             (
673                 $qpack: expr $(, $input: literal)*,
674                 { $($(,)? $k1: literal => $v1: literal)* },
675                 { $size: expr $(, $($k2: literal)? $($k3: ident)? => $v2: literal)* } $(,)?
676             ) => {
677                 let mut _qpack = $qpack;
678                 let (_, map) = get_parts!(_qpack $(, $input)*).into_parts();
679                 check_map!(map, { $($k1 => $v1)* });
680             };
681             (
682                 $hpack: expr $(, $input: literal)*,
683                 { $a: expr, $m: expr, $p: expr, $sc: expr, $st: expr },
684                 { $($(,)? $k1: literal => $v1: literal)* },
685                 { $size: expr $(, $($k2: literal)? $($k3: ident)? => $v2: literal)* } $(,)?
686             ) => {
687                 let mut _hpack = $hpack;
688                 let (pseudo, map) = get_parts!(_hpack $(, $input)*).into_parts();
689                 check_pseudo!(pseudo, { $a, $m, $p, $sc, $st });
690                 check_map!(map, { $($k1 => $v1)* });
691             };
692         }
693 
694         fn rfc9204_test_cases() {
695             literal_field_line_with_name_reference();
696             dynamic_table();
697             speculative_insert();
698             duplicate_instruction_stream_cancellation();
699             dynamic_table_insert_eviction();
700             fn literal_field_line_with_name_reference() {
701                 println!("run literal_field_line_with_name_reference");
702                 let mut dynamic_table = DynamicTable::with_empty();
703                 dynamic_table.update_size(4096);
704                 let decoder = QpackDecoder::new(MAX_HEADER_LIST_SIZE, &mut dynamic_table);
705                 qpack_test_case!(
706                 decoder,
707                     "0000510b2f696e6465782e68746d6c",
708                     { None, None, Some("/index.html"), None, None },
709                     { 0 }
710                 );
711                 println!("passed");
712             }
713             fn dynamic_table() {
714                 println!("dynamic_table");
715                 let mut dynamic_table = DynamicTable::with_empty();
716                 dynamic_table.update_size(4096);
717                 let mut decoder = QpackDecoder::new(MAX_HEADER_LIST_SIZE, &mut dynamic_table);
718                 let ins =
719                     decode("3fbd01c00f7777772e6578616d706c652e636f6dc10c2f73616d706c652f70617468")
720                         .unwrap()
721                         .as_slice()
722                         .to_vec();
723                 let _ = decoder.decode_ins(&ins);
724                 get_state(&decoder.repr_state);
725                 qpack_test_case!(
726                 decoder,
727                     "03811011",
728                     { Some("www.example.com"), None, Some("/sample/path"), None, None },
729                     { 0 }
730                 );
731             }
732             fn speculative_insert() {
733                 let mut dynamic_table = DynamicTable::with_empty();
734                 dynamic_table.update_size(4096);
735                 let mut decoder = QpackDecoder::new(MAX_HEADER_LIST_SIZE, &mut dynamic_table);
736                 let ins = decode("4a637573746f6d2d6b65790c637573746f6d2d76616c7565")
737                     .unwrap()
738                     .as_slice()
739                     .to_vec();
740                 let _ = decoder.decode_ins(&ins);
741                 qpack_test_case!(
742                 decoder,
743                     "028010",
744                     { "custom-key"=>"custom-value" },
745                     { 0 }
746                 );
747             }
748             fn duplicate_instruction_stream_cancellation() {
749                 let mut dynamic_table = DynamicTable::with_empty();
750                 dynamic_table.update_size(4096);
751                 dynamic_table.update(Field::Authority, String::from("www.example.com"));
752                 dynamic_table.update(Field::Path, String::from("/sample/path"));
753                 dynamic_table.update(
754                     Field::Other(String::from("custom-key")),
755                     String::from("custom-value"),
756                 );
757                 dynamic_table.known_received_count = 3;
758                 let mut decoder = QpackDecoder::new(MAX_HEADER_LIST_SIZE, &mut dynamic_table);
759                 let ins = decode("02").unwrap().as_slice().to_vec();
760                 let _ = decoder.decode_ins(&ins);
761                 qpack_test_case!(
762                 decoder,
763                     "058010c180",
764                     { Some("www.example.com"), None, Some("/"), None, None },
765                     { "custom-key"=>"custom-value" },
766                     { 0 }
767                 );
768             }
769             fn dynamic_table_insert_eviction() {
770                 let mut dynamic_table = DynamicTable::with_empty();
771                 dynamic_table.update_size(4096);
772                 dynamic_table.update(Field::Authority, String::from("www.example.com"));
773                 dynamic_table.update(Field::Path, String::from("/sample/path"));
774                 dynamic_table.update(
775                     Field::Other(String::from("custom-key")),
776                     String::from("custom-value"),
777                 );
778                 dynamic_table.update(Field::Authority, String::from("www.example.com"));
779                 dynamic_table.known_received_count = 3;
780                 let mut decoder = QpackDecoder::new(MAX_HEADER_LIST_SIZE, &mut dynamic_table);
781                 let ins = decode("810d637573746f6d2d76616c756532")
782                     .unwrap()
783                     .as_slice()
784                     .to_vec();
785                 let _ = decoder.decode_ins(&ins);
786                 qpack_test_case!(
787                 decoder,
788                     "068111",
789                     { "custom-key"=>"custom-value2" },
790                     { 0 }
791                 );
792             }
793         }
794 
795         fn test_need_more() {
796             println!("test_need_more");
797             let mut dynamic_table = DynamicTable::with_empty();
798             dynamic_table.update_size(4096);
799             let mut decoder = QpackDecoder::new(MAX_HEADER_LIST_SIZE, &mut dynamic_table);
800             let text = decode("00").unwrap().as_slice().to_vec(); //510b2f696e6465782e68746d6c
801             println!("text={:?}", text);
802             let _ = decoder.decode_repr(&text);
803             get_state(&decoder.repr_state);
804             let text2 = decode("00510b2f696e6465782e68746d6c")
805                 .unwrap()
806                 .as_slice()
807                 .to_vec();
808             println!("text2={:?}", text2);
809             let _ = decoder.decode_repr(&text2);
810         }
811 
812         fn test_indexed_static() {
813             let mut dynamic_table = DynamicTable::with_empty();
814             dynamic_table.update_size(4096);
815 
816             qpack_test_case!(
817                 QpackDecoder::new(MAX_HEADER_LIST_SIZE,&mut dynamic_table),
818                 "0000d1",
819                 { None, Some("GET"), None, None, None },
820                 { 0 }
821             );
822         }
823         fn test_indexed_dynamic() {
824             // Test index "custom-field"=>"custom-value" in dynamic table
825             let mut dynamic_table = DynamicTable::with_empty();
826             dynamic_table.update_size(4096);
827             //abs = 0
828             dynamic_table.update(
829                 Field::Other(String::from("custom-field")),
830                 String::from("custom-value"),
831             );
832             //abs = 1
833             dynamic_table.update(
834                 Field::Other(String::from("my-field")),
835                 String::from("my-value"),
836             );
837             qpack_test_case!(
838                 QpackDecoder::new(MAX_HEADER_LIST_SIZE,&mut dynamic_table),
839                 //require_insert_count=2, signal=false, delta_base=0
840                 //so base=2
841                 //rel_index=1 (abs=2(base)-1-1=0)
842                 "030081",
843                 {"custom-field"=>"custom-value"},
844                 { 0 }
845             );
846         }
847         fn test_post_indexed_dynamic() {
848             // Test index "custom-field"=>"custom-value" in dynamic table
849             let mut dynamic_table = DynamicTable::with_empty();
850             dynamic_table.update_size(4096);
851             //abs = 0
852             dynamic_table.update(
853                 Field::Other(String::from("custom1-field")),
854                 String::from("custom1-value"),
855             );
856             //abs = 1
857             dynamic_table.update(
858                 Field::Other(String::from("custom2-field")),
859                 String::from("custom2-value"),
860             );
861             //abs = 2
862             dynamic_table.update(
863                 Field::Other(String::from("custom3-field")),
864                 String::from("custom3-value"),
865             );
866             qpack_test_case!(
867                 QpackDecoder::new(MAX_HEADER_LIST_SIZE,&mut dynamic_table),
868                 //require_insert_count=3, signal=true, delta_base=2
869                 //so base = 3-2-1 = 0
870                 //rel_index=1 (abs=0(base)+1=1)
871                 "048211",
872                 {"custom2-field"=>"custom2-value"},
873                 { 0 }
874             );
875         }
876         fn test_literal_indexing_static() {
877             let mut dynamic_table = DynamicTable::with_empty();
878             dynamic_table.update_size(4096);
879             qpack_test_case!(
880                 QpackDecoder::new(MAX_HEADER_LIST_SIZE,&mut dynamic_table),
881                 "00007f020d637573746f6d312d76616c7565",
882                 { None, Some("custom1-value"), None, None, None },
883                 { 0 }
884             );
885         }
886 
887         fn test_literal_indexing_dynamic() {
888             let mut dynamic_table = DynamicTable::with_empty();
889             dynamic_table.update_size(4096);
890             //abs = 0
891             dynamic_table.update(
892                 Field::Other(String::from("custom-field")),
893                 String::from("custom-value"),
894             );
895             //abs = 1
896             dynamic_table.update(
897                 Field::Other(String::from("my-field")),
898                 String::from("my-value"),
899             );
900             qpack_test_case!(
901                 QpackDecoder::new(MAX_HEADER_LIST_SIZE,&mut dynamic_table),
902                 //require_insert_count=2, signal=false, delta_base=0
903                 //so base=2
904                 //rel_index=1 (abs=2(base)-1-1=0)
905                 "0300610d637573746f6d312d76616c7565",
906                 {"custom-field"=>"custom1-value"},
907                 { 0 }
908             );
909         }
910 
911         fn test_literal_post_indexing_dynamic() {
912             // Test index "custom-field"=>"custom-value" in dynamic table
913             let mut dynamic_table = DynamicTable::with_empty();
914             dynamic_table.update_size(4096);
915             //abs = 0
916             dynamic_table.update(
917                 Field::Other(String::from("custom1-field")),
918                 String::from("custom1-value"),
919             );
920             //abs = 1
921             dynamic_table.update(
922                 Field::Other(String::from("custom2-field")),
923                 String::from("custom2-value"),
924             );
925             //abs = 2
926             dynamic_table.update(
927                 Field::Other(String::from("custom3-field")),
928                 String::from("custom3-value"),
929             );
930             qpack_test_case!(
931                 QpackDecoder::new(MAX_HEADER_LIST_SIZE,&mut dynamic_table),
932                 //require_insert_count=3, signal=true, delta_base=2
933                 //so base = 3-2-1 = 0
934                 //rel_index=1 (abs=0(base)+1=1)
935                 "0482010d637573746f6d312d76616c7565",
936                 {"custom2-field"=>"custom1-value"},
937                 { 0 }
938             );
939         }
940 
941         fn test_literal_with_literal_name() {
942             let mut dynamic_table = DynamicTable::with_empty();
943             dynamic_table.update_size(4096);
944             qpack_test_case!(
945                 QpackDecoder::new(MAX_HEADER_LIST_SIZE, &mut dynamic_table),
946                 "00003706637573746f6d322d76616c75650d637573746f6d312d76616c7565",
947                 {"custom2-value"=>"custom1-value"},
948                 {0},
949             );
950         }
951 
952         fn test_setcap() {
953             let mut dynamic_table = DynamicTable::with_empty();
954             dynamic_table.update_size(4096);
955             let mut decoder = QpackDecoder::new(MAX_HEADER_LIST_SIZE, &mut dynamic_table);
956             let ins = decode("3fbd01").unwrap().as_slice().to_vec();
957             let _ = decoder.decode_ins(&ins);
958             assert_eq!(decoder.table.capacity(), 220);
959         }
960 
961         fn decode_long_field() {
962             let mut dynamic_table = DynamicTable::with_empty();
963             dynamic_table.update_size(4096);
964             let mut decoder = QpackDecoder::new(MAX_HEADER_LIST_SIZE, &mut dynamic_table);
965             let repr = decode("ffffff01ffff01037fffff01")
966                 .unwrap()
967                 .as_slice()
968                 .to_vec();
969             let _ = decoder.decode_repr(&repr);
970             assert_eq!(decoder.base, 32382);
971         }
972     }
973 }
974