1use std::os::fd::{AsRawFd, BorrowedFd, RawFd};
2use std::{cell::Cell, cell::UnsafeCell, fmt, io, net, rc::Rc};
3use std::{collections::VecDeque, num::NonZeroUsize, time::Duration};
4
5#[cfg(unix)]
6use std::os::unix::net::UnixStream as OsUnixStream;
7
8use ::ntex_polling::{Event, Events, Notifier, PollMode, Poller};
9use ntex_io::Io;
10use ntex_rt::{DriverType, Notify, PollResult, Runtime};
11use ntex_service::cfg::SharedCfg;
12use socket2::{Protocol, SockAddr, Socket, Type};
13
14use super::{TcpStream, UnixStream, stream::StreamOps};
15use crate::channel::Receiver;
16
17pub trait Handler {
18 fn event(&mut self, id: usize, event: Event);
20
21 fn error(&mut self, id: usize, err: io::Error);
23
24 fn tick(&mut self);
28
29 fn cleanup(&mut self);
31}
32
33type HandlerItem = Box<dyn Handler>;
34
35enum Change {
36 Error {
37 batch: usize,
38 user_data: u32,
39 error: io::Error,
40 },
41}
42
43#[derive(Debug)]
44pub struct ReactorApi {
46 id: usize,
47 batch: u64,
48 poll: Rc<Poller>,
49 changes: Rc<UnsafeCell<VecDeque<Change>>>,
50}
51
52impl ReactorApi {
53 pub fn attach(&self, fd: RawFd, id: u32, event: Event) {
58 self.attach_with_mode(fd, id, event, PollMode::Oneshot);
59 }
60
61 pub fn attach_with_mode(&self, fd: RawFd, id: u32, mut event: Event, mode: PollMode) {
66 event.key = (u64::from(id) | self.batch) as usize;
67 if let Err(err) = unsafe { self.poll.add_with_mode(fd, event, mode) } {
68 self.change(Change::Error {
69 batch: self.id,
70 user_data: id,
71 error: err,
72 });
73 }
74 }
75
76 pub fn detach(&self, fd: RawFd, id: u32) {
78 if let Err(err) = self.poll.delete(unsafe { BorrowedFd::borrow_raw(fd) }) {
79 self.change(Change::Error {
80 batch: self.id,
81 user_data: id,
82 error: err,
83 });
84 }
85 }
86
87 pub fn modify(&self, fd: RawFd, id: u32, event: Event) {
89 self.modify_with_mode(fd, id, event, PollMode::Oneshot);
90 }
91
92 pub fn modify_with_mode(&self, fd: RawFd, id: u32, mut event: Event, mode: PollMode) {
94 event.key = (u64::from(id) | self.batch) as usize;
95
96 let result = self
97 .poll
98 .modify_with_mode(unsafe { BorrowedFd::borrow_raw(fd) }, event, mode);
99 self.check(id, result);
100 }
101
102 pub fn modify_with_mode_deferred(&self, fd: RawFd, id: u32, mut event: Event, mode: PollMode) {
109 event.key = (u64::from(id) | self.batch) as usize;
110
111 let result =
112 self.poll
113 .modify_with_mode_deferred(unsafe { BorrowedFd::borrow_raw(fd) }, event, mode);
114 self.check(id, result);
115 }
116
117 pub fn supports_level(&self) -> bool {
119 self.poll.supports_level()
120 }
121
122 fn check(&self, id: u32, result: io::Result<()>) {
123 if let Err(err) = result {
124 self.change(Change::Error {
125 batch: self.id,
126 user_data: id,
127 error: err,
128 });
129 }
130 }
131
132 fn change(&self, ev: Change) {
133 unsafe { (*self.changes.get()).push_back(ev) };
134 }
135}
136
137pub struct Reactor {
141 poll: Rc<Poller>,
142 capacity: usize,
143 changes: Rc<UnsafeCell<VecDeque<Change>>>,
144 hid: Cell<u64>,
145 #[allow(clippy::box_collection)]
146 handlers: Cell<Option<Box<Vec<HandlerItem>>>>,
147}
148
149impl Reactor {
150 const BATCH: u64 = 48;
151 const BATCH_MASK: u64 = 0xFFFF_0000_0000_0000;
152 const DATA_MASK: u64 = 0x0000_FFFF_FFFF_FFFF;
153
154 pub fn new() -> io::Result<Self> {
155 Reactor::with_capacity(2048)
156 }
157
158 pub fn with_capacity(io_queue_capacity: u32) -> io::Result<Self> {
159 log::trace!("New poll driver");
160
161 Ok(Self {
162 hid: Cell::new(0),
163 poll: Rc::new(Poller::new()?),
164 capacity: io_queue_capacity as usize,
165 changes: Rc::new(UnsafeCell::new(VecDeque::with_capacity(32))),
166 handlers: Cell::new(Some(Box::new(Vec::default()))),
167 })
168 }
169
170 pub const fn tp(&self) -> DriverType {
172 DriverType::Poll
173 }
174
175 pub fn register<F>(&self, f: F)
177 where
178 F: FnOnce(ReactorApi) -> Box<dyn Handler>,
179 {
180 let id = self.hid.get();
181 let mut handlers = self
182 .handlers
183 .take()
184 .expect("Cannot register handler during event handling");
185
186 let api = ReactorApi {
187 id: id as usize,
188 batch: id << Self::BATCH,
189 poll: self.poll.clone(),
190 changes: self.changes.clone(),
191 };
192 handlers.push(f(api));
193 self.hid.set(id + 1);
194 self.handlers.set(Some(handlers));
195 }
196
197 fn apply_changes(&self, handlers: &mut [HandlerItem]) {
198 while let Some(op) = unsafe { (*self.changes.get()).pop_front() } {
199 match op {
200 Change::Error {
201 batch,
202 user_data,
203 error,
204 } => handlers[batch].error(user_data as usize, error),
205 }
206 }
207 }
208
209 fn tick(&self, handlers: &mut [HandlerItem]) {
210 loop {
211 self.apply_changes(handlers);
212 for h in handlers.iter_mut() {
213 h.tick();
214 }
215 if unsafe { (*self.changes.get()).is_empty() } {
218 break;
219 }
220 }
221 }
222}
223
224impl AsRawFd for Reactor {
225 fn as_raw_fd(&self) -> RawFd {
226 self.poll.as_raw_fd()
227 }
228}
229
230impl fmt::Debug for Reactor {
231 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
232 f.debug_struct("Reactor")
233 .field("poll", &self.poll)
234 .field("capacity", &self.capacity)
235 .field("hid", &self.hid)
236 .finish()
237 }
238}
239
240impl crate::Reactor for Reactor {
241 fn tcp_connect(&self, addr: net::SocketAddr, cfg: SharedCfg) -> Receiver<Io> {
242 let addr = SockAddr::from(addr);
243 let result = Socket::new(addr.domain(), Type::STREAM, Some(Protocol::TCP))
244 .and_then(crate::helpers::prep_tcp_socket)
245 .and_then(crate::helpers::prep_socket)
246 .map(move |sock| (addr, sock));
247
248 match result {
249 Err(err) => Receiver::new(Err(err)),
250 Ok((addr, sock)) => {
251 super::connect::ConnectOps::get(self).connect(sock, &addr, cfg, false)
252 }
253 }
254 }
255
256 fn unix_connect(&self, addr: std::path::PathBuf, cfg: SharedCfg) -> Receiver<Io> {
257 let result = SockAddr::unix(addr).and_then(|addr| {
258 Socket::new(addr.domain(), Type::STREAM, None)
259 .and_then(crate::helpers::prep_socket)
260 .map(move |sock| (addr, sock))
261 });
262
263 match result {
264 Err(err) => Receiver::new(Err(err)),
265 Ok((addr, sock)) => {
266 super::connect::ConnectOps::get(self).connect(sock, &addr, cfg, true)
267 }
268 }
269 }
270
271 fn from_tcp_stream(&self, stream: net::TcpStream, cfg: SharedCfg) -> io::Result<Io> {
272 stream.set_nodelay(true)?;
273
274 Ok(Io::new(
275 TcpStream(
276 crate::helpers::prep_socket(Socket::from(stream))?,
277 StreamOps::get(self),
278 ),
279 cfg,
280 ))
281 }
282
283 #[cfg(unix)]
284 fn from_unix_stream(&self, stream: OsUnixStream, cfg: SharedCfg) -> io::Result<Io> {
285 Ok(Io::new(
286 UnixStream(
287 crate::helpers::prep_socket(Socket::from(stream))?,
288 StreamOps::get(self),
289 ),
290 cfg,
291 ))
292 }
293}
294
295impl ntex_rt::Driver for Reactor {
296 fn run(&self, rt: &Runtime) -> io::Result<()> {
298 let mut events = if self.capacity == 0 {
299 Events::new()
300 } else {
301 Events::with_capacity(NonZeroUsize::new(self.capacity).unwrap())
302 };
303
304 let result = loop {
305 let timeout = match rt.poll() {
306 PollResult::Pending => None,
307 PollResult::PollAgain => Some(Duration::ZERO),
308 PollResult::Ready => break Ok(()),
309 };
310 let mut handlers = self.handlers.take().unwrap();
312 self.tick(&mut handlers);
313 self.handlers.set(Some(handlers));
314
315 events.clear();
316 self.poll.wait(&mut events, timeout)?;
317 rt.awake();
319
320 let mut handlers = self.handlers.take().unwrap();
321 for event in events.iter() {
322 let key = event.key as u64;
323 let batch = ((key & Self::BATCH_MASK) >> Self::BATCH) as usize;
324 handlers[batch].event((key & Self::DATA_MASK) as usize, event);
325 }
326 self.tick(&mut handlers);
327 self.handlers.set(Some(handlers));
328 };
329
330 for mut h in self.handlers.take().unwrap().into_iter() {
331 h.cleanup();
332 }
333 result
334 }
335
336 fn handle(&self) -> Box<dyn Notify> {
338 Box::new(NotifyHandle::new(self.poll.notifier()))
339 }
340
341 fn clear(&self) {}
343}
344
345#[derive(Clone, Debug)]
346pub(crate) struct NotifyHandle {
348 notifier: Notifier,
349}
350
351impl NotifyHandle {
352 fn new(notifier: Notifier) -> Self {
353 Self { notifier }
354 }
355}
356
357impl Notify for NotifyHandle {
358 fn notify(&self) -> io::Result<()> {
360 self.notifier.notify()
361 }
362}
363
364#[cfg(test)]
365mod tests {
366 use std::cell::RefCell;
367
368 use super::*;
369
370 struct Recorder(Rc<RefCell<Vec<(usize, io::ErrorKind)>>>);
371
372 impl Handler for Recorder {
373 fn event(&mut self, _: usize, _: Event) {}
374
375 fn error(&mut self, id: usize, err: io::Error) {
376 self.0.borrow_mut().push((id, err.kind()));
377 }
378
379 fn tick(&mut self) {}
380
381 fn cleanup(&mut self) {}
382 }
383
384 #[test]
385 fn reactor_info() {
386 let reactor = Reactor::with_capacity(0).unwrap();
387 assert_eq!(reactor.tp(), DriverType::Poll);
388 assert!(reactor.as_raw_fd() >= 0);
389 let s = format!("{reactor:?}");
390 assert!(s.contains("Reactor") && s.contains("capacity"), "{s}");
391 }
392
393 #[test]
395 fn api_errors_are_reported() {
396 let reactor = Reactor::new().unwrap();
397 let errors = Rc::new(RefCell::new(Vec::new()));
398 let mut api = None;
399 reactor.register(|a| {
400 api = Some(a);
401 Box::new(Recorder(errors.clone()))
402 });
403 let api = api.unwrap();
404
405 let (sock, _peer) = OsUnixStream::pair().unwrap();
407 api.modify(sock.as_raw_fd(), 1, Event::readable(0));
408 api.detach(sock.as_raw_fd(), 2);
409 assert!(errors.borrow().is_empty());
410
411 let mut handlers = reactor.handlers.take().unwrap();
412 reactor.apply_changes(&mut handlers);
413 reactor.handlers.set(Some(handlers));
414
415 let ids: Vec<_> = errors.borrow().iter().map(|(id, _)| *id).collect();
416 assert_eq!(ids, vec![1, 2]);
417 }
418
419 #[test]
420 fn tick_drains_errors_and_their_deferred_work() {
421 struct TickErrors {
422 api: ReactorApi,
423 socket: OsUnixStream,
424 next: Option<u32>,
425 errors: Rc<RefCell<Vec<usize>>>,
426 }
427
428 impl Handler for TickErrors {
429 fn event(&mut self, _: usize, _: Event) {
430 panic!("unexpected socket event");
431 }
432
433 fn error(&mut self, id: usize, _: io::Error) {
434 self.errors.borrow_mut().push(id);
435 if id == 1 {
436 self.next = Some(2);
437 }
438 }
439
440 fn tick(&mut self) {
441 if let Some(id) = self.next.take() {
442 self.api
444 .modify(self.socket.as_raw_fd(), id, Event::readable(0));
445 }
446 }
447
448 fn cleanup(&mut self) {}
449 }
450
451 let reactor = Reactor::new().unwrap();
452 let (socket, _peer) = OsUnixStream::pair().unwrap();
453 let errors = Rc::new(RefCell::new(Vec::new()));
454 reactor.register(|api| {
455 Box::new(TickErrors {
456 api,
457 socket,
458 next: Some(1),
459 errors: errors.clone(),
460 })
461 });
462
463 let mut handlers = reactor.handlers.take().unwrap();
464 reactor.tick(&mut handlers);
465 reactor.handlers.set(Some(handlers));
466
467 assert_eq!(*errors.borrow(), vec![1, 2]);
468 assert!(unsafe { (*reactor.changes.get()).is_empty() });
469 }
470}