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