wip
This commit is contained in:
		| @@ -14,6 +14,13 @@ pub struct WindowUpdate { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl WindowUpdate { | impl WindowUpdate { | ||||||
|  |     pub fn new(stream_id: StreamId, increment: Increment) -> WindowUpdate { | ||||||
|  |         WindowUpdate { | ||||||
|  |             stream_id, | ||||||
|  |             increment, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     pub fn stream_id(&self) -> StreamId { |     pub fn stream_id(&self) -> StreamId { | ||||||
|         self.stream_id |         self.stream_id | ||||||
|     } |     } | ||||||
| @@ -22,13 +29,13 @@ impl WindowUpdate { | |||||||
|         self.increment |         self.increment | ||||||
|     } |     } | ||||||
|  |  | ||||||
|         /// Builds a `Ping` frame from a raw frame. |     /// Builds a `WindowUpdate` frame from a raw frame. | ||||||
|     pub fn load(head: Head, bytes: &[u8]) -> Result<WindowUpdate, Error> { |     pub fn load(head: Head, bytes: &[u8]) -> Result<WindowUpdate, Error> { | ||||||
|         debug_assert_eq!(head.kind(), ::frame::Kind::WindowUpdate); |         debug_assert_eq!(head.kind(), ::frame::Kind::WindowUpdate); | ||||||
|         Ok(WindowUpdate { |         Ok(WindowUpdate { | ||||||
|             stream_id: head.stream_id(), |             stream_id: head.stream_id(), | ||||||
|             // Clear the most significant bit, as that is reserved and MUST be ignored when |             // Clear the most significant bit, as that is reserved and MUST be ignored | ||||||
|             // received. |             // when received. | ||||||
|             increment: NetworkEndian::read_u32(bytes) & !INCREMENT_MASK, |             increment: NetworkEndian::read_u32(bytes) & !INCREMENT_MASK, | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| use {Frame, ConnectionError, Peer, StreamId}; | use {Frame, ConnectionError, Peer, StreamId}; | ||||||
| use client::Client; | use client::Client; | ||||||
| use frame::{Frame as WireFrame}; | use frame::{Frame as WireFrame}; | ||||||
|  | use proto::{self, FlowController, ReadySink, PeerState, State, WindowUpdate}; | ||||||
| use server::Server; | use server::Server; | ||||||
| use proto::{self, ReadySink, State, WindowUpdate}; |  | ||||||
|  |  | ||||||
| use tokio_io::{AsyncRead, AsyncWrite}; | use tokio_io::{AsyncRead, AsyncWrite}; | ||||||
|  |  | ||||||
| @@ -13,49 +13,11 @@ use futures::*; | |||||||
| use ordermap::OrderMap; | use ordermap::OrderMap; | ||||||
| use fnv::FnvHasher; | use fnv::FnvHasher; | ||||||
|  |  | ||||||
| use std::marker::PhantomData; | use std::collections::VecDeque; | ||||||
| use std::hash::BuildHasherDefault; | use std::hash::BuildHasherDefault; | ||||||
|  | use std::marker::PhantomData; | ||||||
|  |  | ||||||
| pub struct FlowControlViolation; | // TODO get window size from `inner`. | ||||||
|  |  | ||||||
| #[derive(Debug)] |  | ||||||
| struct FlowController { |  | ||||||
|     window_size: u32, |  | ||||||
|     underflow: u32, |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl FlowController { |  | ||||||
|     pub fn new(window_size: u32) -> FlowController { |  | ||||||
|         FlowController { |  | ||||||
|             window_size, |  | ||||||
|             underflow: 0, |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     pub fn shrink(&mut self, mut sz: u32) { |  | ||||||
|         self.underflow += sz; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     pub fn consume(&mut self, mut sz: u32) -> Result<(), FlowControlViolation> { |  | ||||||
|         if sz < self.window_size { |  | ||||||
|             self.underflow -= sz; |  | ||||||
|             return Err(FlowControlViolation); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         self.window_size -= sz; |  | ||||||
|         Ok(()) |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     pub fn increment(&mut self, mut sz: u32) { |  | ||||||
|         if sz <= self.underflow { |  | ||||||
|             self.underflow -= sz; |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         sz -= self.underflow; |  | ||||||
|         self.window_size += sz; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// An H2 connection | /// An H2 connection | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| @@ -63,13 +25,24 @@ pub struct Connection<T, P> { | |||||||
|     inner: proto::Inner<T>, |     inner: proto::Inner<T>, | ||||||
|     streams: StreamMap<State>, |     streams: StreamMap<State>, | ||||||
|     peer: PhantomData<P>, |     peer: PhantomData<P>, | ||||||
|  |  | ||||||
|  |     /// Tracks connection-level flow control. | ||||||
|     local_flow_controller: FlowController, |     local_flow_controller: FlowController, | ||||||
|  |     initial_local_window_size: u32, | ||||||
|  |     pending_local_window_updates: VecDeque<WindowUpdate>, | ||||||
|  |  | ||||||
|     remote_flow_controller: FlowController, |     remote_flow_controller: FlowController, | ||||||
|  |     initial_remote_window_size: u32, | ||||||
|  |     pending_remote_window_updates: VecDeque<WindowUpdate>, | ||||||
|  |     blocked_remote_window_update: Option<task::Task> | ||||||
| } | } | ||||||
|  |  | ||||||
| type StreamMap<T> = OrderMap<StreamId, T, BuildHasherDefault<FnvHasher>>; | type StreamMap<T> = OrderMap<StreamId, T, BuildHasherDefault<FnvHasher>>; | ||||||
|  |  | ||||||
| pub fn new<T, P>(transport: proto::Inner<T>, initial_local_window_size: u32, initial_remote_window_size: u32) -> Connection<T, P> | pub fn new<T, P>(transport: proto::Inner<T>, | ||||||
|  |                  initial_local_window_size: u32, | ||||||
|  |                  initial_remote_window_size: u32) | ||||||
|  |     -> Connection<T, P> | ||||||
|     where T: AsyncRead + AsyncWrite, |     where T: AsyncRead + AsyncWrite, | ||||||
|           P: Peer, |           P: Peer, | ||||||
| { | { | ||||||
| @@ -77,35 +50,70 @@ pub fn new<T, P>(transport: proto::Inner<T>, initial_local_window_size: u32, ini | |||||||
|         inner: transport, |         inner: transport, | ||||||
|         streams: StreamMap::default(), |         streams: StreamMap::default(), | ||||||
|         peer: PhantomData, |         peer: PhantomData, | ||||||
|  |  | ||||||
|         local_flow_controller: FlowController::new(initial_local_window_size), |         local_flow_controller: FlowController::new(initial_local_window_size), | ||||||
|  |         initial_local_window_size, | ||||||
|  |         pending_local_window_updates: VecDeque::default(), | ||||||
|  |  | ||||||
|         remote_flow_controller: FlowController::new(initial_remote_window_size), |         remote_flow_controller: FlowController::new(initial_remote_window_size), | ||||||
|  |         initial_remote_window_size, | ||||||
|  |         pending_remote_window_updates: VecDeque::default(), | ||||||
|  |         blocked_remote_window_update: None, | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl<T, P> Connection<T, P> { | impl<T, P> Connection<T, P> { | ||||||
|     /// Publishes stream window updates to the remote. |     /// Publishes local stream window updates to the remote. | ||||||
|     /// |     /// | ||||||
|     /// Connection window updates (StreamId=0) and stream window updates are published |     /// Connection window updates (StreamId=0) and stream window must be published | ||||||
|     /// distinctly. |     /// distinctly. | ||||||
|     pub fn increment_local_window(&mut self, up: WindowUpdate) { |     pub fn increment_local_window(&mut self, up: WindowUpdate) { | ||||||
|         let incr = up.increment(); |         let added = match &up { | ||||||
|         let flow = match up { |             &WindowUpdate::Connection { increment } => { | ||||||
|             WindowUpdate::Connection { .. } => Some(&self.local_flow_controller), |                 if increment == 0 { | ||||||
|             WindowUpdate::Stream { id, .. } => { |                     false | ||||||
|                 self.streams.get(&id).map(|s| s.local_flow_controller()) |                 } else { | ||||||
|  |                     self.local_flow_controller.increment(increment); | ||||||
|  |                     true | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             &WindowUpdate::Stream { id, increment } => { | ||||||
|  |                 if increment == 0 { | ||||||
|  |                     false | ||||||
|  |                 } else { | ||||||
|  |                     match self.streams.get_mut(&id) { | ||||||
|  |                         Some(&mut State::Open { local: PeerState::Data(ref mut fc), .. }) | | ||||||
|  |                         Some(&mut State::HalfClosedRemote(PeerState::Data(ref mut fc))) => { | ||||||
|  |                             fc.increment(increment); | ||||||
|  |                             true | ||||||
|  |                         } | ||||||
|  |                         _ => false, | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|         if let Some(flow) = flow { |  | ||||||
|             flow.increment(incr); |         if added { | ||||||
|  |             self.pending_local_window_updates.push_back(up); | ||||||
|         } |         } | ||||||
|         unimplemented!() |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Advertises stream window updates from the remote. |     /// Advertises the remote's stream window updates. | ||||||
|     /// |     /// | ||||||
|     /// Connection window updates (StreamId=0) and stream window updates are advertised |     /// Connection window updates (StreamId=0) and stream window updates are advertised | ||||||
|     /// distinctly. |     /// distinctly. | ||||||
|     pub fn poll_remote_window(&mut self) -> Poll<WindowUpdate, ()> { |     fn increment_remote_window(&mut self, id: StreamId, incr: u32) { | ||||||
|  |         if id.is_zero() { | ||||||
|  |             self.remote_flow_controller.increment(incr); | ||||||
|  |         } else { | ||||||
|  |             match self.streams.get_mut(&id) { | ||||||
|  |                 Some(&mut State::Open { remote: PeerState::Data(ref mut fc), .. }) | | ||||||
|  |                 Some(&mut State::HalfClosedLocal(PeerState::Data(ref mut fc))) => { | ||||||
|  |                     fc.increment(incr); | ||||||
|  |                 } | ||||||
|  |                 _ => {} | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         unimplemented!() |         unimplemented!() | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -154,6 +162,7 @@ impl<T, P> Stream for Connection<T, P> | |||||||
|     fn poll(&mut self) -> Poll<Option<Self::Item>, ConnectionError> { |     fn poll(&mut self) -> Poll<Option<Self::Item>, ConnectionError> { | ||||||
|         trace!("Connection::poll"); |         trace!("Connection::poll"); | ||||||
|  |  | ||||||
|  |     loop { | ||||||
|             let frame = match try!(self.inner.poll()) { |             let frame = match try!(self.inner.poll()) { | ||||||
|                 Async::Ready(f) => f, |                 Async::Ready(f) => f, | ||||||
|                 Async::NotReady => { |                 Async::NotReady => { | ||||||
| @@ -172,9 +181,12 @@ impl<T, P> Stream for Connection<T, P> | |||||||
|                     let stream_id = v.stream_id(); |                     let stream_id = v.stream_id(); | ||||||
|                     let end_of_stream = v.is_end_stream(); |                     let end_of_stream = v.is_end_stream(); | ||||||
|  |  | ||||||
|  |                     // TODO load window size from settings. | ||||||
|  |                     let init_window_size = 65_535; | ||||||
|  |  | ||||||
|                     let stream_initialized = try!(self.streams.entry(stream_id) |                     let stream_initialized = try!(self.streams.entry(stream_id) | ||||||
|                         .or_insert(State::default()) |                         .or_insert(State::default()) | ||||||
|                      .recv_headers::<P>(end_of_stream)); |                         .recv_headers::<P>(end_of_stream, init_window_size)); | ||||||
|  |  | ||||||
|                     if stream_initialized { |                     if stream_initialized { | ||||||
|                         // TODO: Ensure available capacity for a new stream |                         // TODO: Ensure available capacity for a new stream | ||||||
| @@ -204,11 +216,16 @@ impl<T, P> Stream for Connection<T, P> | |||||||
|                         end_of_stream: end_of_stream, |                         end_of_stream: end_of_stream, | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |                 Some(WireFrame::WindowUpdate(v)) => { | ||||||
|  |                     self.increment_remote_window(v.stream_id(), v.increment()); | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|                 Some(frame) => panic!("unexpected frame; frame={:?}", frame), |                 Some(frame) => panic!("unexpected frame; frame={:?}", frame), | ||||||
|                 None => return Ok(Async::Ready(None)), |                 None => return Ok(Async::Ready(None)), | ||||||
|             }; |             }; | ||||||
|  |  | ||||||
|         Ok(Async::Ready(Some(frame))) |             return Ok(Async::Ready(Some(frame))); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -229,13 +246,15 @@ impl<T, P> Sink for Connection<T, P> | |||||||
|  |  | ||||||
|         match item { |         match item { | ||||||
|             Frame::Headers { id, headers, end_of_stream } => { |             Frame::Headers { id, headers, end_of_stream } => { | ||||||
|  |                 // TODO load window size from settings. | ||||||
|  |                 let init_window_size = 65_535; | ||||||
|  |  | ||||||
|                 // Transition the stream state, creating a new entry if needed |                 // Transition the stream state, creating a new entry if needed | ||||||
|                 // |  | ||||||
|                 // TODO: Response can send multiple headers frames before body |                 // TODO: Response can send multiple headers frames before body | ||||||
|                 // (1xx responses). |                 // (1xx responses). | ||||||
|                 let stream_initialized = try!(self.streams.entry(id) |                 let stream_initialized = try!(self.streams.entry(id) | ||||||
|                      .or_insert(State::default()) |                      .or_insert(State::default()) | ||||||
|                      .send_headers::<P>(end_of_stream)); |                      .send_headers::<P>(end_of_stream, init_window_size)); | ||||||
|  |  | ||||||
|                 if stream_initialized { |                 if stream_initialized { | ||||||
|                     // TODO: Ensure available capacity for a new stream |                     // TODO: Ensure available capacity for a new stream | ||||||
|   | |||||||
							
								
								
									
										40
									
								
								src/proto/flow_control.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/proto/flow_control.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | #[derive(Clone, Copy, Debug)] | ||||||
|  | pub struct WindowUnderflow; | ||||||
|  |  | ||||||
|  | #[derive(Copy, Clone, Debug)] | ||||||
|  | pub struct FlowController { | ||||||
|  |     window_size: u32, | ||||||
|  |     underflow: u32, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl FlowController { | ||||||
|  |     pub fn new(window_size: u32) -> FlowController { | ||||||
|  |         FlowController { | ||||||
|  |             window_size, | ||||||
|  |             underflow: 0, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pub fn shrink(&mut self, sz: u32) { | ||||||
|  |         self.underflow += sz; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pub fn consume(&mut self, sz: u32) -> Result<(), WindowUnderflow> { | ||||||
|  |         if self.window_size < sz { | ||||||
|  |             return Err(WindowUnderflow); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         self.window_size -= sz; | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pub fn increment(&mut self, sz: u32) { | ||||||
|  |         if sz <= self.underflow { | ||||||
|  |             self.underflow -= sz; | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         self.window_size += sz - self.underflow; | ||||||
|  |         self.underflow = 0; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,4 +1,5 @@ | |||||||
| mod connection; | mod connection; | ||||||
|  | mod flow_control; | ||||||
| mod framed_read; | mod framed_read; | ||||||
| mod framed_write; | mod framed_write; | ||||||
| mod ping_pong; | mod ping_pong; | ||||||
| @@ -7,13 +8,14 @@ mod settings; | |||||||
| mod state; | mod state; | ||||||
| mod window_update; | mod window_update; | ||||||
|  |  | ||||||
| pub use self::connection::{Connection}; | pub use self::connection::Connection; | ||||||
|  | pub use self::flow_control::FlowController; | ||||||
| pub use self::framed_read::FramedRead; | pub use self::framed_read::FramedRead; | ||||||
| pub use self::framed_write::FramedWrite; | pub use self::framed_write::FramedWrite; | ||||||
| pub use self::ping_pong::PingPong; | pub use self::ping_pong::PingPong; | ||||||
| pub use self::ready::ReadySink; | pub use self::ready::ReadySink; | ||||||
| pub use self::settings::Settings; | pub use self::settings::Settings; | ||||||
| pub use self::state::State; | pub use self::state::{PeerState, State}; | ||||||
| pub use self::window_update::WindowUpdate; | pub use self::window_update::WindowUpdate; | ||||||
|  |  | ||||||
| use {frame, Peer}; | use {frame, Peer}; | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| use {ConnectionError, Reason, Peer}; | use {ConnectionError, Reason, Peer}; | ||||||
|  | use proto::FlowController; | ||||||
|  |  | ||||||
| /// Represents the state of an H2 stream | /// Represents the state of an H2 stream | ||||||
| /// | /// | ||||||
| @@ -40,7 +41,7 @@ use {ConnectionError, Reason, Peer}; | |||||||
| ///        ES: END_STREAM flag | ///        ES: END_STREAM flag | ||||||
| ///        R:  RST_STREAM frame | ///        R:  RST_STREAM frame | ||||||
| /// ``` | /// ``` | ||||||
| #[derive(Debug, Copy, Clone, Eq, PartialEq)] | #[derive(Debug, Copy, Clone)] | ||||||
| pub enum State { | pub enum State { | ||||||
|     Idle, |     Idle, | ||||||
|     ReservedLocal, |     ReservedLocal, | ||||||
| @@ -54,18 +55,35 @@ pub enum State { | |||||||
|     Closed, |     Closed, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Debug, Copy, Clone, Eq, PartialEq)] | #[derive(Debug, Copy, Clone)] | ||||||
| pub enum PeerState { | pub enum PeerState { | ||||||
|     Headers, |     Headers, | ||||||
|     Data, |     Data(FlowController), | ||||||
| } | } | ||||||
|  |  | ||||||
| impl State { | impl State { | ||||||
|  |     pub fn increment_local_window_size(&mut self, incr: u32) { | ||||||
|  |         use self::State::*; | ||||||
|  |         use self::PeerState::*; | ||||||
|  |  | ||||||
|  |         *self = match *self { | ||||||
|  |             Open { local: Data(mut local), remote } => { | ||||||
|  |                 local.increment(incr); | ||||||
|  |                 Open { local: Data(local), remote } | ||||||
|  |             } | ||||||
|  |             HalfClosedRemote(Data(mut local)) => { | ||||||
|  |                 local.increment(incr); | ||||||
|  |                 HalfClosedRemote(Data(local)) | ||||||
|  |             } | ||||||
|  |             s => s, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /// Transition the state to represent headers being received. |     /// Transition the state to represent headers being received. | ||||||
|     /// |     /// | ||||||
|     /// Returns true if this state transition results in iniitializing the |     /// Returns true if this state transition results in iniitializing the | ||||||
|     /// stream id. `Err` is returned if this is an invalid state transition. |     /// stream id. `Err` is returned if this is an invalid state transition. | ||||||
|     pub fn recv_headers<P: Peer>(&mut self, eos: bool) -> Result<bool, ConnectionError> { |     pub fn recv_headers<P: Peer>(&mut self, eos: bool, remote_window_size: u32) -> Result<bool, ConnectionError> { | ||||||
|         use self::State::*; |         use self::State::*; | ||||||
|         use self::PeerState::*; |         use self::PeerState::*; | ||||||
|  |  | ||||||
| @@ -76,7 +94,7 @@ impl State { | |||||||
|                 } else { |                 } else { | ||||||
|                     Open { |                     Open { | ||||||
|                         local: Headers, |                         local: Headers, | ||||||
|                         remote: Data, |                         remote: Data(FlowController::new(remote_window_size)), | ||||||
|                     } |                     } | ||||||
|                 }; |                 }; | ||||||
|  |  | ||||||
| @@ -88,7 +106,7 @@ impl State { | |||||||
|                 *self = if eos { |                 *self = if eos { | ||||||
|                     HalfClosedRemote(local) |                     HalfClosedRemote(local) | ||||||
|                 } else { |                 } else { | ||||||
|                     let remote = Data; |                     let remote = Data(FlowController::new(remote_window_size)); | ||||||
|                     Open { local, remote } |                     Open { local, remote } | ||||||
|                 }; |                 }; | ||||||
|  |  | ||||||
| @@ -100,7 +118,7 @@ impl State { | |||||||
|                 *self = if eos { |                 *self = if eos { | ||||||
|                     Closed |                     Closed | ||||||
|                 } else { |                 } else { | ||||||
|                     HalfClosedLocal(Data) |                     HalfClosedLocal(Data(FlowController::new(remote_window_size))) | ||||||
|                 }; |                 }; | ||||||
|  |  | ||||||
|                 Ok(false) |                 Ok(false) | ||||||
| @@ -116,7 +134,7 @@ impl State { | |||||||
|     /// |     /// | ||||||
|     /// Returns true if this state transition results in initializing the stream |     /// Returns true if this state transition results in initializing the stream | ||||||
|     /// id. `Err` is returned if this is an invalid state transition. |     /// id. `Err` is returned if this is an invalid state transition. | ||||||
|     pub fn send_headers<P: Peer>(&mut self, eos: bool) -> Result<bool, ConnectionError> { |     pub fn send_headers<P: Peer>(&mut self, eos: bool, local_window_size: u32) -> Result<bool, ConnectionError> { | ||||||
|         use self::State::*; |         use self::State::*; | ||||||
|         use self::PeerState::*; |         use self::PeerState::*; | ||||||
|  |  | ||||||
| @@ -126,7 +144,7 @@ impl State { | |||||||
|                     HalfClosedLocal(Headers) |                     HalfClosedLocal(Headers) | ||||||
|                 } else { |                 } else { | ||||||
|                     Open { |                     Open { | ||||||
|                         local: Data, |                         local: Data(FlowController::new(local_window_size)), | ||||||
|                         remote: Headers, |                         remote: Headers, | ||||||
|                     } |                     } | ||||||
|                 }; |                 }; | ||||||
| @@ -139,7 +157,7 @@ impl State { | |||||||
|                 *self = if eos { |                 *self = if eos { | ||||||
|                     HalfClosedLocal(remote) |                     HalfClosedLocal(remote) | ||||||
|                 } else { |                 } else { | ||||||
|                     let local = Data; |                     let local = Data(FlowController::new(local_window_size)); | ||||||
|                     Open { local, remote } |                     Open { local, remote } | ||||||
|                 }; |                 }; | ||||||
|  |  | ||||||
| @@ -151,7 +169,7 @@ impl State { | |||||||
|                 *self = if eos { |                 *self = if eos { | ||||||
|                     Closed |                     Closed | ||||||
|                 } else { |                 } else { | ||||||
|                     HalfClosedRemote(Data) |                     HalfClosedRemote(Data(FlowController::new(local_window_size))) | ||||||
|                 }; |                 }; | ||||||
|  |  | ||||||
|                 Ok(false) |                 Ok(false) | ||||||
|   | |||||||
| @@ -1,16 +1,36 @@ | |||||||
| use StreamId; | use StreamId; | ||||||
|  | use frame; | ||||||
|  |  | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub enum WindowUpdate { | pub enum WindowUpdate { | ||||||
|     Connection { increment: usize }, |     Connection { increment: u32 }, | ||||||
|     Stream { id: StreamId, increment: usize }, |     Stream { id: StreamId, increment: u32 }, | ||||||
| } | } | ||||||
|  |  | ||||||
| impl WindowUpdate { | impl WindowUpdate { | ||||||
|     pub fn increment(&self) -> usize { |     pub fn increment(&self) -> u32 { | ||||||
|         match *self { |         match *self { | ||||||
|             WindowUpdate::Connection { increment } | |             WindowUpdate::Connection { increment } | | ||||||
|             WindowUpdate::Stream { increment, .. } => increment |             WindowUpdate::Stream { increment, .. } => increment | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | impl From<WindowUpdate> for frame::WindowUpdate { | ||||||
|  |     fn from(src: WindowUpdate) -> Self { | ||||||
|  |         match src { | ||||||
|  |             WindowUpdate::Connection { increment } => { | ||||||
|  |                 frame::WindowUpdate::new(StreamId::zero(), increment) | ||||||
|  |             } | ||||||
|  |             WindowUpdate::Stream { id, increment } => { | ||||||
|  |                 frame::WindowUpdate::new(id, increment) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl From<WindowUpdate> for frame::Frame { | ||||||
|  |     fn from(src: WindowUpdate) -> Self { | ||||||
|  |         frame::Frame::WindowUpdate(src.into()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user