1use std::{fmt, io, net, sync::Arc};
2
3use ntex_io::Io;
4use ntex_rt::System;
5use ntex_service::{IntoService, Service, cfg::SharedCfg};
6use ntex_util::time::Millis;
7use socket2::{Domain, SockAddr, Socket, Type};
8
9use crate::{Affinity, LoadBalancing, NoConfig, Server, ServerAppConfig, WorkerPool};
10
11use super::accept::AcceptLoop;
12use super::config::ServiceConfig;
13use super::factory::{self, FactoryServiceType};
14use super::{Connection, StreamServer, Token, socket::Listener};
15
16pub struct ServerBuilder<Cfg = NoConfig> {
21 name: String,
22 token: Token,
23 backlog: i32,
24 state: Arc<Cfg>,
25 services: Vec<FactoryServiceType<Cfg>>,
26 sockets: Vec<(Token, String, Listener)>,
27 accept: AcceptLoop,
28 acceptors: usize,
29 pool: WorkerPool,
30}
31
32impl Default for ServerBuilder {
33 fn default() -> Self {
34 Self::new(NoConfig)
35 }
36}
37
38impl<Cfg> ServerBuilder<Cfg>
39where
40 Cfg: ServerAppConfig,
41{
42 #[must_use]
43 pub fn new(cfg: Cfg) -> ServerBuilder<Cfg> {
45 let sys = System::current();
46 let mut accept = AcceptLoop::default();
47 accept.name(sys.name());
48 if sys.testing() {
49 accept.testing();
50 }
51
52 ServerBuilder {
53 accept,
54 acceptors: 1,
55 name: sys.name().to_string(),
56 token: Token(0),
57 state: Arc::new(cfg),
58 services: Vec::new(),
59 sockets: Vec::new(),
60 backlog: 2048,
61 pool: WorkerPool::default().name(sys.name()),
62 }
63 }
64
65 #[must_use]
66 pub fn name<T: AsRef<str>>(mut self, name: T) -> Self {
71 self.name = name.as_ref().to_string();
72 self.accept.name(self.name.as_str());
73 self.pool = self.pool.name(self.name.as_str());
74 self
75 }
76
77 #[must_use]
78 pub fn workers(mut self, num: usize) -> Self {
82 self.pool = self.pool.workers(num);
83 self
84 }
85
86 #[must_use]
87 pub fn backlog(mut self, num: i32) -> Self {
100 self.backlog = num;
101 self.accept.backlog(num);
102 self
103 }
104
105 #[must_use]
106 pub fn acceptors(mut self, num: usize) -> Self {
121 self.acceptors = num;
122 self
123 }
124
125 #[must_use]
126 pub fn max_connections(self, num: usize) -> Self {
137 super::max_concurrent_connections(num);
138 self
139 }
140
141 #[must_use]
142 pub fn stop_runtime(mut self) -> Self {
146 self.pool = self.pool.stop_runtime();
147 self
148 }
149
150 #[must_use]
151 pub fn stop_on_panic(mut self) -> Self {
159 self.pool = self.pool.stop_on_panic();
160 self
161 }
162
163 #[must_use]
164 pub fn disable_signals(mut self) -> Self {
168 self.pool = self.pool.disable_signals();
169 self
170 }
171
172 #[must_use]
173 pub fn affinity(mut self, affinity: Affinity) -> Self {
177 self.pool = self.pool.affinity(affinity);
178 self
179 }
180
181 #[must_use]
182 pub fn load_balancing(mut self, balancing: LoadBalancing) -> Self {
186 self.pool = self.pool.load_balancing(balancing);
187 self
188 }
189
190 #[must_use]
191 pub fn graceful_shutdown(mut self) -> Self {
199 self.pool = self.pool.graceful_shutdown();
200 self
201 }
202
203 #[must_use]
204 pub fn graceful_shutdown_timeout<T: Into<Millis>>(mut self, timeout: T) -> Self {
217 self.pool = self.pool.graceful_shutdown_timeout(timeout);
218 self
219 }
220
221 pub async fn configure<F>(mut self, f: F) -> io::Result<Self>
229 where
230 F: AsyncFnOnce(ServiceConfig<Cfg>) -> io::Result<()>,
231 {
232 let cfg = ServiceConfig::new(self.token, self.backlog);
233
234 f(cfg.clone()).await?;
235
236 let (token, sockets, factory) = cfg.into_factory();
237 self.token = token;
238 self.sockets.extend(sockets);
239 self.services.push(factory);
240
241 Ok(self)
242 }
243
244 #[allow(clippy::needless_pass_by_value)]
245 pub fn bind<F, S, I>(
255 mut self,
256 name: impl AsRef<str>,
257 addr: impl net::ToSocketAddrs,
258 cfg: impl Into<SharedCfg>,
259 factory: F,
260 ) -> io::Result<Self>
261 where
262 F: AsyncFn(&Cfg::State) -> I + Send + Clone + 'static,
263 S: Service<Cfg::State, Io> + 'static,
264 I: IntoService<S, Cfg::State, Io> + 'static,
265 {
266 let cfg = cfg.into();
267 let sockets = bind_addr(addr, self.backlog)?;
268
269 let mut tokens = Vec::new();
270 for lst in sockets {
271 let token = self.token.next();
272 self.sockets
273 .push((token, name.as_ref().to_string(), Listener::from_tcp(lst)));
274 tokens.push((token, cfg.clone()));
275 }
276
277 self.services.push(factory::create_factory_service(
278 name.as_ref().to_string(),
279 tokens,
280 factory,
281 ));
282
283 Ok(self)
284 }
285
286 #[cfg(unix)]
287 pub fn bind_uds<F, I, S>(
293 self,
294 name: impl AsRef<str>,
295 addr: impl AsRef<std::path::Path>,
296 cfg: impl Into<SharedCfg>,
297 factory: F,
298 ) -> io::Result<Self>
299 where
300 F: AsyncFn(&Cfg::State) -> I + Send + Clone + 'static,
301 I: IntoService<S, Cfg::State, Io> + 'static,
302 S: Service<Cfg::State, Io> + 'static,
303 {
304 use std::os::unix::net::UnixListener;
305
306 if let Err(e) = std::fs::remove_file(addr.as_ref()) {
309 if e.kind() != std::io::ErrorKind::NotFound {
311 return Err(e);
312 }
313 }
314
315 let lst = UnixListener::bind(addr)?;
316 self.listen_uds(name, lst, cfg.into(), factory)
317 }
318
319 #[cfg(unix)]
320 pub fn listen_uds<F, I, S>(
326 mut self,
327 name: impl AsRef<str>,
328 lst: std::os::unix::net::UnixListener,
329 cfg: impl Into<SharedCfg>,
330 factory: F,
331 ) -> io::Result<Self>
332 where
333 F: AsyncFn(&Cfg::State) -> I + Send + Clone + 'static,
334 I: IntoService<S, Cfg::State, Io> + 'static,
335 S: Service<Cfg::State, Io> + 'static,
336 {
337 let token = self.token.next();
338 self.services.push(factory::create_factory_service(
339 name.as_ref().to_string(),
340 vec![(token, cfg.into())],
341 factory,
342 ));
343 self.sockets
344 .push((token, name.as_ref().to_string(), Listener::from_uds(lst)));
345 Ok(self)
346 }
347
348 pub fn listen<F, S, I>(
353 mut self,
354 name: impl AsRef<str>,
355 lst: net::TcpListener,
356 cfg: impl Into<SharedCfg>,
357 factory: F,
358 ) -> io::Result<Self>
359 where
360 F: AsyncFn(&Cfg::State) -> I + Send + Clone + 'static,
361 S: Service<Cfg::State, Io> + 'static,
362 I: IntoService<S, Cfg::State, Io> + 'static,
363 {
364 let token = self.token.next();
365 self.services.push(factory::create_factory_service(
366 name.as_ref().to_string(),
367 vec![(token, cfg.into())],
368 factory,
369 ));
370 self.sockets
371 .push((token, name.as_ref().to_string(), Listener::from_tcp(lst)));
372 Ok(self)
373 }
374
375 pub fn run(mut self) -> Server<Connection> {
381 assert!(
382 !self.sockets.is_empty(),
383 "Server should have at least one bound socket"
384 );
385 self.accept.acceptors(self.acceptors);
386 let srv = StreamServer::new(self.accept.notify(), self.state, self.services);
387 let svc = self.pool.run(srv);
388
389 svc.metrics_ref().listeners(
390 self.sockets
391 .iter()
392 .map(|sock| (sock.1.clone(), sock.2.local_addr().to_string())),
393 );
394 let sockets = self
395 .sockets
396 .into_iter()
397 .map(|sock| {
398 log::info!("Starting \"{}\" service on {}", sock.1, sock.2);
399 (sock.0, sock.2)
400 })
401 .collect();
402 self.accept.start(sockets, svc.clone());
403
404 svc
405 }
406}
407
408impl<Cfg> fmt::Debug for ServerBuilder<Cfg> {
409 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
410 f.debug_struct("ServerBuilder")
411 .field("name", &self.name)
412 .field("token", &self.token)
413 .field("backlog", &self.backlog)
414 .field("sockets", &self.sockets)
415 .field("accept", &self.accept)
416 .field("acceptors", &self.acceptors)
417 .field("worker-pool", &self.pool)
418 .finish()
419 }
420}
421
422pub fn bind_addr<S: net::ToSocketAddrs>(
427 addr: S,
428 backlog: i32,
429) -> io::Result<Vec<net::TcpListener>> {
430 let mut err = None;
431 let mut succ = false;
432 let mut sockets = Vec::new();
433 for addr in addr.to_socket_addrs()? {
434 match create_tcp_listener(addr, backlog) {
435 Ok(lst) => {
436 succ = true;
437 sockets.push(lst);
438 }
439 Err(e) => err = Some(e),
440 }
441 }
442
443 if succ {
444 Ok(sockets)
445 } else if let Some(e) = err.take() {
446 Err(e)
447 } else {
448 Err(io::Error::new(
449 io::ErrorKind::InvalidInput,
450 "Cannot bind to address.",
451 ))
452 }
453}
454
455pub fn create_tcp_listener(addr: net::SocketAddr, backlog: i32) -> io::Result<net::TcpListener> {
457 let builder = match addr {
458 net::SocketAddr::V4(_) => Socket::new(Domain::IPV4, Type::STREAM, None)?,
459 net::SocketAddr::V6(_) => Socket::new(Domain::IPV6, Type::STREAM, None)?,
460 };
461
462 #[cfg(not(windows))]
466 builder.set_reuse_address(true)?;
467
468 builder.bind(&SockAddr::from(addr))?;
469 builder.listen(backlog)?;
470 Ok(net::TcpListener::from(builder))
471}
472
473#[cfg(test)]
474mod tests {
475 use super::*;
476
477 #[test]
478 fn test_bind_addr() {
479 let addrs: Vec<net::SocketAddr> = Vec::new();
480 assert!(bind_addr(&addrs[..], 10).is_err());
481 }
482
483 #[ntex::test]
484 async fn test_debug() {
485 let builder = ServerBuilder::default();
486 assert!(format!("{builder:?}").contains("ServerBuilder"));
487 }
488
489 #[ntex::test]
499 async fn test_paused_wakeup_does_not_accept() {
500 use crate::ServerStatus;
501 use crate::net::AcceptorCommand;
502 use ntex_service::{cfg::SharedCfg, fn_service};
503
504 let lst = net::TcpListener::bind("127.0.0.1:0").unwrap();
505 let addr = lst.local_addr().unwrap();
506 let builder = ServerBuilder::default()
507 .workers(1)
508 .acceptors(1)
509 .disable_signals()
510 .listen("test", lst, SharedCfg::default(), async |&()| {
511 fn_service(async |_: ntex_io::Io| Ok::<_, ()>(()))
512 })
513 .unwrap();
514 let notify = builder.accept.notify();
515 let srv = builder.run();
516 ntex_util::time::timeout(Millis(3000), async {
517 while srv.status() != ServerStatus::Ready {
518 srv.status_changed().await;
519 }
520 })
521 .await
522 .unwrap();
523
524 srv.pause().await;
525 ntex_util::time::sleep(Millis(100)).await;
526 notify.send(AcceptorCommand::Timer);
527 ntex_util::time::sleep(Millis(100)).await;
528
529 let _conn = net::TcpStream::connect(addr).unwrap();
530 ntex_util::time::sleep(Millis(200)).await;
531 assert_eq!(srv.metrics().listeners[0].accepted, 0);
532
533 srv.resume().await;
534 ntex_util::time::timeout(Millis(3000), async {
535 while srv.metrics().listeners[0].accepted == 0 {
536 ntex_util::time::sleep(Millis(10)).await;
537 }
538 })
539 .await
540 .unwrap();
541 srv.stop(false).await;
542 }
543}