put each interface in its own file
This commit is contained in:
23
src/proto/apply_settings.rs
Normal file
23
src/proto/apply_settings.rs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
use ConnectionError;
|
||||||
|
use frame::SettingSet;
|
||||||
|
|
||||||
|
/// Allows settings updates to be pushed "down" the transport (i.e. from Settings down to
|
||||||
|
/// FramedWrite).
|
||||||
|
pub trait ApplySettings {
|
||||||
|
fn apply_local_settings(&mut self, set: &SettingSet) -> Result<(), ConnectionError>;
|
||||||
|
fn apply_remote_settings(&mut self, set: &SettingSet) -> Result<(), ConnectionError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! proxy_apply_settings {
|
||||||
|
($outer:ident) => (
|
||||||
|
impl<T: ApplySettings> ApplySettings for $outer<T> {
|
||||||
|
fn apply_local_settings(&mut self, set: &frame::SettingSet) -> Result<(), ConnectionError> {
|
||||||
|
self.inner.apply_local_settings(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_remote_settings(&mut self, set: &frame::SettingSet) -> Result<(), ConnectionError> {
|
||||||
|
self.inner.apply_remote_settings(set)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
30
src/proto/control_flow.rs
Normal file
30
src/proto/control_flow.rs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
use ConnectionError;
|
||||||
|
use proto::*;
|
||||||
|
|
||||||
|
/// Exposes flow control states to "upper" layers of the transport (i.e. above
|
||||||
|
/// FlowControl).
|
||||||
|
pub trait ControlFlow {
|
||||||
|
/// Polls for the next window update from the remote.
|
||||||
|
fn poll_window_update(&mut self) -> Poll<WindowUpdate, ConnectionError>;
|
||||||
|
|
||||||
|
/// Increases the local receive capacity of a stream.
|
||||||
|
///
|
||||||
|
/// This may cause a window update to be sent to the remote.
|
||||||
|
///
|
||||||
|
/// Fails if the given stream is not active.
|
||||||
|
fn expand_window(&mut self, id: StreamId, incr: WindowSize) -> Result<(), ConnectionError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! proxy_control_flow {
|
||||||
|
($outer:ident) => (
|
||||||
|
impl<T: ControlFlow> ControlFlow for $outer<T> {
|
||||||
|
fn poll_window_update(&mut self) -> Poll<WindowUpdate, ConnectionError> {
|
||||||
|
self.inner.poll_window_update()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expand_window(&mut self, id: StreamId, incr: WindowSize) -> Result<(), ConnectionError> {
|
||||||
|
self.inner.expand_window(id, incr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
21
src/proto/control_ping.rs
Normal file
21
src/proto/control_ping.rs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
use ConnectionError;
|
||||||
|
use proto::*;
|
||||||
|
|
||||||
|
pub trait ControlPing {
|
||||||
|
fn start_ping(&mut self, body: PingPayload) -> StartSend<PingPayload, ConnectionError>;
|
||||||
|
fn take_pong(&mut self) -> Option<PingPayload>;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! proxy_control_ping {
|
||||||
|
($outer:ident) => (
|
||||||
|
impl<T: ControlPing> ControlPing for $outer<T> {
|
||||||
|
fn start_ping(&mut self, body: PingPayload) -> StartSend<PingPayload, ConnectionError> {
|
||||||
|
self.inner.start_ping(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn take_pong(&mut self) -> Option<PingPayload> {
|
||||||
|
self.inner.take_pong()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
13
src/proto/control_settings.rs
Normal file
13
src/proto/control_settings.rs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
use ConnectionError;
|
||||||
|
use frame::SettingSet;
|
||||||
|
use proto::*;
|
||||||
|
|
||||||
|
/// Exposes settings to "upper" layers of the transport (i.e. from Settings up to---and
|
||||||
|
/// above---Connection).
|
||||||
|
pub trait ControlSettings {
|
||||||
|
fn update_local_settings(&mut self, set: SettingSet) -> Result<(), ConnectionError>;
|
||||||
|
|
||||||
|
fn remote_push_enabled(&self) -> Option<bool>;
|
||||||
|
fn remote_max_concurrent_streams(&self) -> Option<u32>;
|
||||||
|
fn remote_initial_window_size(&self) -> WindowSize;
|
||||||
|
}
|
||||||
@@ -1,88 +1,6 @@
|
|||||||
use ConnectionError;
|
use ConnectionError;
|
||||||
use frame::SettingSet;
|
|
||||||
use proto::*;
|
use proto::*;
|
||||||
|
|
||||||
/// Exposes settings to "upper" layers of the transport (i.e. from Settings up to---and
|
|
||||||
/// above---Connection).
|
|
||||||
pub trait ControlSettings {
|
|
||||||
fn update_local_settings(&mut self, set: SettingSet) -> Result<(), ConnectionError>;
|
|
||||||
|
|
||||||
fn remote_push_enabled(&self) -> Option<bool>;
|
|
||||||
fn remote_max_concurrent_streams(&self) -> Option<u32>;
|
|
||||||
fn remote_initial_window_size(&self) -> WindowSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// macro_rules! proxy_control_settings {
|
|
||||||
// ($outer:ident) => (
|
|
||||||
// impl<T: ControlSettings> ControlSettings for $outer<T> {
|
|
||||||
// fn update_local_settings(&mut self, set: SettingSet) -> Result<(), ConnectionError> {
|
|
||||||
// self.inner.update_local_settings(set)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn remote_push_enabled(&self) -> Option<bool> {
|
|
||||||
// self.inner.remote_push_enabled(set)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn remote_max_concurrent_streams(&self) -> Option<u32> {
|
|
||||||
// self.inner.remote_max_concurrent_streams(set)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn remote_initial_window_size(&self) -> WindowSize {
|
|
||||||
// self.inner.remote_initial_window_size(set)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
|
|
||||||
/// Allows settings updates to be pushed "down" the transport (i.e. from Settings down to
|
|
||||||
/// FramedWrite).
|
|
||||||
pub trait ApplySettings {
|
|
||||||
fn apply_local_settings(&mut self, set: &SettingSet) -> Result<(), ConnectionError>;
|
|
||||||
fn apply_remote_settings(&mut self, set: &SettingSet) -> Result<(), ConnectionError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! proxy_apply_settings {
|
|
||||||
($outer:ident) => (
|
|
||||||
impl<T: ApplySettings> ApplySettings for $outer<T> {
|
|
||||||
fn apply_local_settings(&mut self, set: &frame::SettingSet) -> Result<(), ConnectionError> {
|
|
||||||
self.inner.apply_local_settings(set)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn apply_remote_settings(&mut self, set: &frame::SettingSet) -> Result<(), ConnectionError> {
|
|
||||||
self.inner.apply_remote_settings(set)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Exposes flow control states to "upper" layers of the transport (i.e. above
|
|
||||||
/// FlowControl).
|
|
||||||
pub trait ControlFlow {
|
|
||||||
/// Polls for the next window update from the remote.
|
|
||||||
fn poll_window_update(&mut self) -> Poll<WindowUpdate, ConnectionError>;
|
|
||||||
|
|
||||||
/// Increases the local receive capacity of a stream.
|
|
||||||
///
|
|
||||||
/// This may cause a window update to be sent to the remote.
|
|
||||||
///
|
|
||||||
/// Fails if the given stream is not active.
|
|
||||||
fn expand_window(&mut self, id: StreamId, incr: WindowSize) -> Result<(), ConnectionError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! proxy_control_flow {
|
|
||||||
($outer:ident) => (
|
|
||||||
impl<T: ControlFlow> ControlFlow for $outer<T> {
|
|
||||||
fn poll_window_update(&mut self) -> Poll<WindowUpdate, ConnectionError> {
|
|
||||||
self.inner.poll_window_update()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn expand_window(&mut self, id: StreamId, incr: WindowSize) -> Result<(), ConnectionError> {
|
|
||||||
self.inner.expand_window(id, incr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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 {
|
||||||
@@ -281,22 +199,3 @@ macro_rules! proxy_control_streams {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ControlPing {
|
|
||||||
fn start_ping(&mut self, body: PingPayload) -> StartSend<PingPayload, ConnectionError>;
|
|
||||||
fn take_pong(&mut self) -> Option<PingPayload>;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! proxy_control_ping {
|
|
||||||
($outer:ident) => (
|
|
||||||
impl<T: ControlPing> ControlPing for $outer<T> {
|
|
||||||
fn start_ping(&mut self, body: PingPayload) -> StartSend<PingPayload, ConnectionError> {
|
|
||||||
self.inner.start_ping(body)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn take_pong(&mut self) -> Option<PingPayload> {
|
|
||||||
self.inner.take_pong()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -7,9 +7,23 @@ use futures::*;
|
|||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
use tokio_io::codec::length_delimited;
|
use tokio_io::codec::length_delimited;
|
||||||
|
|
||||||
|
// First, pull in the internal interfaces that support macros used throughout this module.
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod ifaces;
|
mod apply_settings;
|
||||||
use self::ifaces::*;
|
#[macro_use]
|
||||||
|
mod control_flow;
|
||||||
|
#[macro_use]
|
||||||
|
mod control_ping;
|
||||||
|
mod control_settings;
|
||||||
|
#[macro_use]
|
||||||
|
mod control_streams;
|
||||||
|
|
||||||
|
use self::apply_settings::ApplySettings;
|
||||||
|
use self::control_flow::ControlFlow;
|
||||||
|
use self::control_ping::ControlPing;
|
||||||
|
use self::control_settings::ControlSettings;
|
||||||
|
use self::control_streams::ControlStreams;
|
||||||
|
|
||||||
mod connection;
|
mod connection;
|
||||||
mod flow_control;
|
mod flow_control;
|
||||||
@@ -39,7 +53,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_store::StreamStore;
|
use self::stream_store::StreamStates;
|
||||||
|
|
||||||
/// Represents the internals of an HTTP/2 connection.
|
/// Represents the internals of an HTTP/2 connection.
|
||||||
///
|
///
|
||||||
@@ -59,7 +73,7 @@ use self::stream_store::StreamStore;
|
|||||||
///
|
///
|
||||||
/// ### The stream transport
|
/// ### The stream transport
|
||||||
///
|
///
|
||||||
/// The states of all HTTP/2 connections are stored centrally in the `StreamStore` at the
|
/// The states of all HTTP/2 connections are stored centrally in the `StreamStates` at the
|
||||||
/// bottom of the stream transport. Several modules above this access this state via the
|
/// bottom of the stream transport. Several modules above this access this state via the
|
||||||
/// `ControlStreams` API to drive changes to the stream state. In each direction (send
|
/// `ControlStreams` API to drive changes to the stream state. In each direction (send
|
||||||
/// from local to remote, and recv from remote to local), there is an Stream\*Open module
|
/// from local to remote, and recv from remote to local), there is an Stream\*Open module
|
||||||
@@ -103,7 +117,7 @@ use self::stream_store::StreamStore;
|
|||||||
/// - Ensures that the local peer's max stream concurrency is not violated.
|
/// - Ensures that the local peer's max stream concurrency is not violated.
|
||||||
/// - Emits StreamRefused resets to the remote.
|
/// - Emits StreamRefused resets to the remote.
|
||||||
///
|
///
|
||||||
/// #### `StreamStore`
|
/// #### `StreamStates`
|
||||||
///
|
///
|
||||||
/// - Holds the state of all local & remote active streams.
|
/// - Holds the state of all local & remote active streams.
|
||||||
/// - Holds the cause of all reset/closed streams.
|
/// - Holds the cause of all reset/closed streams.
|
||||||
@@ -138,7 +152,7 @@ type Streams<T, P> =
|
|||||||
FlowControl<
|
FlowControl<
|
||||||
StreamSendClose<
|
StreamSendClose<
|
||||||
StreamRecvOpen<
|
StreamRecvOpen<
|
||||||
StreamStore<T, P>>>>>>;
|
StreamStates<T, P>>>>>>;
|
||||||
|
|
||||||
type Codec<T, B> =
|
type Codec<T, B> =
|
||||||
FramedRead<
|
FramedRead<
|
||||||
@@ -238,7 +252,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,
|
||||||
StreamStore::new(
|
StreamStates::new(
|
||||||
PingPong::new(
|
PingPong::new(
|
||||||
FramedRead::new(framed))))))))
|
FramedRead::new(framed))))))))
|
||||||
});
|
});
|
||||||
|
|||||||
340
src/proto/stream_store.rs
Normal file
340
src/proto/stream_store.rs
Normal file
@@ -0,0 +1,340 @@
|
|||||||
|
use {ConnectionError, Peer, StreamId};
|
||||||
|
use error::Reason::{NoError, ProtocolError};
|
||||||
|
use proto::*;
|
||||||
|
use proto::state::StreamState;
|
||||||
|
|
||||||
|
use fnv::FnvHasher;
|
||||||
|
use ordermap::OrderMap;
|
||||||
|
use std::hash::BuildHasherDefault;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
/// Holds the underlying stream state to be accessed by upper layers.
|
||||||
|
// TODO track reserved streams
|
||||||
|
// TODO constrain the size of `reset`
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct StreamStates<T, P> {
|
||||||
|
inner: T,
|
||||||
|
|
||||||
|
/// Holds active streams initiated by the local endpoint.
|
||||||
|
local_active: OrderMap<StreamId, StreamState, BuildHasherDefault<FnvHasher>>,
|
||||||
|
|
||||||
|
/// Holds active streams initiated by the remote endpoint.
|
||||||
|
remote_active: OrderMap<StreamId, StreamState, BuildHasherDefault<FnvHasher>>,
|
||||||
|
|
||||||
|
/// Holds active streams initiated by the remote.
|
||||||
|
reset: OrderMap<StreamId, Reason, BuildHasherDefault<FnvHasher>>,
|
||||||
|
|
||||||
|
_phantom: PhantomData<P>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, P, U> StreamStates<T, P>
|
||||||
|
where T: Stream<Item = Frame, Error = ConnectionError>,
|
||||||
|
T: Sink<SinkItem = Frame<U>, SinkError = ConnectionError>,
|
||||||
|
P: Peer,
|
||||||
|
{
|
||||||
|
pub fn new(inner: T) -> StreamStates<T, P> {
|
||||||
|
StreamStates {
|
||||||
|
inner,
|
||||||
|
local_active: OrderMap::default(),
|
||||||
|
remote_active: OrderMap::default(),
|
||||||
|
reset: OrderMap::default(),
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, P: Peer> StreamStates<T, P> {
|
||||||
|
pub fn get_active(&mut self, id: StreamId) -> Option<&StreamState> {
|
||||||
|
assert!(!id.is_zero());
|
||||||
|
if P::is_valid_local_stream_id(id) {
|
||||||
|
self.local_active.get(&id)
|
||||||
|
} else {
|
||||||
|
self.remote_active.get(&id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_active_mut(&mut self, id: StreamId) -> Option<&mut StreamState> {
|
||||||
|
assert!(!id.is_zero());
|
||||||
|
if P::is_valid_local_stream_id(id) {
|
||||||
|
self.local_active.get_mut(&id)
|
||||||
|
} else {
|
||||||
|
self.remote_active.get_mut(&id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_active(&mut self, id: StreamId) {
|
||||||
|
assert!(!id.is_zero());
|
||||||
|
if P::is_valid_local_stream_id(id) {
|
||||||
|
self.local_active.remove(&id);
|
||||||
|
} else {
|
||||||
|
self.remote_active.remove(&id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, P: Peer> ControlStreams for StreamStates<T, P> {
|
||||||
|
fn local_valid_id(id: StreamId) -> bool {
|
||||||
|
P::is_valid_local_stream_id(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remote_valid_id(id: StreamId) -> bool {
|
||||||
|
P::is_valid_remote_stream_id(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn local_can_open() -> bool {
|
||||||
|
P::local_can_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());
|
||||||
|
}
|
||||||
|
if self.local_active.contains_key(&id) {
|
||||||
|
return Err(ProtocolError.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.local_active.insert(id, StreamState::new_open_sending(sz));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remote_open(&mut self, id: StreamId, sz: WindowSize) -> Result<(), ConnectionError> {
|
||||||
|
if !Self::remote_valid_id(id) || !Self::remote_can_open() {
|
||||||
|
return Err(ProtocolError.into());
|
||||||
|
}
|
||||||
|
if self.remote_active.contains_key(&id) {
|
||||||
|
return Err(ProtocolError.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.remote_active.insert(id, StreamState::new_open_recving(sz));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn local_open_recv_half(&mut self, id: StreamId, sz: WindowSize) -> Result<(), ConnectionError> {
|
||||||
|
if !Self::local_valid_id(id) {
|
||||||
|
return Err(ProtocolError.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.local_active.get_mut(&id) {
|
||||||
|
Some(s) => s.open_recv_half(sz).map(|_| {}),
|
||||||
|
None => Err(ProtocolError.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remote_open_send_half(&mut self, id: StreamId, sz: WindowSize) -> Result<(), ConnectionError> {
|
||||||
|
if !Self::remote_valid_id(id) {
|
||||||
|
return Err(ProtocolError.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.remote_active.get_mut(&id) {
|
||||||
|
Some(s) => s.open_send_half(sz).map(|_| {}),
|
||||||
|
None => Err(ProtocolError.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close_send_half(&mut self, id: StreamId) -> Result<(), ConnectionError> {
|
||||||
|
let fully_closed = self.get_active_mut(id)
|
||||||
|
.map(|s| s.close_send_half())
|
||||||
|
.unwrap_or_else(|| Err(ProtocolError.into()))?;
|
||||||
|
|
||||||
|
if fully_closed {
|
||||||
|
self.remove_active(id);
|
||||||
|
self.reset.insert(id, NoError);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close_recv_half(&mut self, id: StreamId) -> Result<(), ConnectionError> {
|
||||||
|
let fully_closed = self.get_active_mut(id)
|
||||||
|
.map(|s| s.close_recv_half())
|
||||||
|
.unwrap_or_else(|| Err(ProtocolError.into()))?;
|
||||||
|
|
||||||
|
if fully_closed {
|
||||||
|
self.remove_active(id);
|
||||||
|
self.reset.insert(id, NoError);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset_stream(&mut self, id: StreamId, cause: Reason) {
|
||||||
|
self.remove_active(id);
|
||||||
|
self.reset.insert(id, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_reset(&self, id: StreamId) -> Option<Reason> {
|
||||||
|
self.reset.get(&id).map(|r| *r)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_local_active(&self, id: StreamId) -> bool {
|
||||||
|
self.local_active.contains_key(&id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_remote_active(&self, id: StreamId) -> bool {
|
||||||
|
self.remote_active.contains_key(&id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_send_open(&mut self, id: StreamId) -> bool {
|
||||||
|
match self.get_active(id) {
|
||||||
|
Some(s) => s.is_send_open(),
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_recv_open(&mut self, id: StreamId) -> bool {
|
||||||
|
match self.get_active(id) {
|
||||||
|
Some(s) => s.is_recv_open(),
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn local_active_len(&self) -> usize {
|
||||||
|
self.local_active.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remote_active_len(&self) -> usize {
|
||||||
|
self.remote_active.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_inital_recv_window_size(&mut self, old_sz: WindowSize, new_sz: WindowSize) {
|
||||||
|
if new_sz < old_sz {
|
||||||
|
let decr = old_sz - new_sz;
|
||||||
|
|
||||||
|
for s in self.local_active.values_mut() {
|
||||||
|
if let Some(fc) = s.recv_flow_controller() {
|
||||||
|
fc.shrink_window(decr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for s in self.remote_active.values_mut() {
|
||||||
|
if let Some(fc) = s.recv_flow_controller() {
|
||||||
|
fc.shrink_window(decr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let incr = new_sz - old_sz;
|
||||||
|
|
||||||
|
for s in self.local_active.values_mut() {
|
||||||
|
if let Some(fc) = s.recv_flow_controller() {
|
||||||
|
fc.expand_window(incr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for s in self.remote_active.values_mut() {
|
||||||
|
if let Some(fc) = s.recv_flow_controller() {
|
||||||
|
fc.expand_window(incr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_inital_send_window_size(&mut self, old_sz: WindowSize, new_sz: WindowSize) {
|
||||||
|
if new_sz < old_sz {
|
||||||
|
let decr = old_sz - new_sz;
|
||||||
|
|
||||||
|
for s in self.local_active.values_mut() {
|
||||||
|
if let Some(fc) = s.send_flow_controller() {
|
||||||
|
fc.shrink_window(decr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for s in self.remote_active.values_mut() {
|
||||||
|
if let Some(fc) = s.send_flow_controller() {
|
||||||
|
fc.shrink_window(decr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let incr = new_sz - old_sz;
|
||||||
|
|
||||||
|
for s in self.local_active.values_mut() {
|
||||||
|
if let Some(fc) = s.send_flow_controller() {
|
||||||
|
fc.expand_window(incr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for s in self.remote_active.values_mut() {
|
||||||
|
if let Some(fc) = s.send_flow_controller() {
|
||||||
|
fc.expand_window(incr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn recv_flow_controller(&mut self, id: StreamId) -> Option<&mut FlowControlState> {
|
||||||
|
if id.is_zero() {
|
||||||
|
None
|
||||||
|
} else if P::is_valid_local_stream_id(id) {
|
||||||
|
self.local_active.get_mut(&id).and_then(|s| s.recv_flow_controller())
|
||||||
|
} else {
|
||||||
|
self.remote_active.get_mut(&id).and_then(|s| s.recv_flow_controller())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_flow_controller(&mut self, id: StreamId) -> Option<&mut FlowControlState> {
|
||||||
|
if id.is_zero() {
|
||||||
|
None
|
||||||
|
} else if P::is_valid_local_stream_id(id) {
|
||||||
|
self.local_active.get_mut(&id).and_then(|s| s.send_flow_controller())
|
||||||
|
} else {
|
||||||
|
self.remote_active.get_mut(&id).and_then(|s| s.send_flow_controller())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Proxy.
|
||||||
|
impl<T, P> Stream for StreamStates<T, P>
|
||||||
|
where T: Stream<Item = Frame, Error = ConnectionError>,
|
||||||
|
{
|
||||||
|
type Item = Frame;
|
||||||
|
type Error = ConnectionError;
|
||||||
|
|
||||||
|
fn poll(&mut self) -> Poll<Option<Frame>, ConnectionError> {
|
||||||
|
self.inner.poll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Proxy.
|
||||||
|
impl<T, P, U> Sink for StreamStates<T, P>
|
||||||
|
where T: Sink<SinkItem = Frame<U>, SinkError = ConnectionError>,
|
||||||
|
{
|
||||||
|
type SinkItem = Frame<U>;
|
||||||
|
type SinkError = ConnectionError;
|
||||||
|
|
||||||
|
fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Frame<U>, ConnectionError> {
|
||||||
|
self.inner.start_send(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_complete(&mut self) -> Poll<(), ConnectionError> {
|
||||||
|
self.inner.poll_complete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Proxy.
|
||||||
|
impl<T, P, U> ReadySink for StreamStates<T, P>
|
||||||
|
where T: Sink<SinkItem = Frame<U>, SinkError = ConnectionError>,
|
||||||
|
T: ReadySink,
|
||||||
|
{
|
||||||
|
fn poll_ready(&mut self) -> Poll<(), ConnectionError> {
|
||||||
|
self.inner.poll_ready()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Proxy.
|
||||||
|
impl<T: ApplySettings, P> ApplySettings for StreamStates<T, P> {
|
||||||
|
fn apply_local_settings(&mut self, set: &frame::SettingSet) -> Result<(), ConnectionError> {
|
||||||
|
self.inner.apply_local_settings(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_remote_settings(&mut self, set: &frame::SettingSet) -> Result<(), ConnectionError> {
|
||||||
|
self.inner.apply_remote_settings(set)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Proxy.
|
||||||
|
impl<T: ControlPing, P> ControlPing for StreamStates<T, P> {
|
||||||
|
fn start_ping(&mut self, body: PingPayload) -> StartSend<PingPayload, ConnectionError> {
|
||||||
|
self.inner.start_ping(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn take_pong(&mut self) -> Option<PingPayload> {
|
||||||
|
self.inner.take_pong()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user