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