This commit is contained in:
Carl Lerche
2017-03-12 22:33:45 -07:00
parent fb09a0e12c
commit 490ae8c05d
4 changed files with 89 additions and 17 deletions

View File

@@ -4,11 +4,13 @@ use tower::http::{HeaderName, Str};
use bytes::{Buf, Bytes};
use std::io::Cursor;
use std::collections::VecDeque;
/// Decodes headers using HPACK
pub struct Decoder {
// Protocol indicated that the max table size will update
max_size_update: Option<usize>,
table: Table,
}
/// Represents all errors that can be encountered while performing the decoding
@@ -112,6 +114,12 @@ enum Representation {
SizeUpdate,
}
struct Table {
entries: VecDeque<Entry>,
size: usize,
max_size: usize,
}
// ===== impl Decoder =====
impl Decoder {
@@ -119,6 +127,7 @@ impl Decoder {
pub fn new() -> Decoder {
Decoder {
max_size_update: None,
table: Table::new(4_096),
}
}
@@ -193,8 +202,6 @@ impl Representation {
}
}
// ===== Utils =====
fn decode_int<B: Buf>(buf: &mut B, prefix_size: u8) -> Result<usize, DecoderError> {
// The octet limit is chosen such that the maximum allowed *value* can
// never overflow an unsigned 32-bit integer. The maximum value of any
@@ -257,3 +264,37 @@ fn decode_int<B: Buf>(buf: &mut B, prefix_size: u8) -> Result<usize, DecoderErro
fn peek_u8<B: Buf>(buf: &mut B) -> u8 {
buf.bytes()[0]
}
// ===== impl Table =====
impl Table {
fn new(max_size: usize) -> Table {
Table {
entries: VecDeque::new(),
size: 0,
max_size: max_size,
}
}
fn max_size(&self) -> usize {
self.max_size
}
fn insert(&mut self, entry: Entry) {
let len = entry.len();
debug_assert!(len <= self.max_size);
while self.size + len > self.max_size {
let last = self.entries.pop_back()
.expect("size of table != 0, but no headers left!");
self.size -= last.len();
}
self.size += len;
// Track the entry
self.entries.push_front(entry);
}
}

40
src/hpack/entry.rs Normal file
View File

@@ -0,0 +1,40 @@
use tower::http::{HeaderName, Method, StatusCode, Str};
/// HPack table entry
pub enum Entry {
Header {
name: HeaderName,
value: Str,
},
Authority(Str),
Method(Method),
Scheme(Str),
Path(Str),
Status(StatusCode),
}
impl Entry {
pub fn len(&self) -> usize {
match *self {
Entry::Header { ref name, ref value } => {
let n: &str = name.as_ref();
32 + n.len() + value.len()
}
Entry::Authority(ref v) => {
32 + 10 + v.len()
}
Entry::Method(ref v) => {
32 + 7 + v.as_ref().len()
}
Entry::Scheme(ref v) => {
32 + 7 + v.len()
}
Entry::Path(ref v) => {
32 + 5 + v.len()
}
Entry::Status(ref v) => {
32 + 7 + 3
}
}
}
}

View File

@@ -1,7 +1,9 @@
mod encoder;
mod decoder;
mod table;
mod entry;
// mod table;
pub use self::encoder::Encoder;
pub use self::entry::Entry;
pub use self::decoder::Decoder;
pub use self::table::Entry;
// pub use self::table::Entry;

View File

@@ -1,19 +1,8 @@
use hpack::Entry;
use tower::http::{HeaderName, StatusCode, Method, Str};
use std::collections::VecDeque;
/// HPack table entry
pub enum Entry {
Header {
name: HeaderName,
value: Str,
},
Authority(Str),
Method(Method),
Scheme(Str),
Path(Str),
Status(StatusCode),
}
/// Get an entry from the static table
pub fn get_static(idx: usize) -> Entry {
use tower::http::StandardHeader::*;