Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_text/tests/annealer_corpus/actix_server.rs

49.5 KiB, 1 run

created by r1870400018:11680, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1use std::{
2 any::Any,
3 cmp, fmt,
4 future::Future,
5 io,
6 marker::PhantomData,
7 net,
8 sync::{Arc, Mutex},
9 time::Duration,
10};
11
12#[cfg(feature = "__tls")]
13use actix_http::TlsAcceptorConfig;
14use actix_http::{body::MessageBody, Extensions, HttpService, KeepAlive, Request, Response};
15use actix_server::{Server, ServerBuilder};
16use actix_service::{
17 map_config, IntoServiceFactory, Service, ServiceFactory, ServiceFactoryExt as _,
18};
19#[cfg(feature = "openssl")]
20use actix_tls::accept::openssl::reexports::{AlpnError, SslAcceptor, SslAcceptorBuilder};
21
22use crate::{config::AppConfig, Error};
23
24struct Socket {
25 scheme: &'static str,
26 addr: net::SocketAddr,
27}
28
29struct Config {
30 host: Option<String>,
31 keep_alive: KeepAlive,
32 tcp_nodelay: Option<bool>,
33 client_request_timeout: Duration,
34 client_disconnect_timeout: Duration,
35 h1_allow_half_closed: bool,
36 h1_write_buffer_size: Option<usize>,
37 h2_initial_window_size: Option<u32>,
38 h2_initial_connection_window_size: Option<u32>,
39 #[allow(dead_code)] // only dead when no TLS features are enabled
40 tls_handshake_timeout: Option<Duration>,
41}
42
43/// An HTTP Server.
44///
45/// Create new HTTP server with application factory.
46///
47/// # Automatic HTTP Version Selection
48///
49/// There are two ways to select the HTTP version of an incoming connection:
50///
51/// - One is to rely on the ALPN information that is provided when using a TLS (HTTPS); both
52/// versions are supported automatically when using either of the `.bind_rustls()` or
53/// `.bind_openssl()` methods.
54/// - The other is to read the first few bytes of the TCP stream. This is the only viable approach
55/// for supporting H2C, which allows the HTTP/2 protocol to work over plaintext connections. Use
56/// the `.bind_auto_h2c()` method to enable this behavior.
57///
58/// # Examples
59///
60/// ```no_run
61/// use actix_web::{web, App, HttpResponse, HttpServer};
62///
63/// #[actix_web::main]
64/// async fn main() -> std::io::Result<()> {
65/// HttpServer::new(|| {
66/// App::new()
67/// .service(web::resource("/").to(|| async { "hello world" }))
68/// })
69/// .bind(("127.0.0.1", 8080))?
70/// .run()
71/// .await
72/// }
73/// ```
74#[must_use]
75pub struct HttpServer<F, I, S, B>
76where
77 F: Fn() -> I + Send + Clone + 'static,
78 I: IntoServiceFactory<S, Request>,
79 S: ServiceFactory<Request, Config = AppConfig>,
80 S::Error: Into<Error>,
81 S::InitError: fmt::Debug,
82 S::Response: Into<Response<B>>,
83 B: MessageBody,
84{
85 pub(super) factory: F,
86 config: Arc<Mutex<Config>>,
87 backlog: u32,
88 sockets: Vec<Socket>,
89 builder: ServerBuilder,
90 #[allow(clippy::type_complexity)]
91 on_connect_fn: Option<Arc<dyn Fn(&dyn Any, &mut Extensions) + Send + Sync>>,
92 _phantom: PhantomData<(S, B)>,
93}
94
95impl<F, I, S, B> HttpServer<F, I, S, B>
96where
97 F: Fn() -> I + Send + Clone + 'static,
98 I: IntoServiceFactory<S, Request>,
99
100 S: ServiceFactory<Request, Config = AppConfig> + 'static,
101 S::Error: Into<Error> + 'static,
102 S::InitError: fmt::Debug,
103 S::Response: Into<Response<B>> + 'static,
104 <S::Service as Service<Request>>::Future: 'static,
105 S::Service: 'static,
106
107 B: MessageBody + 'static,
108{
109 /// Create new HTTP server with application factory
110 ///
111 /// # Worker Count
112 ///
113 /// The `factory` will be instantiated multiple times in most configurations. See
114 /// [`bind()`](Self::bind()) docs for more on how worker count and bind address resolution
115 /// causes multiple server factory instantiations.
116 pub fn new(factory: F) -> Self {
117 HttpServer {
118 factory,
119 config: Arc::new(Mutex::new(Config {
120 host: None,
121 keep_alive: KeepAlive::default(),
122 tcp_nodelay: None,
123 client_request_timeout: Duration::from_secs(5),
124 client_disconnect_timeout: Duration::from_secs(1),
125 h1_allow_half_closed: true,
126 h1_write_buffer_size: None,
127 h2_initial_window_size: None,
128 h2_initial_connection_window_size: None,
129 tls_handshake_timeout: None,
130 })),
131 backlog: 1024,
132 sockets: Vec::new(),
133 builder: ServerBuilder::default(),
134 on_connect_fn: None,
135 _phantom: PhantomData,
136 }
137 }
138
139 /// Sets number of workers to start (per bind address).
140 ///
141 /// The default worker count is the determined by [`std::thread::available_parallelism()`]. See
142 /// its documentation to determine what behavior you should expect when server is run.
143 ///
144 /// Note that the server factory passed to [`new`](Self::new()) will be instantiated **at least
145 /// once per worker**. See [`bind()`](Self::bind()) docs for more on how worker count and bind
146 /// address resolution causes multiple server factory instantiations.
147 ///
148 /// `num` must be greater than 0.
149 ///
150 /// # Panics
151 ///
152 /// Panics if `num` is 0.
153 pub fn workers(mut self, num: usize) -> Self {
154 self.builder = self.builder.workers(num);
155 self
156 }
157
158 /// Sets server keep-alive preference.
159 ///
160 /// By default keep-alive is set to 5 seconds.
161 pub fn keep_alive<T: Into<KeepAlive>>(self, val: T) -> Self {
162 self.config.lock().unwrap().keep_alive = val.into();
163 self
164 }
165
166 /// Sets `TCP_NODELAY` value on accepted TCP connections.
167 ///
168 /// By default, accepted TCP connections keep the OS default.
169 /// This method overrides that behavior for all accepted TCP connections.
170 pub fn tcp_nodelay(self, enabled: bool) -> Self {
171 self.config.lock().unwrap().tcp_nodelay = Some(enabled);
172 self
173 }
174
175 /// Sets the maximum number of pending connections.
176 ///
177 /// This refers to the number of clients that can be waiting to be served. Exceeding this number
178 /// results in the client getting an error when attempting to connect. It should only affect
179 /// servers under significant load.
180 ///
181 /// Generally set in the 64–2048 range. Default value is 1024.
182 ///
183 /// This method will have no effect if called after a `bind()`.
184 pub fn backlog(mut self, backlog: u32) -> Self {
185 self.backlog = backlog;
186 self.builder = self.builder.backlog(backlog);
187 self
188 }
189
190 /// Sets the per-worker maximum number of concurrent connections.
191 ///
192 /// All socket listeners will stop accepting connections when this limit is reached for
193 /// each worker.
194 ///
195 /// By default max connections is set to a 25k.
196 pub fn max_connections(mut self, num: usize) -> Self {
197 self.builder = self.builder.max_concurrent_connections(num);
198 self
199 }
200
201 /// Sets the per-worker maximum concurrent TLS connection limit.
202 ///
203 /// All listeners will stop accepting connections when this limit is reached. It can be used to
204 /// limit the global TLS CPU usage.
205 ///
206 /// By default max connections is set to a 256.
207 #[allow(unused_variables)]
208 pub fn max_connection_rate(self, num: usize) -> Self {
209 #[cfg(feature = "__tls")]
210 actix_tls::accept::max_concurrent_tls_connect(num);
211 self
212 }
213
214 /// Sets max number of threads for each worker's blocking task thread pool.
215 ///
216 /// One thread pool is set up **per worker**; not shared across workers.
217 ///
218 /// By default, set to 512 divided by [available parallelism](std::thread::available_parallelism()).
219 pub fn worker_max_blocking_threads(mut self, num: usize) -> Self {
220 self.builder = self.builder.worker_max_blocking_threads(num);
221 self
222 }
223
224 /// Sets server client timeout for first request.
225 ///
226 /// Defines a timeout for reading client request head. If a client does not transmit the entire
227 /// set headers within this time, the request is terminated with a 408 (Request Timeout) error.
228 ///
229 /// To disable timeout set value to 0.
230 ///
231 /// By default client timeout is set to 5000 milliseconds.
232 pub fn client_request_timeout(self, dur: Duration) -> Self {
233 self.config.lock().unwrap().client_request_timeout = dur;
234 self
235 }
236
237 #[doc(hidden)]
238 #[deprecated(since = "4.0.0", note = "Renamed to `client_request_timeout`.")]
239 pub fn client_timeout(self, dur: Duration) -> Self {
240 self.client_request_timeout(dur)
241 }
242
243 /// Sets server connection shutdown timeout.
244 ///
245 /// Defines a timeout for connection shutdown. If a shutdown procedure does not complete within
246 /// this time, the request is dropped.
247 ///
248 /// To disable timeout set value to 0.
249 ///
250 /// By default client timeout is set to 1000 milliseconds.
251 pub fn client_disconnect_timeout(self, dur: Duration) -> Self {
252 self.config.lock().unwrap().client_disconnect_timeout = dur;
253 self
254 }
255
256 /// Sets TLS handshake timeout.
257 ///
258 /// Defines a timeout for TLS handshake. If the TLS handshake does not complete within this
259 /// time, the connection is closed.
260 ///
261 /// By default, the handshake timeout is 3 seconds.
262 #[cfg(feature = "__tls")]
263 pub fn tls_handshake_timeout(self, dur: Duration) -> Self {
264 self.config
265 .lock()
266 .unwrap()
267 .tls_handshake_timeout
268 .replace(dur);
269
270 self
271 }
272
273 #[doc(hidden)]
274 #[deprecated(since = "4.0.0", note = "Renamed to `client_disconnect_timeout`.")]
275 pub fn client_shutdown(self, dur: u64) -> Self {
276 self.client_disconnect_timeout(Duration::from_millis(dur))
277 }
278
279 /// Sets whether HTTP/1 connections should support half-closures.
280 ///
281 /// Clients can choose to shutdown their writer-side of the connection after completing their
282 /// request and while waiting for the server response. Setting this to `false` will cause the
283 /// server to abort the connection handling as soon as it detects an EOF from the client.
284 ///
285 /// The default behavior is to allow, i.e. `true`
286 pub fn h1_allow_half_closed(self, allow: bool) -> Self {
287 self.config.lock().unwrap().h1_allow_half_closed = allow;
288 self
289 }
290
291 /// Sets the maximum response write buffer size for HTTP/1 connections.
292 ///
293 /// Once the response buffer reaches this size, the dispatcher flushes it to the I/O stream.
294 ///
295 /// The default value is 32 KiB.
296 ///
297 /// # Panics
298 ///
299 /// Panics if `size` is 0.
300 pub fn h1_write_buffer_size(self, size: usize) -> Self {
301 assert!(
302 size > 0,
303 "HTTP/1 write buffer size must be greater than zero"
304 );
305
306 self.config.lock().unwrap().h1_write_buffer_size = Some(size);
307 self
308 }
309
310 /// Sets initial stream-level flow control window size for HTTP/2 connections.
311 ///
312 /// Higher values can improve upload performance on high-latency links at the cost of higher
313 /// worst-case memory usage per connection.
314 ///
315 /// The default value is 1MiB.
316 #[cfg(feature = "http2")]
317 pub fn h2_initial_window_size(self, size: u32) -> Self {
318 self.config.lock().unwrap().h2_initial_window_size = Some(size);
319 self
320 }
321
322 /// Sets initial connection-level flow control window size for HTTP/2 connections.
323 ///
324 /// Higher values can improve upload performance on high-latency links at the cost of higher
325 /// worst-case memory usage per connection.
326 ///
327 /// The default value is 2MiB.
328 #[cfg(feature = "http2")]
329 pub fn h2_initial_connection_window_size(self, size: u32) -> Self {
330 self.config
331 .lock()
332 .unwrap()
333 .h2_initial_connection_window_size = Some(size);
334 self
335 }
336
337 /// Sets function that will be called once before each connection is handled.
338 ///
339 /// It will receive a `&std::any::Any`, which contains underlying connection type and an
340 /// [Extensions] container so that connection data can be accessed in middleware and handlers.
341 ///
342 /// # Connection Types
343 /// - `actix_tls::accept::openssl::TlsStream<actix_web::rt::net::TcpStream>` when using OpenSSL.
344 /// - `actix_tls::accept::rustls_0_20::TlsStream<actix_web::rt::net::TcpStream>` when using
345 /// Rustls v0.20.
346 /// - `actix_tls::accept::rustls_0_21::TlsStream<actix_web::rt::net::TcpStream>` when using
347 /// Rustls v0.21.
348 /// - `actix_tls::accept::rustls_0_22::TlsStream<actix_web::rt::net::TcpStream>` when using
349 /// Rustls v0.22.
350 /// - `actix_tls::accept::rustls_0_23::TlsStream<actix_web::rt::net::TcpStream>` when using
351 /// Rustls v0.23.
352 /// - `actix_web::rt::net::TcpStream` when no encryption is used.
353 ///
354 /// See the `on_connect` example for additional details.
355 pub fn on_connect<CB>(mut self, f: CB) -> HttpServer<F, I, S, B>
356 where
357 CB: Fn(&dyn Any, &mut Extensions) + Send + Sync + 'static,
358 {
359 self.on_connect_fn = Some(Arc::new(f));
360 self
361 }
362
363 /// Sets server host name.
364 ///
365 /// Host name is used by application router as a hostname for url generation. Check
366 /// [`ConnectionInfo`](crate::dev::ConnectionInfo::host()) docs for more info.
367 ///
368 /// By default, hostname is set to "localhost".
369 pub fn server_hostname<T: AsRef<str>>(self, val: T) -> Self {
370 self.config.lock().unwrap().host = Some(val.as_ref().to_owned());
371 self
372 }
373
374 /// Flags the `System` to exit after server shutdown.
375 ///
376 /// Does nothing when running under `#[tokio::main]` runtime.
377 pub fn system_exit(mut self) -> Self {
378 self.builder = self.builder.system_exit();
379 self
380 }
381
382 /// Disables signal handling.
383 pub fn disable_signals(mut self) -> Self {
384 self.builder = self.builder.disable_signals();
385 self
386 }
387
388 /// Specify shutdown signal from a future.
389 ///
390 /// Using this method will prevent OS signal handlers being set up.
391 ///
392 /// Typically, a `CancellationToken` will be used, but any future _can_ be.
393 ///
394 /// # Examples
395 ///
396 /// ```no_run
397 /// use actix_web::{App, HttpServer};
398 /// use tokio_util::sync::CancellationToken;
399 ///
400 /// # #[actix_web::main]
401 /// # async fn main() -> std::io::Result<()> {
402 /// let stop_signal = CancellationToken::new();
403 ///
404 /// HttpServer::new(move || App::new())
405 /// .shutdown_signal(stop_signal.cancelled_owned())
406 /// .bind(("127.0.0.1", 8080))?
407 /// .run()
408 /// .await
409 /// # }
410 /// ```
411 pub fn shutdown_signal<Fut>(mut self, shutdown_signal: Fut) -> Self
412 where
413 Fut: Future<Output = ()> + Send + 'static,
414 {
415 self.builder = self.builder.shutdown_signal(shutdown_signal);
416 self
417 }
418
419 /// Sets timeout for graceful worker shutdown of workers.
420 ///
421 /// After receiving a stop signal, workers have this much time to finish serving requests.
422 /// Workers still alive after the timeout are force dropped.
423 ///
424 /// By default shutdown timeout sets to 30 seconds.
425 pub fn shutdown_timeout(mut self, sec: u64) -> Self {
426 self.builder = self.builder.shutdown_timeout(sec);
427 self
428 }
429
430 /// Returns addresses of bound sockets.
431 pub fn addrs(&self) -> Vec<net::SocketAddr> {
432 self.sockets.iter().map(|s| s.addr).collect()
433 }
434
435 /// Returns addresses of bound sockets and the scheme for it.
436 ///
437 /// This is useful when the server is bound from different sources with some sockets listening
438 /// on HTTP and some listening on HTTPS and the user should be presented with an enumeration of
439 /// which socket requires which protocol.
440 pub fn addrs_with_scheme(&self) -> Vec<(net::SocketAddr, &str)> {
441 self.sockets.iter().map(|s| (s.addr, s.scheme)).collect()
442 }
443
444 /// Resolves socket address(es) and binds server to created listener(s).
445 ///
446 /// # Hostname Resolution
447 ///
448 /// When `addrs` includes a hostname, it is possible for this method to bind to both the IPv4
449 /// and IPv6 addresses that result from a DNS lookup. You can test this by passing
450 /// `localhost:8080` and noting that the server binds to `127.0.0.1:8080` _and_ `[::1]:8080`. To
451 /// bind additional addresses, call this method multiple times.
452 ///
453 /// Note that, if a DNS lookup is required, resolving hostnames is a blocking operation.
454 ///
455 /// # Worker Count
456 ///
457 /// The `factory` will be instantiated multiple times in most scenarios. The number of
458 /// instantiations is number of [`workers`](Self::workers()) × number of sockets resolved by
459 /// `addrs`.
460 ///
461 /// For example, if you've manually set [`workers`](Self::workers()) to 2, and use `127.0.0.1`
462 /// as the bind `addrs`, then `factory` will be instantiated twice. However, using `localhost`
463 /// as the bind `addrs` can often resolve to both `127.0.0.1` (IPv4) _and_ `::1` (IPv6), causing
464 /// the `factory` to be instantiated 4 times (2 workers × 2 bind addresses).
465 ///
466 /// Using a bind address of `0.0.0.0`, which signals to use all interfaces, may also multiple
467 /// the number of instantiations in a similar way.
468 ///
469 /// # Dual-Stack IPv6
470 ///
471 /// On Windows, when this method creates an IPv6 listener (e.g., for `[::]:8080`), this
472 /// attempts to enable dual-stack mode so the socket can accept both IPv4 and IPv6
473 /// connections. On Linux and macOS, dual-stack is typically already the OS default. If you
474 /// need IPv6-only behavior on Windows, create the listener manually and pass it to
475 /// [`listen()`](Self::listen()).
476 ///
477 /// # Typical Usage
478 ///
479 /// In general, use `127.0.0.1:<port>` when testing locally and `0.0.0.0:<port>` when deploying
480 /// (with or without a reverse proxy or load balancer) so that the server is accessible.
481 ///
482 /// # Errors
483 ///
484 /// Returns an `io::Error` if:
485 /// - `addrs` cannot be resolved into one or more socket addresses;
486 /// - all the resolved socket addresses are already bound.
487 ///
488 /// # Example
489 ///
490 /// ```
491 /// # use actix_web::{App, HttpServer};
492 /// # fn inner() -> std::io::Result<()> {
493 /// HttpServer::new(|| App::new())
494 /// .bind(("127.0.0.1", 8080))?
495 /// .bind("[::1]:9000")?
496 /// # ; Ok(()) }
497 /// ```
498 pub fn bind<A: net::ToSocketAddrs>(mut self, addrs: A) -> io::Result<Self> {
499 let sockets = bind_addrs(addrs, self.backlog)?;
500
501 for lst in sockets {
502 self = self.listen(lst)?;
503 }
504
505 Ok(self)
506 }
507
508 /// Resolves socket address(es) and binds server to created listener(s) for plaintext HTTP/1.x
509 /// or HTTP/2 connections.
510 ///
511 /// See [`bind()`](Self::bind()) for more details on `addrs` argument.
512 #[cfg(feature = "http2")]
513 pub fn bind_auto_h2c<A: net::ToSocketAddrs>(mut self, addrs: A) -> io::Result<Self> {
514 let sockets = bind_addrs(addrs, self.backlog)?;
515
516 for lst in sockets {
517 self = self.listen_auto_h2c(lst)?;
518 }
519
520 Ok(self)
521 }
522
523 /// Resolves socket address(es) and binds server to created listener(s) for TLS connections
524 /// using Rustls v0.20.
525 ///
526 /// See [`bind()`](Self::bind()) for more details on `addrs` argument.
527 ///
528 /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
529 #[cfg(feature = "rustls-0_20")]
530 pub fn bind_rustls<A: net::ToSocketAddrs>(
531 mut self,
532 addrs: A,
533 config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
534 ) -> io::Result<Self> {
535 let sockets = bind_addrs(addrs, self.backlog)?;
536 for lst in sockets {
537 self = self.listen_rustls_0_20_inner(lst, config.clone())?;
538 }
539 Ok(self)
540 }
541
542 /// Resolves socket address(es) and binds server to created listener(s) for TLS connections
543 /// using Rustls v0.21.
544 ///
545 /// See [`bind()`](Self::bind()) for more details on `addrs` argument.
546 ///
547 /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
548 #[cfg(feature = "rustls-0_21")]
549 pub fn bind_rustls_021<A: net::ToSocketAddrs>(
550 mut self,
551 addrs: A,
552 config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
553 ) -> io::Result<Self> {
554 let sockets = bind_addrs(addrs, self.backlog)?;
555 for lst in sockets {
556 self = self.listen_rustls_0_21_inner(lst, config.clone())?;
557 }
558 Ok(self)
559 }
560
561 /// Resolves socket address(es) and binds server to created listener(s) for TLS connections
562 /// using Rustls v0.22.
563 ///
564 /// See [`bind()`](Self::bind()) for more details on `addrs` argument.
565 ///
566 /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
567 #[cfg(feature = "rustls-0_22")]
568 pub fn bind_rustls_0_22<A: net::ToSocketAddrs>(
569 mut self,
570 addrs: A,
571 config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
572 ) -> io::Result<Self> {
573 let sockets = bind_addrs(addrs, self.backlog)?;
574 for lst in sockets {
575 self = self.listen_rustls_0_22_inner(lst, config.clone())?;
576 }
577 Ok(self)
578 }
579
580 /// Resolves socket address(es) and binds server to created listener(s) for TLS connections
581 /// using Rustls v0.23.
582 ///
583 /// See [`bind()`](Self::bind()) for more details on `addrs` argument.
584 ///
585 /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
586 #[cfg(feature = "rustls-0_23")]
587 pub fn bind_rustls_0_23<A: net::ToSocketAddrs>(
588 mut self,
589 addrs: A,
590 config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
591 ) -> io::Result<Self> {
592 let sockets = bind_addrs(addrs, self.backlog)?;
593 for lst in sockets {
594 self = self.listen_rustls_0_23_inner(lst, config.clone())?;
595 }
596 Ok(self)
597 }
598
599 /// Resolves socket address(es) and binds server to created listener(s) for TLS connections
600 /// using OpenSSL.
601 ///
602 /// See [`bind()`](Self::bind()) for more details on `addrs` argument.
603 ///
604 /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
605 #[cfg(feature = "openssl")]
606 pub fn bind_openssl<A>(mut self, addrs: A, builder: SslAcceptorBuilder) -> io::Result<Self>
607 where
608 A: net::ToSocketAddrs,
609 {
610 let sockets = bind_addrs(addrs, self.backlog)?;
611 let acceptor = openssl_acceptor(builder)?;
612
613 for lst in sockets {
614 self = self.listen_openssl_inner(lst, acceptor.clone())?;
615 }
616
617 Ok(self)
618 }
619
620 /// Binds to existing listener for accepting incoming connection requests.
621 ///
622 /// No changes are made to `lst`'s configuration. Ensure it is configured properly before
623 /// passing ownership to `listen()`.
624 pub fn listen(mut self, lst: net::TcpListener) -> io::Result<Self> {
625 let cfg = Arc::clone(&self.config);
626 let factory = self.factory.clone();
627 let addr = lst.local_addr().unwrap();
628
629 self.sockets.push(Socket {
630 addr,
631 scheme: "http",
632 });
633
634 let on_connect_fn = self.on_connect_fn.clone();
635
636 self.builder =
637 self.builder
638 .listen(format!("actix-web-service-{}", addr), lst, move || {
639 let cfg = cfg.lock().unwrap();
640 let host = cfg.host.clone().unwrap_or_else(|| format!("{}", addr));
641
642 let mut svc = HttpService::build()
643 .keep_alive(cfg.keep_alive)
644 .client_request_timeout(cfg.client_request_timeout)
645 .client_disconnect_timeout(cfg.client_disconnect_timeout)
646 .h1_allow_half_closed(cfg.h1_allow_half_closed)
647 .local_addr(addr);
648
649 if let Some(enabled) = cfg.tcp_nodelay {
650 svc = svc.tcp_nodelay(enabled);
651 }
652
653 if let Some(size) = cfg.h1_write_buffer_size {
654 svc = svc.h1_write_buffer_size(size);
655 }
656
657 if let Some(val) = cfg.h2_initial_window_size {
658 svc = svc.h2_initial_window_size(val);
659 }
660
661 if let Some(val) = cfg.h2_initial_connection_window_size {
662 svc = svc.h2_initial_connection_window_size(val);
663 }
664
665 if let Some(handler) = on_connect_fn.clone() {
666 svc =
667 svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
668 };
669
670 let fac = factory()
671 .into_factory()
672 .map_err(|err| err.into().error_response());
673
674 svc.finish(map_config(fac, move |_| {
675 AppConfig::new(false, host.clone(), addr)
676 }))
677 .tcp()
678 })?;
679
680 Ok(self)
681 }
682
683 /// Binds to existing listener for accepting incoming plaintext HTTP/1.x or HTTP/2 connections.
684 #[cfg(feature = "http2")]
685 pub fn listen_auto_h2c(mut self, lst: net::TcpListener) -> io::Result<Self> {
686 let cfg = Arc::clone(&self.config);
687 let factory = self.factory.clone();
688 let addr = lst.local_addr().unwrap();
689
690 self.sockets.push(Socket {
691 addr,
692 scheme: "http",
693 });
694
695 let on_connect_fn = self.on_connect_fn.clone();
696
697 self.builder =
698 self.builder
699 .listen(format!("actix-web-service-{}", addr), lst, move || {
700 let cfg = cfg.lock().unwrap();
701 let host = cfg.host.clone().unwrap_or_else(|| format!("{}", addr));
702
703 let mut svc = HttpService::build()
704 .keep_alive(cfg.keep_alive)
705 .client_request_timeout(cfg.client_request_timeout)
706 .client_disconnect_timeout(cfg.client_disconnect_timeout)
707 .h1_allow_half_closed(cfg.h1_allow_half_closed)
708 .local_addr(addr);
709
710 if let Some(enabled) = cfg.tcp_nodelay {
711 svc = svc.tcp_nodelay(enabled);
712 }
713
714 if let Some(size) = cfg.h1_write_buffer_size {
715 svc = svc.h1_write_buffer_size(size);
716 }
717
718 if let Some(val) = cfg.h2_initial_window_size {
719 svc = svc.h2_initial_window_size(val);
720 }
721
722 if let Some(val) = cfg.h2_initial_connection_window_size {
723 svc = svc.h2_initial_connection_window_size(val);
724 }
725
726 if let Some(handler) = on_connect_fn.clone() {
727 svc =
728 svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
729 };
730
731 let fac = factory()
732 .into_factory()
733 .map_err(|err| err.into().error_response());
734
735 svc.finish(map_config(fac, move |_| {
736 AppConfig::new(false, host.clone(), addr)
737 }))
738 .tcp_auto_h2c()
739 })?;
740
741 Ok(self)
742 }
743
744 /// Binds to existing listener for accepting incoming TLS connection requests using Rustls
745 /// v0.20.
746 ///
747 /// See [`listen()`](Self::listen) for more details on the `lst` argument.
748 ///
749 /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
750 #[cfg(feature = "rustls-0_20")]
751 pub fn listen_rustls(
752 self,
753 lst: net::TcpListener,
754 config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
755 ) -> io::Result<Self> {
756 self.listen_rustls_0_20_inner(lst, config)
757 }
758
759 /// Binds to existing listener for accepting incoming TLS connection requests using Rustls
760 /// v0.21.
761 ///
762 /// See [`listen()`](Self::listen()) for more details on the `lst` argument.
763 ///
764 /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
765 #[cfg(feature = "rustls-0_21")]
766 pub fn listen_rustls_0_21(
767 self,
768 lst: net::TcpListener,
769 config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
770 ) -> io::Result<Self> {
771 self.listen_rustls_0_21_inner(lst, config)
772 }
773
774 #[cfg(feature = "rustls-0_20")]
775 fn listen_rustls_0_20_inner(
776 mut self,
777 lst: net::TcpListener,
778 config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
779 ) -> io::Result<Self> {
780 let factory = self.factory.clone();
781 let cfg = Arc::clone(&self.config);
782 let addr = lst.local_addr().unwrap();
783 self.sockets.push(Socket {
784 addr,
785 scheme: "https",
786 });
787
788 let on_connect_fn = self.on_connect_fn.clone();
789
790 self.builder =
791 self.builder
792 .listen(format!("actix-web-service-{}", addr), lst, move || {
793 let c = cfg.lock().unwrap();
794 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
795
796 let mut svc = HttpService::build()
797 .keep_alive(c.keep_alive)
798 .client_request_timeout(c.client_request_timeout)
799 .h1_allow_half_closed(c.h1_allow_half_closed)
800 .client_disconnect_timeout(c.client_disconnect_timeout);
801
802 if let Some(enabled) = c.tcp_nodelay {
803 svc = svc.tcp_nodelay(enabled);
804 }
805
806 if let Some(size) = c.h1_write_buffer_size {
807 svc = svc.h1_write_buffer_size(size);
808 }
809
810 if let Some(val) = c.h2_initial_window_size {
811 svc = svc.h2_initial_window_size(val);
812 }
813
814 if let Some(val) = c.h2_initial_connection_window_size {
815 svc = svc.h2_initial_connection_window_size(val);
816 }
817
818 if let Some(handler) = on_connect_fn.clone() {
819 svc = svc
820 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
821 };
822
823 let fac = factory()
824 .into_factory()
825 .map_err(|err| err.into().error_response());
826
827 let acceptor_config = match c.tls_handshake_timeout {
828 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
829 None => TlsAcceptorConfig::default(),
830 };
831
832 svc.finish(map_config(fac, move |_| {
833 AppConfig::new(true, host.clone(), addr)
834 }))
835 .rustls_with_config(config.clone(), acceptor_config)
836 })?;
837
838 Ok(self)
839 }
840
841 #[cfg(feature = "rustls-0_21")]
842 fn listen_rustls_0_21_inner(
843 mut self,
844 lst: net::TcpListener,
845 config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
846 ) -> io::Result<Self> {
847 let factory = self.factory.clone();
848 let cfg = Arc::clone(&self.config);
849 let addr = lst.local_addr().unwrap();
850 self.sockets.push(Socket {
851 addr,
852 scheme: "https",
853 });
854
855 let on_connect_fn = self.on_connect_fn.clone();
856
857 self.builder =
858 self.builder
859 .listen(format!("actix-web-service-{}", addr), lst, move || {
860 let c = cfg.lock().unwrap();
861 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
862
863 let mut svc = HttpService::build()
864 .keep_alive(c.keep_alive)
865 .client_request_timeout(c.client_request_timeout)
866 .h1_allow_half_closed(c.h1_allow_half_closed)
867 .client_disconnect_timeout(c.client_disconnect_timeout);
868
869 if let Some(enabled) = c.tcp_nodelay {
870 svc = svc.tcp_nodelay(enabled);
871 }
872
873 if let Some(size) = c.h1_write_buffer_size {
874 svc = svc.h1_write_buffer_size(size);
875 }
876
877 if let Some(val) = c.h2_initial_window_size {
878 svc = svc.h2_initial_window_size(val);
879 }
880
881 if let Some(val) = c.h2_initial_connection_window_size {
882 svc = svc.h2_initial_connection_window_size(val);
883 }
884
885 if let Some(handler) = on_connect_fn.clone() {
886 svc = svc
887 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
888 };
889
890 let fac = factory()
891 .into_factory()
892 .map_err(|err| err.into().error_response());
893
894 let acceptor_config = match c.tls_handshake_timeout {
895 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
896 None => TlsAcceptorConfig::default(),
897 };
898
899 svc.finish(map_config(fac, move |_| {
900 AppConfig::new(true, host.clone(), addr)
901 }))
902 .rustls_021_with_config(config.clone(), acceptor_config)
903 })?;
904
905 Ok(self)
906 }
907
908 /// Binds to existing listener for accepting incoming TLS connection requests using Rustls
909 /// v0.22.
910 ///
911 /// See [`listen()`](Self::listen()) for more details on the `lst` argument.
912 ///
913 /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
914 #[cfg(feature = "rustls-0_22")]
915 pub fn listen_rustls_0_22(
916 self,
917 lst: net::TcpListener,
918 config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
919 ) -> io::Result<Self> {
920 self.listen_rustls_0_22_inner(lst, config)
921 }
922
923 #[cfg(feature = "rustls-0_22")]
924 fn listen_rustls_0_22_inner(
925 mut self,
926 lst: net::TcpListener,
927 config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
928 ) -> io::Result<Self> {
929 let factory = self.factory.clone();
930 let cfg = Arc::clone(&self.config);
931 let addr = lst.local_addr().unwrap();
932 self.sockets.push(Socket {
933 addr,
934 scheme: "https",
935 });
936
937 let on_connect_fn = self.on_connect_fn.clone();
938
939 self.builder =
940 self.builder
941 .listen(format!("actix-web-service-{}", addr), lst, move || {
942 let c = cfg.lock().unwrap();
943 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
944
945 let mut svc = HttpService::build()
946 .keep_alive(c.keep_alive)
947 .client_request_timeout(c.client_request_timeout)
948 .h1_allow_half_closed(c.h1_allow_half_closed)
949 .client_disconnect_timeout(c.client_disconnect_timeout);
950
951 if let Some(enabled) = c.tcp_nodelay {
952 svc = svc.tcp_nodelay(enabled);
953 }
954
955 if let Some(size) = c.h1_write_buffer_size {
956 svc = svc.h1_write_buffer_size(size);
957 }
958
959 if let Some(val) = c.h2_initial_window_size {
960 svc = svc.h2_initial_window_size(val);
961 }
962
963 if let Some(val) = c.h2_initial_connection_window_size {
964 svc = svc.h2_initial_connection_window_size(val);
965 }
966
967 if let Some(handler) = on_connect_fn.clone() {
968 svc = svc
969 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
970 };
971
972 let fac = factory()
973 .into_factory()
974 .map_err(|err| err.into().error_response());
975
976 let acceptor_config = match c.tls_handshake_timeout {
977 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
978 None => TlsAcceptorConfig::default(),
979 };
980
981 svc.finish(map_config(fac, move |_| {
982 AppConfig::new(true, host.clone(), addr)
983 }))
984 .rustls_0_22_with_config(config.clone(), acceptor_config)
985 })?;
986
987 Ok(self)
988 }
989
990 /// Binds to existing listener for accepting incoming TLS connection requests using Rustls
991 /// v0.23.
992 ///
993 /// See [`listen()`](Self::listen()) for more details on the `lst` argument.
994 ///
995 /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
996 #[cfg(feature = "rustls-0_23")]
997 pub fn listen_rustls_0_23(
998 self,
999 lst: net::TcpListener,
1000 config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
1001 ) -> io::Result<Self> {
1002 self.listen_rustls_0_23_inner(lst, config)
1003 }
1004
1005 #[cfg(feature = "rustls-0_23")]
1006 fn listen_rustls_0_23_inner(
1007 mut self,
1008 lst: net::TcpListener,
1009 config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
1010 ) -> io::Result<Self> {
1011 let factory = self.factory.clone();
1012 let cfg = Arc::clone(&self.config);
1013 let addr = lst.local_addr().unwrap();
1014 self.sockets.push(Socket {
1015 addr,
1016 scheme: "https",
1017 });
1018
1019 let on_connect_fn = self.on_connect_fn.clone();
1020
1021 self.builder =
1022 self.builder
1023 .listen(format!("actix-web-service-{}", addr), lst, move || {
1024 let c = cfg.lock().unwrap();
1025 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
1026
1027 let mut svc = HttpService::build()
1028 .keep_alive(c.keep_alive)
1029 .client_request_timeout(c.client_request_timeout)
1030 .h1_allow_half_closed(c.h1_allow_half_closed)
1031 .client_disconnect_timeout(c.client_disconnect_timeout);
1032
1033 if let Some(enabled) = c.tcp_nodelay {
1034 svc = svc.tcp_nodelay(enabled);
1035 }
1036
1037 if let Some(size) = c.h1_write_buffer_size {
1038 svc = svc.h1_write_buffer_size(size);
1039 }
1040
1041 if let Some(val) = c.h2_initial_window_size {
1042 svc = svc.h2_initial_window_size(val);
1043 }
1044
1045 if let Some(val) = c.h2_initial_connection_window_size {
1046 svc = svc.h2_initial_connection_window_size(val);
1047 }
1048
1049 if let Some(handler) = on_connect_fn.clone() {
1050 svc = svc
1051 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1052 };
1053
1054 let fac = factory()
1055 .into_factory()
1056 .map_err(|err| err.into().error_response());
1057
1058 let acceptor_config = match c.tls_handshake_timeout {
1059 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
1060 None => TlsAcceptorConfig::default(),
1061 };
1062
1063 svc.finish(map_config(fac, move |_| {
1064 AppConfig::new(true, host.clone(), addr)
1065 }))
1066 .rustls_0_23_with_config(config.clone(), acceptor_config)
1067 })?;
1068
1069 Ok(self)
1070 }
1071
1072 /// Binds to existing listener for accepting incoming TLS connection requests using OpenSSL.
1073 ///
1074 /// See [`listen()`](Self::listen) for more details on the `lst` argument.
1075 ///
1076 /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
1077 #[cfg(feature = "openssl")]
1078 pub fn listen_openssl(
1079 self,
1080 lst: net::TcpListener,
1081 builder: SslAcceptorBuilder,
1082 ) -> io::Result<Self> {
1083 self.listen_openssl_inner(lst, openssl_acceptor(builder)?)
1084 }
1085
1086 #[cfg(feature = "openssl")]
1087 fn listen_openssl_inner(
1088 mut self,
1089 lst: net::TcpListener,
1090 acceptor: SslAcceptor,
1091 ) -> io::Result<Self> {
1092 let factory = self.factory.clone();
1093 let cfg = Arc::clone(&self.config);
1094 let addr = lst.local_addr().unwrap();
1095
1096 self.sockets.push(Socket {
1097 addr,
1098 scheme: "https",
1099 });
1100
1101 let on_connect_fn = self.on_connect_fn.clone();
1102
1103 self.builder =
1104 self.builder
1105 .listen(format!("actix-web-service-{}", addr), lst, move || {
1106 let c = cfg.lock().unwrap();
1107 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
1108
1109 let mut svc = HttpService::build()
1110 .keep_alive(c.keep_alive)
1111 .client_request_timeout(c.client_request_timeout)
1112 .client_disconnect_timeout(c.client_disconnect_timeout)
1113 .h1_allow_half_closed(c.h1_allow_half_closed)
1114 .local_addr(addr);
1115
1116 if let Some(enabled) = c.tcp_nodelay {
1117 svc = svc.tcp_nodelay(enabled);
1118 }
1119
1120 if let Some(size) = c.h1_write_buffer_size {
1121 svc = svc.h1_write_buffer_size(size);
1122 }
1123
1124 if let Some(val) = c.h2_initial_window_size {
1125 svc = svc.h2_initial_window_size(val);
1126 }
1127
1128 if let Some(val) = c.h2_initial_connection_window_size {
1129 svc = svc.h2_initial_connection_window_size(val);
1130 }
1131
1132 if let Some(handler) = on_connect_fn.clone() {
1133 svc = svc
1134 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1135 };
1136
1137 let fac = factory()
1138 .into_factory()
1139 .map_err(|err| err.into().error_response());
1140
1141 // false positive lint (?)
1142 #[allow(clippy::significant_drop_in_scrutinee)]
1143 let acceptor_config = match c.tls_handshake_timeout {
1144 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
1145 None => TlsAcceptorConfig::default(),
1146 };
1147
1148 svc.finish(map_config(fac, move |_| {
1149 AppConfig::new(true, host.clone(), addr)
1150 }))
1151 .openssl_with_config(acceptor.clone(), acceptor_config)
1152 })?;
1153
1154 Ok(self)
1155 }
1156
1157 /// Opens Unix Domain Socket (UDS) from `uds` path and binds server to created listener.
1158 #[cfg(unix)]
1159 pub fn bind_uds<A>(mut self, uds_path: A) -> io::Result<Self>
1160 where
1161 A: AsRef<std::path::Path>,
1162 {
1163 use actix_http::Protocol;
1164 use actix_rt::net::UnixStream;
1165 use actix_service::{fn_service, ServiceFactoryExt as _};
1166
1167 let cfg = Arc::clone(&self.config);
1168 let factory = self.factory.clone();
1169 let socket_addr =
1170 net::SocketAddr::new(net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)), 8080);
1171
1172 self.sockets.push(Socket {
1173 scheme: "http",
1174 addr: socket_addr,
1175 });
1176
1177 self.builder = self.builder.bind_uds(
1178 format!("actix-web-service-{:?}", uds_path.as_ref()),
1179 uds_path,
1180 move || {
1181 let c = cfg.lock().unwrap();
1182 let config = AppConfig::new(
1183 false,
1184 c.host.clone().unwrap_or_else(|| format!("{}", socket_addr)),
1185 socket_addr,
1186 );
1187
1188 let fac = factory()
1189 .into_factory()
1190 .map_err(|err| err.into().error_response());
1191
1192 fn_service(|io: UnixStream| async { Ok((io, Protocol::Http1, None)) }).and_then({
1193 let mut svc = HttpService::build()
1194 .keep_alive(c.keep_alive)
1195 .client_request_timeout(c.client_request_timeout)
1196 .client_disconnect_timeout(c.client_disconnect_timeout)
1197 .h1_allow_half_closed(c.h1_allow_half_closed);
1198
1199 if let Some(size) = c.h1_write_buffer_size {
1200 svc = svc.h1_write_buffer_size(size);
1201 }
1202
1203 svc.finish(map_config(fac, move |_| config.clone()))
1204 })
1205 },
1206 )?;
1207
1208 Ok(self)
1209 }
1210
1211 /// Binds to existing Unix Domain Socket (UDS) listener.
1212 #[cfg(unix)]
1213 pub fn listen_uds(mut self, lst: std::os::unix::net::UnixListener) -> io::Result<Self> {
1214 use actix_http::Protocol;
1215 use actix_rt::net::UnixStream;
1216 use actix_service::{fn_service, ServiceFactoryExt as _};
1217
1218 let cfg = Arc::clone(&self.config);
1219 let factory = self.factory.clone();
1220 let socket_addr =
1221 net::SocketAddr::new(net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)), 8080);
1222
1223 self.sockets.push(Socket {
1224 scheme: "http",
1225 addr: socket_addr,
1226 });
1227
1228 let addr = lst.local_addr()?;
1229 let name = format!("actix-web-service-{:?}", addr);
1230 let on_connect_fn = self.on_connect_fn.clone();
1231
1232 self.builder = self.builder.listen_uds(name, lst, move || {
1233 let c = cfg.lock().unwrap();
1234 let config = AppConfig::new(
1235 false,
1236 c.host.clone().unwrap_or_else(|| format!("{}", socket_addr)),
1237 socket_addr,
1238 );
1239
1240 fn_service(|io: UnixStream| async { Ok((io, Protocol::Http1, None)) }).and_then({
1241 let mut svc = HttpService::build()
1242 .keep_alive(c.keep_alive)
1243 .client_request_timeout(c.client_request_timeout)
1244 .h1_allow_half_closed(c.h1_allow_half_closed)
1245 .client_disconnect_timeout(c.client_disconnect_timeout);
1246
1247 if let Some(handler) = on_connect_fn.clone() {
1248 svc = svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1249 }
1250
1251 if let Some(size) = c.h1_write_buffer_size {
1252 svc = svc.h1_write_buffer_size(size);
1253 }
1254
1255 let fac = factory()
1256 .into_factory()
1257 .map_err(|err| err.into().error_response());
1258
1259 svc.finish(map_config(fac, move |_| config.clone()))
1260 })
1261 })?;
1262 Ok(self)
1263 }
1264}
1265
1266impl<F, I, S, B> HttpServer<F, I, S, B>
1267where
1268 F: Fn() -> I + Send + Clone + 'static,
1269 I: IntoServiceFactory<S, Request>,
1270 S: ServiceFactory<Request, Config = AppConfig>,
1271 S::Error: Into<Error>,
1272 S::InitError: fmt::Debug,
1273 S::Response: Into<Response<B>>,
1274 S::Service: 'static,
1275 B: MessageBody,
1276{
1277 /// Start listening for incoming connections.
1278 ///
1279 /// # Workers
1280 /// This method starts a number of HTTP workers in separate threads. The number of workers in a
1281 /// set is defined by [`workers()`](Self::workers) or, by default, the number of the machine's
1282 /// physical cores. One worker set is created for each socket address to be bound. For example,
1283 /// if workers is set to 4, and there are 2 addresses to bind, then 8 worker threads will be
1284 /// spawned.
1285 ///
1286 /// # Panics
1287 /// This methods panics if no socket addresses were successfully bound or if no Tokio runtime
1288 /// is set up.
1289 pub fn run(self) -> Server {
1290 self.builder.run()
1291 }
1292}
1293
1294/// Bind TCP listeners to socket addresses resolved from `addrs` with options.
1295fn bind_addrs(addrs: impl net::ToSocketAddrs, backlog: u32) -> io::Result<Vec<net::TcpListener>> {
1296 let mut err = None;
1297 let mut success = false;
1298 let mut sockets = Vec::new();
1299
1300 for addr in addrs.to_socket_addrs()? {
1301 match create_tcp_listener(addr, backlog) {
1302 Ok(lst) => {
1303 success = true;
1304 sockets.push(lst);
1305 }
1306 Err(error) => err = Some(error),
1307 }
1308 }
1309
1310 if success {
1311 Ok(sockets)
1312 } else if let Some(err) = err.take() {
1313 Err(err)
1314 } else {
1315 Err(io::Error::other("Could not bind to address"))
1316 }
1317}
1318
1319/// Creates a TCP listener from socket address and options.
1320fn create_tcp_listener(addr: net::SocketAddr, backlog: u32) -> io::Result<net::TcpListener> {
1321 use socket2::{Domain, Protocol, Socket, Type};
1322 let domain = Domain::for_address(addr);
1323 let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))?;
1324 #[cfg(not(windows))]
1325 {
1326 socket.set_reuse_address(true)?;
1327 }
1328 // On Windows, IPV6_V6ONLY defaults to true, preventing IPv6 sockets from accepting IPv4
1329 // connections. Set it to false so that binding to [::] also accepts IPv4 traffic.
1330 #[cfg(windows)]
1331 if addr.is_ipv6() {
1332 if let Err(err) = socket.set_only_v6(false) {
1333 log::warn!("failed to set IPV6_V6ONLY=false: {err}");
1334 }
1335 }
1336 socket.bind(&addr.into())?;
1337 // clamp backlog to max u32 that fits in i32 range
1338 let backlog = cmp::min(backlog, i32::MAX as u32) as i32;
1339 socket.listen(backlog)?;
1340 Ok(net::TcpListener::from(socket))
1341}
1342
1343/// Configures OpenSSL acceptor `builder` with ALPN protocols.
1344#[cfg(feature = "openssl")]
1345fn openssl_acceptor(mut builder: SslAcceptorBuilder) -> io::Result<SslAcceptor> {
1346 builder.set_alpn_select_callback(|_, protocols| {
1347 const H2: &[u8] = b"\x02h2";
1348 const H11: &[u8] = b"\x08http/1.1";
1349
1350 if protocols.windows(3).any(|window| window == H2) {
1351 Ok(b"h2")
1352 } else if protocols.windows(9).any(|window| window == H11) {
1353 Ok(b"http/1.1")
1354 } else {
1355 Err(AlpnError::NOACK)
1356 }
1357 });
1358
1359 builder.set_alpn_protos(b"\x08http/1.1\x02h2")?;
1360
1361 Ok(builder.build())
1362}