Header frame decoding
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use super::{huffman, header as h2_header, Header};
|
||||
use frame;
|
||||
use util::byte_str::FromUtf8Error;
|
||||
|
||||
use http::{method, header, status, StatusCode, Method};
|
||||
@@ -19,7 +20,7 @@ pub struct Decoder {
|
||||
|
||||
/// Represents all errors that can be encountered while performing the decoding
|
||||
/// of an HPACK header set.
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum DecoderError {
|
||||
InvalidRepresentation,
|
||||
InvalidIntegerPrefix,
|
||||
@@ -32,6 +33,7 @@ pub enum DecoderError {
|
||||
IntegerUnderflow,
|
||||
IntegerOverflow,
|
||||
StringUnderflow,
|
||||
RepeatedPseudo,
|
||||
}
|
||||
|
||||
enum Representation {
|
||||
@@ -155,30 +157,29 @@ impl Decoder {
|
||||
}
|
||||
|
||||
/// Decodes the headers found in the given buffer.
|
||||
pub fn decode<F>(&mut self, src: &Bytes, mut f: F) -> Result<(), DecoderError>
|
||||
pub fn decode<F>(&mut self, src: &mut Cursor<Bytes>, mut f: F) -> Result<(), DecoderError>
|
||||
where F: FnMut(Header)
|
||||
{
|
||||
use self::Representation::*;
|
||||
|
||||
let mut buf = Cursor::new(src);
|
||||
let mut can_resize = true;
|
||||
|
||||
if let Some(size) = self.max_size_update.take() {
|
||||
self.last_max_update = size;
|
||||
}
|
||||
|
||||
while buf.has_remaining() {
|
||||
while src.has_remaining() {
|
||||
// At this point we are always at the beginning of the next block
|
||||
// within the HPACK data. The type of the block can always be
|
||||
// determined from the first byte.
|
||||
match try!(Representation::load(peek_u8(&mut buf))) {
|
||||
match try!(Representation::load(peek_u8(src))) {
|
||||
Indexed => {
|
||||
can_resize = false;
|
||||
f(try!(self.decode_indexed(&mut buf)));
|
||||
f(try!(self.decode_indexed(src)));
|
||||
}
|
||||
LiteralWithIndexing => {
|
||||
can_resize = false;
|
||||
let entry = try!(self.decode_literal(&mut buf, true));
|
||||
let entry = try!(self.decode_literal(src, true));
|
||||
|
||||
// Insert the header into the table
|
||||
self.table.insert(entry.clone());
|
||||
@@ -187,12 +188,12 @@ impl Decoder {
|
||||
}
|
||||
LiteralWithoutIndexing => {
|
||||
can_resize = false;
|
||||
let entry = try!(self.decode_literal(&mut buf, false));
|
||||
let entry = try!(self.decode_literal(src, false));
|
||||
f(entry);
|
||||
}
|
||||
LiteralNeverIndexed => {
|
||||
can_resize = false;
|
||||
let entry = try!(self.decode_literal(&mut buf, false));
|
||||
let entry = try!(self.decode_literal(src, false));
|
||||
|
||||
// TODO: Track that this should never be indexed
|
||||
|
||||
@@ -204,7 +205,7 @@ impl Decoder {
|
||||
}
|
||||
|
||||
// Handle the dynamic table size update
|
||||
try!(self.process_size_update(&mut buf));
|
||||
try!(self.process_size_update(src));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -212,7 +213,7 @@ impl Decoder {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn process_size_update(&mut self, buf: &mut Cursor<&Bytes>)
|
||||
fn process_size_update(&mut self, buf: &mut Cursor<Bytes>)
|
||||
-> Result<(), DecoderError>
|
||||
{
|
||||
let new_size = try!(decode_int(buf, 5));
|
||||
@@ -229,14 +230,14 @@ impl Decoder {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn decode_indexed(&self, buf: &mut Cursor<&Bytes>)
|
||||
fn decode_indexed(&self, buf: &mut Cursor<Bytes>)
|
||||
-> Result<Header, DecoderError>
|
||||
{
|
||||
let index = try!(decode_int(buf, 7));
|
||||
self.table.get(index)
|
||||
}
|
||||
|
||||
fn decode_literal(&mut self, buf: &mut Cursor<&Bytes>, index: bool)
|
||||
fn decode_literal(&mut self, buf: &mut Cursor<Bytes>, index: bool)
|
||||
-> Result<Header, DecoderError>
|
||||
{
|
||||
let prefix = if index {
|
||||
@@ -263,7 +264,7 @@ impl Decoder {
|
||||
}
|
||||
}
|
||||
|
||||
fn decode_string(&mut self, buf: &mut Cursor<&Bytes>) -> Result<Bytes, DecoderError> {
|
||||
fn decode_string(&mut self, buf: &mut Cursor<Bytes>) -> Result<Bytes, DecoderError> {
|
||||
const HUFF_FLAG: u8 = 0b10000000;
|
||||
|
||||
// The first bit in the first byte contains the huffman encoded flag.
|
||||
@@ -388,7 +389,7 @@ fn peek_u8<B: Buf>(buf: &mut B) -> u8 {
|
||||
buf.bytes()[0]
|
||||
}
|
||||
|
||||
fn take(buf: &mut Cursor<&Bytes>, n: usize) -> Bytes {
|
||||
fn take(buf: &mut Cursor<Bytes>, n: usize) -> Bytes {
|
||||
let pos = buf.position() as usize;
|
||||
let ret = buf.get_ref().slice(pos, pos + n);
|
||||
buf.set_position((pos + n) as u64);
|
||||
@@ -520,6 +521,12 @@ impl From<status::FromStrError> for DecoderError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DecoderError> for frame::Error {
|
||||
fn from(src: DecoderError) -> Self {
|
||||
frame::Error::Hpack(src)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get an entry from the static table
|
||||
pub fn get_static(idx: usize) -> Header {
|
||||
use http::{status, method, header};
|
||||
|
||||
@@ -20,6 +20,7 @@ use self::rand::{StdRng, Rng, SeedableRng};
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::io::Cursor;
|
||||
use std::path::Path;
|
||||
use std::str;
|
||||
|
||||
@@ -220,7 +221,7 @@ impl FuzzHpack {
|
||||
index = Some(i);
|
||||
|
||||
// Decode the chunk!
|
||||
decoder.decode(&buf.into(), |e| {
|
||||
decoder.decode(&mut Cursor::new(buf.into()), |e| {
|
||||
assert_eq!(e, expect.remove(0).reify().unwrap());
|
||||
}).unwrap();
|
||||
|
||||
@@ -231,7 +232,7 @@ impl FuzzHpack {
|
||||
}
|
||||
|
||||
// Decode the chunk!
|
||||
decoder.decode(&buf.into(), |e| {
|
||||
decoder.decode(&mut Cursor::new(buf.into()), |e| {
|
||||
assert_eq!(e, expect.remove(0).reify().unwrap());
|
||||
}).unwrap();
|
||||
}
|
||||
@@ -506,7 +507,7 @@ fn test_story(story: Value) {
|
||||
decoder.queue_size_update(size);
|
||||
}
|
||||
|
||||
decoder.decode(&case.wire.clone().into(), |e| {
|
||||
decoder.decode(&mut Cursor::new(case.wire.clone().into()), |e| {
|
||||
let (name, value) = expect.remove(0);
|
||||
assert_eq!(name, key_str(&e));
|
||||
assert_eq!(value, value_str(&e));
|
||||
@@ -533,7 +534,7 @@ fn test_story(story: Value) {
|
||||
|
||||
encoder.encode(None, &mut input.clone().into_iter(), &mut buf);
|
||||
|
||||
decoder.decode(&buf.into(), |e| {
|
||||
decoder.decode(&mut Cursor::new(buf.into()), |e| {
|
||||
assert_eq!(e, input.remove(0).reify().unwrap());
|
||||
}).unwrap();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user