• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 pub mod decoder;
15 pub mod encoder;
16 pub(crate) mod error;
17 pub mod format;
18 mod integer;
19 pub mod table;
20 pub(crate) use decoder::{FieldDecodeState, FiledLines, QpackDecoder};
21 pub(crate) use encoder::{DecoderInst, QpackEncoder};
22 
23 use crate::h3::qpack::format::decoder::Name;
24 
25 pub(crate) struct RequireInsertCount(usize);
26 
27 pub(crate) struct DeltaBase(usize);
28 
29 #[derive(Copy, Clone, PartialEq, Eq)]
30 pub(crate) struct EncoderInstPrefixBit(u8);
31 
32 #[derive(Copy, Clone, PartialEq, Eq)]
33 pub(crate) struct DecoderInstPrefixBit(u8);
34 
35 #[derive(Copy, Clone, PartialEq, Eq)]
36 pub(crate) struct ReprPrefixBit(u8);
37 
38 /// # Prefix bit:
39 /// ## Encoder Instructions:
40 /// SET_CAP: 0x20
41 /// INSERT_WITH_INDEX: 0x80
42 /// INSERT_WITH_LITERAL: 0x40
43 /// DUPLICATE: 0x00
44 ///
45 /// ## Decoder Instructions:
46 /// ACK: 0x80
47 /// STREAM_CANCEL: 0x40
48 /// INSERT_COUNT_INCREMENT: 0x00
49 ///
50 /// ## Representation:
51 /// INDEXED: 0x80
52 /// INDEXEDWITHPOSTINDEX: 0x10
53 /// LITERALWITHINDEXING: 0x40
54 /// LITERALWITHPOSTINDEXING: 0x00
55 /// LITERALWITHLITERALNAME: 0x20
56 
57 impl DecoderInstPrefixBit {
58     pub(crate) const ACK: Self = Self(0x80);
59     pub(crate) const STREAM_CANCEL: Self = Self(0x40);
60     pub(crate) const INSERT_COUNT_INCREMENT: Self = Self(0x00);
61 
from_u8(byte: u8) -> Self62     pub(crate) fn from_u8(byte: u8) -> Self {
63         match byte {
64             x if x & 0x80 == 0x80 => Self::ACK,
65             x if x & 0xC0 == 0x40 => Self::STREAM_CANCEL,
66             x if x & 0xC0 == 0x0 => Self::INSERT_COUNT_INCREMENT,
67             _ => unreachable!(),
68         }
69     }
70 
prefix_index_mask(&self) -> PrefixMask71     pub(crate) fn prefix_index_mask(&self) -> PrefixMask {
72         match self.0 {
73             0x80 => PrefixMask::ACK,
74             0x40 => PrefixMask::STREAM_CANCEL,
75             0x0 => PrefixMask::INSERT_COUNT_INCREMENT,
76             _ => unreachable!(),
77         }
78     }
79 
prefix_midbit_value(&self) -> MidBit80     pub(crate) fn prefix_midbit_value(&self) -> MidBit {
81         MidBit {
82             n: None,
83             t: None,
84             h: None,
85         }
86     }
87 }
88 
89 impl EncoderInstPrefixBit {
90     pub(crate) const SET_CAP: Self = Self(0x20);
91     pub(crate) const INSERT_WITH_INDEX: Self = Self(0x80);
92     pub(crate) const INSERT_WITH_LITERAL: Self = Self(0x40);
93     pub(crate) const DUPLICATE: Self = Self(0x00);
94 
from_u8(byte: u8) -> Self95     pub(crate) fn from_u8(byte: u8) -> Self {
96         match byte {
97             x if x >= 0x80 => Self::INSERT_WITH_INDEX,
98             x if x >= 0x40 => Self::INSERT_WITH_LITERAL,
99             x if x >= 0x20 => Self::SET_CAP,
100             _ => Self::DUPLICATE,
101         }
102     }
103 
prefix_index_mask(&self) -> PrefixMask104     pub(crate) fn prefix_index_mask(&self) -> PrefixMask {
105         match self.0 {
106             0x80 => PrefixMask::INSERT_WITH_INDEX,
107             0x40 => PrefixMask::INSERT_WITH_LITERAL,
108             0x20 => PrefixMask::SET_CAP,
109             _ => PrefixMask::DUPLICATE,
110         }
111     }
112 
prefix_midbit_value(&self, byte: u8) -> MidBit113     pub(crate) fn prefix_midbit_value(&self, byte: u8) -> MidBit {
114         match self.0 {
115             0x80 => MidBit {
116                 n: None,
117                 t: Some((byte & 0x40) != 0),
118                 h: None,
119             },
120             0x40 => MidBit {
121                 n: None,
122                 t: None,
123                 h: Some((byte & 0x20) != 0),
124             },
125             0x20 => MidBit {
126                 n: None,
127                 t: None,
128                 h: None,
129             },
130             _ => MidBit {
131                 n: None,
132                 t: None,
133                 h: None,
134             },
135         }
136     }
137 }
138 
139 impl ReprPrefixBit {
140     // 此处的值为前缀1的位置,并没有实际意义
141     pub(crate) const INDEXED: Self = Self(0x80);
142     pub(crate) const INDEXEDWITHPOSTINDEX: Self = Self(0x10);
143     pub(crate) const LITERALWITHINDEXING: Self = Self(0x40);
144     pub(crate) const LITERALWITHPOSTINDEXING: Self = Self(0x00);
145     pub(crate) const LITERALWITHLITERALNAME: Self = Self(0x20);
146 
147     /// Creates a `PrefixBit` from a byte. The interface will convert the
148     /// incoming byte to the most suitable prefix bit.
from_u8(byte: u8) -> Self149     pub(crate) fn from_u8(byte: u8) -> Self {
150         match byte {
151             x if x >= 0x80 => Self::INDEXED,
152             x if x >= 0x40 => Self::LITERALWITHINDEXING,
153             x if x >= 0x20 => Self::LITERALWITHLITERALNAME,
154             x if x >= 0x10 => Self::INDEXEDWITHPOSTINDEX,
155             _ => Self::LITERALWITHPOSTINDEXING,
156         }
157     }
158 
159     /// Returns the corresponding `PrefixIndexMask` according to the current
160     /// prefix bit.
prefix_index_mask(&self) -> PrefixMask161     pub(crate) fn prefix_index_mask(&self) -> PrefixMask {
162         match self.0 {
163             0x80 => PrefixMask::INDEXED,
164             0x40 => PrefixMask::INDEXING_WITH_NAME,
165             0x20 => PrefixMask::INDEXING_WITH_LITERAL,
166             0x10 => PrefixMask::INDEXED_WITH_POST_NAME,
167             _ => PrefixMask::INDEXING_WITH_LITERAL,
168         }
169     }
170 
171     /// Unlike Hpack, QPACK has some special value for the first byte of an
172     /// integer. Like T indicating whether the reference is into the static
173     /// or dynamic table.
prefix_midbit_value(&self, byte: u8) -> MidBit174     pub(crate) fn prefix_midbit_value(&self, byte: u8) -> MidBit {
175         match self.0 {
176             0x80 => MidBit {
177                 n: None,
178                 t: Some((byte & 0x40) != 0),
179                 h: None,
180             },
181             0x40 => MidBit {
182                 n: Some((byte & 0x20) != 0),
183                 t: Some((byte & 0x10) != 0),
184                 h: None,
185             },
186             0x20 => MidBit {
187                 n: Some((byte & 0x10) != 0),
188                 t: None,
189                 h: Some((byte & 0x08) != 0),
190             },
191             0x10 => MidBit {
192                 n: None,
193                 t: None,
194                 h: None,
195             },
196             _ => MidBit {
197                 n: Some((byte & 0x08) != 0),
198                 t: None,
199                 h: None,
200             },
201         }
202     }
203 }
204 
205 pub(crate) enum EncoderInstruction {
206     SetCap {
207         capacity: usize,
208     },
209     InsertWithIndex {
210         mid_bit: MidBit,
211         name: Name,
212         value: Vec<u8>,
213     },
214     InsertWithLiteral {
215         mid_bit: MidBit,
216         name: Name,
217         value: Vec<u8>,
218     },
219     Duplicate {
220         index: usize,
221     },
222 }
223 
224 pub(crate) enum DecoderInstruction {
225     Ack { stream_id: usize },
226     StreamCancel { stream_id: usize },
227     InsertCountIncrement { increment: usize },
228 }
229 
230 pub(crate) enum Representation {
231     /// An indexed field line format identifies an entry in the static table or
232     /// an entry in the dynamic table with an absolute index less than the
233     /// value of the Base. 0   1   2   3   4   5   6   7
234     /// +---+---+---+---+---+---+---+---+
235     /// | 1 | T |      Index (6+)       |
236     /// +---+---+-----------------------+
237     /// This format starts with the '1' 1-bit pattern, followed by the 'T' bit,
238     /// indicating whether the reference is into the static or dynamic
239     /// table. The 6-bit prefix integer (Section 4.1.1) that follows is used
240     /// to locate the table entry for the field line. When T=1, the number
241     /// represents the static table index; when T=0, the number is the relative
242     /// index of the entry in the dynamic table.
243     FieldSectionPrefix {
244         require_insert_count: RequireInsertCount,
245         signal: bool,
246         delta_base: DeltaBase,
247     },
248 
249     Indexed {
250         mid_bit: MidBit,
251         index: usize,
252     },
253     IndexedWithPostIndex {
254         index: usize,
255     },
256     LiteralWithIndexing {
257         mid_bit: MidBit,
258         name: Name,
259         value: Vec<u8>,
260     },
261     LiteralWithPostIndexing {
262         mid_bit: MidBit,
263         name: Name,
264         value: Vec<u8>,
265     },
266     LiteralWithLiteralName {
267         mid_bit: MidBit,
268         name: Name,
269         value: Vec<u8>,
270     },
271 }
272 
273 // impl debug for Representation
274 
275 pub(crate) struct MidBit {
276     //'N', indicates whether an intermediary is permitted to add this field line to the dynamic
277     // table on subsequent hops.
278     n: Option<bool>,
279     //'T', indicating whether the reference is into the static or dynamic table.
280     t: Option<bool>,
281     //'H', indicating whether is represented as a Huffman-encoded.
282     h: Option<bool>,
283 }
284 
285 pub(crate) struct PrefixMask(u8);
286 
287 impl PrefixMask {
288     pub(crate) const REQUIRE_INSERT_COUNT: Self = Self(0xff);
289     pub(crate) const DELTA_BASE: Self = Self(0x7f);
290     pub(crate) const INDEXED: Self = Self(0x3f);
291     pub(crate) const SET_CAP: Self = Self(0x1f);
292     pub(crate) const INSERT_WITH_INDEX: Self = Self(0x3f);
293     pub(crate) const INSERT_WITH_LITERAL: Self = Self(0x1f);
294     pub(crate) const DUPLICATE: Self = Self(0x1f);
295     pub(crate) const ACK: Self = Self(0x7f);
296     pub(crate) const STREAM_CANCEL: Self = Self(0x3f);
297     pub(crate) const INSERT_COUNT_INCREMENT: Self = Self(0x3f);
298     pub(crate) const INDEXING_WITH_NAME: Self = Self(0x0f);
299     pub(crate) const INDEXING_WITH_POST_NAME: Self = Self(0x07);
300     pub(crate) const INDEXING_WITH_LITERAL: Self = Self(0x07);
301     pub(crate) const INDEXED_WITH_POST_NAME: Self = Self(0x0f);
302 }
303