work
This commit is contained in:
@@ -4,11 +4,13 @@ use tower::http::{HeaderName, Str};
|
|||||||
use bytes::{Buf, Bytes};
|
use bytes::{Buf, Bytes};
|
||||||
|
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
/// Decodes headers using HPACK
|
/// Decodes headers using HPACK
|
||||||
pub struct Decoder {
|
pub struct Decoder {
|
||||||
// Protocol indicated that the max table size will update
|
// Protocol indicated that the max table size will update
|
||||||
max_size_update: Option<usize>,
|
max_size_update: Option<usize>,
|
||||||
|
table: Table,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents all errors that can be encountered while performing the decoding
|
/// Represents all errors that can be encountered while performing the decoding
|
||||||
@@ -112,6 +114,12 @@ enum Representation {
|
|||||||
SizeUpdate,
|
SizeUpdate,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Table {
|
||||||
|
entries: VecDeque<Entry>,
|
||||||
|
size: usize,
|
||||||
|
max_size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
// ===== impl Decoder =====
|
// ===== impl Decoder =====
|
||||||
|
|
||||||
impl Decoder {
|
impl Decoder {
|
||||||
@@ -119,6 +127,7 @@ impl Decoder {
|
|||||||
pub fn new() -> Decoder {
|
pub fn new() -> Decoder {
|
||||||
Decoder {
|
Decoder {
|
||||||
max_size_update: None,
|
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> {
|
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
|
// The octet limit is chosen such that the maximum allowed *value* can
|
||||||
// never overflow an unsigned 32-bit integer. The maximum value of any
|
// 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 {
|
fn peek_u8<B: Buf>(buf: &mut B) -> u8 {
|
||||||
buf.bytes()[0]
|
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
40
src/hpack/entry.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
mod encoder;
|
mod encoder;
|
||||||
mod decoder;
|
mod decoder;
|
||||||
mod table;
|
mod entry;
|
||||||
|
// mod table;
|
||||||
|
|
||||||
pub use self::encoder::Encoder;
|
pub use self::encoder::Encoder;
|
||||||
|
pub use self::entry::Entry;
|
||||||
pub use self::decoder::Decoder;
|
pub use self::decoder::Decoder;
|
||||||
pub use self::table::Entry;
|
// pub use self::table::Entry;
|
||||||
|
|||||||
@@ -1,19 +1,8 @@
|
|||||||
|
use hpack::Entry;
|
||||||
|
|
||||||
use tower::http::{HeaderName, StatusCode, Method, Str};
|
use tower::http::{HeaderName, StatusCode, Method, Str};
|
||||||
use std::collections::VecDeque;
|
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
|
/// Get an entry from the static table
|
||||||
pub fn get_static(idx: usize) -> Entry {
|
pub fn get_static(idx: usize) -> Entry {
|
||||||
use tower::http::StandardHeader::*;
|
use tower::http::StandardHeader::*;
|
||||||
|
|||||||
Reference in New Issue
Block a user