WIP: send flow control
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
use hpack;
|
use hpack;
|
||||||
use error::{ConnectionError, Reason};
|
use error::{ConnectionError, Reason};
|
||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::{Bytes, Buf};
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
@@ -78,6 +78,18 @@ impl<T> Frame<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Buf> Frame<T> {
|
||||||
|
/// Returns the length of the frame as it applies to flow control.
|
||||||
|
pub fn flow_len(&self) -> usize {
|
||||||
|
use self::Frame::*;
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
Data(ref frame) => frame.payload().remaining(),
|
||||||
|
_ => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> fmt::Debug for Frame<T> {
|
impl<T> fmt::Debug for Frame<T> {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
use self::Frame::*;
|
use self::Frame::*;
|
||||||
|
|||||||
@@ -47,23 +47,6 @@ impl<T, P, B> Connection<T, P, B>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Polls for the next update to a remote flow control window.
|
|
||||||
pub fn poll_window_update(&mut self) -> Poll<WindowUpdate, ConnectionError> {
|
|
||||||
self.streams.poll_window_update()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Increases the capacity of a local flow control window.
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// THis function panics if `incr` is not a valid window size.
|
|
||||||
pub fn expand_window(&mut self, id: StreamId, incr: usize)
|
|
||||||
-> Result<(), ConnectionError>
|
|
||||||
{
|
|
||||||
assert!(incr <= MAX_WINDOW_SIZE as usize);
|
|
||||||
self.streams.expand_window(id, incr as WindowSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_local_settings(&mut self, _local: frame::SettingSet) -> Result<(), ConnectionError> {
|
pub fn update_local_settings(&mut self, _local: frame::SettingSet) -> Result<(), ConnectionError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
@@ -149,8 +132,7 @@ impl<T, P, B> Connection<T, P, B>
|
|||||||
}
|
}
|
||||||
Some(WindowUpdate(frame)) => {
|
Some(WindowUpdate(frame)) => {
|
||||||
trace!("recv WINDOW_UPDATE; frame={:?}", frame);
|
trace!("recv WINDOW_UPDATE; frame={:?}", frame);
|
||||||
// TODO: implement
|
self.streams.recv_window_update(frame)?;
|
||||||
// try!(self.streams.recv_window_update(frame));
|
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// TODO: Is this correct?
|
// TODO: Is this correct?
|
||||||
|
|||||||
@@ -70,6 +70,26 @@ impl<B> Deque<B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn push_front(&mut self, buf: &mut Buffer<B>, frame: Frame<B>) {
|
||||||
|
let key = buf.slab.insert(Slot {
|
||||||
|
frame,
|
||||||
|
next: None,
|
||||||
|
});
|
||||||
|
|
||||||
|
match self.indices {
|
||||||
|
Some(ref mut idxs) => {
|
||||||
|
buf.slab[key].next = Some(idxs.head);
|
||||||
|
idxs.head = key;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.indices = Some(Indices {
|
||||||
|
head: key,
|
||||||
|
tail: key,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pop_front(&mut self, buf: &mut Buffer<B>) -> Option<Frame<B>> {
|
pub fn pop_front(&mut self, buf: &mut Buffer<B>) -> Option<Frame<B>> {
|
||||||
match self.indices {
|
match self.indices {
|
||||||
Some(mut idxs) => {
|
Some(mut idxs) => {
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ pub struct FlowControl {
|
|||||||
/// Amount to be removed by future increments.
|
/// Amount to be removed by future increments.
|
||||||
underflow: WindowSize,
|
underflow: WindowSize,
|
||||||
|
|
||||||
/// The amount that has been incremented but not yet advertised (to the application or
|
/// The amount that has been incremented but not yet advertised (to the
|
||||||
/// the remote).
|
/// application or the remote).
|
||||||
next_window_update: WindowSize,
|
next_window_update: WindowSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,6 +23,14 @@ impl FlowControl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_capacity(&self) -> bool {
|
||||||
|
self.window_size > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn window_size(&self) -> WindowSize {
|
||||||
|
self.window_size
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true iff `claim_window(sz)` would return succeed.
|
/// Returns true iff `claim_window(sz)` would return succeed.
|
||||||
pub fn ensure_window<T>(&mut self, sz: WindowSize, err: T) -> Result<(), ConnectionError>
|
pub fn ensure_window<T>(&mut self, sz: WindowSize, err: T) -> Result<(), ConnectionError>
|
||||||
where T: Into<ConnectionError>,
|
where T: Into<ConnectionError>,
|
||||||
@@ -49,7 +57,10 @@ impl FlowControl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Increase the _unadvertised_ window capacity.
|
/// Increase the _unadvertised_ window capacity.
|
||||||
pub fn expand_window(&mut self, sz: WindowSize) {
|
pub fn expand_window(&mut self, sz: WindowSize)
|
||||||
|
-> Result<(), ConnectionError>
|
||||||
|
{
|
||||||
|
// TODO: Handle invalid increment
|
||||||
if sz <= self.underflow {
|
if sz <= self.underflow {
|
||||||
self.underflow -= sz;
|
self.underflow -= sz;
|
||||||
return;
|
return;
|
||||||
@@ -60,6 +71,7 @@ impl FlowControl {
|
|||||||
self.underflow = 0;
|
self.underflow = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/// Obtains the unadvertised window update.
|
/// Obtains the unadvertised window update.
|
||||||
///
|
///
|
||||||
/// This does not apply the window update to `self`.
|
/// This does not apply the window update to `self`.
|
||||||
@@ -70,6 +82,7 @@ impl FlowControl {
|
|||||||
Some(self.next_window_update)
|
Some(self.next_window_update)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/// Obtains and applies an unadvertised window update.
|
/// Obtains and applies an unadvertised window update.
|
||||||
pub fn apply_window_update(&mut self) -> Option<WindowSize> {
|
pub fn apply_window_update(&mut self) -> Option<WindowSize> {
|
||||||
|
|||||||
@@ -2,8 +2,18 @@ use super::*;
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(super) struct Prioritize<B> {
|
pub(super) struct Prioritize<B> {
|
||||||
|
/// Streams that have pending frames
|
||||||
pending_send: store::List<B>,
|
pending_send: store::List<B>,
|
||||||
|
|
||||||
|
/// Streams that are waiting for connection level flow control capacity
|
||||||
|
pending_capacity: store::List<B>,
|
||||||
|
|
||||||
|
/// Connection level flow control governing sent data
|
||||||
|
flow_control: FlowControl,
|
||||||
|
|
||||||
|
/// Total amount of buffered data in data frames
|
||||||
|
buffered_data: usize,
|
||||||
|
|
||||||
/// Holds frames that are waiting to be written to the socket
|
/// Holds frames that are waiting to be written to the socket
|
||||||
buffer: Buffer<B>,
|
buffer: Buffer<B>,
|
||||||
}
|
}
|
||||||
@@ -11,17 +21,44 @@ pub(super) struct Prioritize<B> {
|
|||||||
impl<B> Prioritize<B>
|
impl<B> Prioritize<B>
|
||||||
where B: Buf,
|
where B: Buf,
|
||||||
{
|
{
|
||||||
pub fn new() -> Prioritize<B> {
|
pub fn new(config: &Config) -> Prioritize<B> {
|
||||||
Prioritize {
|
Prioritize {
|
||||||
pending_send: store::List::new(),
|
pending_send: store::List::new(),
|
||||||
|
pending_capacity: store::List::new(),
|
||||||
|
flow_control: FlowControl::new(config.init_local_window_sz),
|
||||||
|
buffered_data: 0,
|
||||||
buffer: Buffer::new(),
|
buffer: Buffer::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn available_window(&self) -> WindowSize {
|
||||||
|
let win = self.flow_control.window_size();
|
||||||
|
|
||||||
|
if self.buffered_data >= win as usize {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
win - self.buffered_data as WindowSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn recv_window_update(&mut self, frame: frame::WindowUpdate)
|
||||||
|
-> Result<(), ConnectionError>
|
||||||
|
{
|
||||||
|
// Expand the window
|
||||||
|
self.flow_control.expand_window(frame.size_increment())?;
|
||||||
|
|
||||||
|
// Imediately apply the update
|
||||||
|
self.flow.apply_window_update();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn queue_frame(&mut self,
|
pub fn queue_frame(&mut self,
|
||||||
frame: Frame<B>,
|
frame: Frame<B>,
|
||||||
stream: &mut store::Ptr<B>)
|
stream: &mut store::Ptr<B>)
|
||||||
{
|
{
|
||||||
|
self.buffered_data += frame.flow_len();
|
||||||
|
|
||||||
// queue the frame in the buffer
|
// queue the frame in the buffer
|
||||||
stream.pending_send.push_back(&mut self.buffer, frame);
|
stream.pending_send.push_back(&mut self.buffer, frame);
|
||||||
|
|
||||||
@@ -33,7 +70,7 @@ impl<B> Prioritize<B>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Queue the stream
|
// Queue the stream
|
||||||
self.push_sender(stream);
|
push_sender(&mut self.pending_send, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll_complete<T>(&mut self,
|
pub fn poll_complete<T>(&mut self,
|
||||||
@@ -48,7 +85,9 @@ impl<B> Prioritize<B>
|
|||||||
|
|
||||||
match self.pop_frame(store) {
|
match self.pop_frame(store) {
|
||||||
Some(frame) => {
|
Some(frame) => {
|
||||||
// TODO: data frames should be handled specially...
|
// Subtract the data size
|
||||||
|
self.buffered_data -= frame.flow_len();
|
||||||
|
|
||||||
let res = dst.start_send(frame)?;
|
let res = dst.start_send(frame)?;
|
||||||
|
|
||||||
// We already verified that `dst` is ready to accept the
|
// We already verified that `dst` is ready to accept the
|
||||||
@@ -63,29 +102,50 @@ impl<B> Prioritize<B>
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn pop_frame(&mut self, store: &mut Store<B>) -> Option<Frame<B>> {
|
fn pop_frame(&mut self, store: &mut Store<B>) -> Option<Frame<B>> {
|
||||||
|
loop {
|
||||||
match self.pop_sender(store) {
|
match self.pop_sender(store) {
|
||||||
Some(mut stream) => {
|
Some(mut stream) => {
|
||||||
let frame = stream.pending_send.pop_front(&mut self.buffer).unwrap();
|
let frame = match stream.pending_send.pop_front(&mut self.buffer).unwrap() {
|
||||||
|
Frame::Data(frame) => {
|
||||||
|
let len = frame.payload().remaining();
|
||||||
|
|
||||||
|
if len > self.flow_control.window_size() as usize {
|
||||||
|
// TODO: This could be smarter...
|
||||||
|
stream.pending_send.push_front(&mut self.buffer, frame.into());
|
||||||
|
|
||||||
|
// Push the stream onto the list of streams
|
||||||
|
// waiting for connection capacity
|
||||||
|
push_sender(&mut self.pending_capacity, &mut stream);
|
||||||
|
|
||||||
|
// Try again w/ the next stream
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.into()
|
||||||
|
}
|
||||||
|
frame => frame,
|
||||||
|
};
|
||||||
|
|
||||||
if !stream.pending_send.is_empty() {
|
if !stream.pending_send.is_empty() {
|
||||||
self.push_sender(&mut stream);
|
push_sender(&mut self.pending_send, &mut stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(frame)
|
return Some(frame);
|
||||||
}
|
}
|
||||||
None => None,
|
None => return None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_sender(&mut self, stream: &mut store::Ptr<B>) {
|
|
||||||
debug_assert!(!stream.is_pending_send);
|
|
||||||
|
|
||||||
self.pending_send.push(stream);
|
|
||||||
|
|
||||||
stream.is_pending_send = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop_sender<'a>(&mut self, store: &'a mut Store<B>) -> Option<store::Ptr<'a, B>> {
|
fn pop_sender<'a>(&mut self, store: &'a mut Store<B>) -> Option<store::Ptr<'a, B>> {
|
||||||
|
// If the connection level window has capacity, pop off of the pending
|
||||||
|
// capacity list first.
|
||||||
|
|
||||||
|
if self.flow_control.has_capacity() && !self.pending_capacity.is_empty() {
|
||||||
|
let mut stream = self.pending_capacity.pop(store).unwrap();
|
||||||
|
stream.is_pending_send = false;
|
||||||
|
Some(stream)
|
||||||
|
} else {
|
||||||
match self.pending_send.pop(store) {
|
match self.pending_send.pop(store) {
|
||||||
Some(mut stream) => {
|
Some(mut stream) => {
|
||||||
stream.is_pending_send = false;
|
stream.is_pending_send = false;
|
||||||
@@ -95,3 +155,10 @@ impl<B> Prioritize<B>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_sender<B>(list: &mut store::List<B>, stream: &mut store::Ptr<B>) {
|
||||||
|
debug_assert!(!stream.is_pending_send);
|
||||||
|
list.push(stream);
|
||||||
|
stream.is_pending_send = true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -360,6 +360,7 @@ impl<B> Recv<B> where B: Buf {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/// Send connection level window update
|
/// Send connection level window update
|
||||||
pub fn send_connection_window_update<T>(&mut self, dst: &mut Codec<T, B>)
|
pub fn send_connection_window_update<T>(&mut self, dst: &mut Codec<T, B>)
|
||||||
-> Poll<(), ConnectionError>
|
-> Poll<(), ConnectionError>
|
||||||
@@ -377,6 +378,7 @@ impl<B> Recv<B> where B: Buf {
|
|||||||
|
|
||||||
Ok(().into())
|
Ok(().into())
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
pub fn next_incoming(&mut self, store: &mut Store<B>) -> Option<store::Key> {
|
pub fn next_incoming(&mut self, store: &mut Store<B>) -> Option<store::Key> {
|
||||||
self.pending_accept.pop(store)
|
self.pending_accept.pop(store)
|
||||||
@@ -413,6 +415,7 @@ impl<B> Recv<B> where B: Buf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/// Send stream level window update
|
/// Send stream level window update
|
||||||
pub fn send_stream_window_update<T>(&mut self,
|
pub fn send_stream_window_update<T>(&mut self,
|
||||||
streams: &mut Store<B>,
|
streams: &mut Store<B>,
|
||||||
@@ -441,6 +444,7 @@ impl<B> Recv<B> where B: Buf {
|
|||||||
|
|
||||||
Ok(().into())
|
Ok(().into())
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
fn reset(&mut self, _stream_id: StreamId, _reason: Reason) {
|
fn reset(&mut self, _stream_id: StreamId, _reason: Reason) {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use bytes::Buf;
|
|||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
/// Manages state transitions related to outbound frames.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(super) struct Send<B> {
|
pub(super) struct Send<B> {
|
||||||
/// Maximum number of locally initiated streams
|
/// Maximum number of locally initiated streams
|
||||||
@@ -23,19 +24,7 @@ pub(super) struct Send<B> {
|
|||||||
/// Initial window size of locally initiated streams
|
/// Initial window size of locally initiated streams
|
||||||
init_window_sz: WindowSize,
|
init_window_sz: WindowSize,
|
||||||
|
|
||||||
/// Connection level flow control governing sent data
|
|
||||||
flow_control: FlowControl,
|
|
||||||
|
|
||||||
/// Holds the list of streams on which local window updates may be sent.
|
|
||||||
// XXX It would be cool if this didn't exist.
|
|
||||||
pending_window_updates: VecDeque<StreamId>,
|
|
||||||
|
|
||||||
prioritize: Prioritize<B>,
|
prioritize: Prioritize<B>,
|
||||||
|
|
||||||
/// When `poll_window_update` is not ready, then the calling task is saved to
|
|
||||||
/// be notified later. Access to poll_window_update must not be shared across tasks,
|
|
||||||
/// as we only track a single task (and *not* i.e. a task per stream id).
|
|
||||||
blocked: Option<task::Task>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B> Send<B> where B: Buf {
|
impl<B> Send<B> where B: Buf {
|
||||||
@@ -53,10 +42,7 @@ impl<B> Send<B> where B: Buf {
|
|||||||
num_streams: 0,
|
num_streams: 0,
|
||||||
next_stream_id: next_stream_id.into(),
|
next_stream_id: next_stream_id.into(),
|
||||||
init_window_sz: config.init_local_window_sz,
|
init_window_sz: config.init_local_window_sz,
|
||||||
flow_control: FlowControl::new(config.init_local_window_sz),
|
prioritize: Prioritize::new(config),
|
||||||
prioritize: Prioritize::new(),
|
|
||||||
pending_window_updates: VecDeque::new(),
|
|
||||||
blocked: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,15 +105,16 @@ impl<B> Send<B> where B: Buf {
|
|||||||
|
|
||||||
// Make borrow checker happy
|
// Make borrow checker happy
|
||||||
loop {
|
loop {
|
||||||
|
let unadvertised = stream.unadvertised_send_window;
|
||||||
|
|
||||||
match stream.send_flow_control() {
|
match stream.send_flow_control() {
|
||||||
Some(flow) => {
|
Some(flow) => {
|
||||||
try!(self.flow_control.ensure_window(sz, FlowControlViolation));
|
// Ensure that the size fits within the advertised size
|
||||||
|
try!(flow.ensure_window(
|
||||||
|
sz + unadvertised, FlowControlViolation));
|
||||||
|
|
||||||
// Claim the window on the stream
|
// Now, claim the window on the stream
|
||||||
try!(flow.claim_window(sz, FlowControlViolation));
|
flow.claim_window(sz, FlowControlViolation)
|
||||||
|
|
||||||
// Claim the window on the connection
|
|
||||||
self.flow_control.claim_window(sz, FlowControlViolation)
|
|
||||||
.expect("local connection flow control error");
|
.expect("local connection flow control error");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -160,6 +147,7 @@ impl<B> Send<B> where B: Buf {
|
|||||||
self.prioritize.poll_complete(store, dst)
|
self.prioritize.poll_complete(store, dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/// Get pending window updates
|
/// Get pending window updates
|
||||||
pub fn poll_window_update(&mut self, streams: &mut Store<B>)
|
pub fn poll_window_update(&mut self, streams: &mut Store<B>)
|
||||||
-> Poll<WindowUpdate, ConnectionError>
|
-> Poll<WindowUpdate, ConnectionError>
|
||||||
@@ -191,16 +179,15 @@ impl<B> Send<B> where B: Buf {
|
|||||||
|
|
||||||
return Ok(Async::NotReady);
|
return Ok(Async::NotReady);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
pub fn recv_connection_window_update(&mut self, frame: frame::WindowUpdate)
|
pub fn recv_connection_window_update(&mut self, frame: frame::WindowUpdate)
|
||||||
-> Result<(), ConnectionError>
|
-> Result<(), ConnectionError>
|
||||||
{
|
{
|
||||||
// TODO: Handle invalid increment
|
self.priority.recv_window_update(frame)?;
|
||||||
self.flow_control.expand_window(frame.size_increment());
|
|
||||||
|
|
||||||
if let Some(task) = self.blocked.take() {
|
// TODO: If there is available connection capacity, release pending
|
||||||
task.notify();
|
// streams.
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -210,6 +197,8 @@ impl<B> Send<B> where B: Buf {
|
|||||||
stream: &mut store::Ptr<B>)
|
stream: &mut store::Ptr<B>)
|
||||||
-> Result<(), ConnectionError>
|
-> Result<(), ConnectionError>
|
||||||
{
|
{
|
||||||
|
unimplemented!();
|
||||||
|
/*
|
||||||
if let Some(flow) = stream.send_flow_control() {
|
if let Some(flow) = stream.send_flow_control() {
|
||||||
// TODO: Handle invalid increment
|
// TODO: Handle invalid increment
|
||||||
flow.expand_window(frame.size_increment());
|
flow.expand_window(frame.size_increment());
|
||||||
@@ -220,6 +209,7 @@ impl<B> Send<B> where B: Buf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dec_num_streams(&mut self) {
|
pub fn dec_num_streams(&mut self) {
|
||||||
|
|||||||
@@ -28,6 +28,11 @@ pub(super) struct Stream<B> {
|
|||||||
|
|
||||||
/// True if the stream is currently pending send
|
/// True if the stream is currently pending send
|
||||||
pub is_pending_send: bool,
|
pub is_pending_send: bool,
|
||||||
|
|
||||||
|
/// A stream's capacity is never advertised past the connection's capacity.
|
||||||
|
/// This value represents the amount of the stream window that has been
|
||||||
|
/// temporarily withheld.
|
||||||
|
pub unadvertised_send_window: WindowSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B> Stream<B> {
|
impl<B> Stream<B> {
|
||||||
@@ -41,6 +46,7 @@ impl<B> Stream<B> {
|
|||||||
next: None,
|
next: None,
|
||||||
pending_push_promises: store::List::new(),
|
pending_push_promises: store::List::new(),
|
||||||
is_pending_send: false,
|
is_pending_send: false,
|
||||||
|
unadvertised_send_window: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -154,7 +154,8 @@ impl<B> Streams<B>
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn recv_window_update(&mut self, frame: frame::WindowUpdate)
|
pub fn recv_window_update(&mut self, frame: frame::WindowUpdate)
|
||||||
-> Result<(), ConnectionError> {
|
-> Result<(), ConnectionError>
|
||||||
|
{
|
||||||
let id = frame.stream_id();
|
let id = frame.stream_id();
|
||||||
let mut me = self.inner.lock().unwrap();
|
let mut me = self.inner.lock().unwrap();
|
||||||
let me = &mut *me;
|
let me = &mut *me;
|
||||||
@@ -238,14 +239,6 @@ impl<B> Streams<B>
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll_window_update(&mut self)
|
|
||||||
-> Poll<WindowUpdate, ConnectionError>
|
|
||||||
{
|
|
||||||
let mut me = self.inner.lock().unwrap();
|
|
||||||
let me = &mut *me;
|
|
||||||
me.actions.send.poll_window_update(&mut me.store)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn expand_window(&mut self, id: StreamId, sz: WindowSize)
|
pub fn expand_window(&mut self, id: StreamId, sz: WindowSize)
|
||||||
-> Result<(), ConnectionError>
|
-> Result<(), ConnectionError>
|
||||||
{
|
{
|
||||||
@@ -279,12 +272,6 @@ impl<B> Streams<B>
|
|||||||
let mut me = self.inner.lock().unwrap();
|
let mut me = self.inner.lock().unwrap();
|
||||||
let me = &mut *me;
|
let me = &mut *me;
|
||||||
|
|
||||||
// TODO: sending window updates should be part of Prioritize
|
|
||||||
/*
|
|
||||||
try_ready!(me.actions.recv.send_connection_window_update(dst));
|
|
||||||
try_ready!(me.actions.recv.send_stream_window_update(&mut me.store, dst));
|
|
||||||
*/
|
|
||||||
|
|
||||||
me.actions.send.poll_complete(&mut me.store, dst)
|
me.actions.send.poll_complete(&mut me.store, dst)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user