A lot of structural work
This commit is contained in:
		| @@ -6,7 +6,7 @@ mod store; | ||||
| mod stream; | ||||
| mod streams; | ||||
|  | ||||
| pub use self::streams::Streams; | ||||
| pub use self::streams::{Streams, Stream}; | ||||
|  | ||||
| use self::flow_control::FlowControl; | ||||
| use self::recv::Recv; | ||||
| @@ -19,6 +19,8 @@ use proto::*; | ||||
| use error::Reason::*; | ||||
| use error::User::*; | ||||
|  | ||||
| use http::{Request, Response}; | ||||
|  | ||||
| #[derive(Debug)] | ||||
| pub struct Config { | ||||
|     /// Maximum number of remote initiated streams | ||||
|   | ||||
| @@ -17,6 +17,9 @@ pub struct Send<P> { | ||||
|     /// Current number of locally initiated streams | ||||
|     num_streams: usize, | ||||
|  | ||||
|     /// Stream identifier to use for next initialized stream. | ||||
|     next_stream_id: StreamId, | ||||
|  | ||||
|     /// Initial window size of locally initiated streams | ||||
|     init_window_sz: WindowSize, | ||||
|  | ||||
| @@ -37,9 +40,16 @@ pub struct Send<P> { | ||||
|  | ||||
| impl<P: Peer> Send<P> { | ||||
|     pub fn new(config: &Config) -> Self { | ||||
|         let next_stream_id = if P::is_server() { | ||||
|             2 | ||||
|         } else { | ||||
|             1 | ||||
|         }; | ||||
|  | ||||
|         Send { | ||||
|             max_streams: config.max_local_initiated, | ||||
|             num_streams: 0, | ||||
|             next_stream_id: next_stream_id.into(), | ||||
|             init_window_sz: config.init_local_window_sz, | ||||
|             flow_control: FlowControl::new(config.init_local_window_sz), | ||||
|             pending_window_updates: VecDeque::new(), | ||||
| @@ -51,8 +61,8 @@ impl<P: Peer> Send<P> { | ||||
|     /// Update state reflecting a new, locally opened stream | ||||
|     /// | ||||
|     /// Returns the stream state if successful. `None` if refused | ||||
|     pub fn open(&mut self, id: StreamId) -> Result<State, ConnectionError> { | ||||
|         try!(self.ensure_can_open(id)); | ||||
|     pub fn open(&mut self) -> Result<(StreamId, State), ConnectionError> { | ||||
|         try!(self.ensure_can_open()); | ||||
|  | ||||
|         if let Some(max) = self.max_streams { | ||||
|             if max <= self.num_streams { | ||||
| @@ -60,10 +70,13 @@ impl<P: Peer> Send<P> { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         let ret = (self.next_stream_id, State::default()); | ||||
|  | ||||
|         // Increment the number of locally initiated streams | ||||
|         self.num_streams += 1; | ||||
|         self.next_stream_id.increment(); | ||||
|  | ||||
|         Ok(State::default()) | ||||
|         Ok(ret) | ||||
|     } | ||||
|  | ||||
|     pub fn send_headers(&mut self, state: &mut State, eos: bool) | ||||
| @@ -191,15 +204,13 @@ impl<P: Peer> Send<P> { | ||||
|     } | ||||
|  | ||||
|     /// Returns true if the local actor can initiate a stream with the given ID. | ||||
|     fn ensure_can_open(&self, id: StreamId) -> Result<(), ConnectionError> { | ||||
|     fn ensure_can_open(&self) -> Result<(), ConnectionError> { | ||||
|         if P::is_server() { | ||||
|             // Servers cannot open streams. PushPromise must first be reserved. | ||||
|             return Err(UnexpectedFrameType.into()); | ||||
|         } | ||||
|  | ||||
|         if !id.is_client_initiated() { | ||||
|             return Err(InvalidStreamId.into()); | ||||
|         } | ||||
|         // TODO: Handle StreamId overflow | ||||
|  | ||||
|         Ok(()) | ||||
|     } | ||||
|   | ||||
| @@ -42,6 +42,11 @@ impl Store { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn insert(&mut self, id: StreamId, val: State) { | ||||
|         let handle = self.slab.insert(val); | ||||
|         assert!(self.ids.insert(id, handle).is_none()); | ||||
|     } | ||||
|  | ||||
|     pub fn entry(&mut self, id: StreamId) -> Entry { | ||||
|         use self::hash_map::Entry::*; | ||||
|  | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| use client; | ||||
| use proto::*; | ||||
| use super::*; | ||||
|  | ||||
| @@ -10,6 +11,12 @@ pub struct Streams<P> { | ||||
|     inner: Arc<Mutex<Inner<P>>>, | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| pub struct Stream<P> { | ||||
|     inner: Arc<Mutex<Inner<P>>>, | ||||
|     id: StreamId, | ||||
| } | ||||
|  | ||||
| /// Fields needed to manage state related to managing the set of streams. This | ||||
| /// is mostly split out to make ownership happy. | ||||
| /// | ||||
| @@ -139,28 +146,22 @@ impl<P: Peer> Streams<P> { | ||||
|         unimplemented!(); | ||||
|     } | ||||
|  | ||||
|     pub fn send_headers(&mut self, frame: &frame::Headers) | ||||
|     pub fn send_headers(&mut self, headers: frame::Headers) | ||||
|         -> Result<(), ConnectionError> | ||||
|     { | ||||
|         unimplemented!(); | ||||
|         /* | ||||
|         let id = frame.stream_id(); | ||||
|         let mut me = self.inner.lock().unwrap(); | ||||
|         let me = &mut *me; | ||||
|  | ||||
|         trace!("send_headers; id={:?}", id); | ||||
|         // let (id, state) = me.actions.send.open()); | ||||
|  | ||||
|  | ||||
|         let state = match me.store.entry(id) { | ||||
|             Entry::Occupied(e) => e.into_mut(), | ||||
|             Entry::Vacant(e) => { | ||||
|                 // Trailers cannot open a stream. Trailers are header frames | ||||
|                 // that do not contain pseudo headers. Requests MUST contain a | ||||
|                 // method and responses MUST contain a status. If they do not,t | ||||
|                 // hey are considered to be malformed. | ||||
|                 if frame.is_trailers() { | ||||
|                     // TODO: Should this be a different error? | ||||
|                     return Err(UnexpectedFrameType.into()); | ||||
|                 } | ||||
|  | ||||
|                 let state = try!(me.actions.send.open(id)); | ||||
|                 let (id, state) = try!(me.actions.send.open()); | ||||
|                 e.insert(state) | ||||
|             } | ||||
|         }; | ||||
| @@ -176,6 +177,7 @@ impl<P: Peer> Streams<P> { | ||||
|         } | ||||
|  | ||||
|         Ok(()) | ||||
|         */ | ||||
|     } | ||||
|  | ||||
|     pub fn send_data<B: Buf>(&mut self, frame: &frame::Data<B>) | ||||
| @@ -250,6 +252,40 @@ impl<P: Peer> Streams<P> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Streams<client::Peer> { | ||||
|     pub fn send_request(&mut self, request: Request<()>, end_of_stream: bool) | ||||
|         -> Result<Stream<client::Peer>, ConnectionError> | ||||
|     { | ||||
|         let id = { | ||||
|             let mut me = self.inner.lock().unwrap(); | ||||
|             let me = &mut *me; | ||||
|  | ||||
|             // Initialize a new stream. This fails if the connection is at capacity. | ||||
|             let (id, mut state) = me.actions.send.open()?; | ||||
|  | ||||
|             // Convert the message | ||||
|             let headers = client::Peer::convert_send_message( | ||||
|                 id, request, end_of_stream); | ||||
|  | ||||
|             me.actions.send.send_headers(&mut state, end_of_stream)?; | ||||
|  | ||||
|             // Given that the stream has been initialized, it should not be in the | ||||
|             // closed state. | ||||
|             debug_assert!(!state.is_closed()); | ||||
|  | ||||
|             // Store the state | ||||
|             me.store.insert(id, state); | ||||
|  | ||||
|             id | ||||
|         }; | ||||
|  | ||||
|         Ok(Stream { | ||||
|             inner: self.inner.clone(), | ||||
|             id: id, | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<P: Peer> Actions<P> { | ||||
|     fn dec_num_streams(&mut self, id: StreamId) { | ||||
|         if self.is_local_init(id) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user