sui_http/
config.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use std::time::Duration;
5
6const DEFAULT_HTTP2_KEEPALIVE_TIMEOUT_SECS: u64 = 20;
7const DEFAULT_TLS_HANDSHAKE_TIMEOUT: Duration = Duration::from_secs(5);
8const DEFAULT_MAX_PENDING_CONNECTIONS: usize = 4096;
9
10#[derive(Debug, Clone)]
11pub struct Config {
12    init_stream_window_size: Option<u32>,
13    init_connection_window_size: Option<u32>,
14    max_concurrent_streams: Option<u32>,
15    pub(crate) tcp_keepalive: Option<Duration>,
16    http2_keepalive_interval: Option<Duration>,
17    http2_keepalive_timeout: Option<Duration>,
18    http2_adaptive_window: Option<bool>,
19    http2_max_pending_accept_reset_streams: Option<usize>,
20    http2_max_header_list_size: Option<u32>,
21    max_frame_size: Option<u32>,
22    pub(crate) accept_http1: bool,
23    enable_connect_protocol: bool,
24    pub(crate) max_connection_age: Option<Duration>,
25    pub(crate) tls_handshake_timeout: Duration,
26    pub(crate) max_pending_connections: usize,
27}
28
29impl Default for Config {
30    fn default() -> Self {
31        Self {
32            init_stream_window_size: None,
33            init_connection_window_size: None,
34            max_concurrent_streams: None,
35            tcp_keepalive: None,
36            http2_keepalive_interval: None,
37            http2_keepalive_timeout: None,
38            http2_adaptive_window: None,
39            http2_max_pending_accept_reset_streams: None,
40            http2_max_header_list_size: None,
41            max_frame_size: None,
42            accept_http1: true,
43            enable_connect_protocol: true,
44            max_connection_age: None,
45            tls_handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
46            max_pending_connections: DEFAULT_MAX_PENDING_CONNECTIONS,
47        }
48    }
49}
50
51impl Config {
52    /// Sets the [`SETTINGS_INITIAL_WINDOW_SIZE`][spec] option for HTTP2
53    /// stream-level flow control.
54    ///
55    /// Default is 65,535
56    ///
57    /// [spec]: https://httpwg.org/specs/rfc9113.html#InitialWindowSize
58    pub fn initial_stream_window_size(self, sz: impl Into<Option<u32>>) -> Self {
59        Self {
60            init_stream_window_size: sz.into(),
61            ..self
62        }
63    }
64
65    /// Sets the max connection-level flow control for HTTP2
66    ///
67    /// Default is 65,535
68    pub fn initial_connection_window_size(self, sz: impl Into<Option<u32>>) -> Self {
69        Self {
70            init_connection_window_size: sz.into(),
71            ..self
72        }
73    }
74
75    /// Sets the [`SETTINGS_MAX_CONCURRENT_STREAMS`][spec] option for HTTP2
76    /// connections.
77    ///
78    /// Default is no limit (`None`).
79    ///
80    /// [spec]: https://httpwg.org/specs/rfc9113.html#n-stream-concurrency
81    pub fn max_concurrent_streams(self, max: impl Into<Option<u32>>) -> Self {
82        Self {
83            max_concurrent_streams: max.into(),
84            ..self
85        }
86    }
87
88    /// Sets the maximum time option in milliseconds that a connection may exist
89    ///
90    /// Default is no limit (`None`).
91    pub fn max_connection_age(self, max_connection_age: Duration) -> Self {
92        Self {
93            max_connection_age: Some(max_connection_age),
94            ..self
95        }
96    }
97
98    /// Set whether HTTP2 Ping frames are enabled on accepted connections.
99    ///
100    /// If `None` is specified, HTTP2 keepalive is disabled, otherwise the duration
101    /// specified will be the time interval between HTTP2 Ping frames.
102    /// The timeout for receiving an acknowledgement of the keepalive ping
103    /// can be set with [`Config::http2_keepalive_timeout`].
104    ///
105    /// Default is no HTTP2 keepalive (`None`)
106    pub fn http2_keepalive_interval(self, http2_keepalive_interval: Option<Duration>) -> Self {
107        Self {
108            http2_keepalive_interval,
109            ..self
110        }
111    }
112
113    /// Sets a timeout for receiving an acknowledgement of the keepalive ping.
114    ///
115    /// If the ping is not acknowledged within the timeout, the connection will be closed.
116    /// Does nothing if http2_keep_alive_interval is disabled.
117    ///
118    /// Default is 20 seconds.
119    pub fn http2_keepalive_timeout(self, http2_keepalive_timeout: Option<Duration>) -> Self {
120        Self {
121            http2_keepalive_timeout,
122            ..self
123        }
124    }
125
126    /// Sets whether to use an adaptive flow control. Defaults to false.
127    /// Enabling this will override the limits set in http2_initial_stream_window_size and
128    /// http2_initial_connection_window_size.
129    pub fn http2_adaptive_window(self, enabled: Option<bool>) -> Self {
130        Self {
131            http2_adaptive_window: enabled,
132            ..self
133        }
134    }
135
136    /// Configures the maximum number of pending reset streams allowed before a GOAWAY will be sent.
137    ///
138    /// This will default to whatever the default in h2 is. As of v0.3.17, it is 20.
139    ///
140    /// See <https://github.com/hyperium/hyper/issues/2877> for more information.
141    pub fn http2_max_pending_accept_reset_streams(self, max: Option<usize>) -> Self {
142        Self {
143            http2_max_pending_accept_reset_streams: max,
144            ..self
145        }
146    }
147
148    /// Set whether TCP keepalive messages are enabled on accepted connections.
149    ///
150    /// If `None` is specified, keepalive is disabled, otherwise the duration
151    /// specified will be the time to remain idle before sending TCP keepalive
152    /// probes.
153    ///
154    /// Default is no keepalive (`None`)
155    pub fn tcp_keepalive(self, tcp_keepalive: Option<Duration>) -> Self {
156        Self {
157            tcp_keepalive,
158            ..self
159        }
160    }
161
162    /// Sets the max size of received header frames.
163    ///
164    /// This will default to whatever the default in hyper is. As of v1.4.1, it is 16 KiB.
165    pub fn http2_max_header_list_size(self, max: impl Into<Option<u32>>) -> Self {
166        Self {
167            http2_max_header_list_size: max.into(),
168            ..self
169        }
170    }
171
172    /// Sets the maximum frame size to use for HTTP2.
173    ///
174    /// Passing `None` will do nothing.
175    ///
176    /// If not set, will default from underlying transport.
177    pub fn max_frame_size(self, frame_size: impl Into<Option<u32>>) -> Self {
178        Self {
179            max_frame_size: frame_size.into(),
180            ..self
181        }
182    }
183
184    /// Allow this accepting http1 requests.
185    ///
186    /// Default is `true`.
187    pub fn accept_http1(self, accept_http1: bool) -> Self {
188        Config {
189            accept_http1,
190            ..self
191        }
192    }
193
194    /// Sets the timeout for TLS handshakes on incoming connections.
195    ///
196    /// Connections that do not complete the TLS handshake within this duration are dropped.
197    ///
198    /// Default is 5 seconds.
199    pub fn tls_handshake_timeout(self, timeout: Duration) -> Self {
200        Config {
201            tls_handshake_timeout: timeout,
202            ..self
203        }
204    }
205
206    /// Sets the maximum number of pending TLS handshakes.
207    ///
208    /// When this limit is reached, new incoming connections are dropped until existing
209    /// handshakes complete or time out.
210    ///
211    /// Default is 4096.
212    pub fn max_pending_connections(self, max: usize) -> Self {
213        Config {
214            max_pending_connections: max,
215            ..self
216        }
217    }
218
219    pub(crate) fn connection_builder(
220        &self,
221    ) -> hyper_util::server::conn::auto::Builder<hyper_util::rt::TokioExecutor> {
222        let mut builder =
223            hyper_util::server::conn::auto::Builder::new(hyper_util::rt::TokioExecutor::new());
224
225        if !self.accept_http1 {
226            builder = builder.http2_only();
227        }
228
229        if self.enable_connect_protocol {
230            builder.http2().enable_connect_protocol();
231        }
232
233        let http2_keepalive_timeout = self
234            .http2_keepalive_timeout
235            .unwrap_or_else(|| Duration::new(DEFAULT_HTTP2_KEEPALIVE_TIMEOUT_SECS, 0));
236
237        builder
238            .http2()
239            .timer(hyper_util::rt::TokioTimer::new())
240            .initial_connection_window_size(self.init_connection_window_size)
241            .initial_stream_window_size(self.init_stream_window_size)
242            .max_concurrent_streams(self.max_concurrent_streams)
243            .keep_alive_interval(self.http2_keepalive_interval)
244            .keep_alive_timeout(http2_keepalive_timeout)
245            .adaptive_window(self.http2_adaptive_window.unwrap_or_default())
246            .max_pending_accept_reset_streams(self.http2_max_pending_accept_reset_streams)
247            .max_frame_size(self.max_frame_size);
248
249        if let Some(max_header_list_size) = self.http2_max_header_list_size {
250            builder.http2().max_header_list_size(max_header_list_size);
251        }
252
253        builder
254    }
255}