Skip to main content

compio_driver/sys/op/socket/
unix.rs

1use std::{net::Shutdown, num::NonZeroU32};
2
3use compio_buf::{IoBufExt, IoBufMutExt};
4use rustix::{
5    io::close,
6    net::{
7        AddressFamily, Protocol, RecvAncillaryBuffer, SendAncillaryBuffer, SocketAddrAny,
8        SocketType, acceptfrom_with, bind, connect, listen, recv, recvfrom, recvmsg, send, sendmsg,
9        sendmsg_addr, sendto, shutdown, socket_with,
10    },
11};
12
13use crate::sys::op::*;
14
15impl<S: AsFd> Accept<S> {
16    pub(crate) fn call(&mut self) -> io::Result<usize> {
17        let (owned, addr) = acceptfrom_with(self.fd.as_fd(), SOCKET_FLAG)?;
18        let fd = owned.as_raw_fd();
19        let socket: Socket2 = owned.into();
20
21        if cfg!(apple) {
22            socket.set_cloexec(true)?;
23            socket.set_nonblocking(true)?;
24        }
25
26        copy_addr_from(&mut self.buffer, &mut self.addr_len, addr);
27        self.accepted_fd = Some(socket);
28
29        Ok(fd as usize)
30    }
31}
32
33impl<S: AsFd> Connect<S> {
34    pub(crate) fn call(&self) -> io::Result<usize> {
35        connect(&self.fd, &SockAddrArg(&self.addr))?;
36        Ok(0)
37    }
38}
39
40impl<T: IoBuf, S: AsFd> Send<T, S> {
41    pub(crate) fn call(&mut self) -> io::Result<usize> {
42        send(self.fd.as_fd(), self.buffer.as_init(), self.flags).map_err(Into::into)
43    }
44}
45
46impl<T: IoBuf, S: AsFd> SendTo<T, S> {
47    pub(crate) fn call(&self) -> io::Result<usize> {
48        sendto(
49            self.header.fd.as_fd(),
50            self.buffer.as_init(),
51            self.header.flags,
52            &SockAddrArg(&self.header.addr),
53        )
54        .map_err(Into::into)
55    }
56}
57
58impl<T: IoVectoredBuf, S: AsFd> SendVectored<T, S> {
59    pub(crate) fn call(&self, control: &mut SendVectoredControl) -> io::Result<usize> {
60        let mut anc = SendAncillaryBuffer::default();
61
62        sendmsg(
63            self.fd.as_fd(),
64            io_slice(&control.slices),
65            &mut anc,
66            self.flags,
67        )
68        .map_err(Into::into)
69    }
70}
71
72impl<T: IoVectoredBuf, S: AsFd> SendToVectored<T, S> {
73    pub(crate) fn call(&mut self, control: &mut SendMsgControl) -> io::Result<usize> {
74        let addr = SockAddrArg(&self.header.addr);
75        let mut anc = SendAncillaryBuffer::default();
76        let buf = io_slice(&control.slices);
77
78        sendmsg_addr(
79            self.header.fd.as_fd(),
80            &addr,
81            buf,
82            &mut anc,
83            self.header.flags,
84        )
85        .map_err(Into::into)
86    }
87}
88
89impl<T: IoVectoredBuf, C: IoBuf, S: AsFd> SendMsg<T, C, S> {
90    pub(crate) fn call(&mut self, control: &mut SendMsgControl) -> io::Result<usize> {
91        // Both rustix and nix expose api that uses structured AncillaryBuffer
92        // building, no way to just throw in an ancillary buf. Fallback to libc
93        // here.
94        syscall!(libc::sendmsg(
95            self.fd.as_fd().as_raw_fd(),
96            &control.msg,
97            self.flags.bits() as _,
98        ))
99    }
100}
101
102impl<T: IoBufMut, S: AsFd> Recv<T, S> {
103    pub(crate) fn call(&mut self) -> io::Result<usize> {
104        // SAFETY: The kernel only writes initialized bytes.
105        let (_, len) = recv(
106            self.fd.as_fd(),
107            unsafe { self.buffer.as_uninit() },
108            self.flags,
109        )?;
110
111        Ok(len)
112    }
113}
114
115impl<T: IoVectoredBufMut, S: AsFd> RecvVectored<T, S> {
116    pub(crate) fn call(&mut self, control: &mut RecvVectoredControl) -> io::Result<usize> {
117        let res = recvmsg(
118            self.fd.as_fd(),
119            io_slice_mut(&mut control.slices),
120            &mut RecvAncillaryBuffer::default(),
121            self.flags,
122        )?;
123
124        // Kernel may truncate and return a larger-than-buffer size
125        Ok(res.bytes.min(self.buffer.total_capacity()))
126    }
127}
128
129impl<S: AsFd> RecvFromHeader<S> {
130    pub fn set_addr(&mut self, addr: Option<SocketAddrAny>) {
131        copy_addr_from(&mut self.addr, &mut self.addr_len, addr)
132    }
133}
134
135impl<T: IoBufMut, S: AsFd> RecvFrom<T, S> {
136    pub(crate) fn call(&mut self) -> io::Result<usize> {
137        // SAFETY: The kernel only writes initialized bytes.
138        let (_, len, addr) = recvfrom(
139            &self.header.fd,
140            unsafe { self.buffer.as_uninit() },
141            self.header.flags,
142        )?;
143
144        self.header.set_addr(addr);
145
146        Ok(len.min(self.buffer.buf_capacity()))
147    }
148}
149
150impl<T: IoVectoredBufMut, C: IoBufMut, S: AsFd> RecvMsg<T, C, S> {
151    pub(crate) fn call(&mut self, control: &mut RecvMsgControl) -> io::Result<usize> {
152        let res = syscall!(libc::recvmsg(
153            self.header.fd.as_fd().as_raw_fd(),
154            &raw mut control.msg,
155            self.header.flags.bits() as _,
156        ))?;
157
158        self.update_control(control);
159
160        Ok(res)
161    }
162}
163
164impl<T: IoVectoredBufMut, S: AsFd> RecvFromVectored<T, S> {
165    pub(crate) fn call(&mut self, control: &mut RecvMsgControl) -> io::Result<usize> {
166        let res = recvmsg(
167            &self.header.fd,
168            io_slice_mut(&mut control.slices),
169            &mut RecvAncillaryBuffer::default(),
170            self.header.flags,
171        )?;
172
173        self.header.set_addr(res.address);
174
175        Ok(res.bytes)
176    }
177}
178
179/// Create a socket.
180pub struct CreateSocket {
181    pub(crate) domain: AddressFamily,
182    pub(crate) socket_type: SocketType,
183    pub(crate) protocol: Option<Protocol>,
184    pub(crate) opened_fd: Option<Socket2>,
185}
186
187impl CreateSocket {
188    /// Create [`CreateSocket`].
189    pub fn new(domain: i32, socket_type: i32, protocol: i32) -> Self {
190        let domain = AddressFamily::from_raw(domain as _);
191        let socket_type = SocketType::from_raw(socket_type as _);
192        let protocol = NonZeroU32::new(protocol as _).map(Protocol::from_raw);
193
194        Self {
195            domain,
196            socket_type,
197            protocol,
198            opened_fd: None,
199        }
200    }
201
202    pub(crate) fn call(&mut self) -> io::Result<usize> {
203        let owned = socket_with(self.domain, self.socket_type, SOCKET_FLAG, self.protocol)?;
204        let fd = owned.as_raw_fd();
205        let socket: Socket2 = owned.into();
206
207        #[cfg(apple)]
208        {
209            socket.set_cloexec(true)?;
210            socket.set_nosigpipe(true)?;
211            socket.set_nonblocking(true)?;
212        }
213
214        self.opened_fd = Some(socket);
215        Ok(fd as _)
216    }
217}
218
219impl IntoInner for CreateSocket {
220    type Inner = Socket2;
221
222    fn into_inner(self) -> Self::Inner {
223        self.opened_fd.expect("socket not created")
224    }
225}
226
227/// Bind a socket to an address.
228pub struct Bind<S> {
229    pub(crate) fd: S,
230    pub(crate) addr: SockAddr,
231}
232
233impl<S> Bind<S> {
234    /// Create [`Bind`].
235    pub fn new(fd: S, addr: SockAddr) -> Self {
236        Self { fd, addr }
237    }
238}
239
240impl<S: AsFd> Bind<S> {
241    pub(crate) fn call(&self) -> io::Result<usize> {
242        bind(self.fd.as_fd(), &SockAddrArg(&self.addr))?;
243        Ok(0)
244    }
245}
246
247/// Listen for connections on a socket.
248pub struct Listen<S> {
249    pub(crate) fd: S,
250    pub(crate) backlog: i32,
251}
252
253impl<S> Listen<S> {
254    /// Create [`Listen`].
255    pub fn new(fd: S, backlog: i32) -> Self {
256        Self { fd, backlog }
257    }
258}
259
260impl<S: AsFd> Listen<S> {
261    pub(crate) fn call(&self) -> io::Result<usize> {
262        listen(self.fd.as_fd(), self.backlog)?;
263        Ok(0)
264    }
265}
266
267/// Shutdown a socket.
268pub struct ShutdownSocket<S> {
269    pub(crate) fd: S,
270    pub(crate) how: Shutdown,
271}
272
273impl<S> ShutdownSocket<S> {
274    /// Create [`ShutdownSocket`].
275    pub fn new(fd: S, how: Shutdown) -> Self {
276        Self { fd, how }
277    }
278}
279
280impl<S: AsFd> ShutdownSocket<S> {
281    #[cfg(io_uring)]
282    pub(crate) fn how(&self) -> i32 {
283        match self.how {
284            Shutdown::Write => libc::SHUT_WR,
285            Shutdown::Read => libc::SHUT_RD,
286            Shutdown::Both => libc::SHUT_RDWR,
287        }
288    }
289
290    pub(crate) fn call(&mut self) -> io::Result<usize> {
291        let how = match self.how {
292            Shutdown::Write => rustix::net::Shutdown::Write,
293            Shutdown::Read => rustix::net::Shutdown::Read,
294            Shutdown::Both => rustix::net::Shutdown::Both,
295        };
296        shutdown(&self.fd, how)?;
297        Ok(0)
298    }
299}
300
301impl CloseSocket {
302    pub(crate) fn call(&mut self) -> io::Result<usize> {
303        unsafe { close(self.fd.as_raw_fd()) };
304        Ok(0)
305    }
306}
307
308/// Accept a connection.
309pub struct Accept<S> {
310    pub(crate) fd: S,
311    pub(crate) buffer: SockAddrStorage,
312    pub(crate) addr_len: socklen_t,
313    pub(crate) accepted_fd: Option<Socket2>,
314}
315
316impl<S> Accept<S> {
317    /// Create [`Accept`].
318    pub fn new(fd: S) -> Self {
319        let buffer = SockAddrStorage::zeroed();
320        let addr_len = buffer.size_of();
321        Self {
322            fd,
323            buffer,
324            addr_len,
325            accepted_fd: None,
326        }
327    }
328}
329
330impl<S> IntoInner for Accept<S> {
331    type Inner = (Socket2, SockAddr);
332
333    fn into_inner(mut self) -> Self::Inner {
334        let socket = self.accepted_fd.take().expect("socket not accepted");
335        (socket, unsafe { SockAddr::new(self.buffer, self.addr_len) })
336    }
337}
338
339#[doc(hidden)]
340pub struct RecvVectoredControl {
341    pub(crate) msg: libc::msghdr,
342    #[allow(dead_code)]
343    pub(crate) slices: Vec<SysSlice>,
344}
345
346impl Default for RecvVectoredControl {
347    fn default() -> Self {
348        Self {
349            msg: unsafe { std::mem::zeroed() },
350            slices: Vec::new(),
351        }
352    }
353}
354
355impl<T: IoVectoredBufMut, S> RecvVectored<T, S> {
356    pub(crate) fn init_control(&mut self, ctrl: &mut RecvVectoredControl) {
357        ctrl.slices = self.buffer.sys_slices_mut();
358        ctrl.msg.msg_iov = ctrl.slices.as_mut_ptr() as _;
359        ctrl.msg.msg_iovlen = ctrl.slices.len() as _;
360    }
361}
362
363#[doc(hidden)]
364pub struct SendVectoredControl {
365    pub(crate) msg: libc::msghdr,
366    #[allow(dead_code)]
367    pub(crate) slices: Vec<SysSlice>,
368}
369
370impl Default for SendVectoredControl {
371    fn default() -> Self {
372        Self {
373            msg: unsafe { std::mem::zeroed() },
374            slices: Vec::new(),
375        }
376    }
377}
378
379impl<T: IoVectoredBuf, S> SendVectored<T, S> {
380    pub(crate) fn init_control(&mut self, ctrl: &mut SendVectoredControl) {
381        ctrl.slices = self.buffer.sys_slices();
382        ctrl.msg.msg_iov = ctrl.slices.as_ptr() as _;
383        ctrl.msg.msg_iovlen = ctrl.slices.len() as _;
384    }
385}
386
387#[doc(hidden)]
388pub struct SendMsgControl {
389    pub(crate) msg: libc::msghdr,
390    #[allow(dead_code)]
391    pub(crate) slices: Multi<SysSlice>,
392}
393
394impl<S: AsFd> SendToHeader<S> {
395    #[allow(dead_code)]
396    pub(crate) fn create_control(
397        &mut self,
398        ctrl: &mut SendMsgControl,
399        slices: impl Into<Multi<SysSlice>>,
400    ) {
401        ctrl.msg.msg_name = self.addr.as_ptr() as _;
402        ctrl.msg.msg_namelen = self.addr.len();
403        ctrl.slices = slices.into();
404        ctrl.msg.msg_iov = ctrl.slices.as_mut_ptr() as _;
405        ctrl.msg.msg_iovlen = ctrl.slices.len() as _;
406    }
407}
408
409impl Default for SendMsgControl {
410    fn default() -> Self {
411        Self {
412            msg: unsafe { std::mem::zeroed() },
413            slices: Multi::new(),
414        }
415    }
416}
417
418impl<T: IoVectoredBuf, C: IoBuf, S> SendMsg<T, C, S> {
419    pub(crate) fn init_control(&mut self, ctrl: &mut SendMsgControl) {
420        ctrl.slices = self.buffer.sys_slices();
421        match self.addr.as_ref() {
422            Some(addr) => {
423                ctrl.msg.msg_name = addr.as_ptr() as _;
424                ctrl.msg.msg_namelen = addr.len();
425            }
426            None => {
427                ctrl.msg.msg_name = std::ptr::null_mut();
428                ctrl.msg.msg_namelen = 0;
429            }
430        }
431        ctrl.msg.msg_iov = ctrl.slices.as_ptr() as _;
432        ctrl.msg.msg_iovlen = ctrl.slices.len() as _;
433        ctrl.msg.msg_control = self.control.buf_ptr() as _;
434        ctrl.msg.msg_controllen = self.control.buf_len() as _;
435    }
436}
437
438#[doc(hidden)]
439pub struct RecvMsgControl {
440    pub(crate) msg: libc::msghdr,
441    #[allow(dead_code)]
442    pub(crate) slices: Multi<SysSlice>,
443}
444
445impl Default for RecvMsgControl {
446    fn default() -> Self {
447        Self {
448            msg: unsafe { std::mem::zeroed() },
449            slices: Multi::new(),
450        }
451    }
452}
453
454impl<T: IoVectoredBufMut, C: IoBufMut, S> RecvMsg<T, C, S> {
455    pub(crate) fn init_control(&mut self, ctrl: &mut RecvMsgControl) {
456        ctrl.slices = self.buffer.sys_slices_mut();
457        ctrl.msg.msg_name = &raw mut self.header.addr as _;
458        ctrl.msg.msg_namelen = self.header.addr.size_of() as _;
459        ctrl.msg.msg_iov = ctrl.slices.as_mut_ptr() as _;
460        ctrl.msg.msg_iovlen = ctrl.slices.len() as _;
461        ctrl.msg.msg_control = self.control.buf_mut_ptr() as _;
462        ctrl.msg.msg_controllen = self.control.buf_capacity() as _;
463    }
464
465    pub(crate) fn update_control(&mut self, control: &RecvMsgControl) {
466        self.header.addr_len = control.msg.msg_namelen as _;
467        self.control_len = control.msg.msg_controllen as _;
468        self.return_flags = ReturnFlags::from_bits_retain(control.msg.msg_flags as _);
469    }
470}