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 {
483 sleep(ERR_SLEEP_TIMEOUT).await;
484 notify.send(Command::Timer);
485 });
486 } else {
487 info.registered.set(true);
488 }
489
490 break;
491 }
492 }
493
494 fn remove_source(&self, key: usize) {
495 let info = &self.sockets[key];
496
497 let result = if info.registered.get() {
498 self.poller.modify(&info.sock, Event::none(key))
499 } else {
500 return;
501 };
502
503 if let Err(err) = result {
505 log::error!("Cannot stop socket listener for {} err: {}", info.addr, err);
506 }
507 }
508
509 fn process_timer(&mut self) {
510 let now = Instant::now();
511 for key in 0..self.sockets.len() {
512 let info = &mut self.sockets[key];
513 if let Some(inst) = info.timeout.get()
514 && now > inst
515 && !self.backpressure
516 {
517 log::info!("Resuming socket listener on {} after timeout", info.addr);
518 info.timeout.take();
519 self.add_source(key);
520 }
521 }
522 }
523
524 fn process_cmd(&mut self) -> Either<(), Option<Arc<StopSignal>>> {
525 loop {
526 match self.rx.try_recv() {
527 Ok(cmd) => match cmd {
528 Command::Stop(rx) => {
529 if !self.backpressure {
530 log::info!("Stopping accept loop {:?}", self.name);
531 self.backpressure(true);
532 }
533 break Either::Right(Some(rx));
534 }
535 Command::Terminate => {
536 log::info!("Stopping accept loop {:?}", self.name);
537 self.backpressure(true);
538 break Either::Right(None);
539 }
540 Command::Pause => {
541 if !self.backpressure {
542 log::info!("Pausing accept loop {:?}", self.name);
543 self.backpressure(true);
544 }
545 }
546 Command::Resume => {
547 if self.backpressure {
548 log::info!("Resuming accept loop {:?}", self.name);
549 self.backpressure(false);
550 }
551 }
552 Command::Timer => {
553 self.process_timer();
554 }
555 },
556 Err(err) => {
557 break match err {
558 mpsc::TryRecvError::Empty => Either::Left(()),
559 mpsc::TryRecvError::Disconnected => {
560 log::error!("Dropping accept loop {:?}", self.name);
561 self.backpressure(true);
562 Either::Right(None)
563 }
564 };
565 }
566 }
567 }
568 }
569
570 fn backpressure(&mut self, on: bool) {
571 if self.backpressure && !on {
572 while let Some(msg) = self.backlog.pop_front() {
574 if let Err(msg) = self.srv.process_with(msg, Connection::incoming_cpu) {
575 log::trace!("Server is unavailable");
576 self.backlog.push_front(msg);
577 self.report_backlog();
578 return;
579 }
580 }
581 self.report_backlog();
582 self.report_paused(false);
583
584 self.backpressure = false;
586 for (key, info) in self.sockets.iter().enumerate() {
587 if info.timeout.get().is_none() {
588 log::info!(
590 "Resuming socket listener on {} after back-pressure",
591 info.addr
592 );
593 self.add_source(key);
594 }
595 }
596 } else if !self.backpressure && on {
597 self.backpressure = true;
598 self.report_paused(true);
599 for key in 0..self.sockets.len() {
600 let info = &mut self.sockets[key];
602 if info.timeout.take().is_none() {
603 log::info!("Stopping socket listener on {}", info.addr);
604 self.remove_source(key);
605 }
606 }
607 }
608 }
609
610 fn accept(&mut self, token: usize) -> bool {
611 loop {
612 if let Some(info) = self.sockets.get_mut(token) {
613 let idx = info.idx;
614 match info.sock.accept() {
615 Ok(Some(io)) => {
616 self.srv.metrics_ref().listeners([]).accepted(idx);
617 let msg = Connection {
618 io,
619 token: info.token,
620 };
621 if let Err(msg) = self.srv.process_with(msg, Connection::incoming_cpu) {
622 log::trace!("Server is unavailable");
623 self.backlog.push_back(msg);
624 self.report_backlog();
625 self.backpressure(true);
626 return false;
627 }
628 }
629 Ok(None) => return true,
630 Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => return true,
631 Err(ref e) if connection_error(e) => {
632 self.srv.metrics_ref().listeners([]).connection_error(idx);
633 }
634 Err(e) => {
635 log::error!("Error accepting socket: {e}");
636 self.srv.metrics_ref().listeners([]).resource_error(idx);
637
638 info.timeout.set(Some(Instant::now() + ERR_TIMEOUT));
640
641 let notify = self.notify.clone();
642 System::current().handle().spawn_detached(async move {
643 sleep(ERR_SLEEP_TIMEOUT).await;
644 notify.send(Command::Timer);
645 });
646 return false;
647 }
648 }
649 }
650 }
651 }
652}
653
654impl Drop for Accept {
655 fn drop(&mut self) {
656 for info in &self.sockets {
658 delete_source(&self.poller, info);
659 }
660 }
661}
662
663fn delete_source(poller: &Poller, info: &ServerSocketInfo) {
666 if info.registered.replace(false)
667 && let Err(err) = poller.delete(&info.sock)
668 {
669 log::error!(
670 "Cannot delete socket listener for {} err: {}",
671 info.addr,
672 err
673 );
674 }
675}
676
677fn connection_error(e: &io::Error) -> bool {
685 matches!(
686 e.kind(),
687 io::ErrorKind::ConnectionRefused
688 | io::ErrorKind::ConnectionAborted
689 | io::ErrorKind::ConnectionReset
690 )
691}