dope_uring/sockets/reuse/
mod.rs1use std::{
2 mem,
3 os::fd::{AsRawFd as _, BorrowedFd},
4 ptr,
5};
6
7use dope_sys::io::socket::route::{
8 Attach, Plan, Source,
9 count::Index,
10 install::{Error, Operation},
11};
12
13use crate::Uring;
14
15mod program;
16
17pub struct Installer<'a> {
18 plan: Plan,
19 filter: &'a mut [libc::sock_filter],
20}
21
22impl Attach for Installer<'_> {
23 fn try_attach(&self, socket: BorrowedFd<'_>) -> Result<(), Error> {
24 let mut code = [program::EMPTY; program::MAX];
25 attach(
26 socket,
27 program::build(&mut code, self.plan, None),
28 Operation::ProgramAttach,
29 )
30 }
31
32 fn try_filter(&mut self, key: Index, socket: BorrowedFd<'_>) -> Result<(), Error> {
33 let index = self.filter.len() - 3;
34 self.filter[index].k = key.into_raw() as u32;
35 attach(socket, self.filter, Operation::FilterAttach)
36 }
37}
38
39impl Source for Uring {
40 type Storage = [libc::sock_filter; program::MAX];
41 type Install<'a> = Installer<'a>;
42 type Ready = ();
43 type Lease<'a> = BorrowedFd<'a>;
44
45 const STORAGE: Self::Storage = [program::EMPTY; program::MAX];
46
47 #[inline]
48 fn try_prepare(
49 filter: &mut Self::Storage,
50 plan: Plan,
51 ) -> Result<(Self::Install<'_>, Self::Ready), Plan> {
52 let installer = Installer {
53 plan,
54 filter: program::build(filter, plan, Some(Index::ZERO)),
55 };
56 Ok((installer, ()))
57 }
58
59 fn lease<'a>((): &(), socket: BorrowedFd<'a>) -> Self::Lease<'a> {
60 socket
61 }
62}
63
64fn attach(
65 socket: BorrowedFd<'_>,
66 code: &[libc::sock_filter],
67 operation: Operation,
68) -> Result<(), Error> {
69 let program = libc::sock_fprog {
70 len: code.len() as u16,
71 filter: code.as_ptr().cast_mut(),
72 };
73 let option = match operation {
74 Operation::ProgramAttach => libc::SO_ATTACH_REUSEPORT_CBPF,
75 Operation::FilterAttach => libc::SO_ATTACH_FILTER,
76 };
77 let result = unsafe {
79 libc::setsockopt(
80 socket.as_raw_fd(),
81 libc::SOL_SOCKET,
82 option,
83 ptr::from_ref(&program).cast(),
84 mem::size_of_val(&program) as libc::socklen_t,
85 )
86 };
87 unsafe { dope_sys::kernel::raw::Status::new(result).try_zero::<Uring, dope_sys::Errno>() }
89 .map_err(|errno| Error { operation, errno })
90}