Many more changes
This commit is contained in:
@@ -34,3 +34,6 @@ openssl = { version = "0.9.14", "features" = ["v102"] }
|
|||||||
tokio-openssl = "0.1.3"
|
tokio-openssl = "0.1.3"
|
||||||
env_logger = "0.4.3"
|
env_logger = "0.4.3"
|
||||||
io-dump = { git = "https://github.com/carllerche/io-dump" }
|
io-dump = { git = "https://github.com/carllerche/io-dump" }
|
||||||
|
|
||||||
|
[replace]
|
||||||
|
"tokio-io:0.1.2" = { git = "https://github.com/tokio-rs/tokio-io" }
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ pub use self::headers::{Headers, PushPromise, Continuation, Pseudo};
|
|||||||
pub use self::ping::Ping;
|
pub use self::ping::Ping;
|
||||||
pub use self::priority::{Priority, StreamDependency};
|
pub use self::priority::{Priority, StreamDependency};
|
||||||
pub use self::reset::Reset;
|
pub use self::reset::Reset;
|
||||||
pub use self::settings::{Settings, SettingSet};
|
pub use self::settings::Settings;
|
||||||
pub use self::stream_id::StreamId;
|
pub use self::stream_id::StreamId;
|
||||||
pub use self::window_update::WindowUpdate;
|
pub use self::window_update::WindowUpdate;
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,6 @@ use bytes::{BytesMut, BufMut, BigEndian};
|
|||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
flags: SettingsFlags,
|
flags: SettingsFlags,
|
||||||
// Fields
|
// Fields
|
||||||
values: SettingSet,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Eq, PartialEq)]
|
|
||||||
pub struct SettingSet {
|
|
||||||
header_table_size: Option<u32>,
|
header_table_size: Option<u32>,
|
||||||
enable_push: Option<u32>,
|
enable_push: Option<u32>,
|
||||||
max_concurrent_streams: Option<u32>,
|
max_concurrent_streams: Option<u32>,
|
||||||
@@ -19,20 +14,6 @@ pub struct SettingSet {
|
|||||||
max_header_list_size: Option<u32>,
|
max_header_list_size: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SettingSet {
|
|
||||||
pub fn enable_push(&self) -> Option<bool> {
|
|
||||||
self.enable_push.map(|n| n != 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn initial_window_size(&self) -> Option<u32> {
|
|
||||||
self.initial_window_size
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn max_concurrent_streams(&self) -> Option<u32> {
|
|
||||||
self.max_concurrent_streams
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An enum that lists all valid settings that can be sent in a SETTINGS
|
/// An enum that lists all valid settings that can be sent in a SETTINGS
|
||||||
/// frame.
|
/// frame.
|
||||||
///
|
///
|
||||||
@@ -73,6 +54,22 @@ impl Settings {
|
|||||||
self.flags.is_ack()
|
self.flags.is_ack()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn enable_push(&self) -> Option<bool> {
|
||||||
|
self.enable_push.map(|n| n != 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn initial_window_size(&self) -> Option<u32> {
|
||||||
|
self.initial_window_size
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn max_concurrent_streams(&self) -> Option<u32> {
|
||||||
|
self.max_concurrent_streams
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn max_frame_size(&self) -> Option<u32> {
|
||||||
|
self.max_frame_size
|
||||||
|
}
|
||||||
|
|
||||||
pub fn load(head: Head, payload: &[u8]) -> Result<Settings, Error> {
|
pub fn load(head: Head, payload: &[u8]) -> Result<Settings, Error> {
|
||||||
use self::Setting::*;
|
use self::Setting::*;
|
||||||
|
|
||||||
@@ -107,12 +104,12 @@ impl Settings {
|
|||||||
for raw in payload.chunks(6) {
|
for raw in payload.chunks(6) {
|
||||||
match Setting::load(raw) {
|
match Setting::load(raw) {
|
||||||
Some(HeaderTableSize(val)) => {
|
Some(HeaderTableSize(val)) => {
|
||||||
settings.values.header_table_size = Some(val);
|
settings.header_table_size = Some(val);
|
||||||
}
|
}
|
||||||
Some(EnablePush(val)) => {
|
Some(EnablePush(val)) => {
|
||||||
match val {
|
match val {
|
||||||
0 | 1 => {
|
0 | 1 => {
|
||||||
settings.values.enable_push = Some(val);
|
settings.enable_push = Some(val);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::InvalidSettingValue);
|
return Err(Error::InvalidSettingValue);
|
||||||
@@ -120,24 +117,24 @@ impl Settings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(MaxConcurrentStreams(val)) => {
|
Some(MaxConcurrentStreams(val)) => {
|
||||||
settings.values.max_concurrent_streams = Some(val);
|
settings.max_concurrent_streams = Some(val);
|
||||||
}
|
}
|
||||||
Some(InitialWindowSize(val)) => {
|
Some(InitialWindowSize(val)) => {
|
||||||
if val as usize > MAX_INITIAL_WINDOW_SIZE {
|
if val as usize > MAX_INITIAL_WINDOW_SIZE {
|
||||||
return Err(Error::InvalidSettingValue);
|
return Err(Error::InvalidSettingValue);
|
||||||
} else {
|
} else {
|
||||||
settings.values.initial_window_size = Some(val);
|
settings.initial_window_size = Some(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(MaxFrameSize(val)) => {
|
Some(MaxFrameSize(val)) => {
|
||||||
if val < DEFAULT_MAX_FRAME_SIZE || val as usize > MAX_MAX_FRAME_SIZE {
|
if val < DEFAULT_MAX_FRAME_SIZE || val as usize > MAX_MAX_FRAME_SIZE {
|
||||||
return Err(Error::InvalidSettingValue);
|
return Err(Error::InvalidSettingValue);
|
||||||
} else {
|
} else {
|
||||||
settings.values.max_frame_size = Some(val);
|
settings.max_frame_size = Some(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(MaxHeaderListSize(val)) => {
|
Some(MaxHeaderListSize(val)) => {
|
||||||
settings.values.max_header_list_size = Some(val);
|
settings.max_header_list_size = Some(val);
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
@@ -171,27 +168,27 @@ impl Settings {
|
|||||||
fn for_each<F: FnMut(Setting)>(&self, mut f: F) {
|
fn for_each<F: FnMut(Setting)>(&self, mut f: F) {
|
||||||
use self::Setting::*;
|
use self::Setting::*;
|
||||||
|
|
||||||
if let Some(v) = self.values.header_table_size {
|
if let Some(v) = self.header_table_size {
|
||||||
f(HeaderTableSize(v));
|
f(HeaderTableSize(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(v) = self.values.enable_push {
|
if let Some(v) = self.enable_push {
|
||||||
f(EnablePush(v));
|
f(EnablePush(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(v) = self.values.max_concurrent_streams {
|
if let Some(v) = self.max_concurrent_streams {
|
||||||
f(MaxConcurrentStreams(v));
|
f(MaxConcurrentStreams(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(v) = self.values.initial_window_size {
|
if let Some(v) = self.initial_window_size {
|
||||||
f(InitialWindowSize(v));
|
f(InitialWindowSize(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(v) = self.values.max_frame_size {
|
if let Some(v) = self.max_frame_size {
|
||||||
f(MaxFrameSize(v));
|
f(MaxFrameSize(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(v) = self.values.max_header_list_size {
|
if let Some(v) = self.max_header_list_size {
|
||||||
f(MaxHeaderListSize(v));
|
f(MaxHeaderListSize(v));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
69
src/proto/codec.rs
Normal file
69
src/proto/codec.rs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
use super::*;
|
||||||
|
use futures::*;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Codec<T, B> {
|
||||||
|
inner: FramedRead<FramedWrite<T, B>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, B> Codec<T, B> {
|
||||||
|
pub fn apply_remote_settings(&mut self, frame: &frame::Settings) {
|
||||||
|
self.framed_read().apply_remote_settings(frame);
|
||||||
|
self.framed_write().apply_remote_settings(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn framed_read(&mut self) -> &mut FramedRead<FramedWrite<T, B>> {
|
||||||
|
&mut self.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
fn framed_write(&mut self) -> &mut FramedWrite<T, B> {
|
||||||
|
self.inner.get_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, B> Codec<T, B>
|
||||||
|
where T: AsyncRead + AsyncWrite,
|
||||||
|
B: Buf,
|
||||||
|
{
|
||||||
|
pub fn from_framed(inner: FramedRead<FramedWrite<T, B>>) -> Self {
|
||||||
|
Codec { inner }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, B> Codec<T, B>
|
||||||
|
where T: AsyncWrite,
|
||||||
|
B: Buf,
|
||||||
|
{
|
||||||
|
pub fn poll_ready(&mut self) -> Poll<(), ConnectionError> {
|
||||||
|
self.inner.poll_ready()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, B> futures::Stream for Codec<T, B>
|
||||||
|
where T: AsyncRead,
|
||||||
|
{
|
||||||
|
type Item = Frame;
|
||||||
|
type Error = ConnectionError;
|
||||||
|
|
||||||
|
fn poll(&mut self) -> Poll<Option<Frame>, ConnectionError> {
|
||||||
|
use futures::Stream;
|
||||||
|
self.inner.poll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, B> Sink for Codec<T, B>
|
||||||
|
where T: AsyncWrite,
|
||||||
|
B: Buf,
|
||||||
|
{
|
||||||
|
type SinkItem = Frame<B>;
|
||||||
|
type SinkError = ConnectionError;
|
||||||
|
|
||||||
|
fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
|
||||||
|
self.inner.start_send(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
|
||||||
|
self.inner.poll_complete()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,22 +47,6 @@ impl<T, P, B> Connection<T, P, B>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_local_settings(&mut self, _local: frame::SettingSet) -> Result<(), ConnectionError> {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remote_initial_window_size(&self) -> u32 {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remote_max_concurrent_streams(&self) -> Option<usize> {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remote_push_enabled(&self) -> Option<bool> {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `Ready` when the connection is ready to receive a frame.
|
/// Returns `Ready` when the connection is ready to receive a frame.
|
||||||
pub fn poll_ready(&mut self) -> Poll<(), ConnectionError> {
|
pub fn poll_ready(&mut self) -> Poll<(), ConnectionError> {
|
||||||
try_ready!(self.poll_send_ready());
|
try_ready!(self.poll_send_ready());
|
||||||
@@ -125,8 +109,6 @@ impl<T, P, B> Connection<T, P, B>
|
|||||||
Some(Settings(frame)) => {
|
Some(Settings(frame)) => {
|
||||||
trace!("recv SETTINGS; frame={:?}", frame);
|
trace!("recv SETTINGS; frame={:?}", frame);
|
||||||
self.settings.recv_settings(frame);
|
self.settings.recv_settings(frame);
|
||||||
|
|
||||||
// TODO: ACK must be sent THEN settings applied.
|
|
||||||
}
|
}
|
||||||
Some(GoAway(frame)) => {
|
Some(GoAway(frame)) => {
|
||||||
// TODO: handle the last_stream_id. Also, should this be
|
// TODO: handle the last_stream_id. Also, should this be
|
||||||
@@ -160,12 +142,10 @@ impl<T, P, B> Connection<T, P, B>
|
|||||||
/// Returns `Ready` when the `Connection` is ready to receive a frame from
|
/// Returns `Ready` when the `Connection` is ready to receive a frame from
|
||||||
/// the socket.
|
/// the socket.
|
||||||
fn poll_recv_ready(&mut self) -> Poll<(), ConnectionError> {
|
fn poll_recv_ready(&mut self) -> Poll<(), ConnectionError> {
|
||||||
// Pong, settings ack, and stream refusals are high priority frames to
|
// The order of these calls don't really matter too much as only one
|
||||||
// send. If the write buffer is full, we stop reading any further frames
|
// should have pending work.
|
||||||
// until these high priority writes can be committed to the buffer.
|
|
||||||
|
|
||||||
try_ready!(self.ping_pong.send_pending_pong(&mut self.codec));
|
try_ready!(self.ping_pong.send_pending_pong(&mut self.codec));
|
||||||
try_ready!(self.settings.send_pending_ack(&mut self.codec));
|
try_ready!(self.settings.send_pending_ack(&mut self.codec, &mut self.streams));
|
||||||
try_ready!(self.streams.send_pending_refusal(&mut self.codec));
|
try_ready!(self.streams.send_pending_refusal(&mut self.codec));
|
||||||
|
|
||||||
Ok(().into())
|
Ok(().into())
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ impl<T> FramedRead<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn apply_remote_settings(&mut self, _settings: &frame::Settings) {
|
||||||
|
// TODO: Is this needed?
|
||||||
|
}
|
||||||
|
|
||||||
fn decode_frame(&mut self, mut bytes: BytesMut) -> Result<Option<Frame>, ConnectionError> {
|
fn decode_frame(&mut self, mut bytes: BytesMut) -> Result<Option<Frame>, ConnectionError> {
|
||||||
trace!("decoding frame from {}B", bytes.len());
|
trace!("decoding frame from {}B", bytes.len());
|
||||||
|
|
||||||
@@ -142,6 +146,10 @@ impl<T> FramedRead<T> {
|
|||||||
|
|
||||||
Ok(Some(frame))
|
Ok(Some(frame))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_mut(&mut self) -> &mut T {
|
||||||
|
self.inner.get_mut()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> futures::Stream for FramedRead<T>
|
impl<T> futures::Stream for FramedRead<T>
|
||||||
|
|||||||
@@ -90,6 +90,14 @@ impl<T, B> FramedWrite<T, B>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T, B> FramedWrite<T, B> {
|
||||||
|
pub fn apply_remote_settings(&mut self, settings: &frame::Settings) {
|
||||||
|
if let Some(val) = settings.max_frame_size() {
|
||||||
|
self.max_frame_size = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T, B> Sink for FramedWrite<T, B>
|
impl<T, B> Sink for FramedWrite<T, B>
|
||||||
where T: AsyncWrite,
|
where T: AsyncWrite,
|
||||||
B: Buf,
|
B: Buf,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
mod codec;
|
||||||
mod connection;
|
mod connection;
|
||||||
mod framed_read;
|
mod framed_read;
|
||||||
mod framed_write;
|
mod framed_write;
|
||||||
@@ -8,6 +9,7 @@ mod streams;
|
|||||||
pub use self::connection::Connection;
|
pub use self::connection::Connection;
|
||||||
pub use self::streams::{Streams, StreamRef, Chunk};
|
pub use self::streams::{Streams, StreamRef, Chunk};
|
||||||
|
|
||||||
|
use self::codec::Codec;
|
||||||
use self::framed_read::FramedRead;
|
use self::framed_read::FramedRead;
|
||||||
use self::framed_write::FramedWrite;
|
use self::framed_write::FramedWrite;
|
||||||
use self::ping_pong::PingPong;
|
use self::ping_pong::PingPong;
|
||||||
@@ -52,10 +54,6 @@ pub struct WindowUpdate {
|
|||||||
increment: WindowSize,
|
increment: WindowSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
type Codec<T, B> =
|
|
||||||
FramedRead<
|
|
||||||
FramedWrite<T, B>>;
|
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
pub const DEFAULT_INITIAL_WINDOW_SIZE: WindowSize = 65_535;
|
pub const DEFAULT_INITIAL_WINDOW_SIZE: WindowSize = 65_535;
|
||||||
pub const MAX_WINDOW_SIZE: WindowSize = ::std::u32::MAX;
|
pub const MAX_WINDOW_SIZE: WindowSize = ::std::u32::MAX;
|
||||||
@@ -90,7 +88,7 @@ pub fn from_framed_write<T, P, B>(framed_write: FramedWrite<T, B::Buf>)
|
|||||||
.max_frame_length(frame::DEFAULT_MAX_FRAME_SIZE as usize)
|
.max_frame_length(frame::DEFAULT_MAX_FRAME_SIZE as usize)
|
||||||
.new_read(framed_write);
|
.new_read(framed_write);
|
||||||
|
|
||||||
let codec = FramedRead::new(framed);
|
let codec = Codec::from_framed(FramedRead::new(framed));
|
||||||
|
|
||||||
Connection::new(codec)
|
Connection::new(codec)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,16 @@ use proto::*;
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
pending_ack: bool,
|
/// Received SETTINGS frame pending processing. The ACK must be written to
|
||||||
|
/// the socket first then the settings applied **before** receiving any
|
||||||
|
/// further frames.
|
||||||
|
pending: Option<frame::Settings>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Settings {
|
impl Settings {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Settings {
|
Settings {
|
||||||
pending_ack: false,
|
pending: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,30 +21,31 @@ impl Settings {
|
|||||||
debug!("received remote settings ack");
|
debug!("received remote settings ack");
|
||||||
// TODO: handle acks
|
// TODO: handle acks
|
||||||
} else {
|
} else {
|
||||||
assert!(!self.pending_ack);
|
assert!(self.pending.is_none());
|
||||||
self.pending_ack = true;
|
self.pending = Some(frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_pending_ack<T, B>(&mut self, dst: &mut Codec<T, B>)
|
pub fn send_pending_ack<T, B>(&mut self,
|
||||||
|
dst: &mut Codec<T, B>,
|
||||||
|
streams: &mut Streams<B>)
|
||||||
-> Poll<(), ConnectionError>
|
-> Poll<(), ConnectionError>
|
||||||
where T: AsyncWrite,
|
where T: AsyncWrite,
|
||||||
B: Buf,
|
B: Buf,
|
||||||
{
|
{
|
||||||
if self.pending_ack {
|
if let Some(ref settings) = self.pending {
|
||||||
let frame = frame::Settings::ack();
|
let frame = frame::Settings::ack();
|
||||||
|
|
||||||
match dst.start_send(frame.into())? {
|
if let AsyncSink::NotReady(_) = dst.start_send(frame.into())? {
|
||||||
AsyncSink::Ready => {
|
return Ok(Async::NotReady);
|
||||||
self.pending_ack = false;
|
|
||||||
return Ok(().into());
|
|
||||||
}
|
|
||||||
AsyncSink::NotReady(_) => {
|
|
||||||
return Ok(Async::NotReady);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dst.apply_remote_settings(settings);
|
||||||
|
streams.apply_remote_settings(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.pending = None;
|
||||||
|
|
||||||
Ok(().into())
|
Ok(().into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,21 @@ impl FlowControl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reduce future capacity of the window.
|
||||||
|
///
|
||||||
|
/// This accomodates updates to SETTINGS_INITIAL_WINDOW_SIZE.
|
||||||
|
pub fn shrink_window(&mut self, dec: WindowSize) {
|
||||||
|
/*
|
||||||
|
if decr < self.next_window_update {
|
||||||
|
self.next_window_update -= decr
|
||||||
|
} else {
|
||||||
|
self.underflow += decr - self.next_window_update;
|
||||||
|
self.next_window_update = 0;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Claims the provided amount from the window, if there is enough space.
|
/// Claims the provided amount from the window, if there is enough space.
|
||||||
///
|
///
|
||||||
/// Fails when `apply_window_update()` hasn't returned at least `sz` more bytes than
|
/// Fails when `apply_window_update()` hasn't returned at least `sz` more bytes than
|
||||||
|
|||||||
@@ -221,14 +221,15 @@ impl<B> Recv<B> where B: Buf {
|
|||||||
|
|
||||||
pub fn recv_push_promise<P: Peer>(&mut self,
|
pub fn recv_push_promise<P: Peer>(&mut self,
|
||||||
frame: frame::PushPromise,
|
frame: frame::PushPromise,
|
||||||
stream: &mut store::Ptr<B>)
|
stream: store::Key,
|
||||||
|
store: &mut Store<B>)
|
||||||
-> Result<(), ConnectionError>
|
-> Result<(), ConnectionError>
|
||||||
{
|
{
|
||||||
// First, make sure that the values are legit
|
// First, make sure that the values are legit
|
||||||
self.ensure_can_reserve::<P>(frame.promised_id())?;
|
self.ensure_can_reserve::<P>(frame.promised_id())?;
|
||||||
|
|
||||||
// Make sure that the stream state is valid
|
// Make sure that the stream state is valid
|
||||||
stream.state.ensure_recv_open()?;
|
store[stream].state.ensure_recv_open()?;
|
||||||
|
|
||||||
// TODO: Streams in the reserved states do not count towards the concurrency
|
// TODO: Streams in the reserved states do not count towards the concurrency
|
||||||
// limit. However, it seems like there should be a cap otherwise this
|
// limit. However, it seems like there should be a cap otherwise this
|
||||||
@@ -247,16 +248,18 @@ impl<B> Recv<B> where B: Buf {
|
|||||||
let mut new_stream = Stream::new(frame.promised_id());
|
let mut new_stream = Stream::new(frame.promised_id());
|
||||||
new_stream.state.reserve_remote();
|
new_stream.state.reserve_remote();
|
||||||
|
|
||||||
let mut ppp = stream.pending_push_promises.take();
|
let mut ppp = store[stream].pending_push_promises.take();
|
||||||
|
|
||||||
{
|
{
|
||||||
// Store the stream
|
// Store the stream
|
||||||
let mut new_stream = stream.store()
|
let mut new_stream = store
|
||||||
.insert(frame.promised_id(), new_stream);
|
.insert(frame.promised_id(), new_stream);
|
||||||
|
|
||||||
ppp.push::<stream::Next>(&mut new_stream);
|
ppp.push::<stream::Next>(&mut new_stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let stream = &mut store[stream];
|
||||||
|
|
||||||
stream.pending_push_promises = ppp;
|
stream.pending_push_promises = ppp;
|
||||||
stream.notify_recv();
|
stream.notify_recv();
|
||||||
|
|
||||||
|
|||||||
@@ -273,6 +273,63 @@ impl<B> Send<B> where B: Buf {
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn apply_remote_settings(&mut self,
|
||||||
|
settings: &frame::Settings,
|
||||||
|
store: &mut Store<B>) {
|
||||||
|
if let Some(val) = settings.max_concurrent_streams() {
|
||||||
|
self.max_streams = Some(val as usize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Applies an update to the remote endpoint's initial window size.
|
||||||
|
//
|
||||||
|
// Per RFC 7540 §6.9.2:
|
||||||
|
//
|
||||||
|
// In addition to changing the flow-control window for streams that are
|
||||||
|
// not yet active, a SETTINGS frame can alter the initial flow-control
|
||||||
|
// window size for streams with active flow-control windows (that is,
|
||||||
|
// streams in the "open" or "half-closed (remote)" state). When the
|
||||||
|
// value of SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver MUST adjust
|
||||||
|
// the size of all stream flow-control windows that it maintains by the
|
||||||
|
// difference between the new value and the old value.
|
||||||
|
//
|
||||||
|
// A change to `SETTINGS_INITIAL_WINDOW_SIZE` can cause the available
|
||||||
|
// space in a flow-control window to become negative. A sender MUST
|
||||||
|
// track the negative flow-control window and MUST NOT send new
|
||||||
|
// flow-controlled frames until it receives WINDOW_UPDATE frames that
|
||||||
|
// cause the flow-control window to become positive.
|
||||||
|
if let Some(val) = settings.initial_window_size() {
|
||||||
|
let old_val = self.init_window_sz;
|
||||||
|
self.init_window_sz = val;
|
||||||
|
|
||||||
|
if val < old_val {
|
||||||
|
let dec = old_val - val;
|
||||||
|
|
||||||
|
store.for_each(|mut stream| {
|
||||||
|
let stream = &mut *stream;
|
||||||
|
|
||||||
|
if let Some(flow) = stream.state.send_flow_control() {
|
||||||
|
flow.shrink_window(val);
|
||||||
|
|
||||||
|
// Update the unadvertised number as well
|
||||||
|
if stream.unadvertised_send_window < dec {
|
||||||
|
stream.unadvertised_send_window = 0;
|
||||||
|
} else {
|
||||||
|
stream.unadvertised_send_window -= dec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if val > old_val {
|
||||||
|
let inc = val - old_val;
|
||||||
|
|
||||||
|
store.for_each(|mut stream| {
|
||||||
|
if let Some(flow) = stream.state.send_flow_control() {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ensure_not_idle(&self, id: StreamId) -> Result<(), ConnectionError> {
|
pub fn ensure_not_idle(&self, id: StreamId) -> Result<(), ConnectionError> {
|
||||||
if id >= self.next_stream_id {
|
if id >= self.next_stream_id {
|
||||||
return Err(ProtocolError.into());
|
return Err(ProtocolError.into());
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ pub(super) struct Store<B> {
|
|||||||
/// "Pointer" to an entry in the store
|
/// "Pointer" to an entry in the store
|
||||||
pub(super) struct Ptr<'a, B: 'a> {
|
pub(super) struct Ptr<'a, B: 'a> {
|
||||||
key: Key,
|
key: Key,
|
||||||
store: &'a mut Store<B>,
|
slab: &'a mut slab::Slab<Stream<B>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// References an entry in the store.
|
/// References an entry in the store.
|
||||||
@@ -72,7 +72,7 @@ impl<B> Store<B> {
|
|||||||
pub fn resolve(&mut self, key: Key) -> Ptr<B> {
|
pub fn resolve(&mut self, key: Key) -> Ptr<B> {
|
||||||
Ptr {
|
Ptr {
|
||||||
key: key,
|
key: key,
|
||||||
store: self,
|
slab: &mut self.slab,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ impl<B> Store<B> {
|
|||||||
if let Some(&key) = self.ids.get(id) {
|
if let Some(&key) = self.ids.get(id) {
|
||||||
Some(Ptr {
|
Some(Ptr {
|
||||||
key: Key(key),
|
key: Key(key),
|
||||||
store: self,
|
slab: &mut self.slab,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -93,7 +93,7 @@ impl<B> Store<B> {
|
|||||||
|
|
||||||
Ptr {
|
Ptr {
|
||||||
key: Key(key),
|
key: Key(key),
|
||||||
store: self,
|
slab: &mut self.slab,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,10 +117,13 @@ impl<B> Store<B> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn for_each<F>(&mut self, mut f: F)
|
pub fn for_each<F>(&mut self, mut f: F)
|
||||||
where F: FnMut(&mut Stream<B>)
|
where F: FnMut(Ptr<B>)
|
||||||
{
|
{
|
||||||
for &id in self.ids.values() {
|
for &key in self.ids.values() {
|
||||||
f(&mut self.slab[id])
|
f(Ptr {
|
||||||
|
key: Key(key),
|
||||||
|
slab: &mut self.slab,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -265,19 +268,15 @@ impl<'a, B: 'a> Ptr<'a, B> {
|
|||||||
self.key
|
self.key
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn store(&mut self) -> &mut Store<B> {
|
|
||||||
&mut self.store
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve(&mut self, key: Key) -> Ptr<B> {
|
pub fn resolve(&mut self, key: Key) -> Ptr<B> {
|
||||||
Ptr {
|
Ptr {
|
||||||
key: key,
|
key: key,
|
||||||
store: self.store,
|
slab: &mut *self.slab,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_mut(self) -> &'a mut Stream<B> {
|
pub fn into_mut(self) -> &'a mut Stream<B> {
|
||||||
&mut self.store.slab[self.key.0]
|
&mut self.slab[self.key.0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,13 +284,13 @@ impl<'a, B: 'a> ops::Deref for Ptr<'a, B> {
|
|||||||
type Target = Stream<B>;
|
type Target = Stream<B>;
|
||||||
|
|
||||||
fn deref(&self) -> &Stream<B> {
|
fn deref(&self) -> &Stream<B> {
|
||||||
&self.store.slab[self.key.0]
|
&self.slab[self.key.0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, B: 'a> ops::DerefMut for Ptr<'a, B> {
|
impl<'a, B: 'a> ops::DerefMut for Ptr<'a, B> {
|
||||||
fn deref_mut(&mut self) -> &mut Stream<B> {
|
fn deref_mut(&mut self) -> &mut Stream<B> {
|
||||||
&mut self.store.slab[self.key.0]
|
&mut self.slab[self.key.0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -154,7 +154,9 @@ impl<B> Streams<B>
|
|||||||
let me = &mut *me;
|
let me = &mut *me;
|
||||||
|
|
||||||
let actions = &mut me.actions;
|
let actions = &mut me.actions;
|
||||||
me.store.for_each(|stream| actions.recv.recv_err(err, stream));
|
me.store.for_each(|mut stream| {
|
||||||
|
actions.recv.recv_err(err, &mut *stream)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recv_window_update(&mut self, frame: frame::WindowUpdate)
|
pub fn recv_window_update(&mut self, frame: frame::WindowUpdate)
|
||||||
@@ -189,11 +191,11 @@ impl<B> Streams<B>
|
|||||||
let id = frame.stream_id();
|
let id = frame.stream_id();
|
||||||
|
|
||||||
let mut stream = match me.store.find_mut(&id) {
|
let mut stream = match me.store.find_mut(&id) {
|
||||||
Some(stream) => stream,
|
Some(stream) => stream.key(),
|
||||||
None => return Err(ProtocolError.into()),
|
None => return Err(ProtocolError.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
me.actions.recv.recv_push_promise::<P>(frame, &mut stream)
|
me.actions.recv.recv_push_promise::<P>(frame, stream, &mut me.store)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_incoming(&mut self) -> Option<StreamRef<B>> {
|
pub fn next_incoming(&mut self) -> Option<StreamRef<B>> {
|
||||||
@@ -247,6 +249,13 @@ impl<B> Streams<B>
|
|||||||
|
|
||||||
me.actions.send.poll_complete(&mut me.store, dst)
|
me.actions.send.poll_complete(&mut me.store, dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn apply_remote_settings(&mut self, frame: &frame::Settings) {
|
||||||
|
let mut me = self.inner.lock().unwrap();
|
||||||
|
let me = &mut *me;
|
||||||
|
|
||||||
|
me.actions.send.apply_remote_settings(frame, &mut me.store);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B> Streams<B>
|
impl<B> Streams<B>
|
||||||
|
|||||||
Reference in New Issue
Block a user