1use std::future::Future;
2use std::io;
3use std::time::Duration;
4
5use crate::addr::SockAddr;
6use crate::submit::SendMsgPacket;
7use crate::{Fd, FixedFd};
8
9pub trait RecvMsgOutView {
10 fn parse_with<R>(
11 raw: &[u8],
12 msghdr: &libc::msghdr,
13 f: impl FnOnce(&[u8], &[u8]) -> R,
14 ) -> Option<R>;
15}
16
17pub trait DriverLifecycle {
18 fn drive(&mut self) -> io::Result<bool>;
19 fn has_pending(&mut self) -> bool;
20 fn park(&mut self) -> io::Result<()>;
21 fn park_for(&mut self, duration: Duration) -> io::Result<()>;
22 fn submit_only(&mut self) -> io::Result<()>;
23
24 #[inline]
25 fn arm_with_retry<F>(&mut self, mut op: F) -> bool
26 where
27 F: FnMut(&mut Self) -> bool,
28 {
29 if op(self) {
30 return true;
31 }
32 let _ = self.submit_only();
33 op(self)
34 }
35}
36
37pub trait FixedBuffers {
38 type Guard;
39 fn fixed_guard(&mut self) -> Option<Self::Guard>;
40 fn register_fixed(&mut self, fd: Fd) -> io::Result<Option<u32>>;
41 fn unregister_fixed(&mut self, idx: u32);
42}
43
44pub trait ProvidedBufRing {
45 type Provided: AsRef<[u8]> + 'static;
46 fn provided_group(&mut self) -> Option<(u16, u32)>;
47 fn provided(&mut self, bid: u16, len: usize) -> Option<Self::Provided>;
48}
49
50pub trait DriverConfig: Sized + Copy {
51 fn for_profile<P: crate::profile::Profile>() -> Self;
52
53 fn for_tcp_profile(ring_entries: u32, max_conn: usize, ingress_buf_cap: usize) -> Self;
54 fn for_quic_udp(provided_buf_entries: u32, provided_buf_len: u32) -> Self;
55
56 #[inline(always)]
57 fn with_defer_taskrun(self, _enable: bool) -> Self {
58 self
59 }
60
61 #[inline(always)]
62 fn with_cpu_id(self, _cpu: Option<u16>) -> Self {
63 self
64 }
65}
66
67pub trait Backend: Sized {
68 type Driver: DriverLifecycle + FixedBuffers + ProvidedBufRing + 'static;
69 type Config: DriverConfig;
70 type RecvMsgOut: RecvMsgOutView;
71 type ProvidedBuf;
72
73 fn new_driver(cfg: Self::Config) -> io::Result<Self::Driver>;
74}
75
76pub trait BackendToken: Copy + 'static {
77 fn parts(self) -> (usize, u32);
78 fn next_for_slot(index: usize, seq: &mut u32) -> Self;
79 fn from_index_raw(index: usize, epoch: u32) -> Self;
80}
81
82pub enum Completion<B: CompletionBackend> {
83 Accept {
84 token: B::Token,
85 result: i32,
86 more: bool,
87 },
88 Recv {
89 token: B::Token,
90 result: i32,
91 more: bool,
92 bid: Option<u16>,
93 },
94 Write {
95 token: B::Token,
96 result: i32,
97 notif: bool,
98 },
99}
100
101impl<B: CompletionBackend> Completion<B> {
102 #[inline(always)]
103 pub fn buffer_select(&self) -> Option<u16> {
104 match self {
105 Self::Recv { bid, .. } => *bid,
106 _ => None,
107 }
108 }
109}
110
111pub struct CurrentSlot<B: CompletionBackend> {
112 driver: std::ptr::NonNull<B::Driver>,
113 extra: *const (),
114}
115
116impl<B: CompletionBackend> Clone for CurrentSlot<B> {
117 fn clone(&self) -> Self {
118 *self
119 }
120}
121
122impl<B: CompletionBackend> Copy for CurrentSlot<B> {}
123
124impl<B: CompletionBackend> CurrentSlot<B> {
125 #[inline(always)]
126 pub fn new(driver: std::ptr::NonNull<B::Driver>, extra: *const ()) -> Self {
127 Self { driver, extra }
128 }
129
130 #[inline(always)]
131 pub fn driver(self) -> std::ptr::NonNull<B::Driver> {
132 self.driver
133 }
134
135 #[inline(always)]
136 pub fn extra(self) -> *const () {
137 self.extra
138 }
139}
140
141pub struct ExternalDispatch<B: CompletionBackend> {
142 pub state: *mut (),
143 pub route: unsafe fn(*mut (), &mut B::Driver, Completion<B>),
144 pub pump: unsafe fn(*mut (), &mut B::Driver),
145}
146
147impl<B: CompletionBackend> Clone for ExternalDispatch<B> {
148 fn clone(&self) -> Self {
149 *self
150 }
151}
152
153impl<B: CompletionBackend> Copy for ExternalDispatch<B> {}
154
155pub trait CompletionBackend: Backend {
156 type Token: BackendToken;
157
158 fn current_slot() -> Option<CurrentSlot<Self>>;
159 fn set_slot(slot: Option<CurrentSlot<Self>>);
160
161 #[inline(always)]
162 fn current_driver_mut() -> *mut Self::Driver {
163 match Self::current_slot() {
164 Some(slot) => slot.driver().as_ptr(),
165 None => std::ptr::null_mut(),
166 }
167 }
168
169 #[inline(always)]
170 fn set_current(driver: *mut Self::Driver) {
171 let slot = std::ptr::NonNull::new(driver).map(|d| CurrentSlot::new(d, std::ptr::null()));
172 Self::set_slot(slot);
173 }
174
175 #[inline(always)]
176 fn clear_current() {
177 Self::set_slot(None);
178 }
179
180 fn install_external(aux: Option<ExternalDispatch<Self>>) -> Option<ExternalDispatch<Self>>;
181 fn current_external() -> Option<ExternalDispatch<Self>>;
182
183 fn drive_with<R: CompletionRouter<Self>>(
184 driver: &mut Self::Driver,
185 router: &mut R,
186 ) -> io::Result<bool>;
187
188 fn dispatch_completions<R: CompletionRouter<Self>>(driver: &mut Self::Driver, router: &mut R);
189}
190
191pub trait CompletionRouter<B: CompletionBackend> {
192 fn on_complete(&mut self, driver: &mut B::Driver, ev: Completion<B>);
193}
194
195pub trait ProvidedRingOps {
196 fn defer(&mut self, bid: u16);
197 fn ptr_len(&self, bid: u16) -> (*mut u8, usize);
198}
199
200pub trait DriverOps: 'static {
201 type Token: BackendToken;
202 type ProvidedRing: ProvidedRingOps + 'static;
203 type IoRequest<O: Unpin + 'static>: Future<Output = (io::Result<u32>, u32, O)> + Unpin + 'static;
204
205 fn buf_group(&self) -> u16;
206 fn provided_ring(&mut self) -> &mut Self::ProvidedRing;
207
208 fn arm_accept_multi(&mut self, token: Self::Token, fd: Fd) -> bool;
209 fn arm_recv_multi(&mut self, token: Self::Token, fd: FixedFd, buf_group: u16) -> bool;
210
211 unsafe fn arm_recv_msg_multi(
214 &mut self,
215 token: Self::Token,
216 fd: FixedFd,
217 buf_group: u16,
218 msghdr: *const libc::msghdr,
219 ) -> bool;
220
221 fn submit_send_tagged(
222 &mut self,
223 token: Self::Token,
224 fd: FixedFd,
225 ptr: *const u8,
226 len: u32,
227 ) -> bool;
228
229 unsafe fn submit_send_msg_tagged(
232 &mut self,
233 token: Self::Token,
234 fd: FixedFd,
235 msg: *const libc::msghdr,
236 ) -> bool;
237
238 fn cancel_recv(&mut self, token: Self::Token);
239
240 fn try_submit_connect_raw(
241 &mut self,
242 fd: Fd,
243 addr: SockAddr,
244 ) -> Result<Self::IoRequest<SockAddr>, (io::Error, SockAddr)>;
245
246 fn try_submit_sendmsg_raw<P: SendMsgPacket + Unpin + 'static>(
247 &mut self,
248 fd: Fd,
249 packet: P,
250 ) -> Result<Self::IoRequest<P>, (io::Error, P)>;
251
252 fn try_submit_send_raw<B: AsRef<[u8]> + Unpin + 'static>(
253 &mut self,
254 fd: Fd,
255 buf: B,
256 ) -> Result<Self::IoRequest<B>, (io::Error, B)>;
257}
258
259pub trait PoolDriver:
260 CompletionBackend<Driver: DriverOps<Token = <Self as CompletionBackend>::Token>> + 'static
261{
262}
263
264impl<B> PoolDriver for B
265where
266 B: CompletionBackend + 'static,
267 B::Driver: DriverOps<Token = B::Token>,
268{
269}
270
271pub type IoRequest<B, O> = <<B as Backend>::Driver as DriverOps>::IoRequest<O>;
272pub type ProvidedRing<B> = <<B as Backend>::Driver as DriverOps>::ProvidedRing;