Skip to main content

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