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 pub mod decoder;
17 pub mod encoder;
18 pub(crate) mod error;
19 pub mod format;
20 mod integer;
21 pub mod table;
22 use crate::h3::qpack::format::decoder::Name;
23 pub(crate) use decoder::FiledLines;
24 pub(crate) use decoder::QpackDecoder;
25 pub(crate) use encoder::DecoderInst;
26 pub(crate) use encoder::QpackEncoder;
27 
28 pub(crate) struct RequireInsertCount(usize);
29 
30 pub(crate) struct DeltaBase(usize);
31 
32 #[derive(Copy, Clone, PartialEq, Eq)]
33 pub(crate) struct EncoderInstPrefixBit(u8);
34 
35 #[derive(Copy, Clone, PartialEq, Eq)]
36 pub(crate) struct DecoderInstPrefixBit(u8);
37 
38 #[derive(Copy, Clone, PartialEq, Eq)]
39 pub(crate) struct ReprPrefixBit(u8);
40 
41 /// # Prefix bit:
42 /// ## Encoder Instructions:
43 /// SETCAP: 0x20
44 /// INSERTWITHINDEX: 0x80
45 /// INSERTWITHLITERAL: 0x40
46 /// DUPLICATE: 0x00
47 ///
48 /// ## Decoder Instructions:
49 /// ACK: 0x80
50 /// STREAMCANCEL: 0x40
51 /// INSERTCOUNTINCREMENT: 0x00
52 ///
53 /// ## Representation:
54 /// INDEXED: 0x80
55 /// INDEXEDWITHPOSTINDEX: 0x10
56 /// LITERALWITHINDEXING: 0x40
57 /// LITERALWITHPOSTINDEXING: 0x00
58 /// LITERALWITHLITERALNAME: 0x20
59 
60 impl DecoderInstPrefixBit {
61     pub(crate) const ACK: Self = Self(0x80);
62     pub(crate) const STREAMCANCEL: Self = Self(0x40);
63     pub(crate) const INSERTCOUNTINCREMENT: Self = Self(0x00);
64 
from_u8(byte: u8) -> Self65     pub(crate) fn from_u8(byte: u8) -> Self {
66         match byte {
67             x if x >= 0x80 => Self::ACK,
68             x if x >= 0x40 => Self::STREAMCANCEL,
69             _ => Self::INSERTCOUNTINCREMENT,
70         }
71     }
72 
prefix_index_mask(&self) -> PrefixMask73     pub(crate) fn prefix_index_mask(&self) -> PrefixMask {
74         match self.0 {
75             0x80 => PrefixMask::ACK,
76             0x40 => PrefixMask::STREAMCANCEL,
77             _ => PrefixMask::INSERTCOUNTINCREMENT,
78         }
79     }
80 
prefix_midbit_value(&self) -> MidBit81     pub(crate) fn prefix_midbit_value(&self) -> MidBit {
82         MidBit {
83             n: None,
84             t: None,
85             h: None,
86         }
87     }
88 }
89 
90 impl EncoderInstPrefixBit {
91     pub(crate) const SETCAP: Self = Self(0x20);
92     pub(crate) const INSERTWITHINDEX: Self = Self(0x80);
93     pub(crate) const INSERTWITHLITERAL: Self = Self(0x40);
94     pub(crate) const DUPLICATE: Self = Self(0x00);
95 
from_u8(byte: u8) -> Self96     pub(crate) fn from_u8(byte: u8) -> Self {
97         match byte {
98             x if x >= 0x80 => Self::INSERTWITHINDEX,
99             x if x >= 0x40 => Self::INSERTWITHLITERAL,
100             x if x >= 0x20 => Self::SETCAP,
101             _ => Self::DUPLICATE,
102         }
103     }
104 
prefix_index_mask(&self) -> PrefixMask105     pub(crate) fn prefix_index_mask(&self) -> PrefixMask {
106         match self.0 {
107             0x80 => PrefixMask::INSERTWITHINDEX,
108             0x40 => PrefixMask::INSERTWITHLITERAL,
109             0x20 => PrefixMask::SETCAP,
110             _ => PrefixMask::DUPLICATE,
111         }
112     }
113 
prefix_midbit_value(&self, byte: u8) -> MidBit114     pub(crate) fn prefix_midbit_value(&self, byte: u8) -> MidBit {
115         match self.0 {
116             0x80 => MidBit {
117                 n: None,
118                 t: Some((byte & 0x40) != 0),
119                 h: None,
120             },
121             0x40 => MidBit {
122                 n: None,
123                 t: None,
124                 h: Some((byte & 0x20) != 0),
125             },
126             0x20 => MidBit {
127                 n: None,
128                 t: None,
129                 h: None,
130             },
131             _ => MidBit {
132                 n: None,
133                 t: None,
134                 h: None,
135             },
136         }
137     }
138 }
139 
140 impl ReprPrefixBit {
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::INDEXINGWITHNAME,
165             0x20 => PrefixMask::INDEXINGWITHLITERAL,
166             0x10 => PrefixMask::INDEXEDWITHPOSTNAME,
167             _ => PrefixMask::INDEXINGWITHPOSTNAME,
168         }
169     }
170 
171     /// Unlike Hpack, QPACK has some special value for the first byte of an integer.
172     /// Like T indicating whether the reference is into the static or dynamic table.
prefix_midbit_value(&self, byte: u8) -> MidBit173     pub(crate) fn prefix_midbit_value(&self, byte: u8) -> MidBit {
174         match self.0 {
175             0x80 => MidBit {
176                 n: None,
177                 t: Some((byte & 0x40) != 0),
178                 h: None,
179             },
180             0x40 => MidBit {
181                 n: Some((byte & 0x20) != 0),
182                 t: Some((byte & 0x10) != 0),
183                 h: None,
184             },
185             0x20 => MidBit {
186                 n: Some((byte & 0x10) != 0),
187                 t: None,
188                 h: Some((byte & 0x08) != 0),
189             },
190             0x10 => MidBit {
191                 n: None,
192                 t: None,
193                 h: None,
194             },
195             _ => MidBit {
196                 n: Some((byte & 0x08) != 0),
197                 t: None,
198                 h: None,
199             },
200         }
201     }
202 }
203 
204 pub(crate) enum EncoderInstruction {
205     SetCap {
206         capacity: usize,
207     },
208     InsertWithIndex {
209         mid_bit: MidBit,
210         name: Name,
211         value: Vec<u8>,
212     },
213     InsertWithLiteral {
214         mid_bit: MidBit,
215         name: Name,
216         value: Vec<u8>,
217     },
218     Duplicate {
219         index: usize,
220     },
221 }
222 
223 pub(crate) enum DecoderInstruction {
224     Ack { stream_id: usize },
225     StreamCancel { stream_id: usize },
226     InsertCountIncrement { increment: usize },
227 }
228 
229 pub(crate) enum Representation {
230     /// An indexed field line format identifies an entry in the static table or an entry in
231     /// the dynamic table with an absolute index less than the value of the Base.
232     /// 0   1   2   3   4   5   6   7
233     /// +---+---+---+---+---+---+---+---+
234     /// | 1 | T |      Index (6+)       |
235     /// +---+---+-----------------------+
236     /// This format starts with the '1' 1-bit pattern, followed by the 'T' bit, indicating
237     /// whether the reference is into the static or dynamic table. The 6-bit prefix integer
238     /// (Section 4.1.1) that follows is used to locate the table entry for the field line. When T=1,
239     /// the number represents the static table index; when T=0, the number is the relative index of
240     /// the entry in the dynamic table.
241     FieldSectionPrefix {
242         require_insert_count: RequireInsertCount,
243         signal: bool,
244         delta_base: DeltaBase,
245     },
246 
247     Indexed {
248         mid_bit: MidBit,
249         index: usize,
250     },
251     IndexedWithPostIndex {
252         index: usize,
253     },
254     LiteralWithIndexing {
255         mid_bit: MidBit,
256         name: Name,
257         value: Vec<u8>,
258     },
259     LiteralWithPostIndexing {
260         mid_bit: MidBit,
261         name: Name,
262         value: Vec<u8>,
263     },
264     LiteralWithLiteralName {
265         mid_bit: MidBit,
266         name: Name,
267         value: Vec<u8>,
268     },
269 }
270 
271 //impl debug for Representation
272 
273 pub(crate) struct MidBit {
274     //'N', indicates whether an intermediary is permitted to add this field line to the dynamic
275     // table on subsequent hops.
276     n: Option<bool>,
277     //'T', indicating whether the reference is into the static or dynamic table.
278     t: Option<bool>,
279     //'H', indicating whether is represented as a Huffman-encoded.
280     h: Option<bool>,
281 }
282 
283 pub(crate) struct PrefixMask(u8);
284 
285 impl PrefixMask {
286     pub(crate) const REQUIREINSERTCOUNT: Self = Self(0xff);
287     pub(crate) const DELTABASE: Self = Self(0x7f);
288     pub(crate) const INDEXED: Self = Self(0x3f);
289     pub(crate) const SETCAP: Self = Self(0x1f);
290     pub(crate) const INSERTWITHINDEX: Self = Self(0x3f);
291     pub(crate) const INSERTWITHLITERAL: Self = Self(0x1f);
292     pub(crate) const DUPLICATE: Self = Self(0x1f);
293 
294     pub(crate) const ACK: Self = Self(0x7f);
295     pub(crate) const STREAMCANCEL: Self = Self(0x3f);
296     pub(crate) const INSERTCOUNTINCREMENT: Self = Self(0x3f);
297 
298     pub(crate) const INDEXINGWITHNAME: Self = Self(0x0f);
299     pub(crate) const INDEXINGWITHPOSTNAME: Self = Self(0x07);
300     pub(crate) const INDEXINGWITHLITERAL: Self = Self(0x07);
301     pub(crate) const INDEXEDWITHPOSTNAME: Self = Self(0x0f);
302 }
303