1#![allow(clippy::missing_panics_doc)]
2use std::time::{Duration, Instant};
3use std::{cell::Cell, fmt, io, sync::mpsc, thread};
4use std::{collections::VecDeque, num::NonZeroUsize};
5
6use ntex_polling::{Event, Events, Notifier, Poller};
7use ntex_rt::System;
8use ntex_util::{future::Either, time::Millis, time::sleep};
9
10use super::socket::{Connection, Listener, SocketAddr};
11use super::{Server, Token};
12use crate::metrics::AcceptSlot;
13
14const EXIT_TIMEOUT: Duration = Duration::from_millis(100);
15const ERR_TIMEOUT: Duration = Duration::from_millis(500);
16const ERR_SLEEP_TIMEOUT: Millis = Millis(525);
17
18#[derive(Debug)]
20pub enum AcceptorCommand {
21 Stop(oneshot::Sender<()>),
23 Terminate,
25 Pause,
27 Resume,
29 Timer,
31}
32
33#[derive(Debug)]
34struct ServerSocketInfo {
35 addr: SocketAddr,
36 token: Token,
37 sock: Listener,
38 registered: Cell<bool>,
39 timeout: Cell<Option<Instant>>,
40}
41
42#[derive(Debug, Clone)]
44pub struct AcceptNotify(Notifier, mpsc::Sender<AcceptorCommand>);
45
46impl AcceptNotify {
47 fn new(waker: Notifier, tx: mpsc::Sender<AcceptorCommand>) -> Self {
48 AcceptNotify(waker, tx)
49 }
50
51 pub fn send(&self, cmd: AcceptorCommand) {
53 let _ = self.1.send(cmd);
54 let _ = self.0.notify();
55 }
56}
57
58pub struct AcceptLoop {
63 name: String,
64 testing: bool,
65 notify: AcceptNotify,
66 inner: Option<(mpsc::Receiver<AcceptorCommand>, Poller)>,
67}
68
69impl Default for AcceptLoop {
70 fn default() -> Self {
71 Self::new()
72 }
73}
74
75impl AcceptLoop {
76 pub fn new() -> AcceptLoop {
82 let poll = Poller::new()
84 .map_err(|e| panic!("Cannot create Poller {e}"))
85 .unwrap();
86
87 let (tx, rx) = mpsc::channel();
88 let notify = AcceptNotify::new(poll.notifier(), tx);
89
90 AcceptLoop {
91 notify,
92 name: "ntex:accept".to_string(),
93 inner: Some((rx, poll)),
94 testing: false,
95 }
96 }
97
98 pub fn name<T: AsRef<str>>(&mut self, name: T) {
102 self.name = format!("{}:accept", name.as_ref());
103 }
104
105 pub fn notify(&self) -> AcceptNotify {
107 self.notify.clone()
108 }
109
110 pub fn testing(&mut self) {
112 self.testing = true;
113 }
114
115 pub fn start(mut self, socks: Vec<(Token, Listener)>, srv: Server) {
119 let (tx, rx_start) = oneshot::channel();
120 let (rx, poll) = self
121 .inner
122 .take()
123 .expect("AcceptLoop cannot be used multiple times");
124
125 Accept::start(
126 tx,
127 rx,
128 poll,
129 socks,
130 srv,
131 self.name.clone(),
132 self.notify.clone(),
133 self.testing,
134 );
135
136 let _ = rx_start.recv();
137 }
138}
139
140impl fmt::Debug for AcceptLoop {
141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142 f.debug_struct("AcceptLoop")
143 .field("name", &self.name)
144 .field("notify", &self.notify)
145 .field("inner", &self.inner)
146 .finish()
147 }
148}
149
150struct Accept {
151 name: String,
152 poller: Poller,
153 rx: mpsc::Receiver<AcceptorCommand>,
154 tx: Option<oneshot::Sender<()>>,
155 sockets: Vec<ServerSocketInfo>,
156 srv: Server,
157 notify: AcceptNotify,
158 testing: bool,
159 backpressure: bool,
160 backlog: VecDeque<Connection>,
161}
162
163impl Accept {
164 #[allow(clippy::too_many_arguments)]
165 fn start(
166 tx: oneshot::Sender<()>,
167 rx: mpsc::Receiver<AcceptorCommand>,
168 poller: Poller,
169 socks: Vec<(Token, Listener)>,
170 srv: Server,
171 name: String,
172 notify: AcceptNotify,
173 testing: bool,
174 ) {
175 log::info!("Starting {name:?} accept loop");
176
177 let sys = System::current();
179 let _ = thread::Builder::new().name(name.clone()).spawn(move || {
180 System::set_current(sys);
181 Accept::new(name, tx, rx, poller, socks, srv, notify, testing).poll();
182 });
183 }
184
185 #[allow(clippy::too_many_arguments)]
186 fn new(
187 name: String,
188 tx: oneshot::Sender<()>,
189 rx: mpsc::Receiver<AcceptorCommand>,
190 poller: Poller,
191 socks: Vec<(Token, Listener)>,
192 srv: Server,
193 notify: AcceptNotify,
194 testing: bool,
195 ) -> Accept {
196 let mut sockets = Vec::new();
197 srv.metrics_ref().listeners(
199 socks
200 .iter()
201 .map(|(_, lst)| (String::new(), lst.local_addr().to_string())),
202 );
203 for (hnd_token, lst) in socks {
204 sockets.push(ServerSocketInfo {
205 addr: lst.local_addr(),
206 sock: lst,
207 token: hnd_token,
208 registered: Cell::new(false),
209 timeout: Cell::new(None),
210 });
211 }
212
213 Accept {
214 name,
215 poller,
216 rx,
217 sockets,
218 notify,
219 srv,
220 testing,
221 tx: Some(tx),
222 backpressure: true,
223 backlog: VecDeque::new(),
224 }
225 }
226
227 fn metrics(&self) -> &AcceptSlot {
228 self.srv.metrics_ref().listeners([])
229 }
230
231 fn poll(mut self) {
232 let mut events = Events::with_capacity(NonZeroUsize::new(512).unwrap());
234
235 for idx in 0..self.sockets.len() {
237 self.add_source(idx);
238 }
239 if let Some(tx) = self.tx.take() {
240 thread::sleep(Duration::from_millis(25));
241 let _ = tx.send(());
242 }
243
244 loop {
245 for idx in 0..self.sockets.len() {
246 if self.sockets[idx].registered.get() {
247 let readd = self.accept(idx);
248 if readd {
249 self.add_source(idx);
250 }
251 }
252 }
253
254 if let Either::Right(rx) = self.process_cmd() {
255 for info in self.sockets.drain(..) {
257 info.sock.remove_source();
258 }
259 log::info!("Accept loop {:?} has been stopped", self.name);
260
261 if let Some(rx) = rx {
262 if !self.testing {
263 thread::sleep(EXIT_TIMEOUT);
264 }
265 let _ = rx.send(());
266 }
267
268 break;
269 }
270
271 events.clear();
272 if let Err(e) = self.poller.wait(&mut events, None) {
273 assert!(
274 e.kind() == io::ErrorKind::Interrupted,
275 "Cannot wait for events in poller: {e}"
276 );
277 }
278 }
279 }
280
281 fn add_source(&self, idx: usize) {
282 let info = &self.sockets[idx];
283
284 loop {
285 let result = if info.registered.get() {
287 self.poller.modify(&info.sock, Event::readable(idx))
288 } else {
289 unsafe { self.poller.add(&info.sock, Event::readable(idx)) }
290 };
291 if let Err(err) = result {
292 if err.kind() == io::ErrorKind::WouldBlock {
293 continue;
294 }
295 log::error!("Cannot register socket listener: {err}");
296
297 info.timeout.set(Some(Instant::now() + ERR_TIMEOUT));
299
300 let notify = self.notify.clone();
301 System::current().handle().spawn_detached(async move {
302 sleep(ERR_SLEEP_TIMEOUT).await;
303 notify.send(AcceptorCommand::Timer);
304 });
305 } else {
306 info.registered.set(true);
307 }
308
309 break;
310 }
311 }
312
313 fn remove_source(&self, key: usize) {
314 let info = &self.sockets[key];
315
316 let result = if info.registered.get() {
317 self.poller.modify(&info.sock, Event::none(key))
318 } else {
319 return;
320 };
321
322 if let Err(err) = result {
324 log::error!("Cannot stop socket listener for {} err: {}", info.addr, err);
325 }
326 }
327
328 fn process_timer(&mut self) {
329 let now = Instant::now();
330 for key in 0..self.sockets.len() {
331 let info = &mut self.sockets[key];
332 if let Some(inst) = info.timeout.get()
333 && now > inst
334 && !self.backpressure
335 {
336 log::info!("Resuming socket listener on {} after timeout", info.addr);
337 info.timeout.take();
338 self.add_source(key);
339 }
340 }
341 }
342
343 fn process_cmd(&mut self) -> Either<(), Option<oneshot::Sender<()>>> {
344 loop {
345 match self.rx.try_recv() {
346 Ok(cmd) => match cmd {
347 AcceptorCommand::Stop(rx) => {
348 if !self.backpressure {
349 log::info!("Stopping accept loop {:?}", self.name);
350 self.backpressure(true);
351 }
352 break Either::Right(Some(rx));
353 }
354 AcceptorCommand::Terminate => {
355 log::info!("Stopping accept loop {:?}", self.name);
356 self.backpressure(true);
357 break Either::Right(None);
358 }
359 AcceptorCommand::Pause => {
360 if !self.backpressure {
361 log::info!("Pausing accept loop {:?}", self.name);
362 self.backpressure(true);
363 }
364 }
365 AcceptorCommand::Resume => {
366 if self.backpressure {
367 log::info!("Resuming accept loop {:?}", self.name);
368 self.backpressure(false);
369 }
370 }
371 AcceptorCommand::Timer => {
372 self.process_timer();
373 }
374 },
375 Err(err) => {
376 break match err {
377 mpsc::TryRecvError::Empty => Either::Left(()),
378 mpsc::TryRecvError::Disconnected => {
379 log::error!("Dropping accept loop {:?}", self.name);
380 self.backpressure(true);
381 Either::Right(None)
382 }
383 };
384 }
385 }
386 }
387 }
388
389 fn backpressure(&mut self, on: bool) {
390 if self.backpressure && !on {
391 while let Some(msg) = self.backlog.pop_front() {
393 if let Err(msg) = self.srv.process(msg) {
394 log::trace!("Server is unavailable");
395 self.backlog.push_front(msg);
396 self.metrics().backlog(self.backlog.len());
397 return;
398 }
399 }
400 self.metrics().backlog(0);
401 self.metrics().paused(false);
402
403 self.backpressure = false;
405 for (key, info) in self.sockets.iter().enumerate() {
406 if info.timeout.get().is_none() {
407 log::info!(
409 "Resuming socket listener on {} after back-pressure",
410 info.addr
411 );
412 self.add_source(key);
413 }
414 }
415 } else if !self.backpressure && on {
416 self.backpressure = true;
417 self.metrics().paused(true);
418 for key in 0..self.sockets.len() {
419 let info = &mut self.sockets[key];
421 if info.timeout.take().is_none() {
422 log::info!("Stopping socket listener on {}", info.addr);
423 self.remove_source(key);
424 }
425 }
426 }
427 }
428
429 fn accept(&mut self, token: usize) -> bool {
430 loop {
431 if let Some(info) = self.sockets.get_mut(token) {
432 match info.sock.accept() {
433 Ok(Some(io)) => {
434 self.srv.metrics_ref().listeners([]).accepted(token);
435 let msg = Connection {
436 io,
437 token: info.token,
438 };
439 if let Err(msg) = self.srv.process(msg) {
440 log::trace!("Server is unavailable");
441 self.backlog.push_back(msg);
442 self.metrics().backlog(self.backlog.len());
443 self.backpressure(true);
444 return false;
445 }
446 }
447 Ok(None) => return true,
448 Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => return true,
449 Err(ref e) if connection_error(e) => {
450 self.srv.metrics_ref().listeners([]).connection_error(token);
451 }
452 Err(e) => {
453 log::error!("Error accepting socket: {e}");
454 self.srv.metrics_ref().listeners([]).resource_error(token);
455
456 info.timeout.set(Some(Instant::now() + ERR_TIMEOUT));
458
459 let notify = self.notify.clone();
460 System::current().handle().spawn_detached(async move {
461 sleep(ERR_SLEEP_TIMEOUT).await;
462 notify.send(AcceptorCommand::Timer);
463 });
464 return false;
465 }
466 }
467 }
468 }
469 }
470}
471
472fn connection_error(e: &io::Error) -> bool {
480 matches!(
481 e.kind(),
482 io::ErrorKind::ConnectionRefused
483 | io::ErrorKind::ConnectionAborted
484 | io::ErrorKind::ConnectionReset
485 )
486}