use ConnectionError; use error::User::{InvalidStreamId, StreamReset}; use frame::{Frame, SettingSet}; use proto::*; #[derive(Debug)] pub struct StreamSendOpen { inner: T, max_concurrency: Option, initial_window_size: WindowSize, } impl StreamSendOpen where T: Stream, T: Sink, SinkError = ConnectionError>, T: ControlStreams, { pub fn new(initial_window_size: WindowSize, max_concurrency: Option, inner: T) -> StreamSendOpen { StreamSendOpen { inner, max_concurrency, initial_window_size, } } } /// Handles updates to `SETTINGS_MAX_CONCURRENT_STREAMS`. /// /// > Indicates the maximum number of concurrent streams that the senderg will allow. This /// > limit is directional: it applies to the number of streams that the sender permits /// > the receiver to create. Initially, there is no limit to this value. It is /// > recommended that this value be no smaller than 100, so as to not unnecessarily limit /// > parallelism. /// > /// > A value of 0 for SETTINGS_MAX_CONCURRENT_STREAMS SHOULD NOT be treated as special by /// > endpoints. A zero value does prevent the creation of new streams; however, this can /// > also happen for any limit that is exhausted with active streams. Servers SHOULD only /// > set a zero value for short durations; if a server does not wish to accept requests, /// > closing the connection is more appropriate. /// /// > An endpoint that wishes to reduce the value of SETTINGS_MAX_CONCURRENT_STREAMS to a /// > value that is below the current number of open streams can either close streams that /// > exceed the new value or allow streams to complete. /// /// This module does NOT close streams when the setting changes. impl ApplySettings for StreamSendOpen { fn apply_local_settings(&mut self, set: &SettingSet) -> Result<(), ConnectionError> { self.inner.apply_local_settings(set) } fn apply_remote_settings(&mut self, set: &SettingSet) -> Result<(), ConnectionError> { self.max_concurrency = set.max_concurrent_streams(); self.initial_window_size = set.initial_window_size(); self.inner.apply_remote_settings(set) } } impl Stream for StreamSendOpen where T: Stream, T: ControlStreams, { type Item = Frame; type Error = ConnectionError; fn poll(&mut self) -> Poll, ConnectionError> { self.inner.poll() } } impl Sink for StreamSendOpen where T: Sink, SinkError = ConnectionError>, T: ControlStreams, { type SinkItem = T::SinkItem; type SinkError = T::SinkError; fn start_send(&mut self, frame: T::SinkItem) -> StartSend { use frame::Frame::*; let id = frame.stream_id(); if id.is_zero() { // Nothing to do on connection frames. return self.inner.start_send(frame); } // Reset the stream immediately and send the Reset on the underlying transport. if let Reset(rst) = frame { self.inner.reset_stream(id, rst.reason()); return self.inner.start_send(Reset(rst)); } // Ensure that the stream hasn't been closed otherwise. if let Some(reason) = self.inner.get_reset(id) { return Err(StreamReset(reason).into()) } if T::is_valid_local_id(id) { if self.inner.is_local_active(id) { // If the frame ends thestream, it will be handled in stream_recv. return self.inner.start_send(frame); } if T::can_create_local_stream() { let has_capacity = match self.max_concurrency { None => true, Some(max) => self.inner.local_active_len() < (max as usize), }; if has_capacity { // create that shit. unimplemented!(); } } } else { if self.inner.is_remote_active(id) { // If the frame was part of a remote stream, it MUST already exist. If the // frame ends thestream, it will be handled in stream_recv. return self.inner.start_send(frame); } if let Reset(rst) = frame { return self.inner.start_send(Reset(rst)); } } // Tried to send a frame on a stream return Err(InvalidStreamId.into()); } fn poll_complete(&mut self) -> Poll<(), T::SinkError> { self.inner.poll_complete() } } impl ReadySink for StreamSendOpen where T: Stream, T: Sink, SinkError = ConnectionError>, T: ControlStreams, T: ReadySink, { fn poll_ready(&mut self) -> Poll<(), ConnectionError> { self.inner.poll_ready() } } impl ControlStreams for StreamSendOpen { fn is_valid_local_id(id: StreamId) -> bool { T::is_valid_local_id(id) } fn is_valid_remote_id(id: StreamId) -> bool { T::is_valid_remote_id(id) } fn can_create_local_stream() -> bool { T::can_create_local_stream() } fn get_reset(&self, id: StreamId) -> Option { self.inner.get_reset(id) } fn reset_stream(&mut self, id: StreamId, cause: Reason) { self.inner.reset_stream(id, cause) } 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 local_update_inital_window_size(&mut self, old_sz: u32, new_sz: u32) { self.inner.local_update_inital_window_size(old_sz, new_sz) } fn remote_update_inital_window_size(&mut self, old_sz: u32, new_sz: u32) { self.inner.remote_update_inital_window_size(old_sz, new_sz) } fn local_flow_controller(&mut self, id: StreamId) -> Option<&mut FlowControlState> { self.inner.local_flow_controller(id) } fn remote_flow_controller(&mut self, id: StreamId) -> Option<&mut FlowControlState> { self.inner.remote_flow_controller(id) } } impl ControlFlow for StreamSendOpen { fn poll_window_update(&mut self) -> Poll { self.inner.poll_window_update() } fn expand_window(&mut self, id: StreamId, incr: WindowSize) -> Result<(), ConnectionError> { self.inner.expand_window(id, incr) } } impl ControlPing for StreamSendOpen { fn start_ping(&mut self, body: PingPayload) -> StartSend { self.inner.start_ping(body) } fn take_pong(&mut self) -> Option { self.inner.take_pong() } }