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