add set_target_window_size methods to Server and Client (#149)

Closes #101
This commit is contained in:
Sean McArthur
2017-10-13 11:19:56 -07:00
committed by GitHub
parent 2fcf8c3740
commit 5c1bde7d62
10 changed files with 347 additions and 33 deletions

View File

@@ -20,6 +20,9 @@ where
/// Connection level flow control governing received data
flow: FlowControl,
/// Amount of connection window capacity currently used by outstanding streams.
in_flight_data: WindowSize,
/// The lowest stream ID that is still idle
next_stream_id: Result<StreamId, StreamIdOverflow>,
@@ -75,6 +78,7 @@ where
Recv {
init_window_sz: config.local_init_window_sz,
flow: flow,
in_flight_data: 0 as WindowSize,
next_stream_id: Ok(next_stream_id.into()),
pending_window_updates: store::Queue::new(),
last_processed_id: StreamId::zero(),
@@ -223,6 +227,7 @@ where
// Decrement in-flight data
stream.in_flight_recv_data -= capacity;
self.in_flight_data -= capacity;
// Assign capacity to connection & stream
self.flow.assign_capacity(capacity);
@@ -246,6 +251,48 @@ where
Ok(())
}
/// Set the "target" connection window size.
///
/// By default, all new connections start with 64kb of window size. As
/// streams used and release capacity, we will send WINDOW_UPDATEs for the
/// connection to bring it back up to the initial "target".
///
/// Setting a target means that we will try to tell the peer about
/// WINDOW_UPDATEs so the peer knows it has about `target` window to use
/// for the whole conection.
///
/// The `task` is an optional parked task for the `Connection` that might
/// be blocked on needing more window capacity.
pub fn set_target_connection_window(&mut self, target: WindowSize, task: &mut Option<Task>) {
trace!(
"set_target_connection_window; target={}; available={}, reserved={}",
target,
self.flow.available(),
self.in_flight_data,
);
// The current target connection window is our `available` plus any
// in-flight data reserved by streams.
//
// Update the flow controller with the difference between the new
// target and the current target.
let current = (self.flow.available() + self.in_flight_data).checked_size();
if target > current {
self.flow.assign_capacity(target - current);
} else {
self.flow.claim_capacity(current - target);
}
// If changing the target capacity means we gained a bunch of capacity,
// enough that we went over the update threshold, then schedule sending
// a connection WINDOW_UPDATE.
if self.flow.unclaimed_capacity().is_some() {
if let Some(task) = task.take() {
task.notify();
}
}
}
pub fn body_is_empty(&self, stream: &store::Ptr<B, P>) -> bool {
if !stream.state.is_recv_closed() {
return false;
@@ -298,6 +345,7 @@ where
// Track the data as in-flight
stream.in_flight_recv_data += sz;
self.in_flight_data += sz;
if stream.dec_content_length(frame.payload().len()).is_err() {
return Err(RecvError::Stream {