Misc streams cleanup
This commit is contained in:
85
src/proto/streams/flow_control.rs
Normal file
85
src/proto/streams/flow_control.rs
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
use ConnectionError;
|
||||||
|
use proto::*;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct FlowControl {
|
||||||
|
/// Amount that may be claimed.
|
||||||
|
window_size: WindowSize,
|
||||||
|
|
||||||
|
/// Amount to be removed by future increments.
|
||||||
|
underflow: WindowSize,
|
||||||
|
|
||||||
|
/// The amount that has been incremented but not yet advertised (to the application or
|
||||||
|
/// the remote).
|
||||||
|
next_window_update: WindowSize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FlowControl {
|
||||||
|
pub fn new(window_size: WindowSize) -> FlowControl {
|
||||||
|
FlowControl {
|
||||||
|
window_size,
|
||||||
|
underflow: 0,
|
||||||
|
next_window_update: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true iff `claim_window(sz)` would return succeed.
|
||||||
|
pub fn ensure_window<T>(&mut self, sz: WindowSize, err: T) -> Result<(), ConnectionError>
|
||||||
|
where T: Into<ConnectionError>,
|
||||||
|
{
|
||||||
|
if sz <= self.window_size {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(err.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Claims the provided amount from the window, if there is enough space.
|
||||||
|
///
|
||||||
|
/// Fails when `apply_window_update()` hasn't returned at least `sz` more bytes than
|
||||||
|
/// have been previously claimed.
|
||||||
|
pub fn claim_window<T>(&mut self, sz: WindowSize, err: T)
|
||||||
|
-> Result<(), ConnectionError>
|
||||||
|
where T: Into<ConnectionError>,
|
||||||
|
{
|
||||||
|
self.ensure_window(sz, err)?;
|
||||||
|
|
||||||
|
self.window_size -= sz;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Increase the _unadvertised_ window capacity.
|
||||||
|
pub fn expand_window(&mut self, sz: WindowSize) {
|
||||||
|
if sz <= self.underflow {
|
||||||
|
self.underflow -= sz;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let added = sz - self.underflow;
|
||||||
|
self.next_window_update += added;
|
||||||
|
self.underflow = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtains the unadvertised window update.
|
||||||
|
///
|
||||||
|
/// This does not apply the window update to `self`.
|
||||||
|
pub fn peek_window_update(&mut self) -> Option<WindowSize> {
|
||||||
|
if self.next_window_update == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(self.next_window_update)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtains and applies an unadvertised window update.
|
||||||
|
pub fn apply_window_update(&mut self) -> Option<WindowSize> {
|
||||||
|
if self.next_window_update == 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let incr = self.next_window_update;
|
||||||
|
self.next_window_update = 0;
|
||||||
|
self.window_size += incr;
|
||||||
|
Some(incr)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
|
mod flow_control;
|
||||||
mod recv;
|
mod recv;
|
||||||
mod send;
|
mod send;
|
||||||
mod state;
|
mod state;
|
||||||
mod store;
|
mod store;
|
||||||
|
|
||||||
|
use self::flow_control::FlowControl;
|
||||||
use self::recv::Recv;
|
use self::recv::Recv;
|
||||||
use self::send::Send;
|
use self::send::Send;
|
||||||
|
use self::state::State;
|
||||||
use self::store::{Store, Entry};
|
use self::store::{Store, Entry};
|
||||||
|
|
||||||
use {frame, Peer, StreamId, ConnectionError};
|
use {frame, Peer, StreamId, ConnectionError};
|
||||||
@@ -12,7 +15,7 @@ use proto::*;
|
|||||||
use error::Reason::*;
|
use error::Reason::*;
|
||||||
use error::User::*;
|
use error::User::*;
|
||||||
|
|
||||||
// TODO: All the VecDeques should become linked lists using the state::Stream
|
// TODO: All the VecDeques should become linked lists using the State
|
||||||
// values.
|
// values.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Streams<P> {
|
pub struct Streams<P> {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use {frame, Peer, ConnectionError};
|
use {frame, Peer, ConnectionError};
|
||||||
use proto::*;
|
use proto::*;
|
||||||
use super::{state, Config, Store};
|
use super::*;
|
||||||
|
|
||||||
use error::Reason::*;
|
use error::Reason::*;
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ pub struct Recv<P> {
|
|||||||
init_window_sz: WindowSize,
|
init_window_sz: WindowSize,
|
||||||
|
|
||||||
/// Connection level flow control governing received data
|
/// Connection level flow control governing received data
|
||||||
flow_control: state::FlowControl,
|
flow_control: FlowControl,
|
||||||
|
|
||||||
pending_window_updates: VecDeque<StreamId>,
|
pending_window_updates: VecDeque<StreamId>,
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ impl<P: Peer> Recv<P> {
|
|||||||
max_streams: config.max_remote_initiated,
|
max_streams: config.max_remote_initiated,
|
||||||
num_streams: 0,
|
num_streams: 0,
|
||||||
init_window_sz: config.init_remote_window_sz,
|
init_window_sz: config.init_remote_window_sz,
|
||||||
flow_control: state::FlowControl::new(config.init_remote_window_sz),
|
flow_control: FlowControl::new(config.init_remote_window_sz),
|
||||||
pending_window_updates: VecDeque::new(),
|
pending_window_updates: VecDeque::new(),
|
||||||
refused: None,
|
refused: None,
|
||||||
_p: PhantomData,
|
_p: PhantomData,
|
||||||
@@ -45,7 +45,7 @@ impl<P: Peer> Recv<P> {
|
|||||||
/// Update state reflecting a new, remotely opened stream
|
/// Update state reflecting a new, remotely opened stream
|
||||||
///
|
///
|
||||||
/// Returns the stream state if successful. `None` if refused
|
/// Returns the stream state if successful. `None` if refused
|
||||||
pub fn open(&mut self, id: StreamId) -> Result<Option<state::Stream>, ConnectionError> {
|
pub fn open(&mut self, id: StreamId) -> Result<Option<State>, ConnectionError> {
|
||||||
assert!(self.refused.is_none());
|
assert!(self.refused.is_none());
|
||||||
|
|
||||||
try!(self.ensure_can_open(id));
|
try!(self.ensure_can_open(id));
|
||||||
@@ -60,17 +60,17 @@ impl<P: Peer> Recv<P> {
|
|||||||
// Increment the number of remote initiated streams
|
// Increment the number of remote initiated streams
|
||||||
self.num_streams += 1;
|
self.num_streams += 1;
|
||||||
|
|
||||||
Ok(Some(state::Stream::default()))
|
Ok(Some(State::default()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transition the stream state based on receiving headers
|
/// Transition the stream state based on receiving headers
|
||||||
pub fn recv_headers(&mut self, state: &mut state::Stream, eos: bool)
|
pub fn recv_headers(&mut self, state: &mut State, eos: bool)
|
||||||
-> Result<(), ConnectionError>
|
-> Result<(), ConnectionError>
|
||||||
{
|
{
|
||||||
state.recv_open(self.init_window_sz, eos)
|
state.recv_open(self.init_window_sz, eos)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recv_eos(&mut self, state: &mut state::Stream)
|
pub fn recv_eos(&mut self, state: &mut State)
|
||||||
-> Result<(), ConnectionError>
|
-> Result<(), ConnectionError>
|
||||||
{
|
{
|
||||||
state.recv_close()
|
state.recv_close()
|
||||||
@@ -78,7 +78,7 @@ impl<P: Peer> Recv<P> {
|
|||||||
|
|
||||||
pub fn recv_data(&mut self,
|
pub fn recv_data(&mut self,
|
||||||
frame: &frame::Data,
|
frame: &frame::Data,
|
||||||
state: &mut state::Stream)
|
state: &mut State)
|
||||||
-> Result<(), ConnectionError>
|
-> Result<(), ConnectionError>
|
||||||
{
|
{
|
||||||
let sz = frame.payload().len();
|
let sz = frame.payload().len();
|
||||||
@@ -168,7 +168,7 @@ impl<P: Peer> Recv<P> {
|
|||||||
pub fn expand_stream_window(&mut self,
|
pub fn expand_stream_window(&mut self,
|
||||||
id: StreamId,
|
id: StreamId,
|
||||||
sz: WindowSize,
|
sz: WindowSize,
|
||||||
state: &mut state::Stream)
|
state: &mut State)
|
||||||
-> Result<(), ConnectionError>
|
-> Result<(), ConnectionError>
|
||||||
{
|
{
|
||||||
// TODO: handle overflow
|
// TODO: handle overflow
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use {frame, Peer, ConnectionError};
|
use {frame, Peer, ConnectionError};
|
||||||
use proto::*;
|
use proto::*;
|
||||||
use super::{state, Config, Store};
|
use super::*;
|
||||||
|
|
||||||
use error::User::*;
|
use error::User::*;
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ pub struct Send<P> {
|
|||||||
init_window_sz: WindowSize,
|
init_window_sz: WindowSize,
|
||||||
|
|
||||||
/// Connection level flow control governing sent data
|
/// Connection level flow control governing sent data
|
||||||
flow_control: state::FlowControl,
|
flow_control: FlowControl,
|
||||||
|
|
||||||
/// Holds the list of streams on which local window updates may be sent.
|
/// Holds the list of streams on which local window updates may be sent.
|
||||||
// XXX It would be cool if this didn't exist.
|
// XXX It would be cool if this didn't exist.
|
||||||
@@ -41,7 +41,7 @@ impl<P: Peer> Send<P> {
|
|||||||
max_streams: config.max_local_initiated,
|
max_streams: config.max_local_initiated,
|
||||||
num_streams: 0,
|
num_streams: 0,
|
||||||
init_window_sz: config.init_local_window_sz,
|
init_window_sz: config.init_local_window_sz,
|
||||||
flow_control: state::FlowControl::new(config.init_local_window_sz),
|
flow_control: FlowControl::new(config.init_local_window_sz),
|
||||||
pending_window_updates: VecDeque::new(),
|
pending_window_updates: VecDeque::new(),
|
||||||
blocked: None,
|
blocked: None,
|
||||||
_p: PhantomData,
|
_p: PhantomData,
|
||||||
@@ -51,7 +51,7 @@ impl<P: Peer> Send<P> {
|
|||||||
/// Update state reflecting a new, locally opened stream
|
/// Update state reflecting a new, locally opened stream
|
||||||
///
|
///
|
||||||
/// Returns the stream state if successful. `None` if refused
|
/// Returns the stream state if successful. `None` if refused
|
||||||
pub fn open(&mut self, id: StreamId) -> Result<state::Stream, ConnectionError> {
|
pub fn open(&mut self, id: StreamId) -> Result<State, ConnectionError> {
|
||||||
try!(self.ensure_can_open(id));
|
try!(self.ensure_can_open(id));
|
||||||
|
|
||||||
if let Some(max) = self.max_streams {
|
if let Some(max) = self.max_streams {
|
||||||
@@ -63,16 +63,16 @@ impl<P: Peer> Send<P> {
|
|||||||
// Increment the number of locally initiated streams
|
// Increment the number of locally initiated streams
|
||||||
self.num_streams += 1;
|
self.num_streams += 1;
|
||||||
|
|
||||||
Ok(state::Stream::default())
|
Ok(State::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_headers(&mut self, state: &mut state::Stream, eos: bool)
|
pub fn send_headers(&mut self, state: &mut State, eos: bool)
|
||||||
-> Result<(), ConnectionError>
|
-> Result<(), ConnectionError>
|
||||||
{
|
{
|
||||||
state.send_open(self.init_window_sz, eos)
|
state.send_open(self.init_window_sz, eos)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_eos(&mut self, state: &mut state::Stream)
|
pub fn send_eos(&mut self, state: &mut State)
|
||||||
-> Result<(), ConnectionError>
|
-> Result<(), ConnectionError>
|
||||||
{
|
{
|
||||||
state.send_close()
|
state.send_close()
|
||||||
@@ -80,7 +80,7 @@ impl<P: Peer> Send<P> {
|
|||||||
|
|
||||||
pub fn send_data<B: Buf>(&mut self,
|
pub fn send_data<B: Buf>(&mut self,
|
||||||
frame: &frame::Data<B>,
|
frame: &frame::Data<B>,
|
||||||
state: &mut state::Stream)
|
state: &mut State)
|
||||||
-> Result<(), ConnectionError>
|
-> Result<(), ConnectionError>
|
||||||
{
|
{
|
||||||
let sz = frame.payload().remaining();
|
let sz = frame.payload().remaining();
|
||||||
@@ -171,7 +171,7 @@ impl<P: Peer> Send<P> {
|
|||||||
|
|
||||||
pub fn recv_stream_window_update(&mut self,
|
pub fn recv_stream_window_update(&mut self,
|
||||||
frame: frame::WindowUpdate,
|
frame: frame::WindowUpdate,
|
||||||
state: &mut state::Stream)
|
state: &mut State)
|
||||||
-> Result<(), ConnectionError>
|
-> Result<(), ConnectionError>
|
||||||
{
|
{
|
||||||
if let Some(flow) = state.send_flow_control() {
|
if let Some(flow) = state.send_flow_control() {
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ use error::Reason;
|
|||||||
use error::Reason::*;
|
use error::Reason::*;
|
||||||
use error::User::*;
|
use error::User::*;
|
||||||
use proto::*;
|
use proto::*;
|
||||||
|
use super::FlowControl;
|
||||||
|
|
||||||
|
use self::Inner::*;
|
||||||
|
use self::Peer::*;
|
||||||
|
|
||||||
/// Represents the state of an H2 stream
|
/// Represents the state of an H2 stream
|
||||||
///
|
///
|
||||||
@@ -44,8 +48,13 @@ use proto::*;
|
|||||||
/// ES: END_STREAM flag
|
/// ES: END_STREAM flag
|
||||||
/// R: RST_STREAM frame
|
/// R: RST_STREAM frame
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Stream {
|
pub struct State {
|
||||||
|
inner: Inner,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
enum Inner {
|
||||||
Idle,
|
Idle,
|
||||||
// TODO: these states shouldn't count against concurrency limits:
|
// TODO: these states shouldn't count against concurrency limits:
|
||||||
//ReservedLocal,
|
//ReservedLocal,
|
||||||
@@ -61,34 +70,18 @@ pub enum Stream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum Peer {
|
enum Peer {
|
||||||
AwaitingHeaders,
|
AwaitingHeaders,
|
||||||
/// Contains a FlowControl representing the _receiver_ of this this data stream.
|
/// Contains a FlowControl representing the _receiver_ of this this data stream.
|
||||||
Streaming(FlowControl),
|
Streaming(FlowControl),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
impl State {
|
||||||
pub struct FlowControl {
|
|
||||||
/// Amount that may be claimed.
|
|
||||||
window_size: WindowSize,
|
|
||||||
|
|
||||||
/// Amount to be removed by future increments.
|
|
||||||
underflow: WindowSize,
|
|
||||||
|
|
||||||
/// The amount that has been incremented but not yet advertised (to the application or
|
|
||||||
/// the remote).
|
|
||||||
next_window_update: WindowSize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Stream {
|
|
||||||
/// Opens the send-half of a stream if it is not already open.
|
/// Opens the send-half of a stream if it is not already open.
|
||||||
pub fn send_open(&mut self, sz: WindowSize, eos: bool) -> Result<(), ConnectionError> {
|
pub fn send_open(&mut self, sz: WindowSize, eos: bool) -> Result<(), ConnectionError> {
|
||||||
use self::Stream::*;
|
|
||||||
use self::Peer::*;
|
|
||||||
|
|
||||||
let local = Peer::streaming(sz);
|
let local = Peer::streaming(sz);
|
||||||
|
|
||||||
*self = match *self {
|
self.inner = match self.inner {
|
||||||
Idle => {
|
Idle => {
|
||||||
if eos {
|
if eos {
|
||||||
HalfClosedLocal(AwaitingHeaders)
|
HalfClosedLocal(AwaitingHeaders)
|
||||||
@@ -128,12 +121,9 @@ impl Stream {
|
|||||||
/// Open the receive have of the stream, this action is taken when a HEADERS
|
/// Open the receive have of the stream, this action is taken when a HEADERS
|
||||||
/// frame is received.
|
/// frame is received.
|
||||||
pub fn recv_open(&mut self, sz: WindowSize, eos: bool) -> Result<(), ConnectionError> {
|
pub fn recv_open(&mut self, sz: WindowSize, eos: bool) -> Result<(), ConnectionError> {
|
||||||
use self::Stream::*;
|
|
||||||
use self::Peer::*;
|
|
||||||
|
|
||||||
let remote = Peer::streaming(sz);
|
let remote = Peer::streaming(sz);
|
||||||
|
|
||||||
*self = match *self {
|
self.inner = match self.inner {
|
||||||
Idle => {
|
Idle => {
|
||||||
if eos {
|
if eos {
|
||||||
HalfClosedRemote(AwaitingHeaders)
|
HalfClosedRemote(AwaitingHeaders)
|
||||||
@@ -172,18 +162,16 @@ impl Stream {
|
|||||||
|
|
||||||
/// 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<(), ConnectionError> {
|
pub fn recv_close(&mut self) -> Result<(), ConnectionError> {
|
||||||
use self::Stream::*;
|
match self.inner {
|
||||||
|
|
||||||
match *self {
|
|
||||||
Open { local, .. } => {
|
Open { local, .. } => {
|
||||||
// The remote side will continue to receive data.
|
// The remote side will continue to receive data.
|
||||||
trace!("recv_close: Open => HalfClosedRemote({:?})", local);
|
trace!("recv_close: Open => HalfClosedRemote({:?})", local);
|
||||||
*self = HalfClosedRemote(local);
|
self.inner = HalfClosedRemote(local);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
HalfClosedLocal(..) => {
|
HalfClosedLocal(..) => {
|
||||||
trace!("recv_close: HalfClosedLocal => Closed");
|
trace!("recv_close: HalfClosedLocal => Closed");
|
||||||
*self = Closed(None);
|
self.inner = Closed(None);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
_ => Err(ProtocolError.into()),
|
_ => Err(ProtocolError.into()),
|
||||||
@@ -192,18 +180,16 @@ impl Stream {
|
|||||||
|
|
||||||
/// 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) -> Result<(), ConnectionError> {
|
pub fn send_close(&mut self) -> Result<(), ConnectionError> {
|
||||||
use self::Stream::*;
|
match self.inner {
|
||||||
|
|
||||||
match *self {
|
|
||||||
Open { remote, .. } => {
|
Open { remote, .. } => {
|
||||||
// The remote side will continue to receive data.
|
// The remote side will continue to receive data.
|
||||||
trace!("send_close: Open => HalfClosedLocal({:?})", remote);
|
trace!("send_close: Open => HalfClosedLocal({:?})", remote);
|
||||||
*self = HalfClosedLocal(remote);
|
self.inner = HalfClosedLocal(remote);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
HalfClosedRemote(..) => {
|
HalfClosedRemote(..) => {
|
||||||
trace!("send_close: HalfClosedRemote => Closed");
|
trace!("send_close: HalfClosedRemote => Closed");
|
||||||
*self = Closed(None);
|
self.inner = Closed(None);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
_ => Err(ProtocolError.into()),
|
_ => Err(ProtocolError.into()),
|
||||||
@@ -211,18 +197,14 @@ impl Stream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_closed(&self) -> bool {
|
pub fn is_closed(&self) -> bool {
|
||||||
use self::Stream::*;
|
match self.inner {
|
||||||
|
|
||||||
match *self {
|
|
||||||
Closed(_) => true,
|
Closed(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recv_flow_control(&mut self) -> Option<&mut FlowControl> {
|
pub fn recv_flow_control(&mut self) -> Option<&mut FlowControl> {
|
||||||
use self::Stream::*;
|
match self.inner {
|
||||||
|
|
||||||
match *self {
|
|
||||||
Open { ref mut remote, .. } |
|
Open { ref mut remote, .. } |
|
||||||
HalfClosedLocal(ref mut remote) => remote.flow_control(),
|
HalfClosedLocal(ref mut remote) => remote.flow_control(),
|
||||||
_ => None,
|
_ => None,
|
||||||
@@ -230,9 +212,7 @@ impl Stream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_flow_control(&mut self) -> Option<&mut FlowControl> {
|
pub fn send_flow_control(&mut self) -> Option<&mut FlowControl> {
|
||||||
use self::Stream::*;
|
match self.inner {
|
||||||
|
|
||||||
match *self {
|
|
||||||
Open { ref mut local, .. } |
|
Open { ref mut local, .. } |
|
||||||
HalfClosedRemote(ref mut local) => local.flow_control(),
|
HalfClosedRemote(ref mut local) => local.flow_control(),
|
||||||
_ => None,
|
_ => None,
|
||||||
@@ -240,9 +220,9 @@ impl Stream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Stream {
|
impl Default for State {
|
||||||
fn default() -> Stream {
|
fn default() -> State {
|
||||||
Stream::Idle
|
State { inner: Inner::Idle }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,81 +238,9 @@ impl Peer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn flow_control(&mut self) -> Option<&mut FlowControl> {
|
fn flow_control(&mut self) -> Option<&mut FlowControl> {
|
||||||
use self::Peer::*;
|
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Streaming(ref mut flow) => Some(flow),
|
Streaming(ref mut flow) => Some(flow),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FlowControl {
|
|
||||||
pub fn new(window_size: WindowSize) -> FlowControl {
|
|
||||||
FlowControl {
|
|
||||||
window_size,
|
|
||||||
underflow: 0,
|
|
||||||
next_window_update: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true iff `claim_window(sz)` would return succeed.
|
|
||||||
pub fn ensure_window<T>(&mut self, sz: WindowSize, err: T) -> Result<(), ConnectionError>
|
|
||||||
where T: Into<ConnectionError>,
|
|
||||||
{
|
|
||||||
if sz <= self.window_size {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(err.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Claims the provided amount from the window, if there is enough space.
|
|
||||||
///
|
|
||||||
/// Fails when `apply_window_update()` hasn't returned at least `sz` more bytes than
|
|
||||||
/// have been previously claimed.
|
|
||||||
pub fn claim_window<T>(&mut self, sz: WindowSize, err: T)
|
|
||||||
-> Result<(), ConnectionError>
|
|
||||||
where T: Into<ConnectionError>,
|
|
||||||
{
|
|
||||||
self.ensure_window(sz, err)?;
|
|
||||||
|
|
||||||
self.window_size -= sz;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Increase the _unadvertised_ window capacity.
|
|
||||||
pub fn expand_window(&mut self, sz: WindowSize) {
|
|
||||||
if sz <= self.underflow {
|
|
||||||
self.underflow -= sz;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let added = sz - self.underflow;
|
|
||||||
self.next_window_update += added;
|
|
||||||
self.underflow = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Obtains the unadvertised window update.
|
|
||||||
///
|
|
||||||
/// This does not apply the window update to `self`.
|
|
||||||
pub fn peek_window_update(&mut self) -> Option<WindowSize> {
|
|
||||||
if self.next_window_update == 0 {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(self.next_window_update)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Obtains and applies an unadvertised window update.
|
|
||||||
pub fn apply_window_update(&mut self) -> Option<WindowSize> {
|
|
||||||
if self.next_window_update == 0 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let incr = self.next_window_update;
|
|
||||||
self.next_window_update = 0;
|
|
||||||
self.window_size += incr;
|
|
||||||
Some(incr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
extern crate slab;
|
extern crate slab;
|
||||||
|
|
||||||
use proto::*;
|
use super::*;
|
||||||
use super::state;
|
|
||||||
|
|
||||||
use std::collections::{HashMap, hash_map};
|
use std::collections::{HashMap, hash_map};
|
||||||
|
|
||||||
/// Storage for streams
|
/// Storage for streams
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Store {
|
pub struct Store {
|
||||||
slab: slab::Slab<state::Stream>,
|
slab: slab::Slab<State>,
|
||||||
ids: HashMap<StreamId, usize>,
|
ids: HashMap<StreamId, usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,12 +18,12 @@ pub enum Entry<'a> {
|
|||||||
|
|
||||||
pub struct OccupiedEntry<'a> {
|
pub struct OccupiedEntry<'a> {
|
||||||
ids: hash_map::OccupiedEntry<'a, StreamId, usize>,
|
ids: hash_map::OccupiedEntry<'a, StreamId, usize>,
|
||||||
slab: &'a mut slab::Slab<state::Stream>,
|
slab: &'a mut slab::Slab<State>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VacantEntry<'a> {
|
pub struct VacantEntry<'a> {
|
||||||
ids: hash_map::VacantEntry<'a, StreamId, usize>,
|
ids: hash_map::VacantEntry<'a, StreamId, usize>,
|
||||||
slab: &'a mut slab::Slab<state::Stream>,
|
slab: &'a mut slab::Slab<State>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Store {
|
impl Store {
|
||||||
@@ -35,7 +34,7 @@ impl Store {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_mut(&mut self, id: &StreamId) -> Option<&mut state::Stream> {
|
pub fn get_mut(&mut self, id: &StreamId) -> Option<&mut State> {
|
||||||
if let Some(handle) = self.ids.get(id) {
|
if let Some(handle) = self.ids.get(id) {
|
||||||
Some(&mut self.slab[*handle])
|
Some(&mut self.slab[*handle])
|
||||||
} else {
|
} else {
|
||||||
@@ -64,13 +63,13 @@ impl Store {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> OccupiedEntry<'a> {
|
impl<'a> OccupiedEntry<'a> {
|
||||||
pub fn into_mut(self) -> &'a mut state::Stream {
|
pub fn into_mut(self) -> &'a mut State {
|
||||||
&mut self.slab[*self.ids.get()]
|
&mut self.slab[*self.ids.get()]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> VacantEntry<'a> {
|
impl<'a> VacantEntry<'a> {
|
||||||
pub fn insert(self, value: state::Stream) -> &'a mut state::Stream {
|
pub fn insert(self, value: State) -> &'a mut State {
|
||||||
// Insert the value in the slab
|
// Insert the value in the slab
|
||||||
let handle = self.slab.insert(value);
|
let handle = self.slab.insert(value);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user