From 7dcd4618c059cc76987a32d3acb75e2aaed4419e Mon Sep 17 00:00:00 2001 From: Kevin Leimkuhler Date: Fri, 1 Mar 2019 14:44:38 -0800 Subject: [PATCH] feat(http2): Add window size config options for Client and Server Add `fn http2_initial_stream_window_size` and `fn http2_initial_connection_window_size` for client and server. Closes #1771 --- src/client/conn.rs | 31 ++++++++++++++++++++++++++++++- src/client/mod.rs | 19 +++++++++++++++++++ src/proto/h2/client.rs | 7 ++----- src/server/conn.rs | 23 +++++++++++++++++++++++ src/server/mod.rs | 19 +++++++++++++++++++ 5 files changed, 93 insertions(+), 6 deletions(-) diff --git a/src/client/conn.rs b/src/client/conn.rs index ee767104aa..064f9aad3b 100644 --- a/src/client/conn.rs +++ b/src/client/conn.rs @@ -15,6 +15,7 @@ use std::sync::Arc; use bytes::Bytes; use futures::{Async, Future, Poll}; use futures::future::{self, Either, Executor}; +use h2; use tokio_io::{AsyncRead, AsyncWrite}; use body::Payload; @@ -77,6 +78,7 @@ pub struct Builder { h1_read_buf_exact_size: Option, h1_max_buf_size: Option, http2: bool, + h2_builder: h2::client::Builder, } /// A future setting up HTTP over an IO object. @@ -431,6 +433,9 @@ impl Builder { /// Creates a new connection builder. #[inline] pub fn new() -> Builder { + let mut h2_builder = h2::client::Builder::default(); + h2_builder.enable_push(false); + Builder { exec: Exec::Default, h1_writev: true, @@ -438,6 +443,7 @@ impl Builder { h1_title_case_headers: false, h1_max_buf_size: None, http2: false, + h2_builder, } } @@ -485,6 +491,29 @@ impl Builder { self } + /// Sets the [`SETTINGS_INITIAL_WINDOW_SIZE`][spec] option for HTTP2 + /// stream-level flow control. + /// + /// Default is 65,535 + /// + /// [spec]: https://http2.github.io/http2-spec/#SETTINGS_INITIAL_WINDOW_SIZE + pub fn http2_initial_stream_window_size(&mut self, sz: impl Into>) -> &mut Self { + if let Some(sz) = sz.into() { + self.h2_builder.initial_window_size(sz); + } + self + } + + /// Sets the max connection-level flow control for HTTP2 + /// + /// Default is 65,535 + pub fn http2_initial_connection_window_size(&mut self, sz: impl Into>) -> &mut Self { + if let Some(sz) = sz.into() { + self.h2_builder.initial_connection_window_size(sz); + } + self + } + /// Constructs a connection with the configured options and IO. #[inline] pub fn handshake(&self, io: T) -> Handshake @@ -532,7 +561,7 @@ where let dispatch = proto::h1::Dispatcher::new(cd, conn); Either::A(dispatch) } else { - let h2 = proto::h2::Client::new(io, rx, self.builder.exec.clone()); + let h2 = proto::h2::Client::new(io, rx, &self.builder.h2_builder, self.builder.exec.clone()); Either::B(h2) }; diff --git a/src/client/mod.rs b/src/client/mod.rs index dfb2818a19..7c89f65169 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -971,6 +971,25 @@ impl Builder { self } + /// Sets the [`SETTINGS_INITIAL_WINDOW_SIZE`][spec] option for HTTP2 + /// stream-level flow control. + /// + /// Default is 65,535 + /// + /// [spec]: https://http2.github.io/http2-spec/#SETTINGS_INITIAL_WINDOW_SIZE + pub fn http2_initial_stream_window_size(&mut self, sz: impl Into>) -> &mut Self { + self.conn_builder.http2_initial_stream_window_size(sz.into()); + self + } + + /// Sets the max connection-level flow control for HTTP2 + /// + /// Default is 65,535 + pub fn http2_initial_connection_window_size(&mut self, sz: impl Into>) -> &mut Self { + self.conn_builder.http2_initial_connection_window_size(sz.into()); + self + } + /// Sets the maximum idle connection per host allowed in the pool. /// /// Default is `usize::MAX` (no limit). diff --git a/src/proto/h2/client.rs b/src/proto/h2/client.rs index c48561c86c..276e9120bd 100644 --- a/src/proto/h2/client.rs +++ b/src/proto/h2/client.rs @@ -37,11 +37,8 @@ where T: AsyncRead + AsyncWrite + Send + 'static, B: Payload, { - pub(crate) fn new(io: T, rx: ClientRx, exec: Exec) -> Client { - let handshake = Builder::new() - // we don't expose PUSH promises yet - .enable_push(false) - .handshake(io); + pub(crate) fn new(io: T, rx: ClientRx, builder: &Builder, exec: Exec) -> Client { + let handshake = builder.handshake(io); Client { executor: exec, diff --git a/src/server/conn.rs b/src/server/conn.rs index caec9ba44c..ad52944667 100644 --- a/src/server/conn.rs +++ b/src/server/conn.rs @@ -239,6 +239,29 @@ impl Http { self } + /// Sets the [`SETTINGS_INITIAL_WINDOW_SIZE`][spec] option for HTTP2 + /// stream-level flow control. + /// + /// Default is 65,535 + /// + /// [spec]: https://http2.github.io/http2-spec/#SETTINGS_INITIAL_WINDOW_SIZE + pub fn http2_initial_stream_window_size(&mut self, sz: impl Into>) -> &mut Self { + if let Some(sz) = sz.into() { + self.h2_builder.initial_window_size(sz); + } + self + } + + /// Sets the max connection-level flow control for HTTP2 + /// + /// Default is 65,535 + pub fn http2_initial_connection_window_size(&mut self, sz: impl Into>) -> &mut Self { + if let Some(sz) = sz.into() { + self.h2_builder.initial_connection_window_size(sz); + } + self + } + /// Sets the [`SETTINGS_MAX_CONCURRENT_STREAMS`][spec] option for HTTP2 /// connections. /// diff --git a/src/server/mod.rs b/src/server/mod.rs index 59179166e0..826d42b0be 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -302,6 +302,25 @@ impl Builder { self } + /// Sets the [`SETTINGS_INITIAL_WINDOW_SIZE`][spec] option for HTTP2 + /// stream-level flow control. + /// + /// Default is 65,535 + /// + /// [spec]: https://http2.github.io/http2-spec/#SETTINGS_INITIAL_WINDOW_SIZE + pub fn http2_initial_stream_window_size(&mut self, sz: impl Into>) -> &mut Self { + self.protocol.http2_initial_stream_window_size(sz.into()); + self + } + + /// Sets the max connection-level flow control for HTTP2 + /// + /// Default is 65,535 + pub fn http2_initial_connection_window_size(&mut self, sz: impl Into>) -> &mut Self { + self.protocol.http2_initial_connection_window_size(sz.into()); + self + } + /// Sets the [`SETTINGS_MAX_CONCURRENT_STREAMS`][spec] option for HTTP2 /// connections. ///