chore: cargo fmt, clippy

This commit is contained in:
Gurwinder Singh
2019-08-17 09:07:32 +05:30
committed by Sean McArthur
parent e72d6dc189
commit f46840f3fa
43 changed files with 785 additions and 870 deletions

View File

@@ -6,8 +6,8 @@ use bytes::*;
use futures::*; use futures::*;
use http::{Response, StatusCode}; use http::{Response, StatusCode};
use tokio::net::{TcpListener, TcpStream};
use std::error::Error; use std::error::Error;
use tokio::net::{TcpListener, TcpStream};
#[tokio::main] #[tokio::main]
pub async fn main() -> Result<(), Box<dyn Error>> { pub async fn main() -> Result<(), Box<dyn Error>> {
@@ -21,7 +21,7 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
while let Some(socket) = incoming.next().await { while let Some(socket) = incoming.next().await {
tokio::spawn(async move { tokio::spawn(async move {
if let Err(e) = handle(socket).await { if let Err(e) = handle(socket).await {
println!(" -> err={:?}", e); println!(" -> err={:?}", e);
} }
}); });
} }
@@ -45,6 +45,6 @@ async fn handle(socket: io::Result<TcpStream>) -> Result<(), Box<dyn Error>> {
} }
println!("~~~~~~~~~~~~~~~~~~~~~~~~~~~ H2 connection CLOSE !!!!!! ~~~~~~~~~~~"); println!("~~~~~~~~~~~~~~~~~~~~~~~~~~~ H2 connection CLOSE !!!!!! ~~~~~~~~~~~");
Ok(()) Ok(())
} }

View File

@@ -77,7 +77,7 @@
//! #[tokio::main] //! #[tokio::main]
//! pub async fn main() -> Result<(), Box<dyn Error>> { //! pub async fn main() -> Result<(), Box<dyn Error>> {
//! let addr = "127.0.0.1:5928".parse().unwrap(); //! let addr = "127.0.0.1:5928".parse().unwrap();
//! //!
//! // Establish TCP connection to the server. //! // Establish TCP connection to the server.
//! let tcp = TcpStream::connect(&addr).await?; //! let tcp = TcpStream::connect(&addr).await?;
//! let (h2, connection) = client::handshake(tcp).await?; //! let (h2, connection) = client::handshake(tcp).await?;
@@ -96,7 +96,7 @@
//! // Send the request. The second tuple item allows the caller //! // Send the request. The second tuple item allows the caller
//! // to stream a request body. //! // to stream a request body.
//! let (response, _) = h2.send_request(request, true).unwrap(); //! let (response, _) = h2.send_request(request, true).unwrap();
//! //!
//! let (head, mut body) = response.await?.into_parts(); //! let (head, mut body) = response.await?.into_parts();
//! //!
//! println!("Received response: {:?}", head); //! println!("Received response: {:?}", head);
@@ -585,7 +585,7 @@ where
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match &mut self.inner { match &mut self.inner {
Some(send_request) => { Some(send_request) => {
let _ = ready!(send_request.poll_ready(cx))?; ready!(send_request.poll_ready(cx))?;
} }
None => panic!("called `poll` after future completed"), None => panic!("called `poll` after future completed"),
} }
@@ -1269,7 +1269,7 @@ impl Future for ResponseFuture {
let (parts, _) = ready!(self.inner.poll_response(cx))?.into_parts(); let (parts, _) = ready!(self.inner.poll_response(cx))?.into_parts();
let body = RecvStream::new(ReleaseCapacity::new(self.inner.clone())); let body = RecvStream::new(ReleaseCapacity::new(self.inner.clone()));
Poll::Ready(Ok(Response::from_parts(parts, body).into())) Poll::Ready(Ok(Response::from_parts(parts, body)))
} }
} }

View File

@@ -76,9 +76,7 @@ impl error::Error for RecvError {
match *self { match *self {
Connection(ref reason) => reason.description(), Connection(ref reason) => reason.description(),
Stream { Stream { ref reason, .. } => reason.description(),
ref reason, ..
} => reason.description(),
Io(ref e) => e.description(), Io(ref e) => e.description(),
} }
} }

View File

@@ -14,8 +14,8 @@ use std::io;
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use tokio_codec::{LengthDelimitedCodec, LengthDelimitedCodecError};
use tokio_codec::FramedRead as InnerFramedRead; use tokio_codec::FramedRead as InnerFramedRead;
use tokio_codec::{LengthDelimitedCodec, LengthDelimitedCodecError};
use tokio_io::AsyncRead; use tokio_io::AsyncRead;
// 16 MB "sane default" taken from golang http2 // 16 MB "sane default" taken from golang http2
@@ -52,7 +52,7 @@ enum Continuable {
impl<T> FramedRead<T> { impl<T> FramedRead<T> {
pub fn new(inner: InnerFramedRead<T, LengthDelimitedCodec>) -> FramedRead<T> { pub fn new(inner: InnerFramedRead<T, LengthDelimitedCodec>) -> FramedRead<T> {
FramedRead { FramedRead {
inner: inner, inner,
hpack: hpack::Decoder::new(DEFAULT_SETTINGS_HEADER_TABLE_SIZE), hpack: hpack::Decoder::new(DEFAULT_SETTINGS_HEADER_TABLE_SIZE),
max_header_list_size: DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE, max_header_list_size: DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE,
partial: None, partial: None,

View File

@@ -1,5 +1,5 @@
use bytes::{Buf, BufMut, Bytes};
use crate::frame::{util, Error, Frame, Head, Kind, StreamId}; use crate::frame::{util, Error, Frame, Head, Kind, StreamId};
use bytes::{Buf, BufMut, Bytes};
use std::fmt; use std::fmt;
@@ -29,7 +29,7 @@ impl<T> Data<T> {
assert!(!stream_id.is_zero()); assert!(!stream_id.is_zero());
Data { Data {
stream_id: stream_id, stream_id,
data: payload, data: payload,
flags: DataFlags::default(), flags: DataFlags::default(),
pad_len: None, pad_len: None,
@@ -135,8 +135,8 @@ impl Data<Bytes> {
Ok(Data { Ok(Data {
stream_id: head.stream_id(), stream_id: head.stream_id(),
data: payload, data: payload,
flags: flags, flags,
pad_len: pad_len, pad_len,
}) })
} }
} }

View File

@@ -1,6 +1,6 @@
use crate::frame::{self, Error, Head, Kind, Reason, StreamId}; use crate::frame::{self, Error, Head, Kind, Reason, StreamId};
use bytes::{BufMut}; use bytes::BufMut;
#[derive(Debug, Clone, Copy, Eq, PartialEq)] #[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct GoAway { pub struct GoAway {
@@ -33,7 +33,7 @@ impl GoAway {
let error_code = unpack_octets_4!(payload, 4, u32); let error_code = unpack_octets_4!(payload, 4, u32);
Ok(GoAway { Ok(GoAway {
last_stream_id: last_stream_id, last_stream_id,
error_code: error_code.into(), error_code: error_code.into(),
}) })
} }

View File

@@ -1,6 +1,6 @@
use super::StreamId; use super::StreamId;
use bytes::{BufMut}; use bytes::BufMut;
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Head { pub struct Head {
@@ -30,9 +30,9 @@ pub enum Kind {
impl Head { impl Head {
pub fn new(kind: Kind, flag: u8, stream_id: StreamId) -> Head { pub fn new(kind: Kind, flag: u8, stream_id: StreamId) -> Head {
Head { Head {
kind: kind, kind,
flag: flag, flag,
stream_id: stream_id, stream_id,
} }
} }

View File

@@ -2,8 +2,8 @@ use super::{util, StreamDependency, StreamId};
use crate::frame::{Error, Frame, Head, Kind}; use crate::frame::{Error, Frame, Head, Kind};
use crate::hpack; use crate::hpack;
use http::{uri, HeaderMap, Method, StatusCode, Uri};
use http::header::{self, HeaderName, HeaderValue}; use http::header::{self, HeaderName, HeaderValue};
use http::{uri, HeaderMap, Method, StatusCode, Uri};
use bytes::{Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
use string::String; use string::String;
@@ -118,12 +118,12 @@ impl Headers {
/// Create a new HEADERS frame /// Create a new HEADERS frame
pub fn new(stream_id: StreamId, pseudo: Pseudo, fields: HeaderMap) -> Self { pub fn new(stream_id: StreamId, pseudo: Pseudo, fields: HeaderMap) -> Self {
Headers { Headers {
stream_id: stream_id, stream_id,
stream_dep: None, stream_dep: None,
header_block: HeaderBlock { header_block: HeaderBlock {
fields: fields, fields,
is_over_size: false, is_over_size: false,
pseudo: pseudo, pseudo,
}, },
flags: HeadersFlag::default(), flags: HeadersFlag::default(),
} }
@@ -137,11 +137,11 @@ impl Headers {
stream_id, stream_id,
stream_dep: None, stream_dep: None,
header_block: HeaderBlock { header_block: HeaderBlock {
fields: fields, fields,
is_over_size: false, is_over_size: false,
pseudo: Pseudo::default(), pseudo: Pseudo::default(),
}, },
flags: flags, flags,
} }
} }
@@ -156,7 +156,7 @@ impl Headers {
// Read the padding length // Read the padding length
if flags.is_padded() { if flags.is_padded() {
if src.len() < 1 { if src.is_empty() {
return Err(Error::MalformedMessage); return Err(Error::MalformedMessage);
} }
pad = src[0] as usize; pad = src[0] as usize;
@@ -195,19 +195,24 @@ impl Headers {
let headers = Headers { let headers = Headers {
stream_id: head.stream_id(), stream_id: head.stream_id(),
stream_dep: stream_dep, stream_dep,
header_block: HeaderBlock { header_block: HeaderBlock {
fields: HeaderMap::new(), fields: HeaderMap::new(),
is_over_size: false, is_over_size: false,
pseudo: Pseudo::default(), pseudo: Pseudo::default(),
}, },
flags: flags, flags,
}; };
Ok((headers, src)) Ok((headers, src))
} }
pub fn load_hpack(&mut self, src: &mut BytesMut, max_header_list_size: usize, decoder: &mut hpack::Decoder) -> Result<(), Error> { pub fn load_hpack(
&mut self,
src: &mut BytesMut,
max_header_list_size: usize,
decoder: &mut hpack::Decoder,
) -> Result<(), Error> {
self.header_block.load(src, max_header_list_size, decoder) self.header_block.load(src, max_header_list_size, decoder)
} }
@@ -263,9 +268,9 @@ impl Headers {
// Get the HEADERS frame head // Get the HEADERS frame head
let head = self.head(); let head = self.head();
self.header_block.into_encoding() self.header_block
.encode(&head, encoder, dst, |_| { .into_encoding()
}) .encode(&head, encoder, dst, |_| {})
} }
fn head(&self) -> Head { fn head(&self) -> Head {
@@ -307,7 +312,7 @@ impl PushPromise {
// Read the padding length // Read the padding length
if flags.is_padded() { if flags.is_padded() {
if src.len() < 1 { if src.is_empty() {
return Err(Error::MalformedMessage); return Err(Error::MalformedMessage);
} }
@@ -336,19 +341,24 @@ impl PushPromise {
} }
let frame = PushPromise { let frame = PushPromise {
flags: flags, flags,
header_block: HeaderBlock { header_block: HeaderBlock {
fields: HeaderMap::new(), fields: HeaderMap::new(),
is_over_size: false, is_over_size: false,
pseudo: Pseudo::default(), pseudo: Pseudo::default(),
}, },
promised_id: promised_id, promised_id,
stream_id: head.stream_id(), stream_id: head.stream_id(),
}; };
Ok((frame, src)) Ok((frame, src))
} }
pub fn load_hpack(&mut self, src: &mut BytesMut, max_header_list_size: usize, decoder: &mut hpack::Decoder) -> Result<(), Error> { pub fn load_hpack(
&mut self,
src: &mut BytesMut,
max_header_list_size: usize,
decoder: &mut hpack::Decoder,
) -> Result<(), Error> {
self.header_block.load(src, max_header_list_size, decoder) self.header_block.load(src, max_header_list_size, decoder)
} }
@@ -381,7 +391,8 @@ impl PushPromise {
let head = self.head(); let head = self.head();
let promised_id = self.promised_id; let promised_id = self.promised_id;
self.header_block.into_encoding() self.header_block
.into_encoding()
.encode(&head, encoder, dst, |dst| { .encode(&head, encoder, dst, |dst| {
dst.put_u32_be(promised_id.into()); dst.put_u32_be(promised_id.into());
}) })
@@ -456,9 +467,7 @@ impl Continuation {
// Get the CONTINUATION frame head // Get the CONTINUATION frame head
let head = self.head(); let head = self.head();
self.header_block self.header_block.encode(&head, encoder, dst, |_| {})
.encode(&head, encoder, dst, |_| {
})
} }
} }
@@ -471,7 +480,7 @@ impl Pseudo {
let mut path = parts let mut path = parts
.path_and_query .path_and_query
.map(|v| v.into()) .map(|v| v.into())
.unwrap_or_else(|| Bytes::new()); .unwrap_or_else(Bytes::new);
if path.is_empty() && method != Method::OPTIONS { if path.is_empty() && method != Method::OPTIONS {
path = Bytes::from_static(b"/"); path = Bytes::from_static(b"/");
@@ -527,13 +536,15 @@ fn to_string(src: Bytes) -> String<Bytes> {
// ===== impl EncodingHeaderBlock ===== // ===== impl EncodingHeaderBlock =====
impl EncodingHeaderBlock { impl EncodingHeaderBlock {
fn encode<F>(mut self, fn encode<F>(
head: &Head, mut self,
encoder: &mut hpack::Encoder, head: &Head,
dst: &mut BytesMut, encoder: &mut hpack::Encoder,
f: F) dst: &mut BytesMut,
-> Option<Continuation> f: F,
where F: FnOnce(&mut BytesMut), ) -> Option<Continuation>
where
F: FnOnce(&mut BytesMut),
{ {
let head_pos = dst.len(); let head_pos = dst.len();
@@ -610,12 +621,9 @@ impl Iterator for Iter {
self.pseudo = None; self.pseudo = None;
self.fields.next().map(|(name, value)| { self.fields
Field { .next()
name: name, .map(|(name, value)| Field { name, value })
value: value,
}
})
} }
} }
@@ -727,9 +735,13 @@ impl fmt::Debug for PushPromiseFlag {
// ===== HeaderBlock ===== // ===== HeaderBlock =====
impl HeaderBlock { impl HeaderBlock {
fn load(&mut self, src: &mut BytesMut, max_header_list_size: usize, decoder: &mut hpack::Decoder) -> Result<(), Error> { fn load(
&mut self,
src: &mut BytesMut,
max_header_list_size: usize,
decoder: &mut hpack::Decoder,
) -> Result<(), Error> {
let mut reg = !self.fields.is_empty(); let mut reg = !self.fields.is_empty();
let mut malformed = false; let mut malformed = false;
let mut headers_size = self.calculate_header_list_size(); let mut headers_size = self.calculate_header_list_size();
@@ -744,7 +756,8 @@ impl HeaderBlock {
malformed = true; malformed = true;
} else { } else {
let __val = $val; let __val = $val;
headers_size += decoded_header_size(stringify!($ident).len() + 1, __val.as_str().len()); headers_size +=
decoded_header_size(stringify!($ident).len() + 1, __val.as_str().len());
if headers_size < max_header_list_size { if headers_size < max_header_list_size {
self.pseudo.$field = Some(__val); self.pseudo.$field = Some(__val);
} else if !self.is_over_size { } else if !self.is_over_size {
@@ -752,7 +765,7 @@ impl HeaderBlock {
self.is_over_size = true; self.is_over_size = true;
} }
} }
}} }};
} }
let mut cursor = Cursor::new(src); let mut cursor = Cursor::new(src);
@@ -765,10 +778,7 @@ impl HeaderBlock {
use crate::hpack::Header::*; use crate::hpack::Header::*;
match header { match header {
Field { Field { name, value } => {
name,
value,
} => {
// Connection level header fields are not supported and must // Connection level header fields are not supported and must
// result in a protocol error. // result in a protocol error.
@@ -794,7 +804,7 @@ impl HeaderBlock {
self.is_over_size = true; self.is_over_size = true;
} }
} }
}, }
Authority(v) => set_pseudo!(authority, v), Authority(v) => set_pseudo!(authority, v),
Method(v) => set_pseudo!(method, v), Method(v) => set_pseudo!(method, v),
Scheme(v) => set_pseudo!(scheme, v), Scheme(v) => set_pseudo!(scheme, v),
@@ -810,7 +820,7 @@ impl HeaderBlock {
if malformed { if malformed {
log::trace!("malformed message"); log::trace!("malformed message");
return Err(Error::MalformedMessage.into()); return Err(Error::MalformedMessage);
} }
Ok(()) Ok(())
@@ -835,36 +845,38 @@ impl HeaderBlock {
/// > overhead of 32 octets for each header field. /// > overhead of 32 octets for each header field.
fn calculate_header_list_size(&self) -> usize { fn calculate_header_list_size(&self) -> usize {
macro_rules! pseudo_size { macro_rules! pseudo_size {
($name:ident) => ({ ($name:ident) => {{
self.pseudo self.pseudo
.$name .$name
.as_ref() .as_ref()
.map(|m| decoded_header_size(stringify!($name).len() + 1, m.as_str().len())) .map(|m| decoded_header_size(stringify!($name).len() + 1, m.as_str().len()))
.unwrap_or(0) .unwrap_or(0)
}); }};
} }
pseudo_size!(method) + pseudo_size!(method)
pseudo_size!(scheme) + + pseudo_size!(scheme)
pseudo_size!(status) + + pseudo_size!(status)
pseudo_size!(authority) + + pseudo_size!(authority)
pseudo_size!(path) + + pseudo_size!(path)
self.fields.iter() + self
.map(|(name, value)| decoded_header_size(name.as_str().len(), value.len())) .fields
.sum::<usize>() .iter()
.map(|(name, value)| decoded_header_size(name.as_str().len(), value.len()))
.sum::<usize>()
} }
/// Iterate over all pseudos and headers to see if any individual pair /// Iterate over all pseudos and headers to see if any individual pair
/// would be too large to encode. /// would be too large to encode.
pub(crate) fn has_too_big_field(&self) -> bool { pub(crate) fn has_too_big_field(&self) -> bool {
macro_rules! pseudo_size { macro_rules! pseudo_size {
($name:ident) => ({ ($name:ident) => {{
self.pseudo self.pseudo
.$name .$name
.as_ref() .as_ref()
.map(|m| decoded_header_size(stringify!($name).len() + 1, m.as_str().len())) .map(|m| decoded_header_size(stringify!($name).len() + 1, m.as_str().len()))
.unwrap_or(0) .unwrap_or(0)
}); }};
} }
if pseudo_size!(method) > MAX_HEADER_LENGTH { if pseudo_size!(method) > MAX_HEADER_LENGTH {

View File

@@ -18,12 +18,12 @@ use std::fmt;
#[macro_escape] #[macro_escape]
macro_rules! unpack_octets_4 { macro_rules! unpack_octets_4 {
// TODO: Get rid of this macro // TODO: Get rid of this macro
($buf:expr, $offset:expr, $tip:ty) => ( ($buf:expr, $offset:expr, $tip:ty) => {
(($buf[$offset + 0] as $tip) << 24) | (($buf[$offset + 0] as $tip) << 24)
(($buf[$offset + 1] as $tip) << 16) | | (($buf[$offset + 1] as $tip) << 16)
(($buf[$offset + 2] as $tip) << 8) | | (($buf[$offset + 2] as $tip) << 8)
(($buf[$offset + 3] as $tip) << 0) | (($buf[$offset + 3] as $tip) << 0)
); };
} }
mod data; mod data;
@@ -54,11 +54,8 @@ pub use self::window_update::WindowUpdate;
// Re-export some constants // Re-export some constants
pub use self::settings::{ pub use self::settings::{
DEFAULT_INITIAL_WINDOW_SIZE, DEFAULT_INITIAL_WINDOW_SIZE, DEFAULT_MAX_FRAME_SIZE, DEFAULT_SETTINGS_HEADER_TABLE_SIZE,
DEFAULT_MAX_FRAME_SIZE, MAX_INITIAL_WINDOW_SIZE, MAX_MAX_FRAME_SIZE,
DEFAULT_SETTINGS_HEADER_TABLE_SIZE,
MAX_INITIAL_WINDOW_SIZE,
MAX_MAX_FRAME_SIZE,
}; };
pub type FrameSize = u32; pub type FrameSize = u32;

View File

@@ -1,5 +1,5 @@
use bytes::{Buf, BufMut, IntoBuf};
use crate::frame::{Error, Frame, Head, Kind, StreamId}; use crate::frame::{Error, Frame, Head, Kind, StreamId};
use bytes::{Buf, BufMut, IntoBuf};
const ACK_FLAG: u8 = 0x1; const ACK_FLAG: u8 = 0x1;
@@ -17,7 +17,6 @@ const SHUTDOWN_PAYLOAD: Payload = [0x0b, 0x7b, 0xa2, 0xf0, 0x8b, 0x9b, 0xfe, 0x5
const USER_PAYLOAD: Payload = [0x3b, 0x7c, 0xdb, 0x7a, 0x0b, 0x87, 0x16, 0xb4]; const USER_PAYLOAD: Payload = [0x3b, 0x7c, 0xdb, 0x7a, 0x0b, 0x87, 0x16, 0xb4];
impl Ping { impl Ping {
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
pub const SHUTDOWN: Payload = SHUTDOWN_PAYLOAD; pub const SHUTDOWN: Payload = SHUTDOWN_PAYLOAD;
@@ -38,10 +37,7 @@ impl Ping {
} }
pub fn pong(payload: Payload) -> Ping { pub fn pong(payload: Payload) -> Ping {
Ping { Ping { ack: true, payload }
ack: true,
payload,
}
} }
pub fn is_ack(&self) -> bool { pub fn is_ack(&self) -> bool {
@@ -84,10 +80,7 @@ impl Ping {
// endpoint MUST NOT respond to PING frames containing this flag. // endpoint MUST NOT respond to PING frames containing this flag.
let ack = head.flag() & ACK_FLAG != 0; let ack = head.flag() & ACK_FLAG != 0;
Ok(Ping { Ok(Ping { ack, payload })
ack,
payload,
})
} }
pub fn encode<B: BufMut>(&self, dst: &mut B) { pub fn encode<B: BufMut>(&self, dst: &mut B) {

View File

@@ -30,7 +30,7 @@ impl Priority {
Ok(Priority { Ok(Priority {
stream_id: head.stream_id(), stream_id: head.stream_id(),
dependency: dependency, dependency,
}) })
} }
} }

View File

@@ -1,6 +1,5 @@
use std::fmt; use std::fmt;
/// HTTP/2.0 error codes. /// HTTP/2.0 error codes.
/// ///
/// Error codes are used in `RST_STREAM` and `GOAWAY` frames to convey the /// Error codes are used in `RST_STREAM` and `GOAWAY` frames to convey the
@@ -76,7 +75,7 @@ impl Reason {
10 => { 10 => {
"connection established in response to a CONNECT request was reset or abnormally \ "connection established in response to a CONNECT request was reset or abnormally \
closed" closed"
}, }
11 => "detected excessive load generating behavior", 11 => "detected excessive load generating behavior",
12 => "security properties do not meet minimum requirements", 12 => "security properties do not meet minimum requirements",
13 => "endpoint requires HTTP/1.1", 13 => "endpoint requires HTTP/1.1",
@@ -114,9 +113,7 @@ impl fmt::Debug for Reason {
11 => "ENHANCE_YOUR_CALM", 11 => "ENHANCE_YOUR_CALM",
12 => "INADEQUATE_SECURITY", 12 => "INADEQUATE_SECURITY",
13 => "HTTP_1_1_REQUIRED", 13 => "HTTP_1_1_REQUIRED",
other => return f.debug_tuple("Reason") other => return f.debug_tuple("Reason").field(&Hex(other)).finish(),
.field(&Hex(other))
.finish(),
}; };
f.write_str(name) f.write_str(name)
} }

View File

@@ -1,6 +1,6 @@
use crate::frame::{self, Error, Head, Kind, Reason, StreamId}; use crate::frame::{self, Error, Head, Kind, Reason, StreamId};
use bytes::{BufMut}; use bytes::BufMut;
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
pub struct Reset { pub struct Reset {

View File

@@ -1,7 +1,7 @@
use std::fmt; use std::fmt;
use bytes::{BufMut, BytesMut};
use crate::frame::{util, Error, Frame, FrameSize, Head, Kind, StreamId}; use crate::frame::{util, Error, Frame, FrameSize, Head, Kind, StreamId};
use bytes::{BufMut, BytesMut};
#[derive(Clone, Default, Eq, PartialEq)] #[derive(Clone, Default, Eq, PartialEq)]
pub struct Settings { pub struct Settings {
@@ -121,7 +121,7 @@ impl Settings {
if flag.is_ack() { if flag.is_ack() {
// Ensure that the payload is empty // Ensure that the payload is empty
if payload.len() > 0 { if !payload.is_empty() {
return Err(Error::InvalidPayloadLength); return Err(Error::InvalidPayloadLength);
} }
@@ -142,34 +142,36 @@ impl Settings {
match Setting::load(raw) { match Setting::load(raw) {
Some(HeaderTableSize(val)) => { Some(HeaderTableSize(val)) => {
settings.header_table_size = Some(val); settings.header_table_size = Some(val);
}, }
Some(EnablePush(val)) => match val { Some(EnablePush(val)) => match val {
0 | 1 => { 0 | 1 => {
settings.enable_push = Some(val); settings.enable_push = Some(val);
}, }
_ => { _ => {
return Err(Error::InvalidSettingValue); return Err(Error::InvalidSettingValue);
}, }
}, },
Some(MaxConcurrentStreams(val)) => { Some(MaxConcurrentStreams(val)) => {
settings.max_concurrent_streams = Some(val); settings.max_concurrent_streams = Some(val);
}, }
Some(InitialWindowSize(val)) => if val as usize > MAX_INITIAL_WINDOW_SIZE { Some(InitialWindowSize(val)) => {
return Err(Error::InvalidSettingValue); if val as usize > MAX_INITIAL_WINDOW_SIZE {
} else { return Err(Error::InvalidSettingValue);
settings.initial_window_size = Some(val); } else {
}, settings.initial_window_size = Some(val);
}
}
Some(MaxFrameSize(val)) => { Some(MaxFrameSize(val)) => {
if val < DEFAULT_MAX_FRAME_SIZE || val > MAX_MAX_FRAME_SIZE { if val < DEFAULT_MAX_FRAME_SIZE || val > MAX_MAX_FRAME_SIZE {
return Err(Error::InvalidSettingValue); return Err(Error::InvalidSettingValue);
} else { } else {
settings.max_frame_size = Some(val); settings.max_frame_size = Some(val);
} }
}, }
Some(MaxHeaderListSize(val)) => { Some(MaxHeaderListSize(val)) => {
settings.max_header_list_size = Some(val); settings.max_header_list_size = Some(val);
}, }
None => {}, None => {}
} }
} }
@@ -294,7 +296,7 @@ impl Setting {
/// ///
/// If given a buffer shorter than 6 bytes, the function will panic. /// If given a buffer shorter than 6 bytes, the function will panic.
fn load(raw: &[u8]) -> Option<Setting> { fn load(raw: &[u8]) -> Option<Setting> {
let id: u16 = ((raw[0] as u16) << 8) | (raw[1] as u16); let id: u16 = (u16::from(raw[0]) << 8) | u16::from(raw[1]);
let val: u32 = unpack_octets_4!(raw, 2, u32); let val: u32 = unpack_octets_4!(raw, 2, u32);
Setting::from_id(id, val) Setting::from_id(id, val)

View File

@@ -38,7 +38,10 @@ pub fn strip_padding(payload: &mut Bytes) -> Result<u8, Error> {
Ok(pad_len as u8) Ok(pad_len as u8)
} }
pub(super) fn debug_flags<'a, 'f: 'a>(fmt: &'a mut fmt::Formatter<'f>, bits: u8) -> DebugFlags<'a, 'f> { pub(super) fn debug_flags<'a, 'f: 'a>(
fmt: &'a mut fmt::Formatter<'f>,
bits: u8,
) -> DebugFlags<'a, 'f> {
let result = write!(fmt, "({:#x}", bits); let result = write!(fmt, "({:#x}", bits);
DebugFlags { DebugFlags {
fmt, fmt,
@@ -71,8 +74,6 @@ impl<'a, 'f: 'a> DebugFlags<'a, 'f> {
} }
pub(super) fn finish(&mut self) -> fmt::Result { pub(super) fn finish(&mut self) -> fmt::Result {
self.result.and_then(|()| { self.result.and_then(|()| write!(self.fmt, ")"))
write!(self.fmt, ")")
})
} }
} }

View File

@@ -1,6 +1,6 @@
use crate::frame::{self, Error, Head, Kind, StreamId}; use crate::frame::{self, Error, Head, Kind, StreamId};
use bytes::{BufMut}; use bytes::BufMut;
const SIZE_INCREMENT_MASK: u32 = 1 << 31; const SIZE_INCREMENT_MASK: u32 = 1 << 31;
@@ -38,7 +38,7 @@ impl WindowUpdate {
let size_increment = unpack_octets_4!(payload, 0, u32) & !SIZE_INCREMENT_MASK; let size_increment = unpack_octets_4!(payload, 0, u32) & !SIZE_INCREMENT_MASK;
if size_increment == 0 { if size_increment == 0 {
return Err(Error::InvalidWindowUpdateValue.into()); return Err(Error::InvalidWindowUpdateValue);
} }
Ok(WindowUpdate { Ok(WindowUpdate {

View File

@@ -168,7 +168,11 @@ impl Decoder {
} }
/// Decodes the headers found in the given buffer. /// Decodes the headers found in the given buffer.
pub fn decode<F>(&mut self, src: &mut Cursor<&mut BytesMut>, mut f: F) -> Result<(), DecoderError> pub fn decode<F>(
&mut self,
src: &mut Cursor<&mut BytesMut>,
mut f: F,
) -> Result<(), DecoderError>
where where
F: FnMut(Header), F: FnMut(Header),
{ {
@@ -193,7 +197,7 @@ impl Decoder {
let entry = self.decode_indexed(src)?; let entry = self.decode_indexed(src)?;
consume(src); consume(src);
f(entry); f(entry);
}, }
LiteralWithIndexing => { LiteralWithIndexing => {
log::trace!(" LiteralWithIndexing; rem={:?}", src.remaining()); log::trace!(" LiteralWithIndexing; rem={:?}", src.remaining());
can_resize = false; can_resize = false;
@@ -204,14 +208,14 @@ impl Decoder {
consume(src); consume(src);
f(entry); f(entry);
}, }
LiteralWithoutIndexing => { LiteralWithoutIndexing => {
log::trace!(" LiteralWithoutIndexing; rem={:?}", src.remaining()); log::trace!(" LiteralWithoutIndexing; rem={:?}", src.remaining());
can_resize = false; can_resize = false;
let entry = self.decode_literal(src, false)?; let entry = self.decode_literal(src, false)?;
consume(src); consume(src);
f(entry); f(entry);
}, }
LiteralNeverIndexed => { LiteralNeverIndexed => {
log::trace!(" LiteralNeverIndexed; rem={:?}", src.remaining()); log::trace!(" LiteralNeverIndexed; rem={:?}", src.remaining());
can_resize = false; can_resize = false;
@@ -221,7 +225,7 @@ impl Decoder {
// TODO: Track that this should never be indexed // TODO: Track that this should never be indexed
f(entry); f(entry);
}, }
SizeUpdate => { SizeUpdate => {
log::trace!(" SizeUpdate; rem={:?}", src.remaining()); log::trace!(" SizeUpdate; rem={:?}", src.remaining());
if !can_resize { if !can_resize {
@@ -231,7 +235,7 @@ impl Decoder {
// Handle the dynamic table size update // Handle the dynamic table size update
self.process_size_update(src)?; self.process_size_update(src)?;
consume(src); consume(src);
}, }
} }
} }
@@ -287,7 +291,7 @@ impl Decoder {
} }
fn decode_string(&mut self, buf: &mut Cursor<&mut BytesMut>) -> Result<Bytes, DecoderError> { fn decode_string(&mut self, buf: &mut Cursor<&mut BytesMut>) -> Result<Bytes, DecoderError> {
const HUFF_FLAG: u8 = 0b10000000; const HUFF_FLAG: u8 = 0b1000_0000;
// The first bit in the first byte contains the huffman encoded flag. // The first bit in the first byte contains the huffman encoded flag.
let huff = match peek_u8(buf) { let huff = match peek_u8(buf) {
@@ -331,12 +335,12 @@ impl Default for Decoder {
impl Representation { impl Representation {
pub fn load(byte: u8) -> Result<Representation, DecoderError> { pub fn load(byte: u8) -> Result<Representation, DecoderError> {
const INDEXED: u8 = 0b10000000; const INDEXED: u8 = 0b1000_0000;
const LITERAL_WITH_INDEXING: u8 = 0b01000000; const LITERAL_WITH_INDEXING: u8 = 0b0100_0000;
const LITERAL_WITHOUT_INDEXING: u8 = 0b11110000; const LITERAL_WITHOUT_INDEXING: u8 = 0b1111_0000;
const LITERAL_NEVER_INDEXED: u8 = 0b00010000; const LITERAL_NEVER_INDEXED: u8 = 0b0001_0000;
const SIZE_UPDATE_MASK: u8 = 0b11100000; const SIZE_UPDATE_MASK: u8 = 0b1110_0000;
const SIZE_UPDATE: u8 = 0b00100000; const SIZE_UPDATE: u8 = 0b0010_0000;
// TODO: What did I even write here? // TODO: What did I even write here?
@@ -361,8 +365,8 @@ fn decode_int<B: Buf>(buf: &mut B, prefix_size: u8) -> Result<usize, DecoderErro
// never overflow an unsigned 32-bit integer. The maximum value of any // never overflow an unsigned 32-bit integer. The maximum value of any
// integer that can be encoded with 5 octets is ~2^28 // integer that can be encoded with 5 octets is ~2^28
const MAX_BYTES: usize = 5; const MAX_BYTES: usize = 5;
const VARINT_MASK: u8 = 0b01111111; const VARINT_MASK: u8 = 0b0111_1111;
const VARINT_FLAG: u8 = 0b10000000; const VARINT_FLAG: u8 = 0b1000_0000;
if prefix_size < 1 || prefix_size > 8 { if prefix_size < 1 || prefix_size > 8 {
return Err(DecoderError::InvalidIntegerPrefix); return Err(DecoderError::InvalidIntegerPrefix);
@@ -445,7 +449,7 @@ impl Table {
Table { Table {
entries: VecDeque::new(), entries: VecDeque::new(),
size: 0, size: 0,
max_size: max_size, max_size,
} }
} }
@@ -516,7 +520,7 @@ impl Table {
// Can never happen as the size of the table must reach // Can never happen as the size of the table must reach
// 0 by the time we've exhausted all elements. // 0 by the time we've exhausted all elements.
panic!("Size of table != 0, but no headers left!"); panic!("Size of table != 0, but no headers left!");
}, }
}; };
self.size -= last.len(); self.size -= last.len();
@@ -827,15 +831,20 @@ mod test {
let mut buf = buf.into(); let mut buf = buf.into();
let mut res = vec![]; let mut res = vec![];
let _ = de.decode(&mut Cursor::new(&mut buf), |h| { let _ = de
res.push(h); .decode(&mut Cursor::new(&mut buf), |h| {
}).unwrap(); res.push(h);
})
.unwrap();
assert_eq!(res.len(), 1); assert_eq!(res.len(), 1);
assert_eq!(de.table.size(), 0); assert_eq!(de.table.size(), 0);
match res[0] { match res[0] {
Header::Field { ref name, ref value } => { Header::Field {
ref name,
ref value,
} => {
assert_eq!(name, "foo"); assert_eq!(name, "foo");
assert_eq!(value, "bar"); assert_eq!(value, "bar");
} }

View File

@@ -1,5 +1,5 @@
use super::{huffman, Header};
use super::table::{Index, Table}; use super::table::{Index, Table};
use super::{huffman, Header};
use bytes::{BufMut, BytesMut}; use bytes::{BufMut, BytesMut};
use http::header::{HeaderName, HeaderValue}; use http::header::{HeaderName, HeaderValue};
@@ -47,27 +47,31 @@ impl Encoder {
#[allow(dead_code)] #[allow(dead_code)]
pub fn update_max_size(&mut self, val: usize) { pub fn update_max_size(&mut self, val: usize) {
match self.size_update { match self.size_update {
Some(SizeUpdate::One(old)) => if val > old { Some(SizeUpdate::One(old)) => {
if old > self.table.max_size() { if val > old {
if old > self.table.max_size() {
self.size_update = Some(SizeUpdate::One(val));
} else {
self.size_update = Some(SizeUpdate::Two(old, val));
}
} else {
self.size_update = Some(SizeUpdate::One(val));
}
}
Some(SizeUpdate::Two(min, _)) => {
if val < min {
self.size_update = Some(SizeUpdate::One(val)); self.size_update = Some(SizeUpdate::One(val));
} else { } else {
self.size_update = Some(SizeUpdate::Two(old, val)); self.size_update = Some(SizeUpdate::Two(min, val));
} }
} else { }
self.size_update = Some(SizeUpdate::One(val));
},
Some(SizeUpdate::Two(min, _)) => if val < min {
self.size_update = Some(SizeUpdate::One(val));
} else {
self.size_update = Some(SizeUpdate::Two(min, val));
},
None => { None => {
if val != self.table.max_size() { if val != self.table.max_size() {
// Don't bother writing a frame if the value already matches // Don't bother writing a frame if the value already matches
// the table's max size. // the table's max size.
self.size_update = Some(SizeUpdate::One(val)); self.size_update = Some(SizeUpdate::One(val));
} }
}, }
} }
} }
@@ -120,14 +124,11 @@ impl Encoder {
if res.is_err() { if res.is_err() {
dst.truncate(len); dst.truncate(len);
return Encode::Partial(EncodeState { return Encode::Partial(EncodeState { index, value: None });
index: index,
value: None,
});
} }
last_index = Some(index); last_index = Some(index);
}, }
// The header does not have an associated name. This means that // The header does not have an associated name. This means that
// the name is the same as the previously yielded header. In // the name is the same as the previously yielded header. In
// which case, we skip table lookup and just use the same index // which case, we skip table lookup and just use the same index
@@ -148,7 +149,7 @@ impl Encoder {
value: Some(value), value: Some(value),
}); });
} }
}, }
}; };
} }
@@ -160,14 +161,14 @@ impl Encoder {
Some(SizeUpdate::One(val)) => { Some(SizeUpdate::One(val)) => {
self.table.resize(val); self.table.resize(val);
encode_size_update(val, dst)?; encode_size_update(val, dst)?;
}, }
Some(SizeUpdate::Two(min, max)) => { Some(SizeUpdate::Two(min, max)) => {
self.table.resize(min); self.table.resize(min);
self.table.resize(max); self.table.resize(max);
encode_size_update(min, dst)?; encode_size_update(min, dst)?;
encode_size_update(max, dst)?; encode_size_update(max, dst)?;
}, }
None => {}, None => {}
} }
Ok(()) Ok(())
@@ -177,12 +178,12 @@ impl Encoder {
match *index { match *index {
Index::Indexed(idx, _) => { Index::Indexed(idx, _) => {
encode_int(idx, 7, 0x80, dst)?; encode_int(idx, 7, 0x80, dst)?;
}, }
Index::Name(idx, _) => { Index::Name(idx, _) => {
let header = self.table.resolve(&index); let header = self.table.resolve(&index);
encode_not_indexed(idx, header.value_slice(), header.is_sensitive(), dst)?; encode_not_indexed(idx, header.value_slice(), header.is_sensitive(), dst)?;
}, }
Index::Inserted(_) => { Index::Inserted(_) => {
let header = self.table.resolve(&index); let header = self.table.resolve(&index);
@@ -192,19 +193,19 @@ impl Encoder {
return Err(EncoderError::BufferOverflow); return Err(EncoderError::BufferOverflow);
} }
dst.put_u8(0b01000000); dst.put_u8(0b0100_0000);
encode_str(header.name().as_slice(), dst)?; encode_str(header.name().as_slice(), dst)?;
encode_str(header.value_slice(), dst)?; encode_str(header.value_slice(), dst)?;
}, }
Index::InsertedValue(idx, _) => { Index::InsertedValue(idx, _) => {
let header = self.table.resolve(&index); let header = self.table.resolve(&index);
assert!(!header.is_sensitive()); assert!(!header.is_sensitive());
encode_int(idx, 6, 0b01000000, dst)?; encode_int(idx, 6, 0b0100_0000, dst)?;
encode_str(header.value_slice(), dst)?; encode_str(header.value_slice(), dst)?;
}, }
Index::NotIndexed(_) => { Index::NotIndexed(_) => {
let header = self.table.resolve(&index); let header = self.table.resolve(&index);
@@ -214,7 +215,7 @@ impl Encoder {
header.is_sensitive(), header.is_sensitive(),
dst, dst,
)?; )?;
}, }
} }
Ok(()) Ok(())
@@ -227,14 +228,14 @@ impl Encoder {
dst: &mut BytesMut, dst: &mut BytesMut,
) -> Result<(), EncoderError> { ) -> Result<(), EncoderError> {
match *last { match *last {
Index::Indexed(..) | Index::Indexed(..)
Index::Name(..) | | Index::Name(..)
Index::Inserted(..) | | Index::Inserted(..)
Index::InsertedValue(..) => { | Index::InsertedValue(..) => {
let idx = self.table.resolve_idx(last); let idx = self.table.resolve_idx(last);
encode_not_indexed(idx, value.as_ref(), value.is_sensitive(), dst)?; encode_not_indexed(idx, value.as_ref(), value.is_sensitive(), dst)?;
}, }
Index::NotIndexed(_) => { Index::NotIndexed(_) => {
let last = self.table.resolve(last); let last = self.table.resolve(last);
@@ -244,7 +245,7 @@ impl Encoder {
value.is_sensitive(), value.is_sensitive(),
dst, dst,
)?; )?;
}, }
} }
Ok(()) Ok(())
@@ -258,7 +259,7 @@ impl Default for Encoder {
} }
fn encode_size_update<B: BufMut>(val: usize, dst: &mut B) -> Result<(), EncoderError> { fn encode_size_update<B: BufMut>(val: usize, dst: &mut B) -> Result<(), EncoderError> {
encode_int(val, 5, 0b00100000, dst) encode_int(val, 5, 0b0010_0000, dst)
} }
fn encode_not_indexed( fn encode_not_indexed(
@@ -305,7 +306,7 @@ fn encode_str(val: &[u8], dst: &mut BytesMut) -> Result<(), EncoderError> {
return Err(EncoderError::BufferOverflow); return Err(EncoderError::BufferOverflow);
} }
if val.len() != 0 { if !val.is_empty() {
let idx = dst.len(); let idx = dst.len();
// Push a placeholder byte for the length header // Push a placeholder byte for the length header
@@ -378,7 +379,7 @@ fn encode_int<B: BufMut>(
value -= low; value -= low;
if value > 0x0fffffff { if value > 0x0fff_ffff {
panic!("value out of range"); panic!("value out of range");
} }
@@ -390,10 +391,10 @@ fn encode_int<B: BufMut>(
return Err(EncoderError::BufferOverflow); return Err(EncoderError::BufferOverflow);
} }
dst.put_u8(0b10000000 | value as u8); dst.put_u8(0b1000_0000 | value as u8);
rem -= 1; rem -= 1;
value = value >> 7; value >>= 7;
} }
if rem == 0 { if rem == 0 {
@@ -560,7 +561,7 @@ mod test {
let header = Header::Field { let header = Header::Field {
name: Some(name), name: Some(name),
value: value, value,
}; };
// Now, try to encode the sensitive header // Now, try to encode the sensitive header
@@ -580,7 +581,7 @@ mod test {
let header = Header::Field { let header = Header::Field {
name: Some(name), name: Some(name),
value: value, value,
}; };
let mut encoder = Encoder::default(); let mut encoder = Encoder::default();
@@ -604,7 +605,7 @@ mod test {
let header = Header::Field { let header = Header::Field {
name: Some(name), name: Some(name),
value: value, value,
}; };
let res = encode(&mut encoder, vec![header]); let res = encode(&mut encoder, vec![header]);
@@ -808,7 +809,8 @@ mod test {
name: None, name: None,
value: HeaderValue::from_bytes(b"sup").unwrap(), value: HeaderValue::from_bytes(b"sup").unwrap(),
}, },
].into_iter(); ]
.into_iter();
let resume = match encoder.encode(None, &mut input, &mut dst) { let resume = match encoder.encode(None, &mut input, &mut dst) {
Encode::Partial(r) => r, Encode::Partial(r) => r,
@@ -823,7 +825,7 @@ mod test {
dst.clear(); dst.clear();
match encoder.encode(Some(resume), &mut input, &mut dst) { match encoder.encode(Some(resume), &mut input, &mut dst) {
Encode::Full => {}, Encode::Full => {}
unexpected => panic!("resume returned unexpected: {:?}", unexpected), unexpected => panic!("resume returned unexpected: {:?}", unexpected),
} }
@@ -856,7 +858,7 @@ mod test {
Header::Field { Header::Field {
name: Some(name), name: Some(name),
value: value, value,
} }
} }

View File

@@ -1,8 +1,8 @@
use super::{DecoderError, NeedMore}; use super::{DecoderError, NeedMore};
use bytes::Bytes; use bytes::Bytes;
use http::{Method, StatusCode};
use http::header::{HeaderName, HeaderValue}; use http::header::{HeaderName, HeaderValue};
use http::{Method, StatusCode};
use string::{String, TryFrom}; use string::{String, TryFrom};
/// HTTP/2.0 Header /// HTTP/2.0 Header
@@ -41,14 +41,8 @@ impl Header<Option<HeaderName>> {
Field { Field {
name: Some(n), name: Some(n),
value, value,
} => Field { } => Field { name: n, value },
name: n, Field { name: None, value } => return Err(value),
value: value,
},
Field {
name: None,
value,
} => return Err(value),
Authority(v) => Authority(v), Authority(v) => Authority(v),
Method(v) => Method(v), Method(v) => Method(v),
Scheme(v) => Scheme(v), Scheme(v) => Scheme(v),
@@ -60,7 +54,7 @@ impl Header<Option<HeaderName>> {
impl Header { impl Header {
pub fn new(name: Bytes, value: Bytes) -> Result<Header, DecoderError> { pub fn new(name: Bytes, value: Bytes) -> Result<Header, DecoderError> {
if name.len() == 0 { if name.is_empty() {
return Err(DecoderError::NeedMore(NeedMore::UnexpectedEndOfStream)); return Err(DecoderError::NeedMore(NeedMore::UnexpectedEndOfStream));
} }
if name[0] == b':' { if name[0] == b':' {
@@ -68,23 +62,23 @@ impl Header {
b"authority" => { b"authority" => {
let value = String::try_from(value)?; let value = String::try_from(value)?;
Ok(Header::Authority(value)) Ok(Header::Authority(value))
}, }
b"method" => { b"method" => {
let method = Method::from_bytes(&value)?; let method = Method::from_bytes(&value)?;
Ok(Header::Method(method)) Ok(Header::Method(method))
}, }
b"scheme" => { b"scheme" => {
let value = String::try_from(value)?; let value = String::try_from(value)?;
Ok(Header::Scheme(value)) Ok(Header::Scheme(value))
}, }
b"path" => { b"path" => {
let value = String::try_from(value)?; let value = String::try_from(value)?;
Ok(Header::Path(value)) Ok(Header::Path(value))
}, }
b"status" => { b"status" => {
let status = StatusCode::from_bytes(&value)?; let status = StatusCode::from_bytes(&value)?;
Ok(Header::Status(status)) Ok(Header::Status(status))
}, }
_ => Err(DecoderError::InvalidPseudoheader), _ => Err(DecoderError::InvalidPseudoheader),
} }
} else { } else {
@@ -92,10 +86,7 @@ impl Header {
let name = HeaderName::from_lowercase(&name)?; let name = HeaderName::from_lowercase(&name)?;
let value = HeaderValue::from_bytes(&value)?; let value = HeaderValue::from_bytes(&value)?;
Ok(Header::Field { Ok(Header::Field { name, value })
name: name,
value: value,
})
} }
} }
@@ -116,9 +107,7 @@ impl Header {
/// Returns the header name /// Returns the header name
pub fn name(&self) -> Name { pub fn name(&self) -> Name {
match *self { match *self {
Header::Field { Header::Field { ref name, .. } => Name::Field(name),
ref name, ..
} => Name::Field(name),
Header::Authority(..) => Name::Authority, Header::Authority(..) => Name::Authority,
Header::Method(..) => Name::Method, Header::Method(..) => Name::Method,
Header::Scheme(..) => Name::Scheme, Header::Scheme(..) => Name::Scheme,
@@ -129,9 +118,7 @@ impl Header {
pub fn value_slice(&self) -> &[u8] { pub fn value_slice(&self) -> &[u8] {
match *self { match *self {
Header::Field { Header::Field { ref value, .. } => value.as_ref(),
ref value, ..
} => value.as_ref(),
Header::Authority(ref v) => v.as_ref(), Header::Authority(ref v) => v.as_ref(),
Header::Method(ref v) => v.as_ref().as_ref(), Header::Method(ref v) => v.as_ref().as_ref(),
Header::Scheme(ref v) => v.as_ref(), Header::Scheme(ref v) => v.as_ref(),
@@ -142,17 +129,13 @@ impl Header {
pub fn value_eq(&self, other: &Header) -> bool { pub fn value_eq(&self, other: &Header) -> bool {
match *self { match *self {
Header::Field { Header::Field { ref value, .. } => {
ref value, ..
} => {
let a = value; let a = value;
match *other { match *other {
Header::Field { Header::Field { ref value, .. } => a == value,
ref value, ..
} => a == value,
_ => false, _ => false,
} }
}, }
Header::Authority(ref a) => match *other { Header::Authority(ref a) => match *other {
Header::Authority(ref b) => a == b, Header::Authority(ref b) => a == b,
_ => false, _ => false,
@@ -178,9 +161,7 @@ impl Header {
pub fn is_sensitive(&self) -> bool { pub fn is_sensitive(&self) -> bool {
match *self { match *self {
Header::Field { Header::Field { ref value, .. } => value.is_sensitive(),
ref value, ..
} => value.is_sensitive(),
// TODO: Technically these other header values can be sensitive too. // TODO: Technically these other header values can be sensitive too.
_ => false, _ => false,
} }
@@ -190,18 +171,16 @@ impl Header {
use http::header; use http::header;
match *self { match *self {
Header::Field { Header::Field { ref name, .. } => match *name {
ref name, .. header::AGE
} => match *name { | header::AUTHORIZATION
header::AGE | | header::CONTENT_LENGTH
header::AUTHORIZATION | | header::ETAG
header::CONTENT_LENGTH | | header::IF_MODIFIED_SINCE
header::ETAG | | header::IF_NONE_MATCH
header::IF_MODIFIED_SINCE | | header::LOCATION
header::IF_NONE_MATCH | | header::COOKIE
header::LOCATION | | header::SET_COOKIE => true,
header::COOKIE |
header::SET_COOKIE => true,
_ => false, _ => false,
}, },
Header::Path(..) => true, Header::Path(..) => true,
@@ -214,10 +193,7 @@ impl Header {
impl From<Header> for Header<Option<HeaderName>> { impl From<Header> for Header<Option<HeaderName>> {
fn from(src: Header) -> Self { fn from(src: Header) -> Self {
match src { match src {
Header::Field { Header::Field { name, value } => Header::Field {
name,
value,
} => Header::Field {
name: Some(name), name: Some(name),
value, value,
}, },
@@ -247,7 +223,7 @@ impl<'a> Name<'a> {
// TODO: better error handling // TODO: better error handling
Err(_) => Err(DecoderError::InvalidStatusCode), Err(_) => Err(DecoderError::InvalidStatusCode),
} }
}, }
} }
} }

View File

@@ -3,37 +3,37 @@
// (num-bits, bits) // (num-bits, bits)
pub const ENCODE_TABLE: [(usize, u64); 257] = [ pub const ENCODE_TABLE: [(usize, u64); 257] = [
(13, 0x1ff8), (13, 0x1ff8),
(23, 0x7fffd8), (23, 0x007f_ffd8),
(28, 0xfffffe2), (28, 0x0fff_ffe2),
(28, 0xfffffe3), (28, 0x0fff_ffe3),
(28, 0xfffffe4), (28, 0x0fff_ffe4),
(28, 0xfffffe5), (28, 0x0fff_ffe5),
(28, 0xfffffe6), (28, 0x0fff_ffe6),
(28, 0xfffffe7), (28, 0x0fff_ffe7),
(28, 0xfffffe8), (28, 0x0fff_ffe8),
(24, 0xffffea), (24, 0x00ff_ffea),
(30, 0x3ffffffc), (30, 0x3fff_fffc),
(28, 0xfffffe9), (28, 0x0fff_ffe9),
(28, 0xfffffea), (28, 0x0fff_ffea),
(30, 0x3ffffffd), (30, 0x3fff_fffd),
(28, 0xfffffeb), (28, 0x0fff_ffeb),
(28, 0xfffffec), (28, 0x0fff_ffec),
(28, 0xfffffed), (28, 0x0fff_ffed),
(28, 0xfffffee), (28, 0x0fff_ffee),
(28, 0xfffffef), (28, 0x0fff_ffef),
(28, 0xffffff0), (28, 0x0fff_fff0),
(28, 0xffffff1), (28, 0x0fff_fff1),
(28, 0xffffff2), (28, 0x0fff_fff2),
(30, 0x3ffffffe), (30, 0x3fff_fffe),
(28, 0xffffff3), (28, 0x0fff_fff3),
(28, 0xffffff4), (28, 0x0fff_fff4),
(28, 0xffffff5), (28, 0x0fff_fff5),
(28, 0xffffff6), (28, 0x0fff_fff6),
(28, 0xffffff7), (28, 0x0fff_fff7),
(28, 0xffffff8), (28, 0x0fff_fff8),
(28, 0xffffff9), (28, 0x0fff_fff9),
(28, 0xffffffa), (28, 0x0fff_fffa),
(28, 0xffffffb), (28, 0x0fff_fffb),
(6, 0x14), (6, 0x14),
(10, 0x3f8), (10, 0x3f8),
(10, 0x3f9), (10, 0x3f9),
@@ -129,136 +129,136 @@ pub const ENCODE_TABLE: [(usize, u64); 257] = [
(11, 0x7fc), (11, 0x7fc),
(14, 0x3ffd), (14, 0x3ffd),
(13, 0x1ffd), (13, 0x1ffd),
(28, 0xffffffc), (28, 0x0fff_fffc),
(20, 0xfffe6), (20, 0xfffe6),
(22, 0x3fffd2), (22, 0x003f_ffd2),
(20, 0xfffe7), (20, 0xfffe7),
(20, 0xfffe8), (20, 0xfffe8),
(22, 0x3fffd3), (22, 0x003f_ffd3),
(22, 0x3fffd4), (22, 0x003f_ffd4),
(22, 0x3fffd5), (22, 0x003f_ffd5),
(23, 0x7fffd9), (23, 0x007f_ffd9),
(22, 0x3fffd6), (22, 0x003f_ffd6),
(23, 0x7fffda), (23, 0x007f_ffda),
(23, 0x7fffdb), (23, 0x007f_ffdb),
(23, 0x7fffdc), (23, 0x007f_ffdc),
(23, 0x7fffdd), (23, 0x007f_ffdd),
(23, 0x7fffde), (23, 0x007f_ffde),
(24, 0xffffeb), (24, 0x00ff_ffeb),
(23, 0x7fffdf), (23, 0x007f_ffdf),
(24, 0xffffec), (24, 0x00ff_ffec),
(24, 0xffffed), (24, 0x00ff_ffed),
(22, 0x3fffd7), (22, 0x003f_ffd7),
(23, 0x7fffe0), (23, 0x007f_ffe0),
(24, 0xffffee), (24, 0x00ff_ffee),
(23, 0x7fffe1), (23, 0x007f_ffe1),
(23, 0x7fffe2), (23, 0x007f_ffe2),
(23, 0x7fffe3), (23, 0x007f_ffe3),
(23, 0x7fffe4), (23, 0x007f_ffe4),
(21, 0x1fffdc), (21, 0x001f_ffdc),
(22, 0x3fffd8), (22, 0x003f_ffd8),
(23, 0x7fffe5), (23, 0x007f_ffe5),
(22, 0x3fffd9), (22, 0x003f_ffd9),
(23, 0x7fffe6), (23, 0x007f_ffe6),
(23, 0x7fffe7), (23, 0x007f_ffe7),
(24, 0xffffef), (24, 0x00ff_ffef),
(22, 0x3fffda), (22, 0x003f_ffda),
(21, 0x1fffdd), (21, 0x001f_ffdd),
(20, 0xfffe9), (20, 0xfffe9),
(22, 0x3fffdb), (22, 0x003f_ffdb),
(22, 0x3fffdc), (22, 0x003f_ffdc),
(23, 0x7fffe8), (23, 0x007f_ffe8),
(23, 0x7fffe9), (23, 0x007f_ffe9),
(21, 0x1fffde), (21, 0x001f_ffde),
(23, 0x7fffea), (23, 0x007f_ffea),
(22, 0x3fffdd), (22, 0x003f_ffdd),
(22, 0x3fffde), (22, 0x003f_ffde),
(24, 0xfffff0), (24, 0x00ff_fff0),
(21, 0x1fffdf), (21, 0x001f_ffdf),
(22, 0x3fffdf), (22, 0x003f_ffdf),
(23, 0x7fffeb), (23, 0x007f_ffeb),
(23, 0x7fffec), (23, 0x007f_ffec),
(21, 0x1fffe0), (21, 0x001f_ffe0),
(21, 0x1fffe1), (21, 0x001f_ffe1),
(22, 0x3fffe0), (22, 0x003f_ffe0),
(21, 0x1fffe2), (21, 0x001f_ffe2),
(23, 0x7fffed), (23, 0x007f_ffed),
(22, 0x3fffe1), (22, 0x003f_ffe1),
(23, 0x7fffee), (23, 0x007f_ffee),
(23, 0x7fffef), (23, 0x007f_ffef),
(20, 0xfffea), (20, 0xfffea),
(22, 0x3fffe2), (22, 0x003f_ffe2),
(22, 0x3fffe3), (22, 0x003f_ffe3),
(22, 0x3fffe4), (22, 0x003f_ffe4),
(23, 0x7ffff0), (23, 0x007f_fff0),
(22, 0x3fffe5), (22, 0x003f_ffe5),
(22, 0x3fffe6), (22, 0x003f_ffe6),
(23, 0x7ffff1), (23, 0x007f_fff1),
(26, 0x3ffffe0), (26, 0x03ff_ffe0),
(26, 0x3ffffe1), (26, 0x03ff_ffe1),
(20, 0xfffeb), (20, 0xfffeb),
(19, 0x7fff1), (19, 0x7fff1),
(22, 0x3fffe7), (22, 0x003f_ffe7),
(23, 0x7ffff2), (23, 0x007f_fff2),
(22, 0x3fffe8), (22, 0x003f_ffe8),
(25, 0x1ffffec), (25, 0x01ff_ffec),
(26, 0x3ffffe2), (26, 0x03ff_ffe2),
(26, 0x3ffffe3), (26, 0x03ff_ffe3),
(26, 0x3ffffe4), (26, 0x03ff_ffe4),
(27, 0x7ffffde), (27, 0x07ff_ffde),
(27, 0x7ffffdf), (27, 0x07ff_ffdf),
(26, 0x3ffffe5), (26, 0x03ff_ffe5),
(24, 0xfffff1), (24, 0x00ff_fff1),
(25, 0x1ffffed), (25, 0x01ff_ffed),
(19, 0x7fff2), (19, 0x7fff2),
(21, 0x1fffe3), (21, 0x001f_ffe3),
(26, 0x3ffffe6), (26, 0x03ff_ffe6),
(27, 0x7ffffe0), (27, 0x07ff_ffe0),
(27, 0x7ffffe1), (27, 0x07ff_ffe1),
(26, 0x3ffffe7), (26, 0x03ff_ffe7),
(27, 0x7ffffe2), (27, 0x07ff_ffe2),
(24, 0xfffff2), (24, 0x00ff_fff2),
(21, 0x1fffe4), (21, 0x001f_ffe4),
(21, 0x1fffe5), (21, 0x001f_ffe5),
(26, 0x3ffffe8), (26, 0x03ff_ffe8),
(26, 0x3ffffe9), (26, 0x03ff_ffe9),
(28, 0xffffffd), (28, 0x0fff_fffd),
(27, 0x7ffffe3), (27, 0x07ff_ffe3),
(27, 0x7ffffe4), (27, 0x07ff_ffe4),
(27, 0x7ffffe5), (27, 0x07ff_ffe5),
(20, 0xfffec), (20, 0xfffec),
(24, 0xfffff3), (24, 0x00ff_fff3),
(20, 0xfffed), (20, 0xfffed),
(21, 0x1fffe6), (21, 0x001f_ffe6),
(22, 0x3fffe9), (22, 0x003f_ffe9),
(21, 0x1fffe7), (21, 0x001f_ffe7),
(21, 0x1fffe8), (21, 0x001f_ffe8),
(23, 0x7ffff3), (23, 0x007f_fff3),
(22, 0x3fffea), (22, 0x003f_ffea),
(22, 0x3fffeb), (22, 0x003f_ffeb),
(25, 0x1ffffee), (25, 0x01ff_ffee),
(25, 0x1ffffef), (25, 0x01ff_ffef),
(24, 0xfffff4), (24, 0x00ff_fff4),
(24, 0xfffff5), (24, 0x00ff_fff5),
(26, 0x3ffffea), (26, 0x03ff_ffea),
(23, 0x7ffff4), (23, 0x007f_fff4),
(26, 0x3ffffeb), (26, 0x03ff_ffeb),
(27, 0x7ffffe6), (27, 0x07ff_ffe6),
(26, 0x3ffffec), (26, 0x03ff_ffec),
(26, 0x3ffffed), (26, 0x03ff_ffed),
(27, 0x7ffffe7), (27, 0x07ff_ffe7),
(27, 0x7ffffe8), (27, 0x07ff_ffe8),
(27, 0x7ffffe9), (27, 0x07ff_ffe9),
(27, 0x7ffffea), (27, 0x07ff_ffea),
(27, 0x7ffffeb), (27, 0x07ff_ffeb),
(28, 0xffffffe), (28, 0x0fff_fffe),
(27, 0x7ffffec), (27, 0x07ff_ffec),
(27, 0x7ffffed), (27, 0x07ff_ffed),
(27, 0x7ffffee), (27, 0x07ff_ffee),
(27, 0x7ffffef), (27, 0x07ff_ffef),
(27, 0x7fffff0), (27, 0x07ff_fff0),
(26, 0x3ffffee), (26, 0x03ff_ffee),
(30, 0x3fffffff), (30, 0x3fff_ffff),
]; ];
// (next-state, byte, flags) // (next-state, byte, flags)

View File

@@ -1,5 +1,5 @@
mod encoder;
mod decoder; mod decoder;
mod encoder;
pub(crate) mod header; pub(crate) mod header;
mod huffman; mod huffman;
mod table; mod table;

View File

@@ -4,9 +4,9 @@ use fnv::FnvHasher;
use http::header; use http::header;
use http::method::Method; use http::method::Method;
use std::{cmp, mem, usize};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::{cmp, mem, usize};
/// HPACK encoder table /// HPACK encoder table
#[derive(Debug)] #[derive(Debug)]
@@ -80,7 +80,7 @@ impl Table {
slots: VecDeque::new(), slots: VecDeque::new(),
inserted: 0, inserted: 0,
size: 0, size: 0,
max_size: max_size, max_size,
} }
} else { } else {
let capacity = cmp::max(to_raw_capacity(capacity).next_power_of_two(), 8); let capacity = cmp::max(to_raw_capacity(capacity).next_power_of_two(), 8);
@@ -91,7 +91,7 @@ impl Table {
slots: VecDeque::with_capacity(usable_capacity(capacity)), slots: VecDeque::with_capacity(usable_capacity(capacity)),
inserted: 0, inserted: 0,
size: 0, size: 0,
max_size: max_size, max_size,
} }
} }
} }
@@ -140,10 +140,7 @@ impl Table {
// Right now, if this is true, the header name is always in the // Right now, if this is true, the header name is always in the
// static table. At some point in the future, this might not be true // static table. At some point in the future, this might not be true
// and this logic will need to be updated. // and this logic will need to be updated.
debug_assert!( debug_assert!(statik.is_some(), "skip_value_index requires a static name",);
statik.is_some(),
"skip_value_index requires a static name",
);
return Index::new(statik, header); return Index::new(statik, header);
} }
@@ -313,7 +310,7 @@ impl Table {
&mut self.indices[probe], &mut self.indices[probe],
Some(Pos { Some(Pos {
index: pos_idx, index: pos_idx,
hash: hash, hash,
}), }),
); );
@@ -344,8 +341,8 @@ impl Table {
self.inserted = self.inserted.wrapping_add(1); self.inserted = self.inserted.wrapping_add(1);
self.slots.push_front(Slot { self.slots.push_front(Slot {
hash: hash, hash,
header: header, header,
next: None, next: None,
}); });
} }
@@ -534,89 +531,89 @@ impl Table {
#[cfg(test)] #[cfg(test)]
fn assert_valid_state(&self, _msg: &'static str) -> bool { fn assert_valid_state(&self, _msg: &'static str) -> bool {
/* /*
// Checks that the internal map structure is valid // Checks that the internal map structure is valid
// //
// Ensure all hash codes in indices match the associated slot // Ensure all hash codes in indices match the associated slot
for pos in &self.indices { for pos in &self.indices {
if let Some(pos) = *pos {
let real_idx = pos.index.wrapping_add(self.inserted);
if real_idx.wrapping_add(1) != 0 {
assert!(real_idx < self.slots.len(),
"out of index; real={}; len={}, msg={}",
real_idx, self.slots.len(), msg);
assert_eq!(pos.hash, self.slots[real_idx].hash,
"index hash does not match slot; msg={}", msg);
}
}
}
// Every index is only available once
for i in 0..self.indices.len() {
if self.indices[i].is_none() {
continue;
}
for j in i+1..self.indices.len() {
assert_ne!(self.indices[i], self.indices[j],
"duplicate indices; msg={}", msg);
}
}
for (index, slot) in self.slots.iter().enumerate() {
let mut indexed = None;
// First, see if the slot is indexed
for (i, pos) in self.indices.iter().enumerate() {
if let Some(pos) = *pos { if let Some(pos) = *pos {
let real_idx = pos.index.wrapping_add(self.inserted); let real_idx = pos.index.wrapping_add(self.inserted);
if real_idx == index {
indexed = Some(i); if real_idx.wrapping_add(1) != 0 {
// Already know that there is no dup, so break assert!(real_idx < self.slots.len(),
break; "out of index; real={}; len={}, msg={}",
real_idx, self.slots.len(), msg);
assert_eq!(pos.hash, self.slots[real_idx].hash,
"index hash does not match slot; msg={}", msg);
} }
} }
} }
if let Some(actual) = indexed { // Every index is only available once
// Ensure that it is accessible.. for i in 0..self.indices.len() {
let desired = desired_pos(self.mask, slot.hash); if self.indices[i].is_none() {
let mut probe = desired; continue;
let mut dist = 0; }
probe_loop!(probe < self.indices.len(), { for j in i+1..self.indices.len() {
assert!(self.indices[probe].is_some(), assert_ne!(self.indices[i], self.indices[j],
"unexpected empty slot; probe={}; hash={:?}; msg={}", "duplicate indices; msg={}", msg);
probe, slot.hash, msg); }
let pos = self.indices[probe].unwrap();
let their_dist = probe_distance(self.mask, pos.hash, probe);
let real_idx = pos.index.wrapping_add(self.inserted);
if real_idx == index {
break;
}
assert!(dist <= their_dist,
"could not find entry; actual={}; desired={};" +
"probe={}, dist={}; their_dist={}; index={}; msg={}",
actual, desired, probe, dist, their_dist,
index.wrapping_sub(self.inserted), msg);
dist += 1;
});
} else {
// There is exactly one next link
let cnt = self.slots.iter().map(|s| s.next)
.filter(|n| *n == Some(index.wrapping_sub(self.inserted)))
.count();
assert_eq!(1, cnt, "more than one node pointing here; msg={}", msg);
} }
}
*/ for (index, slot) in self.slots.iter().enumerate() {
let mut indexed = None;
// First, see if the slot is indexed
for (i, pos) in self.indices.iter().enumerate() {
if let Some(pos) = *pos {
let real_idx = pos.index.wrapping_add(self.inserted);
if real_idx == index {
indexed = Some(i);
// Already know that there is no dup, so break
break;
}
}
}
if let Some(actual) = indexed {
// Ensure that it is accessible..
let desired = desired_pos(self.mask, slot.hash);
let mut probe = desired;
let mut dist = 0;
probe_loop!(probe < self.indices.len(), {
assert!(self.indices[probe].is_some(),
"unexpected empty slot; probe={}; hash={:?}; msg={}",
probe, slot.hash, msg);
let pos = self.indices[probe].unwrap();
let their_dist = probe_distance(self.mask, pos.hash, probe);
let real_idx = pos.index.wrapping_add(self.inserted);
if real_idx == index {
break;
}
assert!(dist <= their_dist,
"could not find entry; actual={}; desired={};" +
"probe={}, dist={}; their_dist={}; index={}; msg={}",
actual, desired, probe, dist, their_dist,
index.wrapping_sub(self.inserted), msg);
dist += 1;
});
} else {
// There is exactly one next link
let cnt = self.slots.iter().map(|s| s.next)
.filter(|n| *n == Some(index.wrapping_sub(self.inserted)))
.count();
assert_eq!(1, cnt, "more than one node pointing here; msg={}", msg);
}
}
*/
// TODO: Ensure linked lists are correct: no cycles, etc... // TODO: Ensure linked lists are correct: no cycles, etc...
@@ -684,11 +681,13 @@ fn index_static(header: &Header) -> Option<(usize, bool)> {
ref value, ref value,
} => match *name { } => match *name {
header::ACCEPT_CHARSET => Some((15, false)), header::ACCEPT_CHARSET => Some((15, false)),
header::ACCEPT_ENCODING => if value == "gzip, deflate" { header::ACCEPT_ENCODING => {
Some((16, true)) if value == "gzip, deflate" {
} else { Some((16, true))
Some((16, false)) } else {
}, Some((16, false))
}
}
header::ACCEPT_LANGUAGE => Some((17, false)), header::ACCEPT_LANGUAGE => Some((17, false)),
header::ACCEPT_RANGES => Some((18, false)), header::ACCEPT_RANGES => Some((18, false)),
header::ACCEPT => Some((19, false)), header::ACCEPT => Some((19, false)),

View File

@@ -5,8 +5,8 @@ use hex::FromHex;
use serde_json::Value; use serde_json::Value;
use std::fs::File; use std::fs::File;
use std::io::Cursor;
use std::io::prelude::*; use std::io::prelude::*;
use std::io::Cursor;
use std::path::Path; use std::path::Path;
use std::str; use std::str;
@@ -30,13 +30,15 @@ fn test_story(story: Value) {
.map(|case| { .map(|case| {
let case = case.as_object().unwrap(); let case = case.as_object().unwrap();
let size = case.get("header_table_size") let size = case
.get("header_table_size")
.map(|v| v.as_u64().unwrap() as usize); .map(|v| v.as_u64().unwrap() as usize);
let wire = case.get("wire").unwrap().as_str().unwrap(); let wire = case.get("wire").unwrap().as_str().unwrap();
let wire: Vec<u8> = FromHex::from_hex(wire.as_bytes()).unwrap(); let wire: Vec<u8> = FromHex::from_hex(wire.as_bytes()).unwrap();
let expect: Vec<_> = case.get("headers") let expect: Vec<_> = case
.get("headers")
.unwrap() .unwrap()
.as_array() .as_array()
.unwrap() .unwrap()
@@ -92,7 +94,8 @@ fn test_story(story: Value) {
decoder.queue_size_update(size); decoder.queue_size_update(size);
} }
let mut input: Vec<_> = case.expect let mut input: Vec<_> = case
.expect
.iter() .iter()
.map(|&(ref name, ref value)| { .map(|&(ref name, ref value)| {
Header::new(name.clone().into(), value.clone().into()) Header::new(name.clone().into(), value.clone().into())
@@ -123,9 +126,7 @@ struct Case {
fn key_str(e: &Header) -> &str { fn key_str(e: &Header) -> &str {
match *e { match *e {
Header::Field { Header::Field { ref name, .. } => name.as_str(),
ref name, ..
} => name.as_str(),
Header::Authority(..) => ":authority", Header::Authority(..) => ":authority",
Header::Method(..) => ":method", Header::Method(..) => ":method",
Header::Scheme(..) => ":scheme", Header::Scheme(..) => ":scheme",
@@ -136,9 +137,7 @@ fn key_str(e: &Header) -> &str {
fn value_str(e: &Header) -> &str { fn value_str(e: &Header) -> &str {
match *e { match *e {
Header::Field { Header::Field { ref value, .. } => value.to_str().unwrap(),
ref value, ..
} => value.to_str().unwrap(),
Header::Authority(ref v) => &**v, Header::Authority(ref v) => &**v,
Header::Method(ref m) => m.as_str(), Header::Method(ref m) => m.as_str(),
Header::Scheme(ref v) => &**v, Header::Scheme(ref v) => &**v,

View File

@@ -78,17 +78,16 @@ impl FuzzHpack {
let low = rng.gen_range(0, high); let low = rng.gen_range(0, high);
frame.resizes.extend(&[low, high]); frame.resizes.extend(&[low, high]);
}, }
1..=3 => { 1..=3 => {
frame.resizes.push(rng.gen_range(128, MAX_CHUNK * 2)); frame.resizes.push(rng.gen_range(128, MAX_CHUNK * 2));
}, }
_ => {}, _ => {}
} }
let mut is_name_required = true; let mut is_name_required = true;
for _ in 0..rng.gen_range(1, (num - added) + 1) { for _ in 0..rng.gen_range(1, (num - added) + 1) {
let x: f64 = rng.gen_range(0.0, 1.0); let x: f64 = rng.gen_range(0.0, 1.0);
let x = x.powi(skew); let x = x.powi(skew);
@@ -100,10 +99,10 @@ impl FuzzHpack {
if is_name_required { if is_name_required {
continue; continue;
} }
}, }
Header::Field { .. } => { Header::Field { .. } => {
is_name_required = false; is_name_required = false;
}, }
_ => { _ => {
// pseudos can't be followed by a header with no name // pseudos can't be followed by a header with no name
is_name_required = true; is_name_required = true;
@@ -153,7 +152,7 @@ impl FuzzHpack {
_ => None, _ => None,
}; };
expect.push(h); expect.push(h);
}, }
Err(value) => { Err(value) => {
expect.push(Header::Field { expect.push(Header::Field {
name: prev_name.as_ref().cloned().expect("previous header name"), name: prev_name.as_ref().cloned().expect("previous header name"),
@@ -161,7 +160,6 @@ impl FuzzHpack {
}); });
} }
} }
} }
let mut input = frame.headers.into_iter(); let mut input = frame.headers.into_iter();
@@ -193,7 +191,7 @@ impl FuzzHpack {
.expect("partial decode"); .expect("partial decode");
buf = BytesMut::with_capacity(chunks.pop().unwrap_or(MAX_CHUNK)); buf = BytesMut::with_capacity(chunks.pop().unwrap_or(MAX_CHUNK));
}, }
} }
} }
@@ -224,7 +222,7 @@ fn gen_header(g: &mut StdRng) -> Header<Option<HeaderName>> {
0 => { 0 => {
let value = gen_string(g, 4, 20); let value = gen_string(g, 4, 20);
Header::Authority(to_shared(value)) Header::Authority(to_shared(value))
}, }
1 => { 1 => {
let method = match g.next_u32() % 6 { let method = match g.next_u32() % 6 {
0 => Method::GET, 0 => Method::GET,
@@ -239,12 +237,12 @@ fn gen_header(g: &mut StdRng) -> Header<Option<HeaderName>> {
.collect(); .collect();
Method::from_bytes(&bytes).unwrap() Method::from_bytes(&bytes).unwrap()
}, }
_ => unreachable!(), _ => unreachable!(),
}; };
Header::Method(method) Header::Method(method)
}, }
2 => { 2 => {
let value = match g.next_u32() % 2 { let value = match g.next_u32() % 2 {
0 => "http", 0 => "http",
@@ -253,7 +251,7 @@ fn gen_header(g: &mut StdRng) -> Header<Option<HeaderName>> {
}; };
Header::Scheme(to_shared(value.to_string())) Header::Scheme(to_shared(value.to_string()))
}, }
3 => { 3 => {
let value = match g.next_u32() % 100 { let value = match g.next_u32() % 100 {
0 => "/".to_string(), 0 => "/".to_string(),
@@ -262,12 +260,12 @@ fn gen_header(g: &mut StdRng) -> Header<Option<HeaderName>> {
}; };
Header::Path(to_shared(value)) Header::Path(to_shared(value))
}, }
4 => { 4 => {
let status = (g.gen::<u16>() % 500) + 100; let status = (g.gen::<u16>() % 500) + 100;
Header::Status(StatusCode::from_u16(status).unwrap()) Header::Status(StatusCode::from_u16(status).unwrap())
}, }
_ => unreachable!(), _ => unreachable!(),
} }
} else { } else {
@@ -282,10 +280,7 @@ fn gen_header(g: &mut StdRng) -> Header<Option<HeaderName>> {
value.set_sensitive(true); value.set_sensitive(true);
} }
Header::Field { Header::Field { name, value }
name,
value,
}
} }
} }
@@ -368,8 +363,9 @@ fn gen_header_name(g: &mut StdRng) -> HeaderName {
header::X_DNS_PREFETCH_CONTROL, header::X_DNS_PREFETCH_CONTROL,
header::X_FRAME_OPTIONS, header::X_FRAME_OPTIONS,
header::X_XSS_PROTECTION, header::X_XSS_PROTECTION,
]).unwrap() ])
.clone() .unwrap()
.clone()
} else { } else {
let value = gen_string(g, 1, 25); let value = gen_string(g, 1, 25);
HeaderName::from_bytes(value.as_bytes()).unwrap() HeaderName::from_bytes(value.as_bytes()).unwrap()

View File

@@ -96,11 +96,11 @@ where
Connection { Connection {
state: State::Open, state: State::Open,
error: None, error: None,
codec: codec, codec,
go_away: GoAway::new(), go_away: GoAway::new(),
ping_pong: PingPong::new(), ping_pong: PingPong::new(),
settings: Settings::new(), settings: Settings::new(),
streams: streams, streams,
_phantom: PhantomData, _phantom: PhantomData,
} }
} }
@@ -210,11 +210,11 @@ where
// This will also handle flushing `self.codec` // This will also handle flushing `self.codec`
ready!(self.streams.poll_complete(cx, &mut self.codec))?; ready!(self.streams.poll_complete(cx, &mut self.codec))?;
if self.error.is_some() || self.go_away.should_close_on_idle() { if (self.error.is_some() || self.go_away.should_close_on_idle())
if !self.streams.has_streams() { && !self.streams.has_streams()
self.go_away_now(Reason::NO_ERROR); {
continue; self.go_away_now(Reason::NO_ERROR);
} continue;
} }
return Poll::Pending; return Poll::Pending;
@@ -289,25 +289,22 @@ where
// The order here matters: // The order here matters:
// - poll_go_away may buffer a graceful shutdown GOAWAY frame // - poll_go_away may buffer a graceful shutdown GOAWAY frame
// - If it has, we've also added a PING to be sent in poll_ready // - If it has, we've also added a PING to be sent in poll_ready
match ready!(self.poll_go_away(cx)?) { if let Some(reason) = ready!(self.poll_go_away(cx)?) {
Some(reason) => { if self.go_away.should_close_now() {
if self.go_away.should_close_now() { if self.go_away.is_user_initiated() {
if self.go_away.is_user_initiated() { // A user initiated abrupt shutdown shouldn't return
// A user initiated abrupt shutdown shouldn't return // the same error back to the user.
// the same error back to the user. return Poll::Ready(Ok(()));
return Poll::Ready(Ok(())); } else {
} else { return Poll::Ready(Err(RecvError::Connection(reason)));
return Poll::Ready(Err(RecvError::Connection(reason)));
}
} }
// Only NO_ERROR should be waiting for idle
debug_assert_eq!(
reason,
Reason::NO_ERROR,
"graceful GOAWAY should be NO_ERROR"
);
} }
None => (), // Only NO_ERROR should be waiting for idle
debug_assert_eq!(
reason,
Reason::NO_ERROR,
"graceful GOAWAY should be NO_ERROR"
);
} }
ready!(self.poll_ready(cx))?; ready!(self.poll_ready(cx))?;
@@ -364,7 +361,7 @@ where
} }
None => { None => {
log::trace!("codec closed"); log::trace!("codec closed");
self.streams.recv_eof(false).ok().expect("mutex poisoned"); self.streams.recv_eof(false).expect("mutex poisoned");
return Poll::Ready(Ok(())); return Poll::Ready(Ok(()));
} }
} }

View File

@@ -137,7 +137,7 @@ impl GoAway {
} }
let reason = frame.reason(); let reason = frame.reason();
dst.buffer(frame.into()).ok().expect("invalid GOAWAY frame"); dst.buffer(frame.into()).expect("invalid GOAWAY frame");
return Poll::Ready(Some(Ok(reason))); return Poll::Ready(Some(Ok(reason)));
} else if self.should_close_now() { } else if self.should_close_now() {

View File

@@ -17,7 +17,9 @@ pub(crate) trait Peer {
fn is_server() -> bool; fn is_server() -> bool;
fn convert_poll_message( fn convert_poll_message(
pseudo: Pseudo, fields: HeaderMap, stream_id: StreamId pseudo: Pseudo,
fields: HeaderMap,
stream_id: StreamId,
) -> Result<Self::Poll, RecvError>; ) -> Result<Self::Poll, RecvError>;
fn is_local_init(id: StreamId) -> bool { fn is_local_init(id: StreamId) -> bool {
@@ -54,7 +56,10 @@ impl Dyn {
} }
pub fn convert_poll_message( pub fn convert_poll_message(
&self, pseudo: Pseudo, fields: HeaderMap, stream_id: StreamId &self,
pseudo: Pseudo,
fields: HeaderMap,
stream_id: StreamId,
) -> Result<PollMessage, RecvError> { ) -> Result<PollMessage, RecvError> {
if self.is_server() { if self.is_server() {
crate::server::Peer::convert_poll_message(pseudo, fields, stream_id) crate::server::Peer::convert_poll_message(pseudo, fields, stream_id)

View File

@@ -1,7 +1,7 @@
use crate::codec::RecvError; use crate::codec::RecvError;
use crate::frame; use crate::frame;
use crate::proto::*; use crate::proto::*;
use std::task::{Poll, Context}; use std::task::{Context, Poll};
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct Settings { pub(crate) struct Settings {
@@ -13,9 +13,7 @@ pub(crate) struct Settings {
impl Settings { impl Settings {
pub fn new() -> Self { pub fn new() -> Self {
Settings { Settings { pending: None }
pending: None,
}
} }
pub fn recv_settings(&mut self, frame: frame::Settings) { pub fn recv_settings(&mut self, frame: frame::Settings) {
@@ -52,9 +50,7 @@ impl Settings {
let frame = frame::Settings::ack(); let frame = frame::Settings::ack();
// Buffer the settings frame // Buffer the settings frame
dst.buffer(frame.into()) dst.buffer(frame.into()).expect("invalid settings frame");
.ok()
.expect("invalid settings frame");
log::trace!("ACK sent; applying settings"); log::trace!("ACK sent; applying settings");

View File

@@ -27,17 +27,13 @@ struct Slot<T> {
impl<T> Buffer<T> { impl<T> Buffer<T> {
pub fn new() -> Self { pub fn new() -> Self {
Buffer { Buffer { slab: Slab::new() }
slab: Slab::new(),
}
} }
} }
impl Deque { impl Deque {
pub fn new() -> Self { pub fn new() -> Self {
Deque { Deque { indices: None }
indices: None,
}
} }
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
@@ -45,42 +41,36 @@ impl Deque {
} }
pub fn push_back<T>(&mut self, buf: &mut Buffer<T>, value: T) { pub fn push_back<T>(&mut self, buf: &mut Buffer<T>, value: T) {
let key = buf.slab.insert(Slot { let key = buf.slab.insert(Slot { value, next: None });
value,
next: None,
});
match self.indices { match self.indices {
Some(ref mut idxs) => { Some(ref mut idxs) => {
buf.slab[idxs.tail].next = Some(key); buf.slab[idxs.tail].next = Some(key);
idxs.tail = key; idxs.tail = key;
}, }
None => { None => {
self.indices = Some(Indices { self.indices = Some(Indices {
head: key, head: key,
tail: key, tail: key,
}); });
}, }
} }
} }
pub fn push_front<T>(&mut self, buf: &mut Buffer<T>, value: T) { pub fn push_front<T>(&mut self, buf: &mut Buffer<T>, value: T) {
let key = buf.slab.insert(Slot { let key = buf.slab.insert(Slot { value, next: None });
value,
next: None,
});
match self.indices { match self.indices {
Some(ref mut idxs) => { Some(ref mut idxs) => {
buf.slab[key].next = Some(idxs.head); buf.slab[key].next = Some(idxs.head);
idxs.head = key; idxs.head = key;
}, }
None => { None => {
self.indices = Some(Indices { self.indices = Some(Indices {
head: key, head: key,
tail: key, tail: key,
}); });
}, }
} }
} }
@@ -97,8 +87,8 @@ impl Deque {
self.indices = Some(idxs); self.indices = Some(idxs);
} }
return Some(slot.value); Some(slot.value)
}, }
None => None, None => None,
} }
} }

View File

@@ -133,16 +133,18 @@ impl Counts {
// TODO: move this to macro? // TODO: move this to macro?
pub fn transition_after(&mut self, mut stream: store::Ptr, is_reset_counted: bool) { pub fn transition_after(&mut self, mut stream: store::Ptr, is_reset_counted: bool) {
log::trace!("transition_after; stream={:?}; state={:?}; is_closed={:?}; \ log::trace!(
pending_send_empty={:?}; buffered_send_data={}; \ "transition_after; stream={:?}; state={:?}; is_closed={:?}; \
num_recv={}; num_send={}", pending_send_empty={:?}; buffered_send_data={}; \
stream.id, num_recv={}; num_send={}",
stream.state, stream.id,
stream.is_closed(), stream.state,
stream.pending_send.is_empty(), stream.is_closed(),
stream.buffered_send_data, stream.pending_send.is_empty(),
self.num_recv_streams, stream.buffered_send_data,
self.num_send_streams); self.num_recv_streams,
self.num_send_streams
);
if stream.is_closed() { if stream.is_closed() {
if !stream.is_pending_reset_expiration() { if !stream.is_pending_reset_expiration() {

View File

@@ -200,7 +200,6 @@ impl PartialEq<WindowSize> for Window {
} }
} }
impl PartialEq<Window> for WindowSize { impl PartialEq<Window> for WindowSize {
fn eq(&self, other: &Window) -> bool { fn eq(&self, other: &Window) -> bool {
other.eq(self) other.eq(self)
@@ -227,7 +226,6 @@ impl PartialOrd<Window> for WindowSize {
} }
} }
impl ::std::ops::SubAssign<WindowSize> for Window { impl ::std::ops::SubAssign<WindowSize> for Window {
fn sub_assign(&mut self, other: WindowSize) { fn sub_assign(&mut self, other: WindowSize) {
self.0 -= other as i32; self.0 -= other as i32;

View File

@@ -12,7 +12,7 @@ mod streams;
pub(crate) use self::prioritize::Prioritized; pub(crate) use self::prioritize::Prioritized;
pub(crate) use self::recv::Open; pub(crate) use self::recv::Open;
pub(crate) use self::send::PollReset; pub(crate) use self::send::PollReset;
pub(crate) use self::streams::{StreamRef, OpaqueStreamRef, Streams}; pub(crate) use self::streams::{OpaqueStreamRef, StreamRef, Streams};
use self::buffer::Buffer; use self::buffer::Buffer;
use self::counts::Counts; use self::counts::Counts;

View File

@@ -1,5 +1,5 @@
use super::*;
use super::store::Resolve; use super::store::Resolve;
use super::*;
use crate::frame::{Reason, StreamId}; use crate::frame::{Reason, StreamId};
@@ -8,9 +8,9 @@ use crate::codec::UserError::*;
use bytes::buf::Take; use bytes::buf::Take;
use futures::ready; use futures::ready;
use std::{cmp, fmt, mem};
use std::io; use std::io;
use std::task::{Context, Poll, Waker}; use std::task::{Context, Poll, Waker};
use std::{cmp, fmt, mem};
/// # Warning /// # Warning
/// ///
@@ -81,7 +81,6 @@ impl Prioritize {
let mut flow = FlowControl::new(); let mut flow = FlowControl::new();
flow.inc_window(config.remote_init_window_sz) flow.inc_window(config.remote_init_window_sz)
.ok()
.expect("invalid initial window size"); .expect("invalid initial window size");
flow.assign_capacity(config.remote_init_window_sz); flow.assign_capacity(config.remote_init_window_sz);
@@ -92,7 +91,7 @@ impl Prioritize {
pending_send: store::Queue::new(), pending_send: store::Queue::new(),
pending_capacity: store::Queue::new(), pending_capacity: store::Queue::new(),
pending_open: store::Queue::new(), pending_open: store::Queue::new(),
flow: flow, flow,
last_opened_id: StreamId::ZERO, last_opened_id: StreamId::ZERO,
in_flight_data_frame: InFlightData::Nothing, in_flight_data_frame: InFlightData::Nothing,
} }
@@ -203,9 +202,7 @@ impl Prioritize {
// The stream has no capacity to send the frame now, save it but // The stream has no capacity to send the frame now, save it but
// don't notify the connection task. Once additional capacity // don't notify the connection task. Once additional capacity
// becomes available, the frame will be flushed. // becomes available, the frame will be flushed.
stream stream.pending_send.push_back(buffer, frame.into());
.pending_send
.push_back(buffer, frame.into());
} }
Ok(()) Ok(())
@@ -216,7 +213,8 @@ impl Prioritize {
&mut self, &mut self,
capacity: WindowSize, capacity: WindowSize,
stream: &mut store::Ptr, stream: &mut store::Ptr,
counts: &mut Counts) { counts: &mut Counts,
) {
log::trace!( log::trace!(
"reserve_capacity; stream={:?}; requested={:?}; effective={:?}; curr={:?}", "reserve_capacity; stream={:?}; requested={:?}; effective={:?}; curr={:?}",
stream.id, stream.id,
@@ -338,8 +336,8 @@ impl Prioritize {
&mut self, &mut self,
inc: WindowSize, inc: WindowSize,
store: &mut R, store: &mut R,
counts: &mut Counts) counts: &mut Counts,
where ) where
R: Resolve, R: Resolve,
{ {
log::trace!("assign_connection_capacity; inc={}", inc); log::trace!("assign_connection_capacity; inc={}", inc);
@@ -419,11 +417,7 @@ impl Prioritize {
// TODO: Should prioritization factor into this? // TODO: Should prioritization factor into this?
let assign = cmp::min(conn_available, additional); let assign = cmp::min(conn_available, additional);
log::trace!( log::trace!(" assigning; stream={:?}, capacity={}", stream.id, assign,);
" assigning; stream={:?}, capacity={}",
stream.id,
assign,
);
// Assign the capacity to the stream // Assign the capacity to the stream
stream.assign_capacity(assign); stream.assign_capacity(assign);
@@ -440,16 +434,16 @@ impl Prioritize {
stream.send_flow.has_unavailable() stream.send_flow.has_unavailable()
); );
if stream.send_flow.available() < stream.requested_send_capacity { if stream.send_flow.available() < stream.requested_send_capacity
if stream.send_flow.has_unavailable() { && stream.send_flow.has_unavailable()
// The stream requires additional capacity and the stream's {
// window has available capacity, but the connection window // The stream requires additional capacity and the stream's
// does not. // window has available capacity, but the connection window
// // does not.
// In this case, the stream needs to be queued up for when the //
// connection has more capacity. // In this case, the stream needs to be queued up for when the
self.pending_capacity.push(stream); // connection has more capacity.
} self.pending_capacity.push(stream);
} }
// If data is buffered and the stream is not pending open, then // If data is buffered and the stream is not pending open, then
@@ -515,26 +509,26 @@ impl Prioritize {
if let Frame::Data(ref frame) = frame { if let Frame::Data(ref frame) = frame {
self.in_flight_data_frame = InFlightData::DataFrame(frame.payload().stream); self.in_flight_data_frame = InFlightData::DataFrame(frame.payload().stream);
} }
dst.buffer(frame).ok().expect("invalid frame"); dst.buffer(frame).expect("invalid frame");
// Ensure the codec is ready to try the loop again. // Ensure the codec is ready to try the loop again.
ready!(dst.poll_ready(cx))?; ready!(dst.poll_ready(cx))?;
// Because, always try to reclaim... // Because, always try to reclaim...
self.reclaim_frame(buffer, store, dst); self.reclaim_frame(buffer, store, dst);
}, }
None => { None => {
// Try to flush the codec. // Try to flush the codec.
ready!(dst.flush(cx))?; ready!(dst.flush(cx))?;
// This might release a data frame... // This might release a data frame...
if !self.reclaim_frame(buffer, store, dst) { if !self.reclaim_frame(buffer, store, dst) {
return Poll::Ready(Ok(())) return Poll::Ready(Ok(()));
} }
// No need to poll ready as poll_complete() does this for // No need to poll ready as poll_complete() does this for
// us... // us...
}, }
} }
} }
} }
@@ -603,11 +597,12 @@ impl Prioritize {
/// Push the frame to the front of the stream's deque, scheduling the /// Push the frame to the front of the stream's deque, scheduling the
/// stream if needed. /// stream if needed.
fn push_back_frame<B>(&mut self, fn push_back_frame<B>(
frame: Frame<B>, &mut self,
buffer: &mut Buffer<Frame<B>>, frame: Frame<B>,
stream: &mut store::Ptr) buffer: &mut Buffer<Frame<B>>,
{ stream: &mut store::Ptr,
) {
// Push the frame to the front of the stream's deque // Push the frame to the front of the stream's deque
stream.pending_send.push_front(buffer, frame); stream.pending_send.push_front(buffer, frame);
@@ -665,8 +660,11 @@ impl Prioritize {
loop { loop {
match self.pending_send.pop(store) { match self.pending_send.pop(store) {
Some(mut stream) => { Some(mut stream) => {
log::trace!("pop_frame; stream={:?}; stream.state={:?}", log::trace!(
stream.id, stream.state); "pop_frame; stream={:?}; stream.state={:?}",
stream.id,
stream.state
);
// It's possible that this stream, besides having data to send, // It's possible that this stream, besides having data to send,
// is also queued to send a reset, and thus is already in the queue // is also queued to send a reset, and thus is already in the queue
@@ -675,8 +673,11 @@ impl Prioritize {
// To be safe, we just always ask the stream. // To be safe, we just always ask the stream.
let is_pending_reset = stream.is_pending_reset_expiration(); let is_pending_reset = stream.is_pending_reset_expiration();
log::trace!(" --> stream={:?}; is_pending_reset={:?};", log::trace!(
stream.id, is_pending_reset); " --> stream={:?}; is_pending_reset={:?};",
stream.id,
is_pending_reset
);
let frame = match stream.pending_send.pop_front(buffer) { let frame = match stream.pending_send.pop_front(buffer) {
Some(Frame::Data(mut frame)) => { Some(Frame::Data(mut frame)) => {
@@ -715,9 +716,7 @@ impl Prioritize {
// happen if the remote reduced the stream // happen if the remote reduced the stream
// window. In this case, we need to buffer the // window. In this case, we need to buffer the
// frame and wait for a window update... // frame and wait for a window update...
stream stream.pending_send.push_front(buffer, frame.into());
.pending_send
.push_front(buffer, frame.into());
continue; continue;
} }
@@ -726,7 +725,8 @@ impl Prioritize {
let len = cmp::min(sz, max_len); let len = cmp::min(sz, max_len);
// Only send up to the stream's window capacity // Only send up to the stream's window capacity
let len = cmp::min(len, stream_capacity.as_size() as usize) as WindowSize; let len =
cmp::min(len, stream_capacity.as_size() as usize) as WindowSize;
// There *must* be be enough connection level // There *must* be be enough connection level
// capacity at this point. // capacity at this point.
@@ -761,20 +761,18 @@ impl Prioritize {
frame.set_end_stream(false); frame.set_end_stream(false);
} }
Frame::Data(frame.map(|buf| { Frame::Data(frame.map(|buf| Prioritized {
Prioritized { inner: buf.take(len),
inner: buf.take(len), end_of_stream: eos,
end_of_stream: eos, stream: stream.key(),
stream: stream.key(),
}
})) }))
}, }
Some(frame) => frame.map(|_| Some(frame) => frame.map(|_| {
unreachable!( unreachable!(
"Frame::map closure will only be called \ "Frame::map closure will only be called \
on DATA frames." on DATA frames."
) )
), }),
None => { None => {
if let Some(reason) = stream.state.get_scheduled_reset() { if let Some(reason) = stream.state.get_scheduled_reset() {
stream.state.set_reset(reason); stream.state.set_reset(reason);
@@ -814,7 +812,7 @@ impl Prioritize {
counts.transition_after(stream, is_pending_reset); counts.transition_after(stream, is_pending_reset);
return Some(frame); return Some(frame);
}, }
None => return None, None => return None,
} }
} }

View File

@@ -1,15 +1,15 @@
use std::task::Context;
use super::*; use super::*;
use crate::{frame, proto};
use crate::codec::{RecvError, UserError}; use crate::codec::{RecvError, UserError};
use crate::frame::{Reason, DEFAULT_INITIAL_WINDOW_SIZE}; use crate::frame::{Reason, DEFAULT_INITIAL_WINDOW_SIZE};
use crate::{frame, proto};
use std::task::Context;
use http::{HeaderMap, Response, Request, Method};
use futures::ready; use futures::ready;
use http::{HeaderMap, Method, Request, Response};
use std::io; use std::io;
use std::time::{Duration, Instant};
use std::task::{Poll, Waker}; use std::task::{Poll, Waker};
use std::time::{Duration, Instant};
#[derive(Debug)] #[derive(Debug)]
pub(super) struct Recv { pub(super) struct Recv {
@@ -98,7 +98,7 @@ impl Recv {
Recv { Recv {
init_window_sz: config.local_init_window_sz, init_window_sz: config.local_init_window_sz,
flow: flow, flow,
in_flight_data: 0 as WindowSize, in_flight_data: 0 as WindowSize,
next_stream_id: Ok(next_stream_id.into()), next_stream_id: Ok(next_stream_id.into()),
pending_window_updates: store::Queue::new(), pending_window_updates: store::Queue::new(),
@@ -186,8 +186,9 @@ impl Recv {
return Err(RecvError::Stream { return Err(RecvError::Stream {
id: stream.id, id: stream.id,
reason: Reason::PROTOCOL_ERROR, reason: Reason::PROTOCOL_ERROR,
}.into()) }
}, .into());
}
}; };
stream.content_length = ContentLength::Remaining(content_length); stream.content_length = ContentLength::Remaining(content_length);
@@ -215,7 +216,7 @@ impl Recv {
let mut res = frame::Headers::new( let mut res = frame::Headers::new(
stream.id, stream.id,
frame::Pseudo::response(::http::StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE), frame::Pseudo::response(::http::StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE),
HeaderMap::new() HeaderMap::new(),
); );
res.set_end_stream(); res.set_end_stream();
Err(RecvHeaderBlockError::Oversize(Some(res))) Err(RecvHeaderBlockError::Oversize(Some(res)))
@@ -226,7 +227,9 @@ impl Recv {
let stream_id = frame.stream_id(); let stream_id = frame.stream_id();
let (pseudo, fields) = frame.into_parts(); let (pseudo, fields) = frame.into_parts();
let message = counts.peer().convert_poll_message(pseudo, fields, stream_id)?; let message = counts
.peer()
.convert_poll_message(pseudo, fields, stream_id)?;
// Push the frame onto the stream's recv buffer // Push the frame onto the stream's recv buffer
stream stream
@@ -246,9 +249,7 @@ impl Recv {
/// Called by the server to get the request /// Called by the server to get the request
/// ///
/// TODO: Should this fn return `Result`? /// TODO: Should this fn return `Result`?
pub fn take_request(&mut self, stream: &mut store::Ptr) pub fn take_request(&mut self, stream: &mut store::Ptr) -> Request<()> {
-> Request<()>
{
use super::peer::PollMessage::*; use super::peer::PollMessage::*;
match stream.pending_recv.pop_front(&mut self.buffer) { match stream.pending_recv.pop_front(&mut self.buffer) {
@@ -261,20 +262,19 @@ impl Recv {
pub fn poll_pushed( pub fn poll_pushed(
&mut self, &mut self,
cx: &Context, cx: &Context,
stream: &mut store::Ptr stream: &mut store::Ptr,
) -> Poll<Option<Result<(Request<()>, store::Key), proto::Error>>> { ) -> Poll<Option<Result<(Request<()>, store::Key), proto::Error>>> {
use super::peer::PollMessage::*; use super::peer::PollMessage::*;
let mut ppp = stream.pending_push_promises.take(); let mut ppp = stream.pending_push_promises.take();
let pushed = ppp.pop(stream.store_mut()).map( let pushed = ppp.pop(stream.store_mut()).map(|mut pushed| {
|mut pushed| match pushed.pending_recv.pop_front(&mut self.buffer) { match pushed.pending_recv.pop_front(&mut self.buffer) {
Some(Event::Headers(Server(headers))) => Some(Event::Headers(Server(headers))) => (headers, pushed.key()),
(headers, pushed.key()),
// When frames are pushed into the queue, it is verified that // When frames are pushed into the queue, it is verified that
// the first frame is a HEADERS frame. // the first frame is a HEADERS frame.
_ => panic!("Headers not set on pushed stream") _ => panic!("Headers not set on pushed stream"),
} }
); });
stream.pending_push_promises = ppp; stream.pending_push_promises = ppp;
if let Some(p) = pushed { if let Some(p) = pushed {
Poll::Ready(Some(Ok(p))) Poll::Ready(Some(Ok(p)))
@@ -301,14 +301,14 @@ impl Recv {
// If the buffer is not empty, then the first frame must be a HEADERS // If the buffer is not empty, then the first frame must be a HEADERS
// frame or the user violated the contract. // frame or the user violated the contract.
match stream.pending_recv.pop_front(&mut self.buffer) { match stream.pending_recv.pop_front(&mut self.buffer) {
Some(Event::Headers(Client(response))) => Poll::Ready(Ok(response.into())), Some(Event::Headers(Client(response))) => Poll::Ready(Ok(response)),
Some(_) => panic!("poll_response called after response returned"), Some(_) => panic!("poll_response called after response returned"),
None => { None => {
stream.state.ensure_recv_open()?; stream.state.ensure_recv_open()?;
stream.recv_task = Some(cx.waker().clone()); stream.recv_task = Some(cx.waker().clone());
Poll::Pending Poll::Pending
}, }
} }
} }
@@ -341,11 +341,7 @@ impl Recv {
} }
/// Releases capacity of the connection /// Releases capacity of the connection
pub fn release_connection_capacity( pub fn release_connection_capacity(&mut self, capacity: WindowSize, task: &mut Option<Waker>) {
&mut self,
capacity: WindowSize,
task: &mut Option<Waker>,
) {
log::trace!( log::trace!(
"release_connection_capacity; size={}, connection in_flight_data={}", "release_connection_capacity; size={}, connection in_flight_data={}",
capacity, capacity,
@@ -386,7 +382,6 @@ impl Recv {
// Assign capacity to stream // Assign capacity to stream
stream.recv_flow.assign_capacity(capacity); stream.recv_flow.assign_capacity(capacity);
if stream.recv_flow.unclaimed_capacity().is_some() { if stream.recv_flow.unclaimed_capacity().is_some() {
// Queue the stream for sending the WINDOW_UPDATE frame. // Queue the stream for sending the WINDOW_UPDATE frame.
self.pending_window_updates.push(stream); self.pending_window_updates.push(stream);
@@ -400,11 +395,7 @@ impl Recv {
} }
/// Release any unclaimed capacity for a closed stream. /// Release any unclaimed capacity for a closed stream.
pub fn release_closed_capacity( pub fn release_closed_capacity(&mut self, stream: &mut store::Ptr, task: &mut Option<Waker>) {
&mut self,
stream: &mut store::Ptr,
task: &mut Option<Waker>,
) {
debug_assert_eq!(stream.ref_count, 0); debug_assert_eq!(stream.ref_count, 0);
if stream.in_flight_recv_data == 0 { if stream.in_flight_recv_data == 0 {
@@ -417,10 +408,7 @@ impl Recv {
stream.in_flight_recv_data, stream.in_flight_recv_data,
); );
self.release_connection_capacity( self.release_connection_capacity(stream.in_flight_recv_data, task);
stream.in_flight_recv_data,
task,
);
stream.in_flight_recv_data = 0; stream.in_flight_recv_data = 0;
self.clear_recv_buffer(stream); self.clear_recv_buffer(stream);
@@ -485,9 +473,7 @@ impl Recv {
return false; return false;
} }
stream stream.pending_recv.is_empty()
.pending_recv
.is_empty()
} }
pub fn recv_data( pub fn recv_data(
@@ -522,7 +508,6 @@ impl Recv {
stream.recv_flow.window_size() stream.recv_flow.window_size()
); );
if is_ignoring_frame { if is_ignoring_frame {
log::trace!( log::trace!(
"recv_data; frame ignored on locally reset {:?} for some time", "recv_data; frame ignored on locally reset {:?} for some time",
@@ -609,7 +594,7 @@ impl Recv {
// the capacity as available to be reclaimed. When the available // the capacity as available to be reclaimed. When the available
// capacity meets a threshold, a WINDOW_UPDATE is then sent. // capacity meets a threshold, a WINDOW_UPDATE is then sent.
self.release_connection_capacity(sz, &mut None); self.release_connection_capacity(sz, &mut None);
return Ok(()); Ok(())
} }
pub fn consume_connection_window(&mut self, sz: WindowSize) -> Result<(), RecvError> { pub fn consume_connection_window(&mut self, sz: WindowSize) -> Result<(), RecvError> {
@@ -670,7 +655,7 @@ impl Recv {
// MUST reset the promised stream with a stream error" // MUST reset the promised stream with a stream error"
if let Some(content_length) = req.headers().get(header::CONTENT_LENGTH) { if let Some(content_length) = req.headers().get(header::CONTENT_LENGTH) {
match parse_u64(content_length.as_bytes()) { match parse_u64(content_length.as_bytes()) {
Ok(0) => {}, Ok(0) => {}
otherwise => { otherwise => {
proto_err!(stream: proto_err!(stream:
"recv_push_promise; promised request has content-length {:?}; promised_id={:?}", "recv_push_promise; promised request has content-length {:?}; promised_id={:?}",
@@ -681,7 +666,7 @@ impl Recv {
id: promised_id, id: promised_id,
reason: Reason::PROTOCOL_ERROR, reason: Reason::PROTOCOL_ERROR,
}); });
}, }
} }
} }
// "The server MUST include a method in the :method pseudo-header field // "The server MUST include a method in the :method pseudo-header field
@@ -699,7 +684,9 @@ impl Recv {
}); });
} }
use super::peer::PollMessage::*; use super::peer::PollMessage::*;
stream.pending_recv.push_back(&mut self.buffer, Event::Headers(Server(req))); stream
.pending_recv
.push_back(&mut self.buffer, Event::Headers(Server(req)));
stream.notify_recv(); stream.notify_recv();
Ok(()) Ok(())
} }
@@ -707,14 +694,17 @@ impl Recv {
fn safe_and_cacheable(method: &Method) -> bool { fn safe_and_cacheable(method: &Method) -> bool {
// Cacheable: https://httpwg.org/specs/rfc7231.html#cacheable.methods // Cacheable: https://httpwg.org/specs/rfc7231.html#cacheable.methods
// Safe: https://httpwg.org/specs/rfc7231.html#safe.methods // Safe: https://httpwg.org/specs/rfc7231.html#safe.methods
return method == Method::GET || method == Method::HEAD; method == Method::GET || method == Method::HEAD
} }
/// Ensures that `id` is not in the `Idle` state. /// Ensures that `id` is not in the `Idle` state.
pub fn ensure_not_idle(&self, id: StreamId) -> Result<(), Reason> { pub fn ensure_not_idle(&self, id: StreamId) -> Result<(), Reason> {
if let Ok(next) = self.next_stream_id { if let Ok(next) = self.next_stream_id {
if id >= next { if id >= next {
log::debug!("stream ID implicitly closed, PROTOCOL_ERROR; stream={:?}", id); log::debug!(
"stream ID implicitly closed, PROTOCOL_ERROR; stream={:?}",
id
);
return Err(Reason::PROTOCOL_ERROR); return Err(Reason::PROTOCOL_ERROR);
} }
} }
@@ -726,7 +716,9 @@ impl Recv {
/// Handle remote sending an explicit RST_STREAM. /// Handle remote sending an explicit RST_STREAM.
pub fn recv_reset(&mut self, frame: frame::Reset, stream: &mut Stream) { pub fn recv_reset(&mut self, frame: frame::Reset, stream: &mut Stream) {
// Notify the stream // Notify the stream
stream.state.recv_reset(frame.reason(), stream.is_pending_send); stream
.state
.recv_reset(frame.reason(), stream.is_pending_send);
stream.notify_send(); stream.notify_send();
stream.notify_recv(); stream.notify_recv();
@@ -777,10 +769,7 @@ impl Recv {
pub fn may_have_created_stream(&self, id: StreamId) -> bool { pub fn may_have_created_stream(&self, id: StreamId) -> bool {
if let Ok(next_id) = self.next_stream_id { if let Ok(next_id) = self.next_stream_id {
// Peer::is_local_init should have been called beforehand // Peer::is_local_init should have been called beforehand
debug_assert_eq!( debug_assert_eq!(id.is_server_initiated(), next_id.is_server_initiated(),);
id.is_server_initiated(),
next_id.is_server_initiated(),
);
id < next_id id < next_id
} else { } else {
true true
@@ -788,9 +777,7 @@ impl Recv {
} }
/// Returns true if the remote peer can reserve a stream with the given ID. /// Returns true if the remote peer can reserve a stream with the given ID.
pub fn ensure_can_reserve(&self) pub fn ensure_can_reserve(&self) -> Result<(), RecvError> {
-> Result<(), RecvError>
{
if !self.is_push_enabled { if !self.is_push_enabled {
proto_err!(conn: "recv_push_promise: push is disabled"); proto_err!(conn: "recv_push_promise: push is disabled");
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR)); return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
@@ -800,11 +787,7 @@ impl Recv {
} }
/// Add a locally reset stream to queue to be eventually reaped. /// Add a locally reset stream to queue to be eventually reaped.
pub fn enqueue_reset_expiration( pub fn enqueue_reset_expiration(&mut self, stream: &mut store::Ptr, counts: &mut Counts) {
&mut self,
stream: &mut store::Ptr,
counts: &mut Counts,
) {
if !stream.state.is_local_reset() || stream.is_pending_reset_expiration() { if !stream.state.is_local_reset() || stream.is_pending_reset_expiration() {
return; return;
} }
@@ -843,9 +826,7 @@ impl Recv {
let frame = frame::Reset::new(stream_id, Reason::REFUSED_STREAM); let frame = frame::Reset::new(stream_id, Reason::REFUSED_STREAM);
// Buffer the frame // Buffer the frame
dst.buffer(frame.into()) dst.buffer(frame.into()).expect("invalid RST_STREAM frame");
.ok()
.expect("invalid RST_STREAM frame");
} }
self.refused = None; self.refused = None;
@@ -864,11 +845,12 @@ impl Recv {
} }
} }
pub fn clear_queues(&mut self, pub fn clear_queues(
clear_pending_accept: bool, &mut self,
store: &mut Store, clear_pending_accept: bool,
counts: &mut Counts) store: &mut Store,
{ counts: &mut Counts,
) {
self.clear_stream_window_update_queue(store, counts); self.clear_stream_window_update_queue(store, counts);
self.clear_all_reset_streams(store, counts); self.clear_all_reset_streams(store, counts);
@@ -921,7 +903,7 @@ impl Recv {
/// Send connection level window update /// Send connection level window update
fn send_connection_window_update<T, B>( fn send_connection_window_update<T, B>(
&mut self, &mut self,
cx: &mut Context, cx: &mut Context,
dst: &mut Codec<T, Prioritized<B>>, dst: &mut Codec<T, Prioritized<B>>,
) -> Poll<io::Result<()>> ) -> Poll<io::Result<()>>
where where
@@ -936,13 +918,11 @@ impl Recv {
// Buffer the WINDOW_UPDATE frame // Buffer the WINDOW_UPDATE frame
dst.buffer(frame.into()) dst.buffer(frame.into())
.ok()
.expect("invalid WINDOW_UPDATE frame"); .expect("invalid WINDOW_UPDATE frame");
// Update flow control // Update flow control
self.flow self.flow
.inc_window(incr) .inc_window(incr)
.ok()
.expect("unexpected flow control state"); .expect("unexpected flow control state");
} }
@@ -992,14 +972,12 @@ impl Recv {
// Buffer it // Buffer it
dst.buffer(frame.into()) dst.buffer(frame.into())
.ok()
.expect("invalid WINDOW_UPDATE frame"); .expect("invalid WINDOW_UPDATE frame");
// Update flow control // Update flow control
stream stream
.recv_flow .recv_flow
.inc_window(incr) .inc_window(incr)
.ok()
.expect("unexpected flow control state"); .expect("unexpected flow control state");
} }
}) })
@@ -1010,7 +988,11 @@ impl Recv {
self.pending_accept.pop(store).map(|ptr| ptr.key()) self.pending_accept.pop(store).map(|ptr| ptr.key())
} }
pub fn poll_data(&mut self, cx: &Context, stream: &mut Stream) -> Poll<Option<Result<Bytes, proto::Error>>> { pub fn poll_data(
&mut self,
cx: &Context,
stream: &mut Stream,
) -> Poll<Option<Result<Bytes, proto::Error>>> {
// TODO: Return error when the stream is reset // TODO: Return error when the stream is reset
match stream.pending_recv.pop_front(&mut self.buffer) { match stream.pending_recv.pop_front(&mut self.buffer) {
Some(Event::Data(payload)) => Poll::Ready(Some(Ok(payload))), Some(Event::Data(payload)) => Poll::Ready(Some(Ok(payload))),
@@ -1030,7 +1012,7 @@ impl Recv {
// No more data frames // No more data frames
Poll::Ready(None) Poll::Ready(None)
}, }
None => self.schedule_recv(cx, stream), None => self.schedule_recv(cx, stream),
} }
} }
@@ -1047,12 +1029,16 @@ impl Recv {
stream.pending_recv.push_front(&mut self.buffer, event); stream.pending_recv.push_front(&mut self.buffer, event);
Poll::Pending Poll::Pending
}, }
None => self.schedule_recv(cx, stream), None => self.schedule_recv(cx, stream),
} }
} }
fn schedule_recv<T>(&mut self, cx: &Context, stream: &mut Stream) -> Poll<Option<Result<T, proto::Error>>> { fn schedule_recv<T>(
&mut self,
cx: &Context,
stream: &mut Stream,
) -> Poll<Option<Result<T, proto::Error>>> {
if stream.state.ensure_recv_open()? { if stream.state.ensure_recv_open()? {
// Request to get notified once more frames arrive // Request to get notified once more frames arrive
stream.recv_task = Some(cx.waker().clone()); stream.recv_task = Some(cx.waker().clone());
@@ -1112,7 +1098,7 @@ fn parse_u64(src: &[u8]) -> Result<u64, ()> {
} }
ret *= 10; ret *= 10;
ret += (d - b'0') as u64; ret += u64::from(d - b'0');
} }
Ok(ret) Ok(ret)

View File

@@ -325,13 +325,7 @@ impl Send {
if let Err(e) = self.prioritize.recv_stream_window_update(sz, stream) { if let Err(e) = self.prioritize.recv_stream_window_update(sz, stream) {
log::debug!("recv_stream_window_update !!; err={:?}", e); log::debug!("recv_stream_window_update !!; err={:?}", e);
self.send_reset( self.send_reset(Reason::FLOW_CONTROL_ERROR, buffer, stream, counts, task);
Reason::FLOW_CONTROL_ERROR.into(),
buffer,
stream,
counts,
task,
);
return Err(e); return Err(e);
} }

View File

@@ -1,7 +1,7 @@
use std::io; use std::io;
use crate::codec::{RecvError, UserError};
use crate::codec::UserError::*; use crate::codec::UserError::*;
use crate::codec::{RecvError, UserError};
use crate::frame::Reason; use crate::frame::Reason;
use crate::proto::{self, PollReset}; use crate::proto::{self, PollReset};
@@ -94,37 +94,40 @@ impl State {
let local = Streaming; let local = Streaming;
self.inner = match self.inner { self.inner = match self.inner {
Idle => if eos { Idle => {
HalfClosedLocal(AwaitingHeaders) if eos {
} else { HalfClosedLocal(AwaitingHeaders)
Open { } else {
local, Open {
remote: AwaitingHeaders, local,
remote: AwaitingHeaders,
}
} }
}, }
Open { Open {
local: AwaitingHeaders, local: AwaitingHeaders,
remote, remote,
} => if eos { } => {
HalfClosedLocal(remote) if eos {
} else { HalfClosedLocal(remote)
Open { } else {
local, Open { local, remote }
remote,
} }
}, }
HalfClosedRemote(AwaitingHeaders) => if eos { HalfClosedRemote(AwaitingHeaders) => {
Closed(Cause::EndStream) if eos {
} else { Closed(Cause::EndStream)
HalfClosedRemote(local) } else {
}, HalfClosedRemote(local)
}
}
_ => { _ => {
// All other transitions result in a protocol error // All other transitions result in a protocol error
return Err(UnexpectedFrameType); return Err(UnexpectedFrameType);
}, }
}; };
return Ok(()); Ok(())
} }
/// Opens the receive-half of the stream when a HEADERS frame is received. /// Opens the receive-half of the stream when a HEADERS frame is received.
@@ -146,7 +149,7 @@ impl State {
remote, remote,
} }
} }
}, }
ReservedRemote => { ReservedRemote => {
initial = true; initial = true;
@@ -155,31 +158,32 @@ impl State {
} else { } else {
HalfClosedLocal(Streaming) HalfClosedLocal(Streaming)
} }
}, }
Open { Open {
local, local,
remote: AwaitingHeaders, remote: AwaitingHeaders,
} => if eos { } => {
HalfClosedRemote(local) if eos {
} else { HalfClosedRemote(local)
Open { } else {
local, Open { local, remote }
remote,
} }
}, }
HalfClosedLocal(AwaitingHeaders) => if eos { HalfClosedLocal(AwaitingHeaders) => {
Closed(Cause::EndStream) if eos {
} else { Closed(Cause::EndStream)
HalfClosedLocal(remote) } else {
}, HalfClosedLocal(remote)
}
}
state => { state => {
// All other transitions result in a protocol error // All other transitions result in a protocol error
proto_err!(conn: "recv_open: in unexpected state {:?}", state); proto_err!(conn: "recv_open: in unexpected state {:?}", state);
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR)); return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
}, }
}; };
return Ok(initial); Ok(initial)
} }
/// Transition from Idle -> ReservedRemote /// Transition from Idle -> ReservedRemote
@@ -188,7 +192,7 @@ impl State {
Idle => { Idle => {
self.inner = ReservedRemote; self.inner = ReservedRemote;
Ok(()) Ok(())
}, }
state => { state => {
proto_err!(conn: "reserve_remote: in unexpected state {:?}", state); proto_err!(conn: "reserve_remote: in unexpected state {:?}", state);
Err(RecvError::Connection(Reason::PROTOCOL_ERROR)) Err(RecvError::Connection(Reason::PROTOCOL_ERROR))
@@ -199,19 +203,17 @@ impl State {
/// Indicates that the remote side will not send more data to the local. /// Indicates that the remote side will not send more data to the local.
pub fn recv_close(&mut self) -> Result<(), RecvError> { pub fn recv_close(&mut self) -> Result<(), RecvError> {
match self.inner { match self.inner {
Open { Open { local, .. } => {
local, ..
} => {
// The remote side will continue to receive data. // The remote side will continue to receive data.
log::trace!("recv_close: Open => HalfClosedRemote({:?})", local); log::trace!("recv_close: Open => HalfClosedRemote({:?})", local);
self.inner = HalfClosedRemote(local); self.inner = HalfClosedRemote(local);
Ok(()) Ok(())
}, }
HalfClosedLocal(..) => { HalfClosedLocal(..) => {
log::trace!("recv_close: HalfClosedLocal => Closed"); log::trace!("recv_close: HalfClosedLocal => Closed");
self.inner = Closed(Cause::EndStream); self.inner = Closed(Cause::EndStream);
Ok(()) Ok(())
}, }
state => { state => {
proto_err!(conn: "recv_close: in unexpected state {:?}", state); proto_err!(conn: "recv_close: in unexpected state {:?}", state);
Err(RecvError::Connection(Reason::PROTOCOL_ERROR)) Err(RecvError::Connection(Reason::PROTOCOL_ERROR))
@@ -228,7 +230,7 @@ impl State {
match self.inner { match self.inner {
// If the stream is already in a `Closed` state, do nothing, // If the stream is already in a `Closed` state, do nothing,
// provided that there are no frames still in the send queue. // provided that there are no frames still in the send queue.
Closed(..) if !queued => {}, Closed(..) if !queued => {}
// A notionally `Closed` stream may still have queued frames in // A notionally `Closed` stream may still have queued frames in
// the following cases: // the following cases:
// //
@@ -246,11 +248,12 @@ impl State {
state => { state => {
log::trace!( log::trace!(
"recv_reset; reason={:?}; state={:?}; queued={:?}", "recv_reset; reason={:?}; state={:?}; queued={:?}",
reason, state, queued reason,
state,
queued
); );
self.inner = Closed(Cause::Proto(reason)); self.inner = Closed(Cause::Proto(reason));
}, }
} }
} }
@@ -259,20 +262,20 @@ impl State {
use crate::proto::Error::*; use crate::proto::Error::*;
match self.inner { match self.inner {
Closed(..) => {}, Closed(..) => {}
_ => { _ => {
log::trace!("recv_err; err={:?}", err); log::trace!("recv_err; err={:?}", err);
self.inner = Closed(match *err { self.inner = Closed(match *err {
Proto(reason) => Cause::LocallyReset(reason), Proto(reason) => Cause::LocallyReset(reason),
Io(..) => Cause::Io, Io(..) => Cause::Io,
}); });
}, }
} }
} }
pub fn recv_eof(&mut self) { pub fn recv_eof(&mut self) {
match self.inner { match self.inner {
Closed(..) => {}, Closed(..) => {}
s => { s => {
log::trace!("recv_eof; state={:?}", s); log::trace!("recv_eof; state={:?}", s);
self.inner = Closed(Cause::Io); self.inner = Closed(Cause::Io);
@@ -283,17 +286,15 @@ impl State {
/// Indicates that the local side will not send more data to the local. /// Indicates that the local side will not send more data to the local.
pub fn send_close(&mut self) { pub fn send_close(&mut self) {
match self.inner { match self.inner {
Open { Open { remote, .. } => {
remote, ..
} => {
// The remote side will continue to receive data. // The remote side will continue to receive data.
log::trace!("send_close: Open => HalfClosedLocal({:?})", remote); log::trace!("send_close: Open => HalfClosedLocal({:?})", remote);
self.inner = HalfClosedLocal(remote); self.inner = HalfClosedLocal(remote);
}, }
HalfClosedRemote(..) => { HalfClosedRemote(..) => {
log::trace!("send_close: HalfClosedRemote => Closed"); log::trace!("send_close: HalfClosedRemote => Closed");
self.inner = Closed(Cause::EndStream); self.inner = Closed(Cause::EndStream);
}, }
state => panic!("send_close: unexpected state {:?}", state), state => panic!("send_close: unexpected state {:?}", state),
} }
} }
@@ -343,8 +344,7 @@ impl State {
pub fn is_send_streaming(&self) -> bool { pub fn is_send_streaming(&self) -> bool {
match self.inner { match self.inner {
Open { Open {
local: Streaming, local: Streaming, ..
..
} => true, } => true,
HalfClosedRemote(Streaming) => true, HalfClosedRemote(Streaming) => true,
_ => false, _ => false,
@@ -368,8 +368,7 @@ impl State {
pub fn is_recv_streaming(&self) -> bool { pub fn is_recv_streaming(&self) -> bool {
match self.inner { match self.inner {
Open { Open {
remote: Streaming, remote: Streaming, ..
..
} => true, } => true,
HalfClosedLocal(Streaming) => true, HalfClosedLocal(Streaming) => true,
_ => false, _ => false,
@@ -407,12 +406,11 @@ impl State {
pub fn ensure_recv_open(&self) -> Result<bool, proto::Error> { pub fn ensure_recv_open(&self) -> Result<bool, proto::Error> {
// TODO: Is this correct? // TODO: Is this correct?
match self.inner { match self.inner {
Closed(Cause::Proto(reason)) | Closed(Cause::Proto(reason))
Closed(Cause::LocallyReset(reason)) | | Closed(Cause::LocallyReset(reason))
Closed(Cause::Scheduled(reason)) => Err(proto::Error::Proto(reason)), | Closed(Cause::Scheduled(reason)) => Err(proto::Error::Proto(reason)),
Closed(Cause::Io) => Err(proto::Error::Io(io::ErrorKind::BrokenPipe.into())), Closed(Cause::Io) => Err(proto::Error::Io(io::ErrorKind::BrokenPipe.into())),
Closed(Cause::EndStream) | Closed(Cause::EndStream) | HalfClosedRemote(..) => Ok(false),
HalfClosedRemote(..) => Ok(false),
_ => Ok(true), _ => Ok(true),
} }
} }
@@ -420,15 +418,15 @@ impl State {
/// Returns a reason if the stream has been reset. /// Returns a reason if the stream has been reset.
pub(super) fn ensure_reason(&self, mode: PollReset) -> Result<Option<Reason>, crate::Error> { pub(super) fn ensure_reason(&self, mode: PollReset) -> Result<Option<Reason>, crate::Error> {
match self.inner { match self.inner {
Closed(Cause::Proto(reason)) | Closed(Cause::Proto(reason))
Closed(Cause::LocallyReset(reason)) | | Closed(Cause::LocallyReset(reason))
Closed(Cause::Scheduled(reason)) => Ok(Some(reason)), | Closed(Cause::Scheduled(reason)) => Ok(Some(reason)),
Closed(Cause::Io) => Err(proto::Error::Io(io::ErrorKind::BrokenPipe.into()).into()), Closed(Cause::Io) => Err(proto::Error::Io(io::ErrorKind::BrokenPipe.into()).into()),
Open { local: Streaming, .. } | Open {
HalfClosedRemote(Streaming) => match mode { local: Streaming, ..
PollReset::AwaitingHeaders => { }
Err(UserError::PollResetAfterSendResponse.into()) | HalfClosedRemote(Streaming) => match mode {
}, PollReset::AwaitingHeaders => Err(UserError::PollResetAfterSendResponse.into()),
PollReset::Streaming => Ok(None), PollReset::Streaming => Ok(None),
}, },
_ => Ok(None), _ => Ok(None),
@@ -438,9 +436,7 @@ impl State {
impl Default for State { impl Default for State {
fn default() -> State { fn default() -> State {
State { State { inner: Inner::Idle }
inner: Inner::Idle,
}
} }
} }

View File

@@ -118,9 +118,7 @@ impl Store {
use self::indexmap::map::Entry::*; use self::indexmap::map::Entry::*;
match self.ids.entry(id) { match self.ids.entry(id) {
Occupied(e) => Entry::Occupied(OccupiedEntry { Occupied(e) => Entry::Occupied(OccupiedEntry { ids: e }),
ids: e,
}),
Vacant(e) => Entry::Vacant(VacantEntry { Vacant(e) => Entry::Vacant(VacantEntry {
ids: e, ids: e,
slab: &mut self.slab, slab: &mut self.slab,
@@ -143,10 +141,7 @@ impl Store {
}; };
f(Ptr { f(Ptr {
key: Key { key: Key { index, stream_id },
index,
stream_id,
},
store: self, store: self,
})?; })?;
@@ -167,10 +162,7 @@ impl Store {
impl Resolve for Store { impl Resolve for Store {
fn resolve(&mut self, key: Key) -> Ptr { fn resolve(&mut self, key: Key) -> Ptr {
Ptr { Ptr { key, store: self }
key: key,
store: self,
}
} }
} }
@@ -267,14 +259,14 @@ where
// Update the tail pointer // Update the tail pointer
idxs.tail = stream.key(); idxs.tail = stream.key();
}, }
None => { None => {
log::trace!(" -> first entry"); log::trace!(" -> first entry");
self.indices = Some(store::Indices { self.indices = Some(store::Indices {
head: stream.key(), head: stream.key(),
tail: stream.key(), tail: stream.key(),
}); });
}, }
} }
true true
@@ -356,7 +348,7 @@ impl<'a> Ptr<'a> {
impl<'a> Resolve for Ptr<'a> { impl<'a> Resolve for Ptr<'a> {
fn resolve(&mut self, key: Key) -> Ptr { fn resolve(&mut self, key: Key) -> Ptr {
Ptr { Ptr {
key: key, key,
store: &mut *self.store, store: &mut *self.store,
} }
} }
@@ -388,10 +380,7 @@ impl<'a> OccupiedEntry<'a> {
pub fn key(&self) -> Key { pub fn key(&self) -> Key {
let stream_id = *self.ids.key(); let stream_id = *self.ids.key();
let index = *self.ids.get(); let index = *self.ids.get();
Key { Key { index, stream_id }
index,
stream_id,
}
} }
} }
@@ -406,9 +395,6 @@ impl<'a> VacantEntry<'a> {
// Insert the handle in the ID map // Insert the handle in the ID map
self.ids.insert(index); self.ids.insert(index);
Key { Key { index, stream_id }
index,
stream_id,
}
} }
} }

View File

@@ -1,8 +1,8 @@
use super::*; use super::*;
use std::task::{Context, Waker};
use std::time::Instant; use std::time::Instant;
use std::usize; use std::usize;
use std::task::{Context, Waker};
/// Tracks Stream related state /// Tracks Stream related state
/// ///
@@ -133,23 +133,17 @@ pub(super) struct NextOpen;
pub(super) struct NextResetExpire; pub(super) struct NextResetExpire;
impl Stream { impl Stream {
pub fn new( pub fn new(id: StreamId, init_send_window: WindowSize, init_recv_window: WindowSize) -> Stream {
id: StreamId,
init_send_window: WindowSize,
init_recv_window: WindowSize,
) -> Stream {
let mut send_flow = FlowControl::new(); let mut send_flow = FlowControl::new();
let mut recv_flow = FlowControl::new(); let mut recv_flow = FlowControl::new();
recv_flow recv_flow
.inc_window(init_recv_window) .inc_window(init_recv_window)
.ok()
.expect("invalid initial receive window"); .expect("invalid initial receive window");
recv_flow.assign_capacity(init_recv_window); recv_flow.assign_capacity(init_recv_window);
send_flow send_flow
.inc_window(init_send_window) .inc_window(init_send_window)
.ok()
.expect("invalid initial send window size"); .expect("invalid initial send window size");
Stream { Stream {
@@ -161,7 +155,7 @@ impl Stream {
// ===== Fields related to sending ===== // ===== Fields related to sending =====
next_pending_send: None, next_pending_send: None,
is_pending_send: false, is_pending_send: false,
send_flow: send_flow, send_flow,
requested_send_capacity: 0, requested_send_capacity: 0,
buffered_send_data: 0, buffered_send_data: 0,
send_task: None, send_task: None,
@@ -175,7 +169,7 @@ impl Stream {
// ===== Fields related to receiving ===== // ===== Fields related to receiving =====
next_pending_accept: None, next_pending_accept: None,
is_pending_accept: false, is_pending_accept: false,
recv_flow: recv_flow, recv_flow,
in_flight_recv_data: 0, in_flight_recv_data: 0,
next_window_update: None, next_window_update: None,
is_pending_window_update: false, is_pending_window_update: false,
@@ -247,8 +241,12 @@ impl Stream {
self.send_capacity_inc = true; self.send_capacity_inc = true;
self.send_flow.assign_capacity(capacity); self.send_flow.assign_capacity(capacity);
log::trace!(" assigned capacity to stream; available={}; buffered={}; id={:?}", log::trace!(
self.send_flow.available(), self.buffered_send_data, self.id); " assigned capacity to stream; available={}; buffered={}; id={:?}",
self.send_flow.available(),
self.buffered_send_data,
self.id
);
// Only notify if the capacity exceeds the amount of buffered data // Only notify if the capacity exceeds the amount of buffered data
if self.send_flow.available() > self.buffered_send_data { if self.send_flow.available() > self.buffered_send_data {
@@ -265,7 +263,7 @@ impl Stream {
None => return Err(()), None => return Err(()),
}, },
ContentLength::Head => return Err(()), ContentLength::Head => return Err(()),
_ => {}, _ => {}
} }
Ok(()) Ok(())

View File

@@ -465,13 +465,10 @@ where
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
// Always try to advance the internal state. Getting Pending also is // Always try to advance the internal state. Getting Pending also is
// needed to allow this function to return Pending. // needed to allow this function to return Pending.
match self.poll_close(cx)? { if let Poll::Ready(_) = self.poll_close(cx)? {
Poll::Ready(_) => { // If the socket is closed, don't return anything
// If the socket is closed, don't return anything // TODO: drop any pending streams
// TODO: drop any pending streams return Poll::Ready(None);
return Poll::Ready(None);
}
_ => {}
} }
if let Some(inner) = self.connection.next_incoming() { if let Some(inner) = self.connection.next_incoming() {

View File

@@ -1,6 +1,6 @@
use bytes::IntoBuf; use bytes::IntoBuf;
use http::Request;
use h2::client::{ResponseFuture, SendRequest}; use h2::client::{ResponseFuture, SendRequest};
use http::Request;
/// Extend the `h2::client::SendRequest` type with convenience methods. /// Extend the `h2::client::SendRequest` type with convenience methods.
pub trait SendRequestExt { pub trait SendRequestExt {
@@ -22,7 +22,7 @@ where
.expect("valid uri"); .expect("valid uri");
let (fut, _tx) = self let (fut, _tx) = self
.send_request(req, /*eos =*/true) .send_request(req, /*eos =*/ true)
.expect("send_request"); .expect("send_request");
fut fut

View File

@@ -137,8 +137,7 @@ impl Mock<frame::Headers> {
Mock(frame) Mock(frame)
} }
pub fn scheme(self, value: &str) -> Self pub fn scheme(self, value: &str) -> Self {
{
let (id, mut pseudo, fields) = self.into_parts(); let (id, mut pseudo, fields) = self.into_parts();
let value = value.parse().unwrap(); let value = value.parse().unwrap();
@@ -206,7 +205,6 @@ impl From<Mock<frame::Data>> for SendFrame {
} }
} }
// PushPromise helpers // PushPromise helpers
impl Mock<frame::PushPromise> { impl Mock<frame::PushPromise> {
@@ -240,7 +238,6 @@ impl Mock<frame::PushPromise> {
Mock(frame) Mock(frame)
} }
fn into_parts(self) -> (StreamId, StreamId, frame::Pseudo, HeaderMap) { fn into_parts(self) -> (StreamId, StreamId, frame::Pseudo, HeaderMap) {
assert!(self.0.is_end_headers(), "unset eoh will be lost"); assert!(self.0.is_end_headers(), "unset eoh will be lost");
let id = self.0.stream_id(); let id = self.0.stream_id();
@@ -280,10 +277,7 @@ impl Mock<frame::GoAway> {
} }
pub fn reason(self, reason: frame::Reason) -> Self { pub fn reason(self, reason: frame::Reason) -> Self {
Mock(frame::GoAway::new( Mock(frame::GoAway::new(self.0.last_stream_id(), reason))
self.0.last_stream_id(),
reason,
))
} }
} }

View File

@@ -1,8 +1,8 @@
use walkdir::WalkDir; use walkdir::WalkDir;
use std::collections::HashMap;
use std::env; use std::env;
use std::path::Path; use std::path::Path;
use std::collections::HashMap;
fn main() { fn main() {
let args: Vec<_> = env::args().collect(); let args: Vec<_> = env::args().collect();
@@ -30,7 +30,9 @@ fn main() {
// Now, split that into the group and the name // Now, split that into the group and the name
let module = fixture_path.split("/").next().unwrap(); let module = fixture_path.split("/").next().unwrap();
tests.entry(module.to_string()).or_insert(vec![]) tests
.entry(module.to_string())
.or_insert(vec![])
.push(fixture_path.to_string()); .push(fixture_path.to_string());
} }
@@ -49,9 +51,7 @@ fn main() {
println!(" {} => {{", module); println!(" {} => {{", module);
for test in tests { for test in tests {
let ident = test let ident = test.split("/").nth(1).unwrap().split(".").next().unwrap();
.split("/").nth(1).unwrap()
.split(".").next().unwrap();
println!(" ({}, {:?});", ident, test); println!(" ({}, {:?});", ident, test);
} }

View File

@@ -98,18 +98,17 @@ impl Node {
} }
} }
fn compute_transition(&self, fn compute_transition(
byte: Option<usize>, &self,
start: &Node, byte: Option<usize>,
root: &Node, start: &Node,
steps_remaining: usize) root: &Node,
{ steps_remaining: usize,
) {
if steps_remaining == 0 { if steps_remaining == 0 {
let (byte, target) = match byte { let (byte, target) = match byte {
Some(256) => (None, None), Some(256) => (None, None),
_ => { _ => (byte, Some(self.id.unwrap_or(0))),
(byte, Some(self.id.unwrap_or(0)))
}
}; };
start.transitions.borrow_mut().push(Transition { start.transitions.borrow_mut().push(Transition {
@@ -257,8 +256,6 @@ pub fn main() {
println!("];"); println!("];");
} }
const TABLE: &'static str = r##" const TABLE: &'static str = r##"
( 0) |11111111|11000 1ff8 [13] ( 0) |11111111|11000 1ff8 [13]
( 1) |11111111|11111111|1011000 7fffd8 [23] ( 1) |11111111|11111111|1011000 7fffd8 [23]