narrow the surface area of the ControlSettings api to expose only a few remote settings
This commit is contained in:
		| @@ -11,8 +11,10 @@ use std::io; | ||||
| /// above---Connection). | ||||
| pub trait ControlSettings { | ||||
|     fn update_local_settings(&mut self, set: frame::SettingSet) -> Result<(), ConnectionError>; | ||||
|     fn local_settings(&self) -> &SettingSet; | ||||
|     fn remote_settings(&self) -> &SettingSet; | ||||
|  | ||||
|     fn remote_push_enabled(&self) -> Option<bool>; | ||||
|     fn remote_max_concurrent_streams(&self) -> Option<u32>; | ||||
|     fn remote_initial_window_size(&self) -> WindowSize; | ||||
| } | ||||
|  | ||||
| /// Allows settings updates to be pushed "down" the transport (i.e. from Settings down to | ||||
| @@ -27,17 +29,15 @@ pub struct Settings<T> { | ||||
|     // Upstream transport | ||||
|     inner: T, | ||||
|  | ||||
|     // Our settings | ||||
|     local: SettingSet, | ||||
|  | ||||
|     // Peer settings | ||||
|     remote: SettingSet, | ||||
|     remote_push_enabled: Option<bool>, | ||||
|     remote_max_concurrent_streams: Option<u32>, | ||||
|     remote_initial_window_size: WindowSize, | ||||
|  | ||||
|     // Number of acks remaining to send to the peer | ||||
|     remaining_acks: usize, | ||||
|  | ||||
|     // True when the local settings must be flushed to the remote | ||||
|     local_valid_id_dirty: bool, | ||||
|     // Holds a new set of local values to be applied. | ||||
|     pending_local: Option<SettingSet>, | ||||
|  | ||||
|     // True when we have received a settings frame from the remote. | ||||
|     received_remote: bool, | ||||
| @@ -49,46 +49,34 @@ impl<T, U> Settings<T> | ||||
|     pub fn new(inner: T, local: SettingSet) -> Settings<T> { | ||||
|         Settings { | ||||
|             inner: inner, | ||||
|             local: local, | ||||
|             remote: SettingSet::default(), | ||||
|             pending_local: Some(local), | ||||
|             remote_push_enabled: None, | ||||
|             remote_max_concurrent_streams: None, | ||||
|             remote_initial_window_size: 65_535, | ||||
|             remaining_acks: 0, | ||||
|             local_valid_id_dirty: true, | ||||
|             received_remote: false, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // TODO remove this | ||||
|     pub fn local_settings(&self) -> &SettingSet { | ||||
|         &self.local | ||||
|     } | ||||
|  | ||||
|     // TODO replace this with settings a client needs to know about (concurrency, initial | ||||
|     // window size, etc). | ||||
|     pub fn remote_settings(&self) -> &SettingSet { | ||||
|         &self.local | ||||
|     } | ||||
|  | ||||
|     /// Swap the inner transport while maintaining the current state. | ||||
|     pub fn swap_inner<T2, F: FnOnce(T) -> T2>(self, f: F) -> Settings<T2> { | ||||
|         let inner = f(self.inner); | ||||
|  | ||||
|         Settings { | ||||
|             inner: inner, | ||||
|             local: self.local, | ||||
|             remote: self.remote, | ||||
|             remote_push_enabled: self.remote_push_enabled, | ||||
|             remote_max_concurrent_streams: self.remote_max_concurrent_streams, | ||||
|             remote_initial_window_size: self.remote_initial_window_size, | ||||
|             remaining_acks: self.remaining_acks, | ||||
|             local_valid_id_dirty: self.local_valid_id_dirty, | ||||
|             pending_local: self.pending_local, | ||||
|             received_remote: self.received_remote, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn try_send_pending(&mut self) -> Poll<(), ConnectionError> { | ||||
|         trace!("try_send_pending; dirty={} acks={}", self.local_valid_id_dirty, self.remaining_acks); | ||||
|         if self.local_valid_id_dirty { | ||||
|             let frame = frame::Settings::new(self.local.clone()); | ||||
|             try_ready!(self.try_send(frame)); | ||||
|  | ||||
|             self.local_valid_id_dirty = false; | ||||
|         trace!("try_send_pending; dirty={} acks={}", self.pending_local.is_some(), self.remaining_acks); | ||||
|         if let Some(local) = self.pending_local.take() { | ||||
|             try_ready!(self.try_send_local(local)); | ||||
|         } | ||||
|  | ||||
|         while self.remaining_acks > 0 { | ||||
| @@ -101,9 +89,19 @@ impl<T, U> Settings<T> | ||||
|         Ok(Async::Ready(())) | ||||
|     } | ||||
|  | ||||
|     fn try_send(&mut self, item: frame::Settings) -> Poll<(), ConnectionError> { | ||||
|     fn try_send_local(&mut self, local: SettingSet) -> Poll<(), ConnectionError> { | ||||
|         let frame = frame::Settings::new(local.clone()).into(); | ||||
|         if self.try_send(frame)?.is_not_ready() { | ||||
|             self.pending_local = Some(local); | ||||
|             Ok(Async::NotReady) | ||||
|         } else { | ||||
|             Ok(Async::Ready(())) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn try_send(&mut self, frame: frame::Settings) -> Poll<(), ConnectionError> { | ||||
|         trace!("try_send"); | ||||
|         if self.inner.start_send(item.into())?.is_ready() { | ||||
|         if self.inner.start_send(frame.into())?.is_ready() { | ||||
|             Ok(Async::Ready(())) | ||||
|         } else { | ||||
|             Ok(Async::NotReady) | ||||
| @@ -111,19 +109,24 @@ impl<T, U> Settings<T> | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T> ControlSettings for Settings<T>{ | ||||
|     fn update_local_settings(&mut self, local: frame::SettingSet) -> Result<(), ConnectionError> { | ||||
|         self.local = local; | ||||
|         self.local_valid_id_dirty = true; | ||||
| impl<T, U> ControlSettings for Settings<T> | ||||
|     where T: Sink<SinkItem = Frame<U>, SinkError = ConnectionError>, | ||||
| { | ||||
|     fn update_local_settings(&mut self, local: SettingSet) -> Result<(), ConnectionError> { | ||||
|         self.try_send_local(local)?; | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     fn local_settings(&self) -> &SettingSet { | ||||
|         &self.local | ||||
|     fn remote_initial_window_size(&self) -> u32 { | ||||
|         self.remote_initial_window_size | ||||
|     } | ||||
|  | ||||
|     fn remote_settings(&self) -> &SettingSet { | ||||
|         &self.remote | ||||
|     fn remote_max_concurrent_streams(&self) -> Option<u32> { | ||||
|         self.remote_max_concurrent_streams | ||||
|     } | ||||
|  | ||||
|     fn remote_push_enabled(&self) -> Option<bool> { | ||||
|         self.remote_push_enabled | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -147,7 +150,16 @@ impl<T, U> Stream for Settings<T> | ||||
|                         // acknowledgements. | ||||
|                         let settings = v.into_set(); | ||||
|                         self.inner.apply_remote_settings(&settings)?; | ||||
|                         self.remote = settings; | ||||
|  | ||||
|                         if let Some(sz) = settings.initial_window_size() { | ||||
|                             self.remote_initial_window_size = sz; | ||||
|                         } | ||||
|                         if let Some(max) = settings.max_concurrent_streams() { | ||||
|                             self.remote_max_concurrent_streams = Some(max); | ||||
|                         } | ||||
|                         if let Some(ok) = settings.enable_push() { | ||||
|                             self.remote_push_enabled = Some(ok); | ||||
|                         } | ||||
|  | ||||
|                         self.remaining_acks += 1; | ||||
|                         let _ = try!(self.try_send_pending()); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user