1#![allow(clippy::missing_panics_doc)]
2use std::sync::{Arc, mpsc};
3use std::time::{Duration, Instant};
4use std::{cell::Cell, fmt, io, thread};
5use std::{collections::VecDeque, num::NonZeroUsize};
6
7use ntex_polling::{Event, Events, Notifier, Poller};
8use ntex_rt::System;
9use ntex_util::{future::Either, time::Millis, time::sleep};
10use parking_lot::Mutex;
11
12use super::socket::{Connection, Listener, SocketAddr};
13use super::{Server, Token};
14use crate::metrics::AcceptSlot;
15
16const EXIT_TIMEOUT: Duration = Duration::from_millis(100);
17const ERR_TIMEOUT: Duration = Duration::from_millis(500);
18const ERR_SLEEP_TIMEOUT: Millis = Millis(525);
19const DEFAULT_BACKLOG: i32 = 2048;
20
21#[derive(Debug)]
23pub enum AcceptorCommand {
24 Stop(oneshot::Sender<()>),
26 Terminate,
28 Pause,
30 Resume,
32 Timer,
34}
35
36#[derive(Debug, Clone)]
38enum Command {
39 Stop(Arc<StopSignal>),
40 Terminate,
41 Pause,
42 Resume,
43 Timer,
44}
45
46#[derive(Debug)]
48struct StopSignal(Option<oneshot::Sender<()>>);
49
50impl Drop for StopSignal {
51 fn drop(&mut self) {
52 if let Some(tx) = self.0.take() {
53 let _ = tx.send(());
54 }
55 }
56}
57
58#[derive(Debug)]
59struct ServerSocketInfo {
60 addr: SocketAddr,
61 token: Token,
62 sock: Listener,
63 idx: usize,
65 registered: Cell<bool>,
66 timeout: Cell<Option<Instant>>,
67}
68
69#[derive(Debug, Clone)]
71struct AcceptHandle(Notifier, mpsc::Sender<Command>);
72
73impl AcceptHandle {
74 fn send(&self, cmd: Command) {
75 let _ = self.1.send(cmd);
76 let _ = self.0.notify();
77 }
78}
79
80#[derive(Debug, Clone)]
84pub struct AcceptNotify(Arc<Mutex<Vec<AcceptHandle>>>);
85
86impl AcceptNotify {
87 pub fn send(&self, cmd: AcceptorCommand) {
91 let handles = self.0.lock().clone();
92 let cmd = match cmd {
93 AcceptorCommand::Stop(tx) => Command::Stop(Arc::new(StopSignal(Some(tx)))),
94 AcceptorCommand::Terminate => Command::Terminate,
95 AcceptorCommand::Pause => Command::Pause,
96 AcceptorCommand::Resume => Command::Resume,
97 AcceptorCommand::Timer => Command::Timer,
98 };
99 for h in &handles {
100 h.send(cmd.clone());
101 }
102 }
103}
104
105pub struct AcceptLoop {
110 name: String,
111 testing: bool,
112 backlog: i32,
113 notify: AcceptNotify,
114 inner: Vec<(mpsc::Receiver<Command>, Poller)>,
115}
116
117impl Default for AcceptLoop {
118 fn default() -> Self {
119 Self::new()
120 }
121}
122
123impl AcceptLoop {
124 pub fn new() -> AcceptLoop {
130 let mut slf = AcceptLoop {
131 notify: AcceptNotify(Arc::new(Mutex::new(Vec::new()))),
132 name: "ntex:accept".to_string(),
133 inner: Vec::new(),
134 testing: false,
135 backlog: DEFAULT_BACKLOG,
136 };
137 slf.add_acceptor();
138 slf
139 }
140
141 fn add_acceptor(&mut self) {
142 let poll = Poller::new()
143 .map_err(|e| panic!("Cannot create Poller {e}"))
144 .unwrap();
145 let (tx, rx) = mpsc::channel();
146 self.notify.0.lock().push(AcceptHandle(poll.notifier(), tx));
147 self.inner.push((rx, poll));
148 }
149
150 pub fn name<T: AsRef<str>>(&mut self, name: T) {
155 self.name = format!("{}:accept", name.as_ref());
156 }
157
158 pub fn acceptors(&mut self, num: usize) {
172 let num = if cfg!(any(target_os = "linux", target_os = "android")) {
173 num.max(1)
174 } else {
175 if num > 1 {
176 log::warn!("Multiple accept threads are not supported on this platform");
177 }
178 1
179 };
180 while self.inner.len() < num {
181 self.add_acceptor();
182 }
183 self.inner.truncate(num);
184 self.notify.0.lock().truncate(num);
185 }
186
187 pub(crate) fn backlog(&mut self, num: i32) {
189 self.backlog = num;
190 }
191
192 pub fn notify(&self) -> AcceptNotify {
194 self.notify.clone()
195 }
196
197 pub fn testing(&mut self) {
199 self.testing = true;
200 }
201
202 #[allow(clippy::needless_pass_by_value)]
206 pub fn start(self, socks: Vec<(Token, Listener)>, srv: Server) {
207 srv.metrics_ref().listeners(
209 socks
210 .iter()
211 .map(|(_, lst)| (String::new(), lst.local_addr().to_string())),
212 );
213
214 let num = self.inner.len();
215 let mut groups: Vec<Vec<(usize, Token, Listener)>> = (0..num).map(|_| Vec::new()).collect();
216 for (idx, (token, lst)) in socks.into_iter().enumerate() {
217 if num > 1 {
218 for (n, lst) in replicate(&lst, num - 1, self.backlog)
219 .into_iter()
220 .enumerate()
221 {
222 groups[n + 1].push((idx, token, lst));
223 }
224 }
225 groups[0].push((idx, token, lst));
226 }
227
228 let handles = self.notify.0.lock().clone();
229 let mut started = Vec::new();
230 for (n, ((rx, poll), socks)) in self.inner.into_iter().zip(groups).enumerate() {
231 if n > 0 && socks.is_empty() {
233 continue;
234 }
235 let name = if n == 0 {
236 self.name.clone()
237 } else {
238 format!("{}{n}", self.name)
239 };
240 let (tx, rx_start) = oneshot::channel();
241 Accept::start(
242 tx,
243 rx,
244 poll,
245 handles[n].clone(),
246 socks,
247 srv.clone(),
248 name,
249 self.testing,
250 );
251 started.push(rx_start);
252 }
253
254 for rx in started {
255 let _ = rx.recv();
256 }
257 }
258}
259
260fn replicate(lst: &Listener, num: usize, backlog: i32) -> Vec<Listener> {
265 #[cfg(any(target_os = "linux", target_os = "android"))]
266 if let Listener::Tcp(lst) = lst {
267 use socket2::{Domain, SockAddr, SockRef, Socket, Type};
268
269 let create = || -> io::Result<std::net::TcpListener> {
270 let addr = lst.local_addr()?;
271 let sock = Socket::new(Domain::for_address(addr), Type::STREAM, None)?;
272 sock.set_reuse_address(true)?;
273 sock.set_reuse_port(true)?;
274 if addr.is_ipv6() {
275 sock.set_only_v6(SockRef::from(lst).only_v6()?)?;
276 }
277 sock.bind(&SockAddr::from(addr))?;
278 sock.listen(backlog)?;
279 Ok(sock.into())
280 };
281
282 if let Err(e) = SockRef::from(lst).set_reuse_port(true) {
283 log::warn!("Cannot enable SO_REUSEPORT for {lst:?}: {e}");
284 return Vec::new();
285 }
286 let mut items = Vec::with_capacity(num);
287 for _ in 0..num {
288 match create() {
289 Ok(item) => items.push(Listener::from_tcp(item)),
290 Err(e) => {
291 log::warn!("Cannot replicate listener {lst:?}: {e}");
292 break;
293 }
294 }
295 }
296 return items;
297 }
298 let _ = (lst, num, backlog);
299 Vec::new()
300}
301
302impl fmt::Debug for AcceptLoop {
303 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
304 f.debug_struct("AcceptLoop")
305 .field("name", &self.name)
306 .field("acceptors", &self.inner.len())
307 .field("notify", &self.notify)
308 .finish()
309 }
310}
311
312struct Accept {
313 name: String,
314 poller: Poller,
315 rx: mpsc::Receiver<Command>,
316 tx: Option<oneshot::Sender<()>>,
317 sockets: Vec<ServerSocketInfo>,
318 srv: Server,
319 notify: AcceptHandle,
320 testing: bool,
321 backpressure: bool,
322 backlog: VecDeque<Connection>,
323 backlog_reported: usize,
325 paused_reported: bool,
327}
328
329impl Accept {
330 #[allow(clippy::too_many_arguments)]
331 fn start(
332 tx: oneshot::Sender<()>,
333 rx: mpsc::Receiver<Command>,
334 poller: Poller,
335 notify: AcceptHandle,
336 socks: Vec<(usize, Token, Listener)>,
337 srv: Server,
338 name: String,
339 testing: bool,
340 ) {
341 log::info!("Starting {name:?} accept loop");
342
343 let sys = System::current();
345 let _ = thread::Builder::new().name(name.clone()).spawn(move || {
346 System::set_current(sys);
347 Accept::new(name, tx, rx, poller, notify, socks, srv, testing).poll();
348 });
349 }
350
351 #[allow(clippy::too_many_arguments)]
352 fn new(
353 name: String,
354 tx: oneshot::Sender<()>,
355 rx: mpsc::Receiver<Command>,
356 poller: Poller,
357 notify: AcceptHandle,
358 socks: Vec<(usize, Token, Listener)>,
359 srv: Server,
360 testing: bool,
361 ) -> Accept {
362 let sockets = socks
363 .into_iter()
364 .map(|(idx, token, sock)| ServerSocketInfo {
365 addr: sock.local_addr(),
366 sock,
367 idx,
368 token,
369 registered: Cell::new(false),
370 timeout: Cell::new(None),
371 })
372 .collect();
373
374 Accept {
375 name,
376 poller,
377 rx,
378 sockets,
379 notify,
380 srv,
381 testing,
382 tx: Some(tx),
383 backpressure: true,
384 backlog: VecDeque::new(),
385 backlog_reported: 0,
386 paused_reported: false,
387 }
388 }
389
390 fn report_paused(&mut self, paused: bool) {
391 if self.paused_reported != paused {
392 self.paused_reported = paused;
393 self.metrics().paused(paused);
394 }
395 }
396
397 fn report_backlog(&mut self) {
398 let len = self.backlog.len();
399 self.metrics().backlog(self.backlog_reported, len);
400 self.backlog_reported = len;
401 }
402
403 fn metrics(&self) -> &AcceptSlot {
404 self.srv.metrics_ref().listeners([])
405 }
406
407 fn poll(mut self) {
408 let mut events = Events::with_capacity(NonZeroUsize::new(512).unwrap());
410
411 for idx in 0..self.sockets.len() {
413 self.add_source(idx);
414 }
415 if let Some(tx) = self.tx.take() {
416 thread::sleep(Duration::from_millis(25));
417 let _ = tx.send(());
418 }
419
420 loop {
421 for idx in 0..self.sockets.len() {
422 let info = &self.sockets[idx];
425 if !self.backpressure && info.registered.get() && info.timeout.get().is_none() {
426 let readd = self.accept(idx);
427 if readd {
428 self.add_source(idx);
429 }
430 }
431 }
432
433 if let Either::Right(rx) = self.process_cmd() {
434 for info in self.sockets.drain(..) {
436 delete_source(&self.poller, &info);
437 info.sock.remove_source();
438 }
439 log::info!("Accept loop {:?} has been stopped", self.name);
440
441 if let Some(signal) = rx {
443 if !self.testing {
444 thread::sleep(EXIT_TIMEOUT);
445 }
446 drop(signal);
447 }
448
449 break;
450 }
451
452 events.clear();
453 if let Err(e) = self.poller.wait(&mut events, None) {
454 assert!(
455 e.kind() == io::ErrorKind::Interrupted,
456 "Cannot wait for events in poller: {e}"
457 );
458 }
459 }
460 }
461
462 fn add_source(&self, idx: usize) {
463 let info = &self.sockets[idx];
464
465 loop {
466 let result = if info.registered.get() {
468 self.poller.modify(&info.sock, Event::readable(idx))
469 } else {
470 unsafe { self.poller.add(&info.sock, Event::readable(idx)) }
471 };
472 if let Err(err) = result {
473 if err.kind() == io::ErrorKind::WouldBlock {
474 continue;
475 }
476 log::error!("Cannot register socket listener: {err}");
477
478 info.timeout.set(Some(Instant::now() + ERR_TIMEOUT));
480
481 let notify = self.notify.clone();
482 System::current().handle().spawn_detached(async move {
484 ntex_rt::spawn_detached(async move {
485 sleep(ERR_SLEEP_TIMEOUT).await;
486 notify.send(Command::Timer);
487 });
488 });
489 } else {
490 info.registered.set(true);
491 }
492
493 break;
494 }
495 }
496
497 fn remove_source(&self, key: usize) {
498 let info = &self.sockets[key];
499
500 let result = if info.registered.get() {
501 self.poller.modify(&info.sock, Event::none(key))
502 } else {
503 return;
504 };
505
506 if let Err(err) = result {
508 log::error!("Cannot stop socket listener for {} err: {}", info.addr, err);
509 }
510 }
511
512 fn process_timer(&mut self) {
513 let now = Instant::now();
514 for key in 0..self.sockets.len() {
515 let info = &mut self.sockets[key];
516 if let Some(inst) = info.timeout.get()
517 && now > inst
518 && !self.backpressure
519 {
520 log::info!("Resuming socket listener on {} after timeout", info.addr);
521 info.timeout.take();
522 self.add_source(key);
523 }
524 }
525 }
526
527 fn process_cmd(&mut self) -> Either<(), Option<Arc<StopSignal>>> {
528 loop {
529 match self.rx.try_recv() {
530 Ok(cmd) => match cmd {
531 Command::Stop(rx) => {
532 if !self.backpressure {
533 log::info!("Stopping accept loop {:?}", self.name);
534 self.backpressure(true);
535 }
536 break Either::Right(Some(rx));
537 }
538 Command::Terminate => {
539 log::info!("Stopping accept loop {:?}", self.name);
540 self.backpressure(true);
541 break Either::Right(None);
542 }
543 Command::Pause => {
544 if !self.backpressure {
545 log::info!("Pausing accept loop {:?}", self.name);
546 self.backpressure(true);
547 }
548 }
549 Command::Resume => {
550 if self.backpressure {
551 log::info!("Resuming accept loop {:?}", self.name);
552 self.backpressure(false);
553 }
554 }
555 Command::Timer => {
556 self.process_timer();
557 }
558 },
559 Err(err) => {
560 break match err {
561 mpsc::TryRecvError::Empty => Either::Left(()),
562 mpsc::TryRecvError::Disconnected => {
563 log::error!("Dropping accept loop {:?}", self.name);
564 self.backpressure(true);
565 Either::Right(None)
566 }
567 };
568 }
569 }
570 }
571 }
572
573 fn backpressure(&mut self, on: bool) {
574 if self.backpressure && !on {
575 while let Some(msg) = self.backlog.pop_front() {
577 if let Err(msg) = self.srv.process_with(msg, Connection::incoming_cpu) {
578 log::trace!("Server is unavailable");
579 self.backlog.push_front(msg);
580 self.report_backlog();
581 return;
582 }
583 }
584 self.report_backlog();
585 self.report_paused(false);
586
587 self.backpressure = false;
589 for (key, info) in self.sockets.iter().enumerate() {
590 if info.timeout.get().is_none() {
591 log::info!(
593 "Resuming socket listener on {} after back-pressure",
594 info.addr
595 );
596 self.add_source(key);
597 }
598 }
599 } else if !self.backpressure && on {
600 self.backpressure = true;
601 self.report_paused(true);
602 for key in 0..self.sockets.len() {
603 let info = &mut self.sockets[key];
605 if info.timeout.take().is_none() {
606 log::info!("Stopping socket listener on {}", info.addr);
607 self.remove_source(key);
608 }
609 }
610 }
611 }
612
613 fn accept(&mut self, token: usize) -> bool {
614 loop {
615 if let Some(info) = self.sockets.get_mut(token) {
616 let idx = info.idx;
617 match info.sock.accept() {
618 Ok(Some(io)) => {
619 self.srv.metrics_ref().listeners([]).accepted(idx);
620 let msg = Connection {
621 io,
622 token: info.token,
623 };
624 if let Err(msg) = self.srv.process_with(msg, Connection::incoming_cpu) {
625 log::trace!("Server is unavailable");
626 self.backlog.push_back(msg);
627 self.report_backlog();
628 self.backpressure(true);
629 return false;
630 }
631 }
632 Ok(None) => return true,
633 Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => return true,
634 Err(ref e) if connection_error(e) => {
635 self.srv.metrics_ref().listeners([]).connection_error(idx);
636 }
637 Err(e) => {
638 log::error!("Error accepting socket: {e}");
639 self.srv.metrics_ref().listeners([]).resource_error(idx);
640
641 info.timeout.set(Some(Instant::now() + ERR_TIMEOUT));
643
644 let notify = self.notify.clone();
645 System::current().handle().spawn_detached(async move {
647 ntex_rt::spawn_detached(async move {
648 sleep(ERR_SLEEP_TIMEOUT).await;
649 notify.send(Command::Timer);
650 });
651 });
652 return false;
653 }
654 }
655 }
656 }
657 }
658}
659
660impl Drop for Accept {
661 fn drop(&mut self) {
662 for info in &self.sockets {
664 delete_source(&self.poller, info);
665 }
666 }
667}
668
669fn delete_source(poller: &Poller, info: &ServerSocketInfo) {
672 if info.registered.replace(false)
673 && let Err(err) = poller.delete(&info.sock)
674 {
675 log::error!(
676 "Cannot delete socket listener for {} err: {}",
677 info.addr,
678 err
679 );
680 }
681}
682
683fn connection_error(e: &io::Error) -> bool {
691 matches!(
692 e.kind(),
693 io::ErrorKind::ConnectionRefused
694 | io::ErrorKind::ConnectionAborted
695 | io::ErrorKind::ConnectionReset
696 )
697}