1 // Copyright (C) 2019, Cloudflare, Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright notice,
9 //       this list of conditions and the following disclaimer.
10 //
11 //     * Redistributions in binary form must reproduce the above copyright
12 //       notice, this list of conditions and the following disclaimer in the
13 //       documentation and/or other materials provided with the distribution.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
19 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 use crate::octets;
28 
29 use super::Error;
30 use super::Result;
31 
32 use crate::h3::Header;
33 
34 use super::INDEXED;
35 use super::INDEXED_WITH_POST_BASE;
36 use super::LITERAL;
37 use super::LITERAL_WITH_NAME_REF;
38 
39 #[derive(Clone, Copy, Debug, PartialEq)]
40 enum Representation {
41     Indexed,
42     IndexedWithPostBase,
43     Literal,
44     LiteralWithNameRef,
45     LiteralWithPostBase,
46 }
47 
48 impl Representation {
from_byte(b: u8) -> Representation49     pub fn from_byte(b: u8) -> Representation {
50         if b & INDEXED == INDEXED {
51             return Representation::Indexed;
52         }
53 
54         if b & LITERAL_WITH_NAME_REF == LITERAL_WITH_NAME_REF {
55             return Representation::LiteralWithNameRef;
56         }
57 
58         if b & LITERAL == LITERAL {
59             return Representation::Literal;
60         }
61 
62         if b & INDEXED_WITH_POST_BASE == INDEXED_WITH_POST_BASE {
63             return Representation::IndexedWithPostBase;
64         }
65 
66         Representation::LiteralWithPostBase
67     }
68 }
69 
70 /// A QPACK decoder.
71 pub struct Decoder {}
72 
73 impl Default for Decoder {
default() -> Decoder74     fn default() -> Decoder {
75         Decoder {}
76     }
77 }
78 
79 impl Decoder {
80     /// Creates a new QPACK decoder.
new() -> Decoder81     pub fn new() -> Decoder {
82         Decoder::default()
83     }
84 
85     /// Processes control instructions from the encoder.
control(&mut self, _buf: &mut [u8]) -> Result<()>86     pub fn control(&mut self, _buf: &mut [u8]) -> Result<()> {
87         // TODO: process control instructions
88         Ok(())
89     }
90 
91     /// Decodes a QPACK header block into a list of headers.
decode(&mut self, buf: &[u8], max_size: u64) -> Result<Vec<Header>>92     pub fn decode(&mut self, buf: &[u8], max_size: u64) -> Result<Vec<Header>> {
93         let mut b = octets::Octets::with_slice(buf);
94 
95         let mut out = Vec::new();
96 
97         let mut left = max_size;
98 
99         let req_insert_count = decode_int(&mut b, 8)?;
100         let base = decode_int(&mut b, 7)?;
101 
102         trace!("Header count={} base={}", req_insert_count, base);
103 
104         while b.cap() > 0 {
105             let first = b.peek_u8()?;
106 
107             match Representation::from_byte(first) {
108                 Representation::Indexed => {
109                     const STATIC: u8 = 0x40;
110 
111                     let s = first & STATIC == STATIC;
112                     let index = decode_int(&mut b, 6)?;
113 
114                     trace!("Indexed index={} static={}", index, s);
115 
116                     if !s {
117                         // TODO: implement dynamic table
118                         return Err(Error::InvalidHeaderValue);
119                     }
120 
121                     let (name, value) = lookup_static(index)?;
122 
123                     left = left
124                         .checked_sub((name.len() + value.len()) as u64)
125                         .ok_or(Error::HeaderListTooLarge)?;
126 
127                     let hdr = Header::new(name, value);
128                     out.push(hdr);
129                 },
130 
131                 Representation::IndexedWithPostBase => {
132                     let index = decode_int(&mut b, 4)?;
133 
134                     trace!("Indexed With Post Base index={}", index);
135 
136                     // TODO: implement dynamic table
137                     return Err(Error::InvalidHeaderValue);
138                 },
139 
140                 Representation::Literal => {
141                     let name_huff = b.as_ref()[0] & 0x08 == 0x08;
142                     let name_len = decode_int(&mut b, 3)? as usize;
143 
144                     let mut name = b.get_bytes(name_len)?;
145 
146                     let name = if name_huff {
147                         super::huffman::decode(&mut name)?
148                     } else {
149                         name.to_vec()
150                     };
151 
152                     let name = String::from_utf8(name)
153                         .map_err(|_| Error::InvalidHeaderValue)?;
154 
155                     let value = decode_str(&mut b)?;
156 
157                     trace!(
158                         "Literal Without Name Reference name={:?} value={:?}",
159                         name,
160                         value,
161                     );
162 
163                     left = left
164                         .checked_sub((name.len() + value.len()) as u64)
165                         .ok_or(Error::HeaderListTooLarge)?;
166 
167                     // Instead of calling Header::new(), create Header directly
168                     // from `name` and `value`, which are already String.
169                     let hdr = Header(name, value);
170                     out.push(hdr);
171                 },
172 
173                 Representation::LiteralWithNameRef => {
174                     const STATIC: u8 = 0x10;
175 
176                     let s = first & STATIC == STATIC;
177                     let name_idx = decode_int(&mut b, 4)?;
178                     let value = decode_str(&mut b)?;
179 
180                     trace!(
181                         "Literal name_idx={} static={} value={:?}",
182                         name_idx,
183                         s,
184                         value
185                     );
186 
187                     if !s {
188                         // TODO: implement dynamic table
189                         return Err(Error::InvalidHeaderValue);
190                     }
191 
192                     let (name, _) = lookup_static(name_idx)?;
193 
194                     left = left
195                         .checked_sub((name.len() + value.len()) as u64)
196                         .ok_or(Error::HeaderListTooLarge)?;
197 
198                     // Instead of calling Header::new(), create Header directly
199                     // from `value`, which is already String, but clone `name`
200                     // as it is just a reference.
201                     let hdr = Header(name.to_string(), value);
202                     out.push(hdr);
203                 },
204 
205                 Representation::LiteralWithPostBase => {
206                     trace!("Literal With Post Base");
207 
208                     // TODO: implement dynamic table
209                     return Err(Error::InvalidHeaderValue);
210                 },
211             }
212         }
213 
214         Ok(out)
215     }
216 }
217 
lookup_static(idx: u64) -> Result<(&'static str, &'static str)>218 fn lookup_static(idx: u64) -> Result<(&'static str, &'static str)> {
219     if idx >= super::static_table::STATIC_TABLE.len() as u64 {
220         return Err(Error::InvalidStaticTableIndex);
221     }
222 
223     Ok(super::static_table::STATIC_TABLE[idx as usize])
224 }
225 
decode_int(b: &mut octets::Octets, prefix: usize) -> Result<u64>226 fn decode_int(b: &mut octets::Octets, prefix: usize) -> Result<u64> {
227     let mask = 2u64.pow(prefix as u32) - 1;
228 
229     let mut val = u64::from(b.get_u8()?);
230     val &= mask;
231 
232     if val < mask {
233         return Ok(val);
234     }
235 
236     let mut shift = 0;
237 
238     while b.cap() > 0 {
239         let byte = b.get_u8()?;
240 
241         let inc = u64::from(byte & 0x7f)
242             .checked_shl(shift)
243             .ok_or(Error::BufferTooShort)?;
244 
245         val = val.checked_add(inc).ok_or(Error::BufferTooShort)?;
246 
247         shift += 7;
248 
249         if byte & 0x80 == 0 {
250             return Ok(val);
251         }
252     }
253 
254     Err(Error::BufferTooShort)
255 }
256 
decode_str<'a>(b: &'a mut octets::Octets) -> Result<String>257 fn decode_str<'a>(b: &'a mut octets::Octets) -> Result<String> {
258     let first = b.peek_u8()?;
259 
260     let huff = first & 0x80 == 0x80;
261 
262     let len = decode_int(b, 7)? as usize;
263 
264     let mut val = b.get_bytes(len)?;
265 
266     let val = if huff {
267         super::huffman::decode(&mut val)?
268     } else {
269         val.to_vec()
270     };
271 
272     let val = String::from_utf8(val).map_err(|_| Error::InvalidHeaderValue)?;
273     Ok(val)
274 }
275 
276 #[cfg(test)]
277 mod tests {
278     use super::*;
279 
280     use crate::octets;
281 
282     #[test]
decode_int1()283     fn decode_int1() {
284         let mut encoded = [0b01010, 0x02];
285         let mut b = octets::Octets::with_slice(&mut encoded);
286 
287         assert_eq!(decode_int(&mut b, 5), Ok(10));
288     }
289 
290     #[test]
decode_int2()291     fn decode_int2() {
292         let mut encoded = [0b11111, 0b10011010, 0b00001010];
293         let mut b = octets::Octets::with_slice(&mut encoded);
294 
295         assert_eq!(decode_int(&mut b, 5), Ok(1337));
296     }
297 
298     #[test]
decode_int3()299     fn decode_int3() {
300         let mut encoded = [0b101010];
301         let mut b = octets::Octets::with_slice(&mut encoded);
302 
303         assert_eq!(decode_int(&mut b, 8), Ok(42));
304     }
305 }
306