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