ignore received frames on a stream locally reset for some time (#174)

- Adds config duration for how long to ignore frames on a reset stream
- Adds config for how many reset streams can be held at a time
This commit is contained in:
Sean McArthur
2017-12-18 11:09:38 -08:00
committed by GitHub
parent edaeaa8941
commit 1ea9a8fc7e
19 changed files with 684 additions and 125 deletions

View File

@@ -60,8 +60,7 @@ enum Inner {
Open { local: Peer, remote: Peer },
HalfClosedLocal(Peer), // TODO: explicitly name this value
HalfClosedRemote(Peer),
// When reset, a reason is provided
Closed(Option<Cause>),
Closed(Cause),
}
#[derive(Debug, Copy, Clone)]
@@ -72,7 +71,9 @@ enum Peer {
#[derive(Debug, Copy, Clone)]
enum Cause {
EndStream,
Proto(Reason),
LocallyReset(Reason),
Io,
/// The user droped all handles to the stream without explicitly canceling.
@@ -84,7 +85,7 @@ enum Cause {
impl State {
/// Opens the send-half of a stream if it is not already open.
pub fn send_open(&mut self, eos: bool) -> Result<(), UserError> {
let local = Peer::Streaming;
let local = Streaming;
self.inner = match self.inner {
Idle => if eos {
@@ -107,7 +108,7 @@ impl State {
}
},
HalfClosedRemote(AwaitingHeaders) => if eos {
Closed(None)
Closed(Cause::EndStream)
} else {
HalfClosedRemote(local)
},
@@ -124,7 +125,7 @@ impl State {
///
/// Returns true if this transitions the state to Open.
pub fn recv_open(&mut self, eos: bool) -> Result<bool, RecvError> {
let remote = Peer::Streaming;
let remote = Streaming;
let mut initial = false;
self.inner = match self.inner {
@@ -144,7 +145,7 @@ impl State {
initial = true;
if eos {
Closed(None)
Closed(Cause::EndStream)
} else {
Open {
local: AwaitingHeaders,
@@ -164,7 +165,7 @@ impl State {
}
},
HalfClosedLocal(AwaitingHeaders) => if eos {
Closed(None)
Closed(Cause::EndStream)
} else {
HalfClosedLocal(remote)
},
@@ -201,13 +202,25 @@ impl State {
},
HalfClosedLocal(..) => {
trace!("recv_close: HalfClosedLocal => Closed");
self.inner = Closed(None);
self.inner = Closed(Cause::EndStream);
Ok(())
},
_ => Err(RecvError::Connection(Reason::PROTOCOL_ERROR)),
}
}
/// The remote explicitly sent a RST_STREAM.
pub fn recv_reset(&mut self, reason: Reason) {
match self.inner {
Closed(..) => {},
_ => {
trace!("recv_reset; reason={:?}", reason);
self.inner = Closed(Cause::Proto(reason));
},
}
}
/// We noticed a protocol error.
pub fn recv_err(&mut self, err: &proto::Error) {
use proto::Error::*;
@@ -216,8 +229,8 @@ impl State {
_ => {
trace!("recv_err; err={:?}", err);
self.inner = Closed(match *err {
Proto(reason) => Some(Cause::Proto(reason)),
Io(..) => Some(Cause::Io),
Proto(reason) => Cause::LocallyReset(reason),
Io(..) => Cause::Io,
});
},
}
@@ -228,7 +241,7 @@ impl State {
Closed(..) => {},
s => {
trace!("recv_eof; state={:?}", s);
self.inner = Closed(Some(Cause::Io));
self.inner = Closed(Cause::Io);
}
}
}
@@ -245,28 +258,34 @@ impl State {
},
HalfClosedRemote(..) => {
trace!("send_close: HalfClosedRemote => Closed");
self.inner = Closed(None);
self.inner = Closed(Cause::EndStream);
},
_ => panic!("transition send_close on unexpected state"),
}
}
/// Set the stream state to reset
/// Set the stream state to reset locally.
pub fn set_reset(&mut self, reason: Reason) {
self.inner = Closed(Some(Cause::Proto(reason)));
self.inner = Closed(Cause::LocallyReset(reason));
}
/// Set the stream state to canceled
pub fn set_canceled(&mut self) {
debug_assert!(!self.is_closed());
self.inner = Closed(Some(Cause::Canceled));
self.inner = Closed(Cause::Canceled);
}
pub fn is_canceled(&self) -> bool {
use self::Cause::Canceled;
match self.inner {
Closed(Some(Canceled)) => true,
Closed(Cause::Canceled) => true,
_ => false,
}
}
pub fn is_local_reset(&self) -> bool {
match self.inner {
Closed(Cause::LocallyReset(_)) => true,
Closed(Cause::Canceled) => true,
_ => false,
}
}
@@ -274,7 +293,8 @@ impl State {
/// Returns true if the stream is already reset.
pub fn is_reset(&self) -> bool {
match self.inner {
Closed(Some(_)) => true,
Closed(Cause::EndStream) => false,
Closed(_) => true,
_ => false,
}
}
@@ -294,10 +314,10 @@ impl State {
pub fn is_send_streaming(&self) -> bool {
match self.inner {
Open {
local: Peer::Streaming,
local: Streaming,
..
} => true,
HalfClosedRemote(Peer::Streaming) => true,
HalfClosedRemote(Streaming) => true,
_ => false,
}
}
@@ -319,10 +339,10 @@ impl State {
pub fn is_recv_streaming(&self) -> bool {
match self.inner {
Open {
remote: Peer::Streaming,
remote: Streaming,
..
} => true,
HalfClosedLocal(Peer::Streaming) => true,
HalfClosedLocal(Streaming) => true,
_ => false,
}
}
@@ -353,10 +373,12 @@ impl State {
// TODO: Is this correct?
match self.inner {
Closed(Some(Cause::Proto(reason))) => Err(proto::Error::Proto(reason)),
Closed(Some(Cause::Canceled)) => Err(proto::Error::Proto(Reason::CANCEL)),
Closed(Some(Cause::Io)) => Err(proto::Error::Io(io::ErrorKind::BrokenPipe.into())),
Closed(None) | HalfClosedRemote(..) => Ok(false),
Closed(Cause::Proto(reason)) |
Closed(Cause::LocallyReset(reason)) => Err(proto::Error::Proto(reason)),
Closed(Cause::Canceled) => Err(proto::Error::Proto(Reason::CANCEL)),
Closed(Cause::Io) => Err(proto::Error::Io(io::ErrorKind::BrokenPipe.into())),
Closed(Cause::EndStream) |
HalfClosedRemote(..) => Ok(false),
_ => Ok(true),
}
}
@@ -372,6 +394,6 @@ impl Default for State {
impl Default for Peer {
fn default() -> Self {
Peer::AwaitingHeaders
AwaitingHeaders
}
}