Skip to main content

net_io/driver/
mod.rs

1//! Drivers: what moves the bytes.
2//!
3//! The blocking pool ships in `0.3.0`, the reactor (epoll, kqueue, IOCP) in
4//! `0.5.0`, io_uring after `1.0.0`. The [`Driver`] trait is public from `0.5.0`
5//! (Tier 3, unstable until `1.0.0`) so an executor adapter and later drivers can
6//! build on it.
7//!
8//! The interface is completion-shaped (decision D-005): an operation owns its
9//! buffers until its completion hands them back, which is what IOCP and io_uring
10//! need; epoll and kqueue adapt by making the non-blocking call when readiness
11//! arrives. Cancellation always ends in exactly one completion.
12
13// Without the reactor only the vocabulary is left, for the public interface.
14#![cfg_attr(not(feature = "reactor"), allow(dead_code, unused_imports))]
15
16#[cfg(all(feature = "reactor", windows))]
17pub(crate) mod iocp;
18#[cfg(all(feature = "reactor", unix))]
19pub(crate) mod ready;
20
21use std::collections::VecDeque;
22use std::fs::File;
23use std::io::IoSlice;
24use std::net::SocketAddr;
25use std::sync::Arc;
26use std::time::Duration;
27
28use crate::buf::Buffer;
29use crate::error::{NetError, OsErrorClass};
30use crate::session::{Chunk, Output};
31
32/// Which driver moves the bytes.
33///
34/// `Auto` picks the reactor where it is built and available, otherwise the
35/// blocking pool.
36///
37/// # Examples
38///
39/// ```
40/// assert_eq!(net_io::DriverKind::default(), net_io::DriverKind::Auto);
41/// ```
42#[non_exhaustive]
43#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
44pub enum DriverKind {
45    /// A bounded pool of threads, one connection per thread.
46    Blocking,
47    /// One event loop per worker (epoll, kqueue, IOCP); from `0.5.0`.
48    Reactor,
49    /// io_uring on Linux; after `1.0.0`.
50    Uring,
51    /// The reactor where available, otherwise the blocking pool.
52    #[default]
53    Auto,
54}
55
56impl DriverKind {
57    /// The driver `Auto` resolves to in this build.
58    pub(crate) fn resolve(self) -> DriverKind {
59        match self {
60            DriverKind::Auto if DriverKind::reactor_built() && !cfg!(net_io_force_blocking) => {
61                DriverKind::Reactor
62            }
63            DriverKind::Auto => DriverKind::Blocking,
64            other => other,
65        }
66    }
67
68    /// Whether this build has a reactor for this OS.
69    pub(crate) const fn reactor_built() -> bool {
70        cfg!(feature = "reactor")
71    }
72}
73
74/// A borrowed socket, as a [`Driver`] registers it.
75#[cfg(unix)]
76pub type BorrowedSocket<'a> = std::os::fd::BorrowedFd<'a>;
77/// A borrowed socket, as a [`Driver`] registers it.
78#[cfg(windows)]
79pub type BorrowedSocket<'a> = std::os::windows::io::BorrowedSocket<'a>;
80
81/// Names a registered socket. The low 32 bits index a dense table inside the
82/// driver, so keep them small; the high bits are free for a generation.
83///
84/// ```
85/// let t = net_io::Token(7);
86/// assert_eq!(t, net_io::Token(7));
87/// ```
88#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
89pub struct Token(pub u64);
90
91impl Token {
92    pub(crate) fn index(self) -> usize {
93        (self.0 & 0xFFFF_FFFF) as usize
94    }
95}
96
97/// What to do on a registered socket. The operation owns its buffers until its
98/// completion returns them.
99#[non_exhaustive]
100#[derive(Debug)]
101pub enum Operation {
102    /// Completes when a connection is waiting (accept it from the listener).
103    /// Refused on Windows, where a listener is never registered (D-016).
104    Accept {
105        /// The listener.
106        listener: Token,
107    },
108    /// Receives into `buffer`'s spare room (at most once); `Ok(0)` is end of stream.
109    Receive {
110        /// The socket.
111        token: Token,
112        /// Where the bytes land; returned by the completion.
113        buffer: Buffer,
114    },
115    /// Completes when bytes can be read, without holding a buffer: idle
116    /// connections wait this way.
117    ReceiveZero {
118        /// The socket.
119        token: Token,
120    },
121    /// Sends what `chunks` holds; the result says how many bytes went out, which
122    /// can be fewer than all of them. The chunks come back with the completion.
123    Send {
124        /// The socket.
125        token: Token,
126        /// The bytes.
127        chunks: SendChunks,
128    },
129    /// Sends up to `len` bytes of `file` from `offset`, zero copy where the OS can. The
130    /// result says how many went out; `Ok(0)` means the file has nothing there.
131    SendFile {
132        /// The socket.
133        token: Token,
134        /// The file; held until the completion.
135        file: Arc<File>,
136        /// Where to start.
137        offset: u64,
138        /// The most to send.
139        len: u32,
140    },
141    /// Connects a registered, non-blocking socket.
142    Connect {
143        /// The socket.
144        token: Token,
145        /// The peer.
146        addr: SocketAddr,
147    },
148    /// Completes once every other operation on the socket has; the caller then
149    /// closes it. Abortive when asked (linger 0).
150    Close {
151        /// The socket.
152        token: Token,
153        /// Reset instead of FIN.
154        abortive: bool,
155    },
156    /// Completes at once (a turn of the loop).
157    Nop {
158        /// Echoed in the completion.
159        token: Token,
160    },
161}
162
163impl Operation {
164    fn token(&self) -> Token {
165        match self {
166            Operation::Accept { listener } => *listener,
167            Operation::Receive { token, .. }
168            | Operation::ReceiveZero { token }
169            | Operation::Send { token, .. }
170            | Operation::SendFile { token, .. }
171            | Operation::Connect { token, .. }
172            | Operation::Close { token, .. }
173            | Operation::Nop { token } => *token,
174        }
175    }
176}
177
178/// Which operation a completion finishes.
179///
180/// ```
181/// assert_ne!(net_io::OperationKind::Receive, net_io::OperationKind::Send);
182/// ```
183#[non_exhaustive]
184#[derive(Clone, Copy, Debug, PartialEq, Eq)]
185pub enum OperationKind {
186    /// [`Operation::Accept`].
187    Accept,
188    /// [`Operation::Receive`] and [`Operation::ReceiveZero`].
189    Receive,
190    /// [`Operation::Send`].
191    Send,
192    /// [`Operation::SendFile`].
193    SendFile,
194    /// [`Operation::Connect`].
195    Connect,
196    /// [`Operation::Close`].
197    Close,
198    /// [`Operation::Nop`].
199    Nop,
200}
201
202/// A finished operation.
203#[non_exhaustive]
204#[derive(Debug)]
205pub struct Completion {
206    /// The socket.
207    pub token: Token,
208    /// Which operation finished.
209    pub kind: OperationKind,
210    /// Bytes moved, or the error class. A cancelled operation is `Aborted`.
211    pub result: Result<usize, OsErrorClass>,
212    /// The receive buffer, returned with its new length.
213    pub buffer: Option<Buffer>,
214    /// The send chunks, returned as they were.
215    pub chunks: Option<SendChunks>,
216}
217
218impl Completion {
219    pub(crate) fn new(
220        token: Token,
221        kind: OperationKind,
222        result: Result<usize, OsErrorClass>,
223    ) -> Completion {
224        Completion {
225            token,
226            kind,
227            result,
228            buffer: None,
229            chunks: None,
230        }
231    }
232}
233
234/// How many completions one wait returns.
235pub(crate) const COMPLETIONS: usize = 256;
236
237/// What a wait fills; fixed capacity (256), so a wait never allocates.
238#[derive(Debug)]
239pub struct Completions {
240    items: Vec<Completion>,
241}
242
243impl Default for Completions {
244    fn default() -> Completions {
245        Completions::new()
246    }
247}
248
249impl Completions {
250    /// Room for 256 completions.
251    #[must_use]
252    pub fn new() -> Completions {
253        Completions {
254            items: Vec::with_capacity(COMPLETIONS),
255        }
256    }
257
258    /// How many completions are held.
259    #[must_use]
260    pub fn len(&self) -> usize {
261        self.items.len()
262    }
263
264    /// Whether none are held.
265    #[must_use]
266    pub fn is_empty(&self) -> bool {
267        self.items.is_empty()
268    }
269
270    /// Takes the completions out, oldest first.
271    pub fn drain(&mut self) -> impl Iterator<Item = Completion> + '_ {
272        self.items.drain(..)
273    }
274
275    #[cfg(feature = "reactor")]
276    pub(crate) fn push(&mut self, c: Completion) {
277        self.items.push(c);
278    }
279
280    #[cfg(feature = "reactor")]
281    pub(crate) fn has_room(&self) -> bool {
282        self.items.len() < COMPLETIONS
283    }
284}
285
286/// The bytes of one send: up to 64 chunks, taken from an [`Output`] or built from
287/// a pool buffer.
288#[derive(Debug, Default)]
289pub struct SendChunks {
290    pub(crate) chunks: VecDeque<Chunk>,
291}
292
293impl SendChunks {
294    /// One pool buffer.
295    #[must_use]
296    pub fn from_buffer(buffer: Buffer) -> SendChunks {
297        let mut chunks = VecDeque::with_capacity(1);
298        chunks.push_back(Chunk::Pooled(buffer, 0));
299        SendChunks { chunks }
300    }
301
302    /// Takes everything queued in `output`; give it back with [`SendChunks::restore`].
303    pub(crate) fn take(output: &mut Output) -> SendChunks {
304        SendChunks {
305            chunks: std::mem::take(&mut output.chunks),
306        }
307    }
308
309    /// Puts the chunks back into `output`, keeping the queue's allocation.
310    pub(crate) fn restore(self, output: &mut Output) {
311        output.chunks = self.chunks;
312    }
313
314    /// Bytes held.
315    #[must_use]
316    pub fn pending(&self) -> usize {
317        self.chunks.iter().map(Chunk::len).sum()
318    }
319
320    /// Marks `n` bytes of the front chunks sent; `true` when bytes remain.
321    #[cfg(feature = "reactor")]
322    pub(crate) fn advance(&mut self, mut n: usize) -> bool {
323        while let Some(front) = self.chunks.front_mut() {
324            let rem = front.len();
325            if n < rem {
326                front.advance(n);
327                return true;
328            }
329            if self.chunks.len() == 1 {
330                return false;
331            }
332            n -= rem;
333            self.chunks.pop_front();
334        }
335        false
336    }
337
338    /// The first buffer back, for a send built with [`SendChunks::from_buffer`].
339    pub(crate) fn into_buffer(mut self) -> Option<Buffer> {
340        match self.chunks.pop_front() {
341            Some(Chunk::Pooled(b, _)) => Some(b),
342            _ => None,
343        }
344    }
345
346    /// Fills `out` with the chunks' bytes; returns how many slices.
347    #[cfg(feature = "reactor")]
348    pub(crate) fn slices<'a>(&'a self, out: &mut [IoSlice<'a>]) -> usize {
349        let mut n = 0;
350        // A file goes by its own operation: the slices stop before it.
351        for chunk in self
352            .chunks
353            .iter()
354            .take(out.len())
355            .take_while(|c| !c.is_file())
356        {
357            out[n] = IoSlice::new(chunk.remaining());
358            n += 1;
359        }
360        n
361    }
362}
363
364/// Why [`Driver::submit`] refused an operation; it comes back with its buffers.
365#[derive(Debug)]
366pub struct Rejected {
367    /// The operation.
368    pub operation: Operation,
369}
370
371/// Wakes a driver's [`Driver::wait`] from any thread.
372#[derive(Clone, Debug)]
373pub struct DriverWaker {
374    pub(crate) inner: Arc<WakerInner>,
375}
376
377#[cfg(feature = "reactor")]
378pub(crate) type WakerInner = crate::sys::PollWaker;
379#[cfg(not(feature = "reactor"))]
380#[derive(Debug)]
381pub(crate) struct WakerInner;
382
383impl DriverWaker {
384    /// Ends the current or next wait. Cheap to call repeatedly.
385    pub fn wake(&self) {
386        #[cfg(feature = "reactor")]
387        self.inner.wake();
388    }
389}
390
391/// The reactor driver for this OS: epoll, kqueue, or an I/O completion port.
392/// `capacity` sizes its tables for that many sockets; they grow past it.
393///
394/// One per worker. A token's low 32 bits index a table the driver keeps, so keep
395/// them small and dense, and put a generation in the high 32 bits to catch a
396/// completion for a slot that moved on. On Windows a listener cannot be registered
397/// and `Operation::Accept` is refused (accept from a thread of your own, D-016).
398///
399/// ```
400/// # fn main() -> Result<(), net_io::NetError> {
401/// use std::time::Duration;
402/// use net_io::{Completions, Operation, Token};
403/// let mut driver = net_io::new_reactor_driver(16)?;
404/// driver.submit(Operation::Nop { token: Token(1) }).expect("a no-op is always taken");
405/// let mut done = Completions::new();
406/// assert_eq!(driver.wait(&mut done, Some(Duration::from_secs(1)))?, 1);
407/// # Ok(())
408/// # }
409/// ```
410///
411/// # Errors
412///
413/// `DriverSetup` when the OS refuses the queue.
414#[cfg(feature = "reactor")]
415pub fn new_reactor_driver(capacity: usize) -> Result<Box<dyn Driver>, NetError> {
416    #[cfg(unix)]
417    let driver = ready::ReadyDriver::new(capacity)?;
418    #[cfg(windows)]
419    let driver = iocp::IocpDriver::new(capacity)?;
420    Ok(Box::new(driver))
421}
422
423/// A driver: one per worker, used from one thread. See the module docs.
424///
425/// Unstable until `1.0.0`. A socket must stay open from [`Driver::register`] until
426/// [`Driver::deregister`] returns.
427pub trait Driver: Send {
428    /// Which driver this is.
429    fn kind(&self) -> DriverKind;
430
431    /// Adds a non-blocking socket under `token`.
432    ///
433    /// # Errors
434    ///
435    /// `Os` when the OS refuses.
436    fn register(&mut self, socket: BorrowedSocket<'_>, token: Token) -> Result<(), NetError>;
437
438    /// Starts an operation; its completion arrives through [`Driver::wait`].
439    ///
440    /// # Errors
441    ///
442    /// [`Rejected`] gives the operation and its buffers back: the token is not
443    /// registered, or the same kind of operation is already pending on it.
444    fn submit(&mut self, operation: Operation) -> Result<(), Rejected>;
445
446    /// Fills `out` with finished operations, waiting up to `timeout` for the
447    /// first (`None`: until one finishes or the waker fires). Returns how many.
448    ///
449    /// # Errors
450    ///
451    /// `Os` when the wait itself fails.
452    fn wait(&mut self, out: &mut Completions, timeout: Option<Duration>)
453    -> Result<usize, NetError>;
454
455    /// Cancels the pending operation of kind `which`; it still completes exactly
456    /// once (with `Aborted`, or with its result if it already finished).
457    ///
458    /// # Errors
459    ///
460    /// `Os` when the OS refuses.
461    fn cancel(&mut self, token: Token, which: OperationKind) -> Result<(), NetError>;
462
463    /// Removes the socket; no completion arrives for it afterwards.
464    ///
465    /// # Errors
466    ///
467    /// `Os` when the OS refuses.
468    fn deregister(&mut self, token: Token) -> Result<(), NetError>;
469
470    /// A waker for this driver.
471    fn waker(&self) -> DriverWaker;
472}
473
474pub(crate) fn operation_token(op: &Operation) -> Token {
475    op.token()
476}