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