Simplify control streams (#8)
This commit is contained in:
		| @@ -52,16 +52,8 @@ impl Peer for Client { | |||||||
|     type Send = http::request::Head; |     type Send = http::request::Head; | ||||||
|     type Poll = http::response::Head; |     type Poll = http::response::Head; | ||||||
|  |  | ||||||
|     fn is_valid_local_stream_id(id: StreamId) -> bool { |     fn is_server() -> bool { | ||||||
|         id.is_client_initiated() |         false | ||||||
|     } |  | ||||||
|  |  | ||||||
|     fn is_valid_remote_stream_id(id: StreamId) -> bool { |  | ||||||
|         id.is_server_initiated() |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     fn local_can_open() -> bool { |  | ||||||
|         true |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn convert_send_message( |     fn convert_send_message( | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								src/lib.rs
									
									
									
									
									
								
							| @@ -77,23 +77,7 @@ pub trait Peer { | |||||||
|     /// Message type polled from the transport |     /// Message type polled from the transport | ||||||
|     type Poll; |     type Poll; | ||||||
|  |  | ||||||
|     /// Returns `true` if `id` is a valid StreamId for a stream initiated by the |     fn is_server() -> bool; | ||||||
|     /// local node. |  | ||||||
|     fn is_valid_local_stream_id(id: StreamId) -> bool; |  | ||||||
|  |  | ||||||
|     /// Returns `true` if `id` is a valid StreamId for a stream initiated by the |  | ||||||
|     /// remote node. |  | ||||||
|     fn is_valid_remote_stream_id(id: StreamId) -> bool; |  | ||||||
|  |  | ||||||
|     fn local_can_open() -> bool; |  | ||||||
|     fn remote_can_open() -> bool { |  | ||||||
|         !Self::local_can_open() |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     //fn can_reserve_local_stream() -> bool; |  | ||||||
|     // fn can_reserve_remote_stream() -> bool { |  | ||||||
|     //     !self.can_reserve_local_stream |  | ||||||
|     // } |  | ||||||
|  |  | ||||||
|     #[doc(hidden)] |     #[doc(hidden)] | ||||||
|     fn convert_send_message( |     fn convert_send_message( | ||||||
|   | |||||||
| @@ -13,13 +13,13 @@ use std::marker::PhantomData; | |||||||
| /// An H2 connection | /// An H2 connection | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct Connection<T, P, B: IntoBuf = Bytes> { | pub struct Connection<T, P, B: IntoBuf = Bytes> { | ||||||
|     inner: Transport<T, P, B::Buf>, |     inner: Transport<T, B::Buf>, | ||||||
|     // Set to `true` as long as the connection is in a valid state. |     // Set to `true` as long as the connection is in a valid state. | ||||||
|     active: bool, |     active: bool, | ||||||
|     _phantom: PhantomData<(P, B)>, |     _phantom: PhantomData<(P, B)>, | ||||||
| } | } | ||||||
|  |  | ||||||
| pub fn new<T, P, B>(transport: Transport<T, P, B::Buf>) | pub fn new<T, P, B>(transport: Transport<T, B::Buf>) | ||||||
|     -> Connection<T, P, B> |     -> Connection<T, P, B> | ||||||
|     where T: AsyncRead + AsyncWrite, |     where T: AsyncRead + AsyncWrite, | ||||||
|           P: Peer, |           P: Peer, | ||||||
|   | |||||||
| @@ -1,204 +1,22 @@ | |||||||
| use ConnectionError; |  | ||||||
| use proto::*; | use proto::*; | ||||||
|  |  | ||||||
| /// Exposes stream states to "upper" layers of the transport (i.e. from StreamTracker up | /// Exposes stream states to "upper" layers of the transport (i.e. from StreamTracker up | ||||||
| /// to Connection). | /// to Connection). | ||||||
| pub trait ControlStreams { | pub trait ControlStreams { | ||||||
|     /// Determines whether the given stream could theoretically be opened by the local |     fn streams(&self) -> &Streams; | ||||||
|     /// side of this connection. |  | ||||||
|     fn local_valid_id(id: StreamId) -> bool; |  | ||||||
|  |  | ||||||
|     /// Determines whether the given stream could theoretically be opened by the remote |     fn streams_mut(&mut self) -> &mut Streams; | ||||||
|     /// side of this connection. |  | ||||||
|     fn remote_valid_id(id: StreamId) -> bool; |  | ||||||
|  |  | ||||||
|     /// Indicates whether this local endpoint may open streams (with HEADERS). |  | ||||||
|     /// |  | ||||||
|     /// Implies that this endpoint is a client. |  | ||||||
|     fn local_can_open() -> bool; |  | ||||||
|  |  | ||||||
|     /// Indicates whether this remote endpoint may open streams (with HEADERS). |  | ||||||
|     /// |  | ||||||
|     /// Implies that this endpoint is a server. |  | ||||||
|     fn remote_can_open() -> bool { |  | ||||||
|         !Self::local_can_open() |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // TODO push promise |  | ||||||
|     // fn local_can_reserve(&mut self, id: StreamId) -> Result<(), ConnectionError>; |  | ||||||
|     // fn remote_can_reserve(&mut self, id: StreamId) -> Result<(), ConnectionError>; |  | ||||||
|  |  | ||||||
|     /// Creates a new stream in the OPEN state from the local side (i.e. as a Client). |  | ||||||
|     /// |  | ||||||
|     /// Must only be called when local_can_open returns true. |  | ||||||
|     fn local_open(&mut self, id: StreamId, sz: WindowSize) -> Result<(), ConnectionError>; |  | ||||||
|  |  | ||||||
|     /// Create a new stream in the OPEN state from the remote side (i.e. as a Server). |  | ||||||
|     /// |  | ||||||
|     /// Must only be called when remote_can_open returns true. |  | ||||||
|     fn remote_open(&mut self, id: StreamId, sz: WindowSize) -> Result<(), ConnectionError>; |  | ||||||
|  |  | ||||||
|     /// Prepare the receive side of a local stream to receive data from the remote. |  | ||||||
|     /// |  | ||||||
|     /// Typically called when a client receives a response header. |  | ||||||
|     fn local_open_recv_half(&mut self, id: StreamId, sz: WindowSize) -> Result<(), ConnectionError>; |  | ||||||
|  |  | ||||||
|     /// Prepare the send side of a remote stream to receive data from the local endpoint. |  | ||||||
|     /// |  | ||||||
|     /// Typically called when a server sends a response header. |  | ||||||
|     fn remote_open_send_half(&mut self, id: StreamId, sz: WindowSize) -> Result<(), ConnectionError>; |  | ||||||
|  |  | ||||||
|     // TODO push promise |  | ||||||
|     // fn local_reserve(&mut self, id: StreamId) -> Result<(), ConnectionError>; |  | ||||||
|     // fn remote_reserve(&mut self, id: StreamId) -> Result<(), ConnectionError>; |  | ||||||
|  |  | ||||||
|     /// Closes the send half of a stream. |  | ||||||
|     /// |  | ||||||
|     /// Fails with a ProtocolError if send half of the stream was not open. |  | ||||||
|     fn close_send_half(&mut self, id: StreamId) -> Result<(), ConnectionError>; |  | ||||||
|  |  | ||||||
|     /// Closes the recv half of a stream. |  | ||||||
|     /// |  | ||||||
|     /// Fails with a ProtocolError if recv half of the stream was not open. |  | ||||||
|     fn close_recv_half(&mut self, id: StreamId) -> Result<(), ConnectionError>; |  | ||||||
|  |  | ||||||
|     /// Resets the given stream. |  | ||||||
|     /// |  | ||||||
|     /// If the stream was already reset, the stored cause is updated. |  | ||||||
|     fn reset_stream(&mut self, id: StreamId, cause: Reason); |  | ||||||
|  |  | ||||||
|     /// Get the reason the stream was reset, if it was reset. |  | ||||||
|     fn get_reset(&self, id: StreamId) -> Option<Reason>; |  | ||||||
|  |  | ||||||
|     /// Returns true if the given stream was opened by the local peer and is not yet |  | ||||||
|     /// closed. |  | ||||||
|     fn is_local_active(&self, id: StreamId) -> bool; |  | ||||||
|  |  | ||||||
|     /// Returns true if the given stream was opened by the remote peer and is not yet |  | ||||||
|     /// closed. |  | ||||||
|     fn is_remote_active(&self, id: StreamId) -> bool; |  | ||||||
|  |  | ||||||
|     /// Returns true if the given stream was opened and is not yet closed. |  | ||||||
|     fn is_active(&self, id: StreamId) -> bool { |  | ||||||
|         if Self::local_valid_id(id) { |  | ||||||
|             self.is_local_active(id) |  | ||||||
|         } else { |  | ||||||
|             self.is_remote_active(id) |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /// Returns the number of open streams initiated by the local peer. |  | ||||||
|     fn local_active_len(&self) -> usize; |  | ||||||
|  |  | ||||||
|     /// Returns the number of open streams initiated by the remote peer. |  | ||||||
|     fn remote_active_len(&self) -> usize; |  | ||||||
|  |  | ||||||
|     /// Returns true iff the recv half of the given stream is open. |  | ||||||
|     fn is_recv_open(&mut self, id: StreamId) -> bool; |  | ||||||
|  |  | ||||||
|     /// Returns true iff the send half of the given stream is open. |  | ||||||
|     fn is_send_open(&mut self, id: StreamId) -> bool; |  | ||||||
|  |  | ||||||
|     /// If the given stream ID is active and able to recv data, get its mutable recv flow |  | ||||||
|     /// control state. |  | ||||||
|     fn recv_flow_controller(&mut self, id: StreamId) -> Option<&mut FlowControlState>; |  | ||||||
|  |  | ||||||
|     /// If the given stream ID is active and able to send data, get its mutable send flow |  | ||||||
|     /// control state. |  | ||||||
|     fn send_flow_controller(&mut self, id: StreamId) -> Option<&mut FlowControlState>; |  | ||||||
|  |  | ||||||
|     /// Updates the initial window size for the local peer. |  | ||||||
|     fn update_inital_recv_window_size(&mut self, old_sz: WindowSize, new_sz: WindowSize); |  | ||||||
|  |  | ||||||
|     /// Updates the initial window size for the remote peer. |  | ||||||
|     fn update_inital_send_window_size(&mut self, old_sz: WindowSize, new_sz: WindowSize); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| macro_rules! proxy_control_streams { | macro_rules! proxy_control_streams { | ||||||
|     ($outer:ident) => ( |     ($outer:ident) => ( | ||||||
|         impl<T: ControlStreams> ControlStreams for $outer<T> { |         impl<T: ControlStreams> ControlStreams for $outer<T> { | ||||||
|             fn local_valid_id(id: StreamId) -> bool { |             fn streams(&self) -> &Streams { | ||||||
|                 T::local_valid_id(id) |                 self.inner.streams() | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             fn remote_valid_id(id: StreamId) -> bool { |             fn streams_mut(&mut self) -> &mut Streams { | ||||||
|                 T::remote_valid_id(id) |                 self.inner.streams_mut() | ||||||
|             } |  | ||||||
|  |  | ||||||
|             fn local_can_open() -> bool { |  | ||||||
|                 T::local_can_open() |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             fn local_open(&mut self, id: StreamId, sz: WindowSize) -> Result<(), ConnectionError> { |  | ||||||
|                 self.inner.local_open(id, sz) |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             fn remote_open(&mut self, id: StreamId, sz: WindowSize) -> Result<(), ConnectionError> { |  | ||||||
|                 self.inner.remote_open(id, sz) |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             fn local_open_recv_half(&mut self, id: StreamId, sz: WindowSize) -> Result<(), ConnectionError> { |  | ||||||
|                 self.inner.local_open_recv_half(id, sz) |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             fn remote_open_send_half(&mut self, id: StreamId, sz: WindowSize) -> Result<(), ConnectionError> { |  | ||||||
|                 self.inner.remote_open_send_half(id, sz) |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             fn close_send_half(&mut self, id: StreamId) -> Result<(), ConnectionError> { |  | ||||||
|                 self.inner.close_send_half(id) |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             fn close_recv_half(&mut self, id: StreamId) -> Result<(), ConnectionError> { |  | ||||||
|                 self.inner.close_recv_half(id) |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             fn reset_stream(&mut self, id: StreamId, cause: Reason) { |  | ||||||
|                 self.inner.reset_stream(id, cause) |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             fn get_reset(&self, id: StreamId) -> Option<Reason> { |  | ||||||
|                 self.inner.get_reset(id) |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             fn is_local_active(&self, id: StreamId) -> bool { |  | ||||||
|                 self.inner.is_local_active(id) |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             fn is_remote_active(&self, id: StreamId) -> bool { |  | ||||||
|                 self.inner.is_remote_active(id) |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             fn local_active_len(&self) -> usize { |  | ||||||
|                 self.inner.local_active_len() |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             fn remote_active_len(&self) -> usize { |  | ||||||
|                 self.inner.remote_active_len() |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             fn update_inital_recv_window_size(&mut self, old_sz: WindowSize, new_sz: WindowSize) { |  | ||||||
|                 self.inner.update_inital_recv_window_size(old_sz, new_sz) |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             fn update_inital_send_window_size(&mut self, old_sz: WindowSize, new_sz: WindowSize) { |  | ||||||
|                 self.inner.update_inital_send_window_size(old_sz, new_sz) |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             fn recv_flow_controller(&mut self, id: StreamId) -> Option<&mut FlowControlState> { |  | ||||||
|                 self.inner.recv_flow_controller(id) |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             fn send_flow_controller(&mut self, id: StreamId) -> Option<&mut FlowControlState> { |  | ||||||
|                 self.inner.send_flow_controller(id) |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             fn is_send_open(&mut self, id: StreamId) -> bool { |  | ||||||
|                 self.inner.is_send_open(id) |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             fn is_recv_open(&mut self, id: StreamId) -> bool  { |  | ||||||
|                 self.inner.is_recv_open(id) |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     ) |     ) | ||||||
|   | |||||||
| @@ -44,7 +44,7 @@ impl<T, U> FlowControlRecv<T> | |||||||
| /// Exposes a public upward API for flow control. | /// Exposes a public upward API for flow control. | ||||||
| impl<T: ControlStreams> ControlFlowRecv for FlowControlRecv<T> { | impl<T: ControlStreams> ControlFlowRecv for FlowControlRecv<T> { | ||||||
|     fn expand_window(&mut self, id: StreamId, incr: WindowSize) -> Result<(), ConnectionError> { |     fn expand_window(&mut self, id: StreamId, incr: WindowSize) -> Result<(), ConnectionError> { | ||||||
|         let added = match self.recv_flow_controller(id) { |         let added = match self.streams_mut().recv_flow_controller(id) { | ||||||
|             None => false, |             None => false, | ||||||
|             Some(mut fc) => { |             Some(mut fc) => { | ||||||
|                 fc.expand_window(incr); |                 fc.expand_window(incr); | ||||||
| @@ -57,7 +57,7 @@ impl<T: ControlStreams> ControlFlowRecv for FlowControlRecv<T> { | |||||||
|                 self.pending_streams.push_back(id); |                 self.pending_streams.push_back(id); | ||||||
|             } |             } | ||||||
|             Ok(()) |             Ok(()) | ||||||
|         } else if let Some(rst) = self.inner.get_reset(id) { |         } else if let Some(rst) = self.streams().get_reset(id) { | ||||||
|             Err(error::User::StreamReset(rst).into()) |             Err(error::User::StreamReset(rst).into()) | ||||||
|         } else { |         } else { | ||||||
|             Err(error::User::InvalidStreamId.into()) |             Err(error::User::InvalidStreamId.into()) | ||||||
| @@ -80,8 +80,8 @@ impl<T, U> FlowControlRecv<T> | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         while let Some(id) = self.pending_streams.pop_front() { |         while let Some(id) = self.pending_streams.pop_front() { | ||||||
|             if self.inner.get_reset(id).is_none() { |             if self.streams().get_reset(id).is_none() { | ||||||
|                 let update = self.recv_flow_controller(id).and_then(|s| s.apply_window_update()); |                 let update = self.streams_mut().recv_flow_controller(id).and_then(|s| s.apply_window_update()); | ||||||
|                 if let Some(incr) = update { |                 if let Some(incr) = update { | ||||||
|                     try_ready!(self.try_send(frame::WindowUpdate::new(id, incr))); |                     try_ready!(self.try_send(frame::WindowUpdate::new(id, incr))); | ||||||
|                 } |                 } | ||||||
| @@ -124,8 +124,9 @@ impl<T> Stream for FlowControlRecv<T> | |||||||
|                         return Err(error::Reason::FlowControlError.into()); |                         return Err(error::Reason::FlowControlError.into()); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     let fc = self.inner.recv_flow_controller(id) |                     let fc = self.inner.streams_mut().recv_flow_controller(id) | ||||||
|                         .expect("receiving data with no flow controller"); |                         .expect("receiving data with no flow controller"); | ||||||
|  |  | ||||||
|                     if fc.claim_window(sz).is_err() { |                     if fc.claim_window(sz).is_err() { | ||||||
|                         // TODO this should cause a GO_AWAY |                         // TODO this should cause a GO_AWAY | ||||||
|                         return Err(error::Reason::FlowControlError.into()); |                         return Err(error::Reason::FlowControlError.into()); | ||||||
| @@ -206,7 +207,7 @@ impl<T> ApplySettings for FlowControlRecv<T> | |||||||
|                 return Ok(()); |                 return Ok(()); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             self.inner.update_inital_recv_window_size(old_window_size, new_window_size); |             self.streams_mut().update_inital_recv_window_size(old_window_size, new_window_size); | ||||||
|             self.initial_window_size = new_window_size; |             self.initial_window_size = new_window_size; | ||||||
|         } |         } | ||||||
|         Ok(()) |         Ok(()) | ||||||
|   | |||||||
| @@ -50,7 +50,7 @@ impl<T: ControlStreams> ControlFlowSend for FlowControlSend<T> { | |||||||
|  |  | ||||||
|         // TODO this should probably account for stream priority? |         // TODO this should probably account for stream priority? | ||||||
|         while let Some(id) = self.pending_streams.pop_front() { |         while let Some(id) = self.pending_streams.pop_front() { | ||||||
|             if let Some(mut flow) = self.send_flow_controller(id) { |             if let Some(mut flow) = self.streams_mut().send_flow_controller(id) { | ||||||
|                 if let Some(incr) = flow.apply_window_update() { |                 if let Some(incr) = flow.apply_window_update() { | ||||||
|                     return Ok(Async::Ready(WindowUpdate::new(id, incr))); |                     return Ok(Async::Ready(WindowUpdate::new(id, incr))); | ||||||
|                 } |                 } | ||||||
| @@ -84,7 +84,7 @@ impl<T> Stream for FlowControlSend<T> | |||||||
|                     } else { |                     } else { | ||||||
|                         // The remote may send window updates for streams that the local |                         // The remote may send window updates for streams that the local | ||||||
|                         // now considers closed. It's okay. |                         // now considers closed. It's okay. | ||||||
|                         if let Some(fc) = self.inner.send_flow_controller(id) { |                         if let Some(fc) = self.streams_mut().send_flow_controller(id) { | ||||||
|                             fc.expand_window(sz); |                             fc.expand_window(sz); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
| @@ -110,7 +110,7 @@ impl<T, U> Sink for FlowControlSend<T> | |||||||
|     type SinkError = T::SinkError; |     type SinkError = T::SinkError; | ||||||
|  |  | ||||||
|     fn start_send(&mut self, frame: Frame<U>) -> StartSend<T::SinkItem, T::SinkError> { |     fn start_send(&mut self, frame: Frame<U>) -> StartSend<T::SinkItem, T::SinkError> { | ||||||
|         debug_assert!(self.inner.get_reset(frame.stream_id()).is_none()); |         debug_assert!(self.streams().get_reset(frame.stream_id()).is_none()); | ||||||
|  |  | ||||||
|         // Ensures that the underlying transport is will accept the frame. It's important |         // Ensures that the underlying transport is will accept the frame. It's important | ||||||
|         //  that this be checked before claiming capacity from the flow controllers. |         //  that this be checked before claiming capacity from the flow controllers. | ||||||
| @@ -130,8 +130,9 @@ impl<T, U> Sink for FlowControlSend<T> | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             // Ensure there's enough capacity on stream. |             // Ensure there's enough capacity on stream. | ||||||
|             let mut fc = self.inner.send_flow_controller(v.stream_id()) |             let mut fc = self.inner.streams_mut().send_flow_controller(v.stream_id()) | ||||||
|                 .expect("no remote stream for data frame"); |                 .expect("no remote stream for data frame"); | ||||||
|  |  | ||||||
|             if fc.claim_window(sz).is_err() { |             if fc.claim_window(sz).is_err() { | ||||||
|                 return Err(error::User::FlowControlViolation.into()) |                 return Err(error::User::FlowControlViolation.into()) | ||||||
|             } |             } | ||||||
| @@ -195,7 +196,7 @@ impl<T> ApplySettings for FlowControlSend<T> | |||||||
|                 return Ok(()); |                 return Ok(()); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             self.inner.update_inital_send_window_size(old_window_size, new_window_size); |             self.streams_mut().update_inital_send_window_size(old_window_size, new_window_size); | ||||||
|             self.initial_window_size = new_window_size; |             self.initial_window_size = new_window_size; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -97,7 +97,7 @@ use self::stream_recv_close::StreamRecvClose; | |||||||
| use self::stream_recv_open::StreamRecvOpen; | use self::stream_recv_open::StreamRecvOpen; | ||||||
| use self::stream_send_close::StreamSendClose; | use self::stream_send_close::StreamSendClose; | ||||||
| use self::stream_send_open::StreamSendOpen; | use self::stream_send_open::StreamSendOpen; | ||||||
| use self::stream_states::StreamStates; | use self::stream_states::{StreamStates, Streams}; | ||||||
|  |  | ||||||
| /// Represents the internals of an HTTP/2 connection. | /// Represents the internals of an HTTP/2 connection. | ||||||
| /// | /// | ||||||
| @@ -187,22 +187,22 @@ use self::stream_states::StreamStates; | |||||||
| /// | /// | ||||||
| /// - Encodes frames to bytes. | /// - Encodes frames to bytes. | ||||||
| /// | /// | ||||||
| type Transport<T, P, B>= | type Transport<T, B>= | ||||||
|     Settings< |     Settings< | ||||||
|         Streams< |         Streams2< | ||||||
|             PingPong< |             PingPong< | ||||||
|                 Codec<T, B>, |                 Codec<T, B>, | ||||||
|                 B>, |                 B>>>; | ||||||
|             P>>; |  | ||||||
|  |  | ||||||
| type Streams<T, P> = | // TODO: rename | ||||||
|  | type Streams2<T> = | ||||||
|     StreamSendOpen< |     StreamSendOpen< | ||||||
|         FlowControlSend< |         FlowControlSend< | ||||||
|             StreamSendClose< |             StreamSendClose< | ||||||
|                 StreamRecvClose< |                 StreamRecvClose< | ||||||
|                     FlowControlRecv< |                     FlowControlRecv< | ||||||
|                         StreamRecvOpen< |                         StreamRecvOpen< | ||||||
|                             StreamStates<T, P>>>>>>>; |                             StreamStates<T>>>>>>>; | ||||||
|  |  | ||||||
| type Codec<T, B> = | type Codec<T, B> = | ||||||
|     FramedRead< |     FramedRead< | ||||||
| @@ -303,7 +303,7 @@ pub fn from_server_handshaker<T, P, B>(settings: Settings<FramedWrite<T, B::Buf> | |||||||
|                             StreamRecvOpen::new( |                             StreamRecvOpen::new( | ||||||
|                                 initial_recv_window_size, |                                 initial_recv_window_size, | ||||||
|                                 local_max_concurrency, |                                 local_max_concurrency, | ||||||
|                                 StreamStates::new( |                                 StreamStates::new::<P>( | ||||||
|                                     PingPong::new( |                                     PingPong::new( | ||||||
|                                         FramedRead::new(framed))))))))) |                                         FramedRead::new(framed))))))))) | ||||||
|     }); |     }); | ||||||
|   | |||||||
| @@ -1,5 +1,4 @@ | |||||||
| use ConnectionError; | use ConnectionError; | ||||||
| use error::Reason; |  | ||||||
| use frame::{self, Frame}; | use frame::{self, Frame}; | ||||||
| use proto::*; | use proto::*; | ||||||
| use proto::ready::ReadySink; | use proto::ready::ReadySink; | ||||||
| @@ -39,10 +38,10 @@ impl<T> Stream for StreamRecvClose<T> | |||||||
|             if frame.is_end_stream() { |             if frame.is_end_stream() { | ||||||
|                 trace!("poll: id={:?} eos", id); |                 trace!("poll: id={:?} eos", id); | ||||||
|                 if let &Frame::Reset(ref rst) = &frame { |                 if let &Frame::Reset(ref rst) = &frame { | ||||||
|                     self.inner.reset_stream(id, rst.reason()); |                     self.streams_mut().reset_stream(id, rst.reason()); | ||||||
|                 } else { |                 } else { | ||||||
|                     debug_assert!(self.inner.is_active(id)); |                     debug_assert!(self.streams().is_active(id)); | ||||||
|                     self.inner.close_recv_half(id)?; |                     self.streams_mut().close_recv_half(id)?; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -42,7 +42,7 @@ impl<T, U> StreamRecvOpen<T> | |||||||
|         let f = frame::Reset::new(id, RefusedStream); |         let f = frame::Reset::new(id, RefusedStream); | ||||||
|         match self.inner.start_send(f.into())? { |         match self.inner.start_send(f.into())? { | ||||||
|             AsyncSink::Ready => { |             AsyncSink::Ready => { | ||||||
|                 self.inner.reset_stream(id, RefusedStream); |                 self.streams_mut().reset_stream(id, RefusedStream); | ||||||
|                 Ok(Async::Ready(())) |                 Ok(Async::Ready(())) | ||||||
|             } |             } | ||||||
|             AsyncSink::NotReady(_) => { |             AsyncSink::NotReady(_) => { | ||||||
| @@ -81,7 +81,7 @@ impl<T> ApplySettings for StreamRecvOpen<T> | |||||||
| impl<T: ControlStreams> StreamRecvOpen<T> { | impl<T: ControlStreams> StreamRecvOpen<T> { | ||||||
|     fn check_not_reset(&self, id: StreamId) -> Result<(), ConnectionError> { |     fn check_not_reset(&self, id: StreamId) -> Result<(), ConnectionError> { | ||||||
|         // Ensure that the stream hasn't been closed otherwise. |         // Ensure that the stream hasn't been closed otherwise. | ||||||
|         match self.inner.get_reset(id) { |         match self.streams().get_reset(id) { | ||||||
|             Some(reason) => Err(reason.into()), |             Some(reason) => Err(reason.into()), | ||||||
|             None => Ok(()), |             None => Ok(()), | ||||||
|         } |         } | ||||||
| @@ -127,20 +127,20 @@ impl<T, U> Stream for StreamRecvOpen<T> | |||||||
|                 &Frame::Headers(..) => { |                 &Frame::Headers(..) => { | ||||||
|                     self.check_not_reset(id)?; |                     self.check_not_reset(id)?; | ||||||
|  |  | ||||||
|                     if T::remote_valid_id(id) { |                     if self.streams().is_valid_remote_stream_id(id) { | ||||||
|                         if self.inner.is_remote_active(id) { |                         if self.streams().is_remote_active(id) { | ||||||
|                             // Can't send a a HEADERS frame on a remote stream that's |                             // Can't send a a HEADERS frame on a remote stream that's | ||||||
|                             // active, because we've already received headers.  This will |                             // active, because we've already received headers.  This will | ||||||
|                             // have to change to support PUSH_PROMISE. |                             // have to change to support PUSH_PROMISE. | ||||||
|                             return Err(ProtocolError.into()); |                             return Err(ProtocolError.into()); | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                         if !T::remote_can_open() { |                         if !self.streams().can_remote_open() { | ||||||
|                             return Err(ProtocolError.into()); |                             return Err(ProtocolError.into()); | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                         if let Some(max) = self.max_concurrency { |                         if let Some(max) = self.max_concurrency { | ||||||
|                             if (max as usize) < self.inner.remote_active_len() { |                             if (max as usize) < self.streams().remote_active_len() { | ||||||
|                                 debug!("refusing stream that would exceed max_concurrency={}", max); |                                 debug!("refusing stream that would exceed max_concurrency={}", max); | ||||||
|                                 self.send_refuse(id)?; |                                 self.send_refuse(id)?; | ||||||
|  |  | ||||||
| @@ -149,17 +149,17 @@ impl<T, U> Stream for StreamRecvOpen<T> | |||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                         self.inner.remote_open(id, self.initial_window_size)?; |                         self.inner.streams_mut().remote_open(id, self.initial_window_size)?; | ||||||
|                     } else { |                     } else { | ||||||
|                         // On remote streams, |                         // On remote streams, | ||||||
|                         self.inner.local_open_recv_half(id, self.initial_window_size)?; |                         self.inner.streams_mut().local_open_recv_half(id, self.initial_window_size)?; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 // All other stream frames are sent only when |                 // All other stream frames are sent only when | ||||||
|                 _ => { |                 _ => { | ||||||
|                     self.check_not_reset(id)?; |                     self.check_not_reset(id)?; | ||||||
|                     if !self.inner.is_recv_open(id) { |                     if !self.streams().is_recv_open(id) { | ||||||
|                         return Err(ProtocolError.into()); |                         return Err(ProtocolError.into()); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|   | |||||||
| @@ -1,5 +1,4 @@ | |||||||
| use ConnectionError; | use ConnectionError; | ||||||
| use error::Reason; |  | ||||||
| use frame::{self, Frame}; | use frame::{self, Frame}; | ||||||
| use proto::*; | use proto::*; | ||||||
|  |  | ||||||
| @@ -34,10 +33,10 @@ impl<T, U> Sink for StreamSendClose<T> | |||||||
|         if !id.is_zero() { |         if !id.is_zero() { | ||||||
|             if eos { |             if eos { | ||||||
|                 if let &Frame::Reset(ref rst) = &frame { |                 if let &Frame::Reset(ref rst) = &frame { | ||||||
|                     self.inner.reset_stream(id, rst.reason()); |                     self.streams_mut().reset_stream(id, rst.reason()); | ||||||
|                 } else { |                 } else { | ||||||
|                     debug_assert!(self.inner.is_active(id)); |                     debug_assert!(self.streams().is_active(id)); | ||||||
|                     self.inner.close_send_half(id)?; |                     self.streams_mut().close_send_half(id)?; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -49,7 +49,7 @@ impl<T: ApplySettings> ApplySettings for StreamSendOpen<T> { | |||||||
| impl<T: ControlStreams> StreamSendOpen<T> { | impl<T: ControlStreams> StreamSendOpen<T> { | ||||||
|     fn check_not_reset(&self, id: StreamId) -> Result<(), ConnectionError> { |     fn check_not_reset(&self, id: StreamId) -> Result<(), ConnectionError> { | ||||||
|         // Ensure that the stream hasn't been closed otherwise. |         // Ensure that the stream hasn't been closed otherwise. | ||||||
|         match self.inner.get_reset(id) { |         match self.streams().get_reset(id) { | ||||||
|             Some(reason) => Err(StreamReset(reason).into()), |             Some(reason) => Err(StreamReset(reason).into()), | ||||||
|             None => Ok(()), |             None => Ok(()), | ||||||
|         } |         } | ||||||
| @@ -82,15 +82,15 @@ impl<T, U> Sink for StreamSendOpen<T> | |||||||
|  |  | ||||||
|             &Frame::Headers(..) => { |             &Frame::Headers(..) => { | ||||||
|                 self.check_not_reset(id)?; |                 self.check_not_reset(id)?; | ||||||
|                 if T::local_valid_id(id) { |                 if self.streams().is_valid_local_stream_id(id) { | ||||||
|                     if self.inner.is_local_active(id) { |                     if self.streams().is_local_active(id) { | ||||||
|                         // Can't send a a HEADERS frame on a local stream that's active, |                         // Can't send a a HEADERS frame on a local stream that's active, | ||||||
|                         // because we've already sent headers.  This will have to change |                         // because we've already sent headers.  This will have to change | ||||||
|                         // to support PUSH_PROMISE. |                         // to support PUSH_PROMISE. | ||||||
|                         return Err(UnexpectedFrameType.into()); |                         return Err(UnexpectedFrameType.into()); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if !T::local_can_open() { |                     if !self.streams().can_local_open() { | ||||||
|                         // A server tried to start a stream with a HEADERS frame. |                         // A server tried to start a stream with a HEADERS frame. | ||||||
|                         return Err(UnexpectedFrameType.into()); |                         return Err(UnexpectedFrameType.into()); | ||||||
|                     } |                     } | ||||||
| @@ -98,15 +98,15 @@ impl<T, U> Sink for StreamSendOpen<T> | |||||||
|                     if let Some(max) = self.max_concurrency { |                     if let Some(max) = self.max_concurrency { | ||||||
|                         // Don't allow this stream to overflow the remote's max stream |                         // Don't allow this stream to overflow the remote's max stream | ||||||
|                         // concurrency. |                         // concurrency. | ||||||
|                         if (max as usize) < self.inner.local_active_len() { |                         if (max as usize) < self.streams().local_active_len() { | ||||||
|                             return Err(Rejected.into()); |                             return Err(Rejected.into()); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     self.inner.local_open(id, self.initial_window_size)?; |                     self.inner.streams_mut().local_open(id, self.initial_window_size)?; | ||||||
|                 } else { |                 } else { | ||||||
|                     // On remote streams, |                     // On remote streams, | ||||||
|                     if self.inner.remote_open_send_half(id, self.initial_window_size).is_err() { |                     if self.inner.streams_mut().remote_open_send_half(id, self.initial_window_size).is_err() { | ||||||
|                         return Err(InvalidStreamId.into()); |                         return Err(InvalidStreamId.into()); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| @@ -116,7 +116,7 @@ impl<T, U> Sink for StreamSendOpen<T> | |||||||
|             // the stream is open (i.e. has already sent headers). |             // the stream is open (i.e. has already sent headers). | ||||||
|             _ => { |             _ => { | ||||||
|                 self.check_not_reset(id)?; |                 self.check_not_reset(id)?; | ||||||
|                 if !self.inner.is_send_open(id) { |                 if !self.streams().is_send_open(id) { | ||||||
|                     return Err(InactiveStreamId.into()); |                     return Err(InactiveStreamId.into()); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -6,14 +6,20 @@ use proto::stream_state::StreamState; | |||||||
| use fnv::FnvHasher; | use fnv::FnvHasher; | ||||||
| use ordermap::OrderMap; | use ordermap::OrderMap; | ||||||
| use std::hash::BuildHasherDefault; | use std::hash::BuildHasherDefault; | ||||||
| use std::marker::PhantomData; |  | ||||||
|  |  | ||||||
| /// Holds the underlying stream state to be accessed by upper layers. | /// Holds the underlying stream state to be accessed by upper layers. | ||||||
| // TODO track reserved streams | // TODO track reserved streams | ||||||
| // TODO constrain the size of `reset` | // TODO constrain the size of `reset` | ||||||
| #[derive(Debug, Default)] | #[derive(Debug)] | ||||||
| pub struct StreamStates<T, P> { | pub struct StreamStates<T> { | ||||||
|     inner: T, |     inner: T, | ||||||
|  |     streams: Streams, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[derive(Debug)] | ||||||
|  | pub struct Streams { | ||||||
|  |     /// True when in the context of an H2 server. | ||||||
|  |     is_server: bool, | ||||||
|  |  | ||||||
|     /// Holds active streams initiated by the local endpoint. |     /// Holds active streams initiated by the local endpoint. | ||||||
|     local_active: OrderMap<StreamId, StreamState, BuildHasherDefault<FnvHasher>>, |     local_active: OrderMap<StreamId, StreamState, BuildHasherDefault<FnvHasher>>, | ||||||
| @@ -23,30 +29,56 @@ pub struct StreamStates<T, P> { | |||||||
|  |  | ||||||
|     /// Holds active streams initiated by the remote. |     /// Holds active streams initiated by the remote. | ||||||
|     reset: OrderMap<StreamId, Reason, BuildHasherDefault<FnvHasher>>, |     reset: OrderMap<StreamId, Reason, BuildHasherDefault<FnvHasher>>, | ||||||
|  |  | ||||||
|     _phantom: PhantomData<P>, |  | ||||||
| } | } | ||||||
|  |  | ||||||
| impl<T, P, U> StreamStates<T, P> | impl<T, U> StreamStates<T> | ||||||
|     where T: Stream<Item = Frame, Error = ConnectionError>, |     where T: Stream<Item = Frame, Error = ConnectionError>, | ||||||
|           T: Sink<SinkItem = Frame<U>, SinkError = ConnectionError>, |           T: Sink<SinkItem = Frame<U>, SinkError = ConnectionError>, | ||||||
|           P: Peer, |  | ||||||
| { | { | ||||||
|     pub fn new(inner: T) -> StreamStates<T, P> { |     pub fn new<P: Peer>(inner: T) -> StreamStates<T> { | ||||||
|         StreamStates { |         StreamStates { | ||||||
|             inner, |             inner, | ||||||
|             local_active: OrderMap::default(), |             streams: Streams { | ||||||
|             remote_active: OrderMap::default(), |                 is_server: P::is_server(), | ||||||
|             reset: OrderMap::default(), |                 local_active: OrderMap::default(), | ||||||
|             _phantom: PhantomData, |                 remote_active: OrderMap::default(), | ||||||
|  |                 reset: OrderMap::default(), | ||||||
|  |             }, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl<T, P: Peer> StreamStates<T, P> { | impl<T> ControlStreams for StreamStates<T> { | ||||||
|     pub fn get_active(&mut self, id: StreamId) -> Option<&StreamState> { |     fn streams(&self) -> &Streams { | ||||||
|  |         &self.streams | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn streams_mut(&mut self) -> &mut Streams { | ||||||
|  |         &mut self.streams | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl Streams { | ||||||
|  |     pub fn is_valid_local_stream_id(&self, id: StreamId) -> bool { | ||||||
|  |         if self.is_server { | ||||||
|  |             id.is_server_initiated() | ||||||
|  |         } else { | ||||||
|  |             id.is_client_initiated() | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pub fn is_valid_remote_stream_id(&self, id: StreamId) -> bool { | ||||||
|  |         if self.is_server { | ||||||
|  |             id.is_client_initiated() | ||||||
|  |         } else { | ||||||
|  |             id.is_server_initiated() | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pub fn get_active(&self, id: StreamId) -> Option<&StreamState> { | ||||||
|         assert!(!id.is_zero()); |         assert!(!id.is_zero()); | ||||||
|         if P::is_valid_local_stream_id(id) { |  | ||||||
|  |         if self.is_valid_local_stream_id(id) { | ||||||
|             self.local_active.get(&id) |             self.local_active.get(&id) | ||||||
|         } else { |         } else { | ||||||
|             self.remote_active.get(&id) |             self.remote_active.get(&id) | ||||||
| @@ -55,7 +87,8 @@ impl<T, P: Peer> StreamStates<T, P> { | |||||||
|  |  | ||||||
|     pub fn get_active_mut(&mut self, id: StreamId) -> Option<&mut StreamState> { |     pub fn get_active_mut(&mut self, id: StreamId) -> Option<&mut StreamState> { | ||||||
|         assert!(!id.is_zero()); |         assert!(!id.is_zero()); | ||||||
|         if P::is_valid_local_stream_id(id) { |  | ||||||
|  |         if self.is_valid_local_stream_id(id) { | ||||||
|             self.local_active.get_mut(&id) |             self.local_active.get_mut(&id) | ||||||
|         } else { |         } else { | ||||||
|             self.remote_active.get_mut(&id) |             self.remote_active.get_mut(&id) | ||||||
| @@ -64,31 +97,27 @@ impl<T, P: Peer> StreamStates<T, P> { | |||||||
|  |  | ||||||
|     pub fn remove_active(&mut self, id: StreamId) { |     pub fn remove_active(&mut self, id: StreamId) { | ||||||
|         assert!(!id.is_zero()); |         assert!(!id.is_zero()); | ||||||
|         if P::is_valid_local_stream_id(id) { |  | ||||||
|  |         if self.is_valid_local_stream_id(id) { | ||||||
|             self.local_active.remove(&id); |             self.local_active.remove(&id); | ||||||
|         } else { |         } else { | ||||||
|             self.remote_active.remove(&id); |             self.remote_active.remove(&id); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } |  | ||||||
|  |  | ||||||
| impl<T, P: Peer> ControlStreams for StreamStates<T, P> { |     pub fn can_local_open(&self) -> bool { | ||||||
|     fn local_valid_id(id: StreamId) -> bool { |         !self.is_server | ||||||
|         P::is_valid_local_stream_id(id) |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn remote_valid_id(id: StreamId) -> bool { |     pub fn can_remote_open(&self) -> bool { | ||||||
|         P::is_valid_remote_stream_id(id) |         !self.can_local_open() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn local_can_open() -> bool { |     pub fn local_open(&mut self, id: StreamId, sz: WindowSize) -> Result<(), ConnectionError> { | ||||||
|         P::local_can_open() |         if !self.is_valid_local_stream_id(id) || !self.can_local_open() { | ||||||
|     } |  | ||||||
|  |  | ||||||
|     fn local_open(&mut self, id: StreamId, sz: WindowSize) -> Result<(), ConnectionError> { |  | ||||||
|         if !Self::local_valid_id(id) || !Self::local_can_open() { |  | ||||||
|             return Err(ProtocolError.into()); |             return Err(ProtocolError.into()); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if self.local_active.contains_key(&id) { |         if self.local_active.contains_key(&id) { | ||||||
|             return Err(ProtocolError.into()); |             return Err(ProtocolError.into()); | ||||||
|         } |         } | ||||||
| @@ -97,8 +126,8 @@ impl<T, P: Peer> ControlStreams for StreamStates<T, P> { | |||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn remote_open(&mut self, id: StreamId, sz: WindowSize) -> Result<(), ConnectionError> { |     pub fn remote_open(&mut self, id: StreamId, sz: WindowSize) -> Result<(), ConnectionError> { | ||||||
|         if !Self::remote_valid_id(id) || !Self::remote_can_open() { |         if !self.is_valid_remote_stream_id(id) || !self.can_remote_open() { | ||||||
|             return Err(ProtocolError.into()); |             return Err(ProtocolError.into()); | ||||||
|         } |         } | ||||||
|         if self.remote_active.contains_key(&id) { |         if self.remote_active.contains_key(&id) { | ||||||
| @@ -109,8 +138,8 @@ impl<T, P: Peer> ControlStreams for StreamStates<T, P> { | |||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn local_open_recv_half(&mut self, id: StreamId, sz: WindowSize) -> Result<(), ConnectionError> { |     pub fn local_open_recv_half(&mut self, id: StreamId, sz: WindowSize) -> Result<(), ConnectionError> { | ||||||
|         if !Self::local_valid_id(id) { |         if !self.is_valid_local_stream_id(id) { | ||||||
|             return Err(ProtocolError.into()); |             return Err(ProtocolError.into()); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -120,8 +149,8 @@ impl<T, P: Peer> ControlStreams for StreamStates<T, P> { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn remote_open_send_half(&mut self, id: StreamId, sz: WindowSize) -> Result<(), ConnectionError> { |     pub fn remote_open_send_half(&mut self, id: StreamId, sz: WindowSize) -> Result<(), ConnectionError> { | ||||||
|         if !Self::remote_valid_id(id) { |         if !self.is_valid_remote_stream_id(id) { | ||||||
|             return Err(ProtocolError.into()); |             return Err(ProtocolError.into()); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -131,7 +160,7 @@ impl<T, P: Peer> ControlStreams for StreamStates<T, P> { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn close_send_half(&mut self, id: StreamId) -> Result<(), ConnectionError> { |     pub fn close_send_half(&mut self, id: StreamId) -> Result<(), ConnectionError> { | ||||||
|         let fully_closed = self.get_active_mut(id) |         let fully_closed = self.get_active_mut(id) | ||||||
|             .map(|s| s.close_send_half()) |             .map(|s| s.close_send_half()) | ||||||
|             .unwrap_or_else(|| Err(ProtocolError.into()))?; |             .unwrap_or_else(|| Err(ProtocolError.into()))?; | ||||||
| @@ -143,7 +172,7 @@ impl<T, P: Peer> ControlStreams for StreamStates<T, P> { | |||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn close_recv_half(&mut self, id: StreamId) -> Result<(), ConnectionError> { |     pub fn close_recv_half(&mut self, id: StreamId) -> Result<(), ConnectionError> { | ||||||
|         let fully_closed = self.get_active_mut(id) |         let fully_closed = self.get_active_mut(id) | ||||||
|             .map(|s| s.close_recv_half()) |             .map(|s| s.close_recv_half()) | ||||||
|             .unwrap_or_else(|| Err(ProtocolError.into()))?; |             .unwrap_or_else(|| Err(ProtocolError.into()))?; | ||||||
| @@ -155,46 +184,55 @@ impl<T, P: Peer> ControlStreams for StreamStates<T, P> { | |||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn reset_stream(&mut self, id: StreamId, cause: Reason) { |     pub fn reset_stream(&mut self, id: StreamId, cause: Reason) { | ||||||
|         self.remove_active(id); |         self.remove_active(id); | ||||||
|         self.reset.insert(id, cause); |         self.reset.insert(id, cause); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_reset(&self, id: StreamId) -> Option<Reason> { |     pub fn get_reset(&self, id: StreamId) -> Option<Reason> { | ||||||
|         self.reset.get(&id).map(|r| *r) |         self.reset.get(&id).map(|r| *r) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn is_local_active(&self, id: StreamId) -> bool { |     pub fn is_local_active(&self, id: StreamId) -> bool { | ||||||
|         self.local_active.contains_key(&id) |         self.local_active.contains_key(&id) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn is_remote_active(&self, id: StreamId) -> bool { |     pub fn is_remote_active(&self, id: StreamId) -> bool { | ||||||
|         self.remote_active.contains_key(&id) |         self.remote_active.contains_key(&id) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn is_send_open(&mut self, id: StreamId) -> bool { |     /// Returns true if the given stream was opened and is not yet closed. | ||||||
|  |     pub fn is_active(&self, id: StreamId) -> bool { | ||||||
|  |         if self.is_valid_local_stream_id(id) { | ||||||
|  |             self.is_local_active(id) | ||||||
|  |         } else { | ||||||
|  |             self.is_remote_active(id) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pub fn is_send_open(&self, id: StreamId) -> bool { | ||||||
|         match self.get_active(id) { |         match self.get_active(id) { | ||||||
|             Some(s) => s.is_send_open(), |             Some(s) => s.is_send_open(), | ||||||
|             None => false, |             None => false, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn is_recv_open(&mut self, id: StreamId) -> bool  { |     pub fn is_recv_open(&self, id: StreamId) -> bool  { | ||||||
|         match self.get_active(id) { |         match self.get_active(id) { | ||||||
|             Some(s) => s.is_recv_open(), |             Some(s) => s.is_recv_open(), | ||||||
|             None => false, |             None => false, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn local_active_len(&self) -> usize { |     pub fn local_active_len(&self) -> usize { | ||||||
|         self.local_active.len() |         self.local_active.len() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn remote_active_len(&self) -> usize { |     pub fn remote_active_len(&self) -> usize { | ||||||
|         self.remote_active.len() |         self.remote_active.len() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn update_inital_recv_window_size(&mut self, old_sz: WindowSize, new_sz: WindowSize) { |     pub fn update_inital_recv_window_size(&mut self, old_sz: WindowSize, new_sz: WindowSize) { | ||||||
|         if new_sz < old_sz { |         if new_sz < old_sz { | ||||||
|             let decr = old_sz - new_sz; |             let decr = old_sz - new_sz; | ||||||
|  |  | ||||||
| @@ -226,7 +264,7 @@ impl<T, P: Peer> ControlStreams for StreamStates<T, P> { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn update_inital_send_window_size(&mut self, old_sz: WindowSize, new_sz: WindowSize) { |     pub fn update_inital_send_window_size(&mut self, old_sz: WindowSize, new_sz: WindowSize) { | ||||||
|         if new_sz < old_sz { |         if new_sz < old_sz { | ||||||
|             let decr = old_sz - new_sz; |             let decr = old_sz - new_sz; | ||||||
|  |  | ||||||
| @@ -258,20 +296,21 @@ impl<T, P: Peer> ControlStreams for StreamStates<T, P> { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn recv_flow_controller(&mut self, id: StreamId) -> Option<&mut FlowControlState> { |     pub fn recv_flow_controller(&mut self, id: StreamId) -> Option<&mut FlowControlState> { | ||||||
|  |         // TODO: Abstract getting the state for a stream ID | ||||||
|         if id.is_zero() { |         if id.is_zero() { | ||||||
|             None |             None | ||||||
|         } else if P::is_valid_local_stream_id(id) { |         } else if self.is_valid_local_stream_id(id) { | ||||||
|             self.local_active.get_mut(&id).and_then(|s| s.recv_flow_controller()) |             self.local_active.get_mut(&id).and_then(|s| s.recv_flow_controller()) | ||||||
|         } else { |         } else { | ||||||
|             self.remote_active.get_mut(&id).and_then(|s| s.recv_flow_controller()) |             self.remote_active.get_mut(&id).and_then(|s| s.recv_flow_controller()) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn send_flow_controller(&mut self, id: StreamId) -> Option<&mut FlowControlState> { |     pub fn send_flow_controller(&mut self, id: StreamId) -> Option<&mut FlowControlState> { | ||||||
|         if id.is_zero() { |         if id.is_zero() { | ||||||
|             None |             None | ||||||
|         } else if P::is_valid_local_stream_id(id) { |         } else if self.is_valid_local_stream_id(id) { | ||||||
|             self.local_active.get_mut(&id).and_then(|s| s.send_flow_controller()) |             self.local_active.get_mut(&id).and_then(|s| s.send_flow_controller()) | ||||||
|         } else { |         } else { | ||||||
|             self.remote_active.get_mut(&id).and_then(|s| s.send_flow_controller()) |             self.remote_active.get_mut(&id).and_then(|s| s.send_flow_controller()) | ||||||
| @@ -279,8 +318,8 @@ impl<T, P: Peer> ControlStreams for StreamStates<T, P> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| proxy_apply_settings!(StreamStates, P); | proxy_apply_settings!(StreamStates); | ||||||
| proxy_control_ping!(StreamStates, P); | proxy_control_ping!(StreamStates); | ||||||
| proxy_stream!(StreamStates, P); | proxy_stream!(StreamStates); | ||||||
| proxy_sink!(StreamStates, P); | proxy_sink!(StreamStates); | ||||||
| proxy_ready_sink!(StreamStates, P); | proxy_ready_sink!(StreamStates); | ||||||
|   | |||||||
| @@ -111,16 +111,8 @@ impl Peer for Server { | |||||||
|     type Send = http::response::Head; |     type Send = http::response::Head; | ||||||
|     type Poll = http::request::Head; |     type Poll = http::request::Head; | ||||||
|  |  | ||||||
|     fn is_valid_local_stream_id(id: StreamId) -> bool { |     fn is_server() -> bool { | ||||||
|         id.is_server_initiated() |         true | ||||||
|     } |  | ||||||
|  |  | ||||||
|     fn is_valid_remote_stream_id(id: StreamId) -> bool { |  | ||||||
|         id.is_client_initiated() |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     fn local_can_open() -> bool { |  | ||||||
|         false |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn convert_send_message( |     fn convert_send_message( | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user