Issue 128: Convert frame::Reason to struct (#142)
Alter frame::Reason to a struct with a single u32 member. Introduce Constants to the impl for existing Reasons. Change all usage in the library and its tests to adopt this change, using the new constants.
This commit is contained in:
committed by
Carl Lerche
parent
1c179f7bf2
commit
2aee78c7d7
@@ -1,6 +1,5 @@
|
|||||||
use codec::{Codec, RecvError};
|
use codec::{Codec, RecvError};
|
||||||
use frame::{Headers, Pseudo, Reason, Settings, StreamId};
|
use frame::{Headers, Pseudo, Reason, Settings, StreamId};
|
||||||
use frame::Reason::*;
|
|
||||||
use proto::{self, WindowSize};
|
use proto::{self, WindowSize};
|
||||||
|
|
||||||
use bytes::{Bytes, IntoBuf};
|
use bytes::{Bytes, IntoBuf};
|
||||||
@@ -445,7 +444,7 @@ impl proto::Peer for Peer {
|
|||||||
// kinds of errors
|
// kinds of errors
|
||||||
return Err(RecvError::Stream {
|
return Err(RecvError::Stream {
|
||||||
id: stream_id,
|
id: stream_id,
|
||||||
reason: ProtocolError,
|
reason: Reason::PROTOCOL_ERROR,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use codec::RecvError;
|
use codec::RecvError;
|
||||||
use frame::{self, Frame, Kind, Reason};
|
use frame::{self, Frame, Kind, Reason};
|
||||||
use frame::{DEFAULT_MAX_FRAME_SIZE, DEFAULT_SETTINGS_HEADER_TABLE_SIZE, MAX_MAX_FRAME_SIZE};
|
use frame::{DEFAULT_MAX_FRAME_SIZE, DEFAULT_SETTINGS_HEADER_TABLE_SIZE, MAX_MAX_FRAME_SIZE};
|
||||||
use frame::Reason::*;
|
|
||||||
|
|
||||||
use hpack;
|
use hpack;
|
||||||
|
|
||||||
@@ -60,7 +59,7 @@ impl<T> FramedRead<T> {
|
|||||||
let head = frame::Head::parse(&bytes);
|
let head = frame::Head::parse(&bytes);
|
||||||
|
|
||||||
if self.partial.is_some() && head.kind() != Kind::Continuation {
|
if self.partial.is_some() && head.kind() != Kind::Continuation {
|
||||||
return Err(Connection(ProtocolError));
|
return Err(Connection(Reason::PROTOCOL_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
let kind = head.kind();
|
let kind = head.kind();
|
||||||
@@ -71,24 +70,24 @@ impl<T> FramedRead<T> {
|
|||||||
Kind::Settings => {
|
Kind::Settings => {
|
||||||
let res = frame::Settings::load(head, &bytes[frame::HEADER_LEN..]);
|
let res = frame::Settings::load(head, &bytes[frame::HEADER_LEN..]);
|
||||||
|
|
||||||
res.map_err(|_| Connection(ProtocolError))?.into()
|
res.map_err(|_| Connection(Reason::PROTOCOL_ERROR))?.into()
|
||||||
},
|
},
|
||||||
Kind::Ping => {
|
Kind::Ping => {
|
||||||
let res = frame::Ping::load(head, &bytes[frame::HEADER_LEN..]);
|
let res = frame::Ping::load(head, &bytes[frame::HEADER_LEN..]);
|
||||||
|
|
||||||
res.map_err(|_| Connection(ProtocolError))?.into()
|
res.map_err(|_| Connection(Reason::PROTOCOL_ERROR))?.into()
|
||||||
},
|
},
|
||||||
Kind::WindowUpdate => {
|
Kind::WindowUpdate => {
|
||||||
let res = frame::WindowUpdate::load(head, &bytes[frame::HEADER_LEN..]);
|
let res = frame::WindowUpdate::load(head, &bytes[frame::HEADER_LEN..]);
|
||||||
|
|
||||||
res.map_err(|_| Connection(ProtocolError))?.into()
|
res.map_err(|_| Connection(Reason::PROTOCOL_ERROR))?.into()
|
||||||
},
|
},
|
||||||
Kind::Data => {
|
Kind::Data => {
|
||||||
let _ = bytes.split_to(frame::HEADER_LEN);
|
let _ = bytes.split_to(frame::HEADER_LEN);
|
||||||
let res = frame::Data::load(head, bytes.freeze());
|
let res = frame::Data::load(head, bytes.freeze());
|
||||||
|
|
||||||
// TODO: Should this always be connection level? Probably not...
|
// TODO: Should this always be connection level? Probably not...
|
||||||
res.map_err(|_| Connection(ProtocolError))?.into()
|
res.map_err(|_| Connection(Reason::PROTOCOL_ERROR))?.into()
|
||||||
},
|
},
|
||||||
Kind::Headers => {
|
Kind::Headers => {
|
||||||
// Drop the frame header
|
// Drop the frame header
|
||||||
@@ -104,10 +103,10 @@ impl<T> FramedRead<T> {
|
|||||||
// `PROTOCOL_ERROR`.
|
// `PROTOCOL_ERROR`.
|
||||||
return Err(Stream {
|
return Err(Stream {
|
||||||
id: head.stream_id(),
|
id: head.stream_id(),
|
||||||
reason: ProtocolError,
|
reason: Reason::PROTOCOL_ERROR,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
_ => return Err(Connection(ProtocolError)),
|
_ => return Err(Connection(Reason::PROTOCOL_ERROR)),
|
||||||
};
|
};
|
||||||
|
|
||||||
if headers.is_end_headers() {
|
if headers.is_end_headers() {
|
||||||
@@ -117,10 +116,10 @@ impl<T> FramedRead<T> {
|
|||||||
Err(frame::Error::MalformedMessage) => {
|
Err(frame::Error::MalformedMessage) => {
|
||||||
return Err(Stream {
|
return Err(Stream {
|
||||||
id: head.stream_id(),
|
id: head.stream_id(),
|
||||||
reason: ProtocolError,
|
reason: Reason::PROTOCOL_ERROR,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
Err(_) => return Err(Connection(ProtocolError)),
|
Err(_) => return Err(Connection(Reason::PROTOCOL_ERROR)),
|
||||||
}
|
}
|
||||||
|
|
||||||
headers.into()
|
headers.into()
|
||||||
@@ -136,11 +135,11 @@ impl<T> FramedRead<T> {
|
|||||||
},
|
},
|
||||||
Kind::Reset => {
|
Kind::Reset => {
|
||||||
let res = frame::Reset::load(head, &bytes[frame::HEADER_LEN..]);
|
let res = frame::Reset::load(head, &bytes[frame::HEADER_LEN..]);
|
||||||
res.map_err(|_| Connection(ProtocolError))?.into()
|
res.map_err(|_| Connection(Reason::PROTOCOL_ERROR))?.into()
|
||||||
},
|
},
|
||||||
Kind::GoAway => {
|
Kind::GoAway => {
|
||||||
let res = frame::GoAway::load(&bytes[frame::HEADER_LEN..]);
|
let res = frame::GoAway::load(&bytes[frame::HEADER_LEN..]);
|
||||||
res.map_err(|_| Connection(ProtocolError))?.into()
|
res.map_err(|_| Connection(Reason::PROTOCOL_ERROR))?.into()
|
||||||
},
|
},
|
||||||
Kind::PushPromise => {
|
Kind::PushPromise => {
|
||||||
// Drop the frame header
|
// Drop the frame header
|
||||||
@@ -148,8 +147,8 @@ impl<T> FramedRead<T> {
|
|||||||
let _ = bytes.split_to(frame::HEADER_LEN);
|
let _ = bytes.split_to(frame::HEADER_LEN);
|
||||||
|
|
||||||
// Parse the frame w/o parsing the payload
|
// Parse the frame w/o parsing the payload
|
||||||
let (mut push, payload) =
|
let (mut push, payload) = frame::PushPromise::load(head, bytes)
|
||||||
frame::PushPromise::load(head, bytes).map_err(|_| Connection(ProtocolError))?;
|
.map_err(|_| Connection(Reason::PROTOCOL_ERROR))?;
|
||||||
|
|
||||||
if push.is_end_headers() {
|
if push.is_end_headers() {
|
||||||
// Load the HPACK encoded headers & return the frame
|
// Load the HPACK encoded headers & return the frame
|
||||||
@@ -158,10 +157,10 @@ impl<T> FramedRead<T> {
|
|||||||
Err(frame::Error::MalformedMessage) => {
|
Err(frame::Error::MalformedMessage) => {
|
||||||
return Err(Stream {
|
return Err(Stream {
|
||||||
id: head.stream_id(),
|
id: head.stream_id(),
|
||||||
reason: ProtocolError,
|
reason: Reason::PROTOCOL_ERROR,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
Err(_) => return Err(Connection(ProtocolError)),
|
Err(_) => return Err(Connection(Reason::PROTOCOL_ERROR)),
|
||||||
}
|
}
|
||||||
|
|
||||||
push.into()
|
push.into()
|
||||||
@@ -178,7 +177,7 @@ impl<T> FramedRead<T> {
|
|||||||
Kind::Priority => {
|
Kind::Priority => {
|
||||||
if head.stream_id() == 0 {
|
if head.stream_id() == 0 {
|
||||||
// Invalid stream identifier
|
// Invalid stream identifier
|
||||||
return Err(Connection(ProtocolError));
|
return Err(Connection(Reason::PROTOCOL_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
match frame::Priority::load(head, &bytes[frame::HEADER_LEN..]) {
|
match frame::Priority::load(head, &bytes[frame::HEADER_LEN..]) {
|
||||||
@@ -189,10 +188,10 @@ impl<T> FramedRead<T> {
|
|||||||
// `PROTOCOL_ERROR`.
|
// `PROTOCOL_ERROR`.
|
||||||
return Err(Stream {
|
return Err(Stream {
|
||||||
id: head.stream_id(),
|
id: head.stream_id(),
|
||||||
reason: ProtocolError,
|
reason: Reason::PROTOCOL_ERROR,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
Err(_) => return Err(Connection(ProtocolError)),
|
Err(_) => return Err(Connection(Reason::PROTOCOL_ERROR)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Kind::Continuation => {
|
Kind::Continuation => {
|
||||||
@@ -201,7 +200,7 @@ impl<T> FramedRead<T> {
|
|||||||
|
|
||||||
let mut partial = match self.partial.take() {
|
let mut partial = match self.partial.take() {
|
||||||
Some(partial) => partial,
|
Some(partial) => partial,
|
||||||
None => return Err(Connection(ProtocolError)),
|
None => return Err(Connection(Reason::PROTOCOL_ERROR)),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extend the buf
|
// Extend the buf
|
||||||
@@ -214,7 +213,7 @@ impl<T> FramedRead<T> {
|
|||||||
|
|
||||||
// The stream identifiers must match
|
// The stream identifiers must match
|
||||||
if partial.frame.stream_id() != head.stream_id() {
|
if partial.frame.stream_id() != head.stream_id() {
|
||||||
return Err(Connection(ProtocolError));
|
return Err(Connection(Reason::PROTOCOL_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
match partial.frame.load_hpack(partial.buf, &mut self.hpack) {
|
match partial.frame.load_hpack(partial.buf, &mut self.hpack) {
|
||||||
@@ -222,10 +221,10 @@ impl<T> FramedRead<T> {
|
|||||||
Err(frame::Error::MalformedMessage) => {
|
Err(frame::Error::MalformedMessage) => {
|
||||||
return Err(Stream {
|
return Err(Stream {
|
||||||
id: head.stream_id(),
|
id: head.stream_id(),
|
||||||
reason: ProtocolError,
|
reason: Reason::PROTOCOL_ERROR,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
Err(_) => return Err(Connection(ProtocolError)),
|
Err(_) => return Err(Connection(Reason::PROTOCOL_ERROR)),
|
||||||
}
|
}
|
||||||
|
|
||||||
partial.frame.into()
|
partial.frame.into()
|
||||||
@@ -296,7 +295,7 @@ fn map_err(err: io::Error) -> RecvError {
|
|||||||
// TODO: with tokio-io v0.1.4, we can check
|
// TODO: with tokio-io v0.1.4, we can check
|
||||||
// err.get_ref().is::<tokio_io::length_delimited::FrameTooBig>()
|
// err.get_ref().is::<tokio_io::length_delimited::FrameTooBig>()
|
||||||
if err.description() == "frame size too big" {
|
if err.description() == "frame size too big" {
|
||||||
return RecvError::Connection(Reason::FrameSizeError);
|
return RecvError::Connection(Reason::FRAME_SIZE_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err.into()
|
err.into()
|
||||||
|
|||||||
@@ -1,99 +1,58 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
|
||||||
pub enum Reason {
|
|
||||||
NoError,
|
|
||||||
ProtocolError,
|
|
||||||
InternalError,
|
|
||||||
FlowControlError,
|
|
||||||
SettingsTimeout,
|
|
||||||
StreamClosed,
|
|
||||||
FrameSizeError,
|
|
||||||
RefusedStream,
|
|
||||||
Cancel,
|
|
||||||
CompressionError,
|
|
||||||
ConnectError,
|
|
||||||
EnhanceYourCalm,
|
|
||||||
InadequateSecurity,
|
|
||||||
Http11Required,
|
|
||||||
Other(u32),
|
|
||||||
// TODO: reserve additional variants
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== impl Reason =====
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub struct Reason(u32);
|
||||||
|
|
||||||
impl Reason {
|
impl Reason {
|
||||||
pub fn description(&self) -> &str {
|
pub const NO_ERROR: Reason = Reason(0);
|
||||||
use self::Reason::*;
|
pub const PROTOCOL_ERROR: Reason = Reason(1);
|
||||||
|
pub const INTERNAL_ERROR: Reason = Reason(2);
|
||||||
|
pub const FLOW_CONTROL_ERROR: Reason = Reason(3);
|
||||||
|
pub const SETTINGS_TIMEOUT: Reason = Reason(4);
|
||||||
|
pub const STREAM_CLOSED: Reason = Reason(5);
|
||||||
|
pub const FRAME_SIZE_ERROR: Reason = Reason(6);
|
||||||
|
pub const REFUSED_STREAM: Reason = Reason(7);
|
||||||
|
pub const CANCEL: Reason = Reason(8);
|
||||||
|
pub const COMPRESSION_ERROR: Reason = Reason(9);
|
||||||
|
pub const CONNECT_ERROR: Reason = Reason(10);
|
||||||
|
pub const ENHANCE_YOUR_CALM: Reason = Reason(11);
|
||||||
|
pub const INADEQUATE_SECURITY: Reason = Reason(12);
|
||||||
|
pub const HTTP11_REQUIRED: Reason = Reason(13);
|
||||||
|
|
||||||
match *self {
|
pub fn description(&self) -> &str {
|
||||||
NoError => "not a result of an error",
|
match self.0 {
|
||||||
ProtocolError => "unspecific protocol error detected",
|
0 => "not a result of an error",
|
||||||
InternalError => "unexpected internal error encountered",
|
1 => "unspecific protocol error detected",
|
||||||
FlowControlError => "flow-control protocol violated",
|
2 => "unexpected internal error encountered",
|
||||||
SettingsTimeout => "settings ACK not received in timely manner",
|
3 => "flow-control protocol violated",
|
||||||
StreamClosed => "received frame when stream half-closed",
|
4 => "settings ACK not received in timely manner",
|
||||||
FrameSizeError => "frame with invalid size",
|
5 => "received frame when stream half-closed",
|
||||||
RefusedStream => "refused stream before processing any application logic",
|
6 => "frame with invalid size",
|
||||||
Cancel => "stream no longer needed",
|
7 => "refused stream before processing any application logic",
|
||||||
CompressionError => "unable to maintain the header compression context",
|
8 => "stream no longer needed",
|
||||||
ConnectError => {
|
9 => "unable to maintain the header compression context",
|
||||||
"connection established in response to a CONNECT request \
|
10 => {
|
||||||
was reset or abnormally closed"
|
"connection established in response to a CONNECT request was reset or abnormally \
|
||||||
|
closed"
|
||||||
},
|
},
|
||||||
EnhanceYourCalm => "detected excessive load generating behavior",
|
11 => "detected excessive load generating behavior",
|
||||||
InadequateSecurity => "security properties do not meet minimum requirements",
|
12 => "security properties do not meet minimum requirements",
|
||||||
Http11Required => "endpoint requires HTTP/1.1",
|
13 => "endpoint requires HTTP/1.1",
|
||||||
Other(_) => "other reason (ain't no tellin')",
|
_ => "unknown reason",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u32> for Reason {
|
impl From<u32> for Reason {
|
||||||
fn from(src: u32) -> Reason {
|
fn from(src: u32) -> Reason {
|
||||||
use self::Reason::*;
|
Reason(src)
|
||||||
|
|
||||||
match src {
|
|
||||||
0x0 => NoError,
|
|
||||||
0x1 => ProtocolError,
|
|
||||||
0x2 => InternalError,
|
|
||||||
0x3 => FlowControlError,
|
|
||||||
0x4 => SettingsTimeout,
|
|
||||||
0x5 => StreamClosed,
|
|
||||||
0x6 => FrameSizeError,
|
|
||||||
0x7 => RefusedStream,
|
|
||||||
0x8 => Cancel,
|
|
||||||
0x9 => CompressionError,
|
|
||||||
0xa => ConnectError,
|
|
||||||
0xb => EnhanceYourCalm,
|
|
||||||
0xc => InadequateSecurity,
|
|
||||||
0xd => Http11Required,
|
|
||||||
_ => Other(src),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Reason> for u32 {
|
impl From<Reason> for u32 {
|
||||||
fn from(src: Reason) -> u32 {
|
fn from(src: Reason) -> u32 {
|
||||||
use self::Reason::*;
|
src.0
|
||||||
|
|
||||||
match src {
|
|
||||||
NoError => 0x0,
|
|
||||||
ProtocolError => 0x1,
|
|
||||||
InternalError => 0x2,
|
|
||||||
FlowControlError => 0x3,
|
|
||||||
SettingsTimeout => 0x4,
|
|
||||||
StreamClosed => 0x5,
|
|
||||||
FrameSizeError => 0x6,
|
|
||||||
RefusedStream => 0x7,
|
|
||||||
Cancel => 0x8,
|
|
||||||
CompressionError => 0x9,
|
|
||||||
ConnectError => 0xa,
|
|
||||||
EnhanceYourCalm => 0xb,
|
|
||||||
InadequateSecurity => 0xc,
|
|
||||||
Http11Required => 0xd,
|
|
||||||
Other(v) => v,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ where
|
|||||||
if self.error.is_some() {
|
if self.error.is_some() {
|
||||||
if self.streams.num_active_streams() == 0 {
|
if self.streams.num_active_streams() == 0 {
|
||||||
let id = self.streams.last_processed_id();
|
let id = self.streams.last_processed_id();
|
||||||
let goaway = frame::GoAway::new(id, Reason::NoError);
|
let goaway = frame::GoAway::new(id, Reason::NO_ERROR);
|
||||||
self.state = State::GoAway(goaway);
|
self.state = State::GoAway(goaway);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -193,8 +193,7 @@ where
|
|||||||
match (ours, theirs) {
|
match (ours, theirs) {
|
||||||
// If either side reported an error, return that
|
// If either side reported an error, return that
|
||||||
// to the user.
|
// to the user.
|
||||||
(Reason::NoError, err) |
|
(Reason::NO_ERROR, err) | (err, Reason::NO_ERROR) => err,
|
||||||
(err, Reason::NoError) => err,
|
|
||||||
// If both sides reported an error, give their
|
// If both sides reported an error, give their
|
||||||
// error back to th user. We assume our error
|
// error back to th user. We assume our error
|
||||||
// was a consequence of their error, and less
|
// was a consequence of their error, and less
|
||||||
@@ -213,12 +212,10 @@ where
|
|||||||
// Transition the state to error
|
// Transition the state to error
|
||||||
self.state = State::Closed(reason);
|
self.state = State::Closed(reason);
|
||||||
},
|
},
|
||||||
State::Closed(reason) => {
|
State::Closed(reason) => if let Reason::NO_ERROR = reason {
|
||||||
if let Reason::NoError = reason {
|
return Ok(Async::Ready(()));
|
||||||
return Ok(Async::Ready(()));
|
} else {
|
||||||
} else {
|
return Err(reason.into());
|
||||||
return Err(reason.into());
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,11 +103,11 @@ impl FlowControl {
|
|||||||
let (val, overflow) = self.window_size.overflowing_add(sz as i32);
|
let (val, overflow) = self.window_size.overflowing_add(sz as i32);
|
||||||
|
|
||||||
if overflow {
|
if overflow {
|
||||||
return Err(Reason::FlowControlError);
|
return Err(Reason::FLOW_CONTROL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if val > MAX_WINDOW_SIZE as i32 {
|
if val > MAX_WINDOW_SIZE as i32 {
|
||||||
return Err(Reason::FlowControlError);
|
return Err(Reason::FLOW_CONTROL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!(
|
trace!(
|
||||||
@@ -126,7 +126,12 @@ impl FlowControl {
|
|||||||
/// This is called after receiving a SETTINGS frame with a lower
|
/// This is called after receiving a SETTINGS frame with a lower
|
||||||
/// INITIAL_WINDOW_SIZE value.
|
/// INITIAL_WINDOW_SIZE value.
|
||||||
pub fn dec_window(&mut self, sz: WindowSize) {
|
pub fn dec_window(&mut self, sz: WindowSize) {
|
||||||
trace!("dec_window; sz={}; window={}, available={}", sz, self.window_size, self.available);
|
trace!(
|
||||||
|
"dec_window; sz={}; window={}, available={}",
|
||||||
|
sz,
|
||||||
|
self.window_size,
|
||||||
|
self.available
|
||||||
|
);
|
||||||
// This should not be able to overflow `window_size` from the bottom.
|
// This should not be able to overflow `window_size` from the bottom.
|
||||||
self.window_size -= sz as i32;
|
self.window_size -= sz as i32;
|
||||||
self.available = self.available.saturating_sub(sz);
|
self.available = self.available.saturating_sub(sz);
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ use self::state::State;
|
|||||||
use self::store::{Entry, Store};
|
use self::store::{Entry, Store};
|
||||||
use self::stream::Stream;
|
use self::stream::Stream;
|
||||||
|
|
||||||
use error::Reason::*;
|
|
||||||
use frame::{StreamId, StreamIdOverflow};
|
use frame::{StreamId, StreamIdOverflow};
|
||||||
use proto::*;
|
use proto::*;
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ where
|
|||||||
|
|
||||||
let next_id = self.next_stream_id()?;
|
let next_id = self.next_stream_id()?;
|
||||||
if id < next_id {
|
if id < next_id {
|
||||||
return Err(RecvError::Connection(ProtocolError));
|
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.next_stream_id = id.next_id();
|
self.next_stream_id = id.next_id();
|
||||||
@@ -152,10 +152,12 @@ where
|
|||||||
if let Some(content_length) = frame.fields().get(header::CONTENT_LENGTH) {
|
if let Some(content_length) = frame.fields().get(header::CONTENT_LENGTH) {
|
||||||
let content_length = match parse_u64(content_length.as_bytes()) {
|
let content_length = match parse_u64(content_length.as_bytes()) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(_) => return Err(RecvError::Stream {
|
Err(_) => {
|
||||||
id: stream.id,
|
return Err(RecvError::Stream {
|
||||||
reason: Reason::ProtocolError,
|
id: stream.id,
|
||||||
}),
|
reason: Reason::PROTOCOL_ERROR,
|
||||||
|
})
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
stream.content_length = ContentLength::Remaining(content_length);
|
stream.content_length = ContentLength::Remaining(content_length);
|
||||||
@@ -191,7 +193,7 @@ where
|
|||||||
if stream.ensure_content_length_zero().is_err() {
|
if stream.ensure_content_length_zero().is_err() {
|
||||||
return Err(RecvError::Stream {
|
return Err(RecvError::Stream {
|
||||||
id: stream.id,
|
id: stream.id,
|
||||||
reason: ProtocolError,
|
reason: Reason::PROTOCOL_ERROR,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,7 +274,7 @@ where
|
|||||||
if !stream.state.is_recv_streaming() {
|
if !stream.state.is_recv_streaming() {
|
||||||
// Receiving a DATA frame when not expecting one is a protocol
|
// Receiving a DATA frame when not expecting one is a protocol
|
||||||
// error.
|
// error.
|
||||||
return Err(RecvError::Connection(ProtocolError));
|
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!(
|
trace!(
|
||||||
@@ -285,7 +287,7 @@ where
|
|||||||
// Ensure that there is enough capacity on the connection before acting
|
// Ensure that there is enough capacity on the connection before acting
|
||||||
// on the stream.
|
// on the stream.
|
||||||
if self.flow.window_size() < sz || stream.recv_flow.window_size() < sz {
|
if self.flow.window_size() < sz || stream.recv_flow.window_size() < sz {
|
||||||
return Err(RecvError::Connection(FlowControlError));
|
return Err(RecvError::Connection(Reason::FLOW_CONTROL_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update connection level flow control
|
// Update connection level flow control
|
||||||
@@ -300,7 +302,7 @@ where
|
|||||||
if stream.dec_content_length(frame.payload().len()).is_err() {
|
if stream.dec_content_length(frame.payload().len()).is_err() {
|
||||||
return Err(RecvError::Stream {
|
return Err(RecvError::Stream {
|
||||||
id: stream.id,
|
id: stream.id,
|
||||||
reason: ProtocolError,
|
reason: Reason::PROTOCOL_ERROR,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,12 +310,12 @@ where
|
|||||||
if stream.ensure_content_length_zero().is_err() {
|
if stream.ensure_content_length_zero().is_err() {
|
||||||
return Err(RecvError::Stream {
|
return Err(RecvError::Stream {
|
||||||
id: stream.id,
|
id: stream.id,
|
||||||
reason: ProtocolError,
|
reason: Reason::PROTOCOL_ERROR,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if stream.state.recv_close().is_err() {
|
if stream.state.recv_close().is_err() {
|
||||||
return Err(RecvError::Connection(ProtocolError));
|
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,7 +384,7 @@ where
|
|||||||
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 {
|
||||||
return Err(ProtocolError);
|
return Err(Reason::PROTOCOL_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if next_stream_id is overflowed, that's ok.
|
// if next_stream_id is overflowed, that's ok.
|
||||||
@@ -417,12 +419,12 @@ where
|
|||||||
if !P::is_server() {
|
if !P::is_server() {
|
||||||
// Remote is a server and cannot open streams. PushPromise is
|
// Remote is a server and cannot open streams. PushPromise is
|
||||||
// registered by reserving, so does not go through this path.
|
// registered by reserving, so does not go through this path.
|
||||||
return Err(RecvError::Connection(ProtocolError));
|
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the ID is a valid server initiated ID
|
// Ensure that the ID is a valid server initiated ID
|
||||||
if !id.is_client_initiated() {
|
if !id.is_client_initiated() {
|
||||||
return Err(RecvError::Connection(ProtocolError));
|
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -432,7 +434,7 @@ where
|
|||||||
if let Ok(id) = self.next_stream_id {
|
if let Ok(id) = self.next_stream_id {
|
||||||
Ok(id)
|
Ok(id)
|
||||||
} else {
|
} else {
|
||||||
Err(RecvError::Connection(ProtocolError))
|
Err(RecvError::Connection(Reason::PROTOCOL_ERROR))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,7 +444,7 @@ where
|
|||||||
if P::is_server() {
|
if P::is_server() {
|
||||||
// The remote is a client and cannot reserve
|
// The remote is a client and cannot reserve
|
||||||
trace!("recv_push_promise; error remote is client");
|
trace!("recv_push_promise; error remote is client");
|
||||||
return Err(RecvError::Connection(ProtocolError));
|
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !promised_id.is_server_initiated() {
|
if !promised_id.is_server_initiated() {
|
||||||
@@ -450,12 +452,12 @@ where
|
|||||||
"recv_push_promise; error promised id is invalid {:?}",
|
"recv_push_promise; error promised id is invalid {:?}",
|
||||||
promised_id
|
promised_id
|
||||||
);
|
);
|
||||||
return Err(RecvError::Connection(ProtocolError));
|
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.is_push_enabled {
|
if !self.is_push_enabled {
|
||||||
trace!("recv_push_promise; error push is disabled");
|
trace!("recv_push_promise; error push is disabled");
|
||||||
return Err(RecvError::Connection(ProtocolError));
|
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -474,7 +476,7 @@ where
|
|||||||
try_ready!(dst.poll_ready());
|
try_ready!(dst.poll_ready());
|
||||||
|
|
||||||
// Create the RST_STREAM frame
|
// Create the RST_STREAM frame
|
||||||
let frame = frame::Reset::new(stream_id, RefusedStream);
|
let frame = frame::Reset::new(stream_id, Reason::REFUSED_STREAM);
|
||||||
|
|
||||||
// Buffer the frame
|
// Buffer the frame
|
||||||
dst.buffer(frame.into())
|
dst.buffer(frame.into())
|
||||||
|
|||||||
@@ -151,8 +151,6 @@ where
|
|||||||
|
|
||||||
trace!("send_reset -- queueing; frame={:?}", frame);
|
trace!("send_reset -- queueing; frame={:?}", frame);
|
||||||
self.prioritize.queue_frame(frame.into(), stream, task);
|
self.prioritize.queue_frame(frame.into(), stream, task);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_data(
|
pub fn send_data(
|
||||||
@@ -253,7 +251,7 @@ where
|
|||||||
) -> Result<(), Reason> {
|
) -> Result<(), Reason> {
|
||||||
if let Err(e) = self.prioritize.recv_stream_window_update(sz, stream) {
|
if let Err(e) = self.prioritize.recv_stream_window_update(sz, stream) {
|
||||||
debug!("recv_stream_window_update !!; err={:?}", e);
|
debug!("recv_stream_window_update !!; err={:?}", e);
|
||||||
self.send_reset(FlowControlError.into(), stream, task, true);
|
self.send_reset(Reason::FLOW_CONTROL_ERROR.into(), stream, task, true);
|
||||||
|
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
@@ -342,7 +340,7 @@ where
|
|||||||
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 {
|
||||||
return Err(ProtocolError);
|
return Err(Reason::PROTOCOL_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if next_stream_id is overflowed, that's ok.
|
// if next_stream_id is overflowed, that's ok.
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use codec::{RecvError, UserError};
|
use codec::{RecvError, UserError};
|
||||||
use codec::UserError::*;
|
use codec::UserError::*;
|
||||||
use frame::Reason;
|
use frame::Reason;
|
||||||
use frame::Reason::*;
|
|
||||||
use proto;
|
use proto;
|
||||||
|
|
||||||
use self::Inner::*;
|
use self::Inner::*;
|
||||||
@@ -166,7 +165,7 @@ impl State {
|
|||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
// All other transitions result in a protocol error
|
// All other transitions result in a protocol error
|
||||||
return Err(RecvError::Connection(ProtocolError));
|
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -180,7 +179,7 @@ impl State {
|
|||||||
self.inner = ReservedRemote;
|
self.inner = ReservedRemote;
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
_ => Err(RecvError::Connection(ProtocolError)),
|
_ => Err(RecvError::Connection(Reason::PROTOCOL_ERROR)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,7 +199,7 @@ impl State {
|
|||||||
self.inner = Closed(None);
|
self.inner = Closed(None);
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
_ => Err(RecvError::Connection(ProtocolError)),
|
_ => Err(RecvError::Connection(Reason::PROTOCOL_ERROR)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ where
|
|||||||
} else {
|
} else {
|
||||||
if !frame.is_end_stream() {
|
if !frame.is_end_stream() {
|
||||||
// TODO: Is this the right error
|
// TODO: Is this the right error
|
||||||
return Err(RecvError::Connection(ProtocolError));
|
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
actions.recv.recv_trailers(frame, stream)
|
actions.recv.recv_trailers(frame, stream)
|
||||||
@@ -135,7 +135,7 @@ where
|
|||||||
|
|
||||||
let stream = match me.store.find_mut(&id) {
|
let stream = match me.store.find_mut(&id) {
|
||||||
Some(stream) => stream,
|
Some(stream) => stream,
|
||||||
None => return Err(RecvError::Connection(ProtocolError)),
|
None => return Err(RecvError::Connection(Reason::PROTOCOL_ERROR)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let actions = &mut me.actions;
|
let actions = &mut me.actions;
|
||||||
@@ -153,7 +153,7 @@ where
|
|||||||
let id = frame.stream_id();
|
let id = frame.stream_id();
|
||||||
|
|
||||||
if id.is_zero() {
|
if id.is_zero() {
|
||||||
return Err(RecvError::Connection(ProtocolError));
|
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
let stream = match me.store.find_mut(&id) {
|
let stream = match me.store.find_mut(&id) {
|
||||||
@@ -213,16 +213,14 @@ where
|
|||||||
let err = frame.reason().into();
|
let err = frame.reason().into();
|
||||||
|
|
||||||
me.store
|
me.store
|
||||||
.for_each(|stream| {
|
.for_each(|stream| if stream.id > last_stream_id {
|
||||||
if stream.id > last_stream_id {
|
counts.transition(stream, |_, stream| {
|
||||||
counts.transition(stream, |_, stream| {
|
actions.recv.recv_err(&err, &mut *stream);
|
||||||
actions.recv.recv_err(&err, &mut *stream);
|
actions.send.recv_err(stream);
|
||||||
actions.send.recv_err(stream);
|
|
||||||
Ok::<_, ()>(())
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Ok::<_, ()>(())
|
Ok::<_, ()>(())
|
||||||
}
|
})
|
||||||
|
} else {
|
||||||
|
Ok::<_, ()>(())
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -274,7 +272,7 @@ where
|
|||||||
|
|
||||||
let stream = match me.store.find_mut(&id) {
|
let stream = match me.store.find_mut(&id) {
|
||||||
Some(stream) => stream.key(),
|
Some(stream) => stream.key(),
|
||||||
None => return Err(RecvError::Connection(ProtocolError)),
|
None => return Err(RecvError::Connection(Reason::PROTOCOL_ERROR)),
|
||||||
};
|
};
|
||||||
|
|
||||||
me.actions
|
me.actions
|
||||||
@@ -513,8 +511,7 @@ impl<B, P> StreamRef<B, P>
|
|||||||
where
|
where
|
||||||
P: Peer,
|
P: Peer,
|
||||||
{
|
{
|
||||||
pub fn send_data(&mut self, data: B, end_stream: bool)
|
pub fn send_data(&mut self, data: B, end_stream: bool) -> Result<(), UserError>
|
||||||
-> Result<(), UserError>
|
|
||||||
where
|
where
|
||||||
B: Buf,
|
B: Buf,
|
||||||
{
|
{
|
||||||
@@ -622,10 +619,7 @@ where
|
|||||||
|
|
||||||
/// Releases recv capacity back to the peer. This may result in sending
|
/// Releases recv capacity back to the peer. This may result in sending
|
||||||
/// WINDOW_UPDATE frames on both the stream and connection.
|
/// WINDOW_UPDATE frames on both the stream and connection.
|
||||||
pub fn release_capacity(
|
pub fn release_capacity(&mut self, capacity: WindowSize) -> Result<(), UserError>
|
||||||
&mut self,
|
|
||||||
capacity: WindowSize
|
|
||||||
) -> Result<(), UserError>
|
|
||||||
where
|
where
|
||||||
B: Buf,
|
B: Buf,
|
||||||
{
|
{
|
||||||
@@ -742,11 +736,9 @@ where
|
|||||||
.field("ref_count", &stream.ref_count)
|
.field("ref_count", &stream.ref_count)
|
||||||
.finish()
|
.finish()
|
||||||
},
|
},
|
||||||
Err(_poisoned) => {
|
Err(_poisoned) => fmt.debug_struct("StreamRef")
|
||||||
fmt.debug_struct("StreamRef")
|
.field("inner", &"<Poisoned>")
|
||||||
.field("inner", &"<Poisoned>")
|
.finish(),
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -786,7 +778,7 @@ where
|
|||||||
stream.id,
|
stream.id,
|
||||||
);
|
);
|
||||||
actions.send.send_reset(
|
actions.send.send_reset(
|
||||||
Reason::Cancel,
|
Reason::CANCEL,
|
||||||
stream,
|
stream,
|
||||||
&mut actions.task,
|
&mut actions.task,
|
||||||
false
|
false
|
||||||
|
|||||||
@@ -408,7 +408,7 @@ where
|
|||||||
|
|
||||||
if PREFACE[self.pos..self.pos + n] != buf[..n] {
|
if PREFACE[self.pos..self.pos + n] != buf[..n] {
|
||||||
// TODO: Should this just write the GO_AWAY frame directly?
|
// TODO: Should this just write the GO_AWAY frame directly?
|
||||||
return Err(Reason::ProtocolError.into());
|
return Err(Reason::PROTOCOL_ERROR.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.pos += n;
|
self.pos += n;
|
||||||
@@ -491,7 +491,7 @@ impl proto::Peer for Peer {
|
|||||||
() => {
|
() => {
|
||||||
return Err(RecvError::Stream {
|
return Err(RecvError::Stream {
|
||||||
id: stream_id,
|
id: stream_id,
|
||||||
reason: Reason::ProtocolError,
|
reason: Reason::PROTOCOL_ERROR,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -506,7 +506,7 @@ impl proto::Peer for Peer {
|
|||||||
|
|
||||||
// Specifying :status for a request is a protocol error
|
// Specifying :status for a request is a protocol error
|
||||||
if pseudo.status.is_some() {
|
if pseudo.status.is_some() {
|
||||||
return Err(RecvError::Connection(Reason::ProtocolError));
|
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the URI
|
// Convert the URI
|
||||||
@@ -543,7 +543,7 @@ impl proto::Peer for Peer {
|
|||||||
// kinds of errors
|
// kinds of errors
|
||||||
return Err(RecvError::Stream {
|
return Err(RecvError::Stream {
|
||||||
id: stream_id,
|
id: stream_id,
|
||||||
reason: Reason::ProtocolError,
|
reason: Reason::PROTOCOL_ERROR,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -54,14 +54,14 @@ pub fn go_away<T>(id: T) -> Mock<frame::GoAway>
|
|||||||
where
|
where
|
||||||
T: Into<StreamId>,
|
T: Into<StreamId>,
|
||||||
{
|
{
|
||||||
Mock(frame::GoAway::new(id.into(), frame::Reason::NoError))
|
Mock(frame::GoAway::new(id.into(), frame::Reason::NO_ERROR))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset<T>(id: T) -> Mock<frame::Reset>
|
pub fn reset<T>(id: T) -> Mock<frame::Reset>
|
||||||
where
|
where
|
||||||
T: Into<StreamId>,
|
T: Into<StreamId>,
|
||||||
{
|
{
|
||||||
Mock(frame::Reset::new(id.into(), frame::Reason::NoError))
|
Mock(frame::Reset::new(id.into(), frame::Reason::NO_ERROR))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn settings() -> Mock<frame::Settings> {
|
pub fn settings() -> Mock<frame::Settings> {
|
||||||
@@ -212,21 +212,21 @@ impl Mock<frame::GoAway> {
|
|||||||
pub fn protocol_error(self) -> Self {
|
pub fn protocol_error(self) -> Self {
|
||||||
Mock(frame::GoAway::new(
|
Mock(frame::GoAway::new(
|
||||||
self.0.last_stream_id(),
|
self.0.last_stream_id(),
|
||||||
frame::Reason::ProtocolError,
|
frame::Reason::PROTOCOL_ERROR,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn flow_control(self) -> Self {
|
pub fn flow_control(self) -> Self {
|
||||||
Mock(frame::GoAway::new(
|
Mock(frame::GoAway::new(
|
||||||
self.0.last_stream_id(),
|
self.0.last_stream_id(),
|
||||||
frame::Reason::FlowControlError,
|
frame::Reason::FLOW_CONTROL_ERROR,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn frame_size(self) -> Self {
|
pub fn frame_size(self) -> Self {
|
||||||
Mock(frame::GoAway::new(
|
Mock(frame::GoAway::new(
|
||||||
self.0.last_stream_id(),
|
self.0.last_stream_id(),
|
||||||
frame::Reason::FrameSizeError,
|
frame::Reason::FRAME_SIZE_ERROR,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -242,12 +242,12 @@ impl From<Mock<frame::GoAway>> for SendFrame {
|
|||||||
impl Mock<frame::Reset> {
|
impl Mock<frame::Reset> {
|
||||||
pub fn protocol_error(self) -> Self {
|
pub fn protocol_error(self) -> Self {
|
||||||
let id = self.0.stream_id();
|
let id = self.0.stream_id();
|
||||||
Mock(frame::Reset::new(id, frame::Reason::ProtocolError))
|
Mock(frame::Reset::new(id, frame::Reason::PROTOCOL_ERROR))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn flow_control(self) -> Self {
|
pub fn flow_control(self) -> Self {
|
||||||
let id = self.0.stream_id();
|
let id = self.0.stream_id();
|
||||||
Mock(frame::Reset::new(id, frame::Reason::FlowControlError))
|
Mock(frame::Reset::new(id, frame::Reason::FLOW_CONTROL_ERROR))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user