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 super::Error;
28 use super::Result;
29 
30 use crate::h3::Header;
31 
32 use super::INDEXED;
33 use super::INDEXED_WITH_POST_BASE;
34 use super::LITERAL;
35 use super::LITERAL_WITH_NAME_REF;
36 
37 #[derive(Clone, Copy, Debug, PartialEq)]
38 enum Representation {
39     Indexed,
40     IndexedWithPostBase,
41     Literal,
42     LiteralWithNameRef,
43     LiteralWithPostBase,
44 }
45 
46 impl Representation {
from_byte(b: u8) -> Representation47     pub fn from_byte(b: u8) -> Representation {
48         if b & INDEXED == INDEXED {
49             return Representation::Indexed;
50         }
51 
52         if b & LITERAL_WITH_NAME_REF == LITERAL_WITH_NAME_REF {
53             return Representation::LiteralWithNameRef;
54         }
55 
56         if b & LITERAL == LITERAL {
57             return Representation::Literal;
58         }
59 
60         if b & INDEXED_WITH_POST_BASE == INDEXED_WITH_POST_BASE {
61             return Representation::IndexedWithPostBase;
62         }
63 
64         Representation::LiteralWithPostBase
65     }
66 }
67 
68 /// A QPACK decoder.
69 #[derive(Default)]
70 pub struct Decoder {}
71 
72 impl Decoder {
73     /// Creates a new QPACK decoder.
new() -> Decoder74     pub fn new() -> Decoder {
75         Decoder::default()
76     }
77 
78     /// Processes control instructions from the encoder.
control(&mut self, _buf: &mut [u8]) -> Result<()>79     pub fn control(&mut self, _buf: &mut [u8]) -> Result<()> {
80         // TODO: process control instructions
81         Ok(())
82     }
83 
84     /// Decodes a QPACK header block into a list of headers.
decode(&mut self, buf: &[u8], max_size: u64) -> Result<Vec<Header>>85     pub fn decode(&mut self, buf: &[u8], max_size: u64) -> Result<Vec<Header>> {
86         let mut b = octets::Octets::with_slice(buf);
87 
88         let mut out = Vec::new();
89 
90         let mut left = max_size;
91 
92         let req_insert_count = decode_int(&mut b, 8)?;
93         let base = decode_int(&mut b, 7)?;
94 
95         trace!("Header count={} base={}", req_insert_count, base);
96 
97         while b.cap() > 0 {
98             let first = b.peek_u8()?;
99 
100             match Representation::from_byte(first) {
101                 Representation::Indexed => {
102                     const STATIC: u8 = 0x40;
103 
104                     let s = first & STATIC == STATIC;
105                     let index = decode_int(&mut b, 6)?;
106 
107                     trace!("Indexed index={} static={}", index, s);
108 
109                     if !s {
110                         // TODO: implement dynamic table
111                         return Err(Error::InvalidHeaderValue);
112                     }
113 
114                     let (name, value) = lookup_static(index)?;
115 
116                     left = left
117                         .checked_sub((name.len() + value.len()) as u64)
118                         .ok_or(Error::HeaderListTooLarge)?;
119 
120                     let hdr = Header::new(name, value);
121                     out.push(hdr);
122                 },
123 
124                 Representation::IndexedWithPostBase => {
125                     let index = decode_int(&mut b, 4)?;
126 
127                     trace!("Indexed With Post Base index={}", index);
128 
129                     // TODO: implement dynamic table
130                     return Err(Error::InvalidHeaderValue);
131                 },
132 
133                 Representation::Literal => {
134                     let name_huff = b.as_ref()[0] & 0x08 == 0x08;
135                     let name_len = decode_int(&mut b, 3)? as usize;
136 
137                     let mut name = b.get_bytes(name_len)?;
138 
139                     let name = if name_huff {
140                         super::huffman::decode(&mut name)?
141                     } else {
142                         name.to_vec()
143                     };
144 
145                     let name = name.to_vec();
146                     let value = decode_str(&mut b)?;
147 
148                     trace!(
149                         "Literal Without Name Reference name={:?} value={:?}",
150                         name,
151                         value,
152                     );
153 
154                     left = left
155                         .checked_sub((name.len() + value.len()) as u64)
156                         .ok_or(Error::HeaderListTooLarge)?;
157 
158                     // Instead of calling Header::new(), create Header directly
159                     // from `name` and `value`, which are already String.
160                     let hdr = Header(name, value);
161                     out.push(hdr);
162                 },
163 
164                 Representation::LiteralWithNameRef => {
165                     const STATIC: u8 = 0x10;
166 
167                     let s = first & STATIC == STATIC;
168                     let name_idx = decode_int(&mut b, 4)?;
169                     let value = decode_str(&mut b)?;
170 
171                     trace!(
172                         "Literal name_idx={} static={} value={:?}",
173                         name_idx,
174                         s,
175                         value
176                     );
177 
178                     if !s {
179                         // TODO: implement dynamic table
180                         return Err(Error::InvalidHeaderValue);
181                     }
182 
183                     let (name, _) = lookup_static(name_idx)?;
184 
185                     left = left
186                         .checked_sub((name.len() + value.len()) as u64)
187                         .ok_or(Error::HeaderListTooLarge)?;
188 
189                     // Instead of calling Header::new(), create Header directly
190                     // from `value`, which is already String, but clone `name`
191                     // as it is just a reference.
192                     let hdr = Header(name.to_vec(), value);
193                     out.push(hdr);
194                 },
195 
196                 Representation::LiteralWithPostBase => {
197                     trace!("Literal With Post Base");
198 
199                     // TODO: implement dynamic table
200                     return Err(Error::InvalidHeaderValue);
201                 },
202             }
203         }
204 
205         Ok(out)
206     }
207 }
208 
lookup_static(idx: u64) -> Result<(&'static [u8], &'static [u8])>209 fn lookup_static(idx: u64) -> Result<(&'static [u8], &'static [u8])> {
210     if idx >= super::static_table::STATIC_TABLE.len() as u64 {
211         return Err(Error::InvalidStaticTableIndex);
212     }
213 
214     Ok(super::static_table::STATIC_TABLE[idx as usize])
215 }
216 
decode_int(b: &mut octets::Octets, prefix: usize) -> Result<u64>217 fn decode_int(b: &mut octets::Octets, prefix: usize) -> Result<u64> {
218     let mask = 2u64.pow(prefix as u32) - 1;
219 
220     let mut val = u64::from(b.get_u8()?);
221     val &= mask;
222 
223     if val < mask {
224         return Ok(val);
225     }
226 
227     let mut shift = 0;
228 
229     while b.cap() > 0 {
230         let byte = b.get_u8()?;
231 
232         let inc = u64::from(byte & 0x7f)
233             .checked_shl(shift)
234             .ok_or(Error::BufferTooShort)?;
235 
236         val = val.checked_add(inc).ok_or(Error::BufferTooShort)?;
237 
238         shift += 7;
239 
240         if byte & 0x80 == 0 {
241             return Ok(val);
242         }
243     }
244 
245     Err(Error::BufferTooShort)
246 }
247 
decode_str(b: &mut octets::Octets) -> Result<Vec<u8>>248 fn decode_str(b: &mut octets::Octets) -> Result<Vec<u8>> {
249     let first = b.peek_u8()?;
250 
251     let huff = first & 0x80 == 0x80;
252 
253     let len = decode_int(b, 7)? as usize;
254 
255     let mut val = b.get_bytes(len)?;
256 
257     let val = if huff {
258         super::huffman::decode(&mut val)?
259     } else {
260         val.to_vec()
261     };
262 
263     Ok(val)
264 }
265 
266 #[cfg(test)]
267 mod tests {
268     use super::*;
269 
270     #[test]
decode_int1()271     fn decode_int1() {
272         let mut encoded = [0b01010, 0x02];
273         let mut b = octets::Octets::with_slice(&mut encoded);
274 
275         assert_eq!(decode_int(&mut b, 5), Ok(10));
276     }
277 
278     #[test]
decode_int2()279     fn decode_int2() {
280         let mut encoded = [0b11111, 0b10011010, 0b00001010];
281         let mut b = octets::Octets::with_slice(&mut encoded);
282 
283         assert_eq!(decode_int(&mut b, 5), Ok(1337));
284     }
285 
286     #[test]
decode_int3()287     fn decode_int3() {
288         let mut encoded = [0b101010];
289         let mut b = octets::Octets::with_slice(&mut encoded);
290 
291         assert_eq!(decode_int(&mut b, 8), Ok(42));
292     }
293 }
294