Skip to content

Commit

Permalink
feat(http2): add config for max_local_error_reset_streams in server (
Browse files Browse the repository at this point in the history
…#3528)

This change exposes a tunable for the max_local_error_reset_streams parameter in h2.
  • Loading branch information
Noah-Kennedy committed Jan 19, 2024
1 parent 98a7ab0 commit dedcb67
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Expand Up @@ -28,7 +28,7 @@ http = "0.2"
http-body = "0.4"
httpdate = "1.0"
httparse = "1.8"
h2 = { version = "0.3.17", optional = true }
h2 = { version = "0.3.24", optional = true }
itoa = "1"
tracing = { version = "0.1", default-features = false, features = ["std"] }
pin-project-lite = "0.2.4"
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Expand Up @@ -2,7 +2,7 @@
#![deny(missing_debug_implementations)]
#![cfg_attr(test, deny(rust_2018_idioms))]
#![cfg_attr(all(test, feature = "full"), deny(unreachable_pub))]
#![cfg_attr(all(test, feature = "full"), deny(warnings))]
#![cfg_attr(all(test, feature = "full", not(feature = "nightly")), deny(warnings))]
#![cfg_attr(all(test, feature = "nightly"), feature(test))]
#![cfg_attr(docsrs, feature(doc_cfg))]

Expand Down
4 changes: 4 additions & 0 deletions src/proto/h2/server.rs
Expand Up @@ -39,6 +39,7 @@ const DEFAULT_STREAM_WINDOW: u32 = 1024 * 1024; // 1mb
const DEFAULT_MAX_FRAME_SIZE: u32 = 1024 * 16; // 16kb
const DEFAULT_MAX_SEND_BUF_SIZE: usize = 1024 * 400; // 400kb
const DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE: u32 = 16 << 20; // 16 MB "sane default" taken from golang http2
const DEFAULT_MAX_LOCAL_ERROR_RESET_STREAMS: usize = 1024;

#[derive(Clone, Debug)]
pub(crate) struct Config {
Expand All @@ -49,6 +50,7 @@ pub(crate) struct Config {
pub(crate) enable_connect_protocol: bool,
pub(crate) max_concurrent_streams: Option<u32>,
pub(crate) max_pending_accept_reset_streams: Option<usize>,
pub(crate) max_local_error_reset_streams: Option<usize>,
#[cfg(feature = "runtime")]
pub(crate) keep_alive_interval: Option<Duration>,
#[cfg(feature = "runtime")]
Expand All @@ -67,6 +69,7 @@ impl Default for Config {
enable_connect_protocol: false,
max_concurrent_streams: None,
max_pending_accept_reset_streams: None,
max_local_error_reset_streams: Some(DEFAULT_MAX_LOCAL_ERROR_RESET_STREAMS),
#[cfg(feature = "runtime")]
keep_alive_interval: None,
#[cfg(feature = "runtime")]
Expand Down Expand Up @@ -125,6 +128,7 @@ where
.initial_connection_window_size(config.initial_conn_window_size)
.max_frame_size(config.max_frame_size)
.max_header_list_size(config.max_header_list_size)
.max_local_error_reset_streams(config.max_local_error_reset_streams)
.max_send_buffer_size(config.max_send_buffer_size);
if let Some(max) = config.max_concurrent_streams {
builder.max_concurrent_streams(max);
Expand Down
17 changes: 17 additions & 0 deletions src/server/conn.rs
Expand Up @@ -414,6 +414,23 @@ impl<E> Http<E> {
self
}

/// Configures the maximum number of pending reset streams allowed before a GOAWAY will be sent.
///
/// This will default to the default value set by the [`h2` crate](https://crates.io/crates/h2).
/// As of v0.3.17, it is 20.
///
/// See <https://github.com/hyperium/hyper/issues/2877> for more information.
#[cfg(feature = "http2")]
#[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
pub fn http2_max_local_error_reset_streams(
&mut self,
max: impl Into<Option<usize>>,
) -> &mut Self {
self.h2_builder.max_local_error_reset_streams = max.into();

self
}

/// Sets the [`SETTINGS_INITIAL_WINDOW_SIZE`][spec] option for HTTP2
/// stream-level flow control.
///
Expand Down
15 changes: 15 additions & 0 deletions src/server/server.rs
Expand Up @@ -387,6 +387,21 @@ impl<I, E> Builder<I, E> {
self
}

/// Configures the maximum number of local reset streams allowed before a GOAWAY will be sent.
///
/// If not set, hyper will use a default, currently of 1024.
///
/// If `None` is supplied, hyper will not apply any limit.
/// This is not advised, as it can potentially expose servers to DOS vulnerabilities.
///
/// See <https://rustsec.org/advisories/RUSTSEC-2024-0003.html> for more information.
#[cfg(feature = "http2")]
#[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
pub fn http2_max_local_error_reset_streams(mut self, max: impl Into<Option<usize>>) -> Self {
self.protocol.http2_max_local_error_reset_streams(max);
self
}

/// Sets the [`SETTINGS_INITIAL_WINDOW_SIZE`][spec] option for HTTP2
/// stream-level flow control.
///
Expand Down

0 comments on commit dedcb67

Please sign in to comment.