monoio/net/unix/datagram/
mod.rs

1//! Unix datagram related.
2
3use std::{
4    io,
5    os::unix::{
6        net::UnixDatagram as StdUnixDatagram,
7        prelude::{AsRawFd, IntoRawFd, RawFd},
8    },
9    path::Path,
10};
11
12use super::{
13    socket_addr::{local_addr, pair, peer_addr, socket_addr},
14    SocketAddr,
15};
16use crate::{
17    buf::{IoBuf, IoBufMut},
18    driver::{op::Op, shared_fd::SharedFd},
19    net::new_socket,
20};
21
22/// UnixDatagram
23pub struct UnixDatagram {
24    fd: SharedFd,
25}
26
27impl UnixDatagram {
28    pub(crate) fn from_shared_fd(fd: SharedFd) -> Self {
29        Self { fd }
30    }
31
32    /// Creates a Unix datagram socket bound to the given path.
33    pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<Self> {
34        StdUnixDatagram::bind(path).and_then(Self::from_std)
35    }
36
37    /// Creates a new `UnixDatagram` which is not bound to any address.
38    pub fn unbound() -> io::Result<Self> {
39        StdUnixDatagram::unbound().and_then(Self::from_std)
40    }
41
42    /// Creates an unnamed pair of connected sockets.
43    pub fn pair() -> io::Result<(Self, Self)> {
44        let (a, b) = pair(libc::SOCK_DGRAM)?;
45        Ok((Self::from_std(a)?, Self::from_std(b)?))
46    }
47
48    /// Connects the socket to the specified address.
49    pub async fn connect<P: AsRef<Path>>(path: P) -> io::Result<Self> {
50        let (addr, addr_len) = socket_addr(path.as_ref())?;
51        Self::inner_connect(addr, addr_len).await
52    }
53
54    /// Connects the socket to an address.
55    pub async fn connect_addr(addr: SocketAddr) -> io::Result<Self> {
56        let (addr, addr_len) = addr.into_parts();
57        Self::inner_connect(addr, addr_len).await
58    }
59
60    #[inline(always)]
61    async fn inner_connect(
62        sockaddr: libc::sockaddr_un,
63        socklen: libc::socklen_t,
64    ) -> io::Result<Self> {
65        let socket = new_socket(libc::AF_UNIX, libc::SOCK_DGRAM)?;
66        let op = Op::connect_unix(SharedFd::new::<false>(socket)?, sockaddr, socklen)?;
67        let completion = op.await;
68        completion.meta.result?;
69
70        Ok(Self::from_shared_fd(completion.data.fd))
71    }
72
73    /// Creates new `UnixDatagram` from a `std::os::unix::net::UnixDatagram`.
74    pub fn from_std(datagram: StdUnixDatagram) -> io::Result<Self> {
75        match SharedFd::new::<false>(datagram.as_raw_fd()) {
76            Ok(shared) => {
77                let _ = datagram.into_raw_fd();
78                Ok(Self::from_shared_fd(shared))
79            }
80            Err(e) => Err(e),
81        }
82    }
83
84    /// Returns the socket address of the local half of this connection.
85    pub fn local_addr(&self) -> io::Result<SocketAddr> {
86        local_addr(self.as_raw_fd())
87    }
88
89    /// Returns the socket address of the remote half of this connection.
90    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
91        peer_addr(self.as_raw_fd())
92    }
93
94    /// Wait for read readiness.
95    /// Note: Do not use it before every io. It is different from other runtimes!
96    ///
97    /// Everytime call to this method may pay a syscall cost.
98    /// In uring impl, it will push a PollAdd op; in epoll impl, it will use use
99    /// inner readiness state; if !relaxed, it will call syscall poll after that.
100    ///
101    /// If relaxed, on legacy driver it may return false positive result.
102    /// If you want to do io by your own, you must maintain io readiness and wait
103    /// for io ready with relaxed=false.
104    pub async fn readable(&self, relaxed: bool) -> io::Result<()> {
105        let op = Op::poll_read(&self.fd, relaxed).unwrap();
106        op.wait().await
107    }
108
109    /// Wait for write readiness.
110    /// Note: Do not use it before every io. It is different from other runtimes!
111    ///
112    /// Everytime call to this method may pay a syscall cost.
113    /// In uring impl, it will push a PollAdd op; in epoll impl, it will use use
114    /// inner readiness state; if !relaxed, it will call syscall poll after that.
115    ///
116    /// If relaxed, on legacy driver it may return false positive result.
117    /// If you want to do io by your own, you must maintain io readiness and wait
118    /// for io ready with relaxed=false.
119    pub async fn writable(&self, relaxed: bool) -> io::Result<()> {
120        let op = Op::poll_write(&self.fd, relaxed).unwrap();
121        op.wait().await
122    }
123
124    /// Sends data on the socket to the given address. On success, returns the
125    /// number of bytes written.
126    pub async fn send_to<T: IoBuf, P: AsRef<Path>>(
127        &self,
128        buf: T,
129        path: P,
130    ) -> crate::BufResult<usize, T> {
131        let addr = match crate::net::unix::socket_addr::socket_addr(path.as_ref()) {
132            Ok(addr) => addr,
133            Err(e) => return (Err(e), buf),
134        };
135        let op = Op::send_msg_unix(
136            self.fd.clone(),
137            buf,
138            Some(SocketAddr::from_parts(addr.0, addr.1)),
139        )
140        .unwrap();
141        op.wait().await
142    }
143
144    /// Receives a single datagram message on the socket. On success, returns the number
145    /// of bytes read and the origin.
146    pub async fn recv_from<T: IoBufMut>(&self, buf: T) -> crate::BufResult<(usize, SocketAddr), T> {
147        let op = Op::recv_msg_unix(self.fd.clone(), buf).unwrap();
148        op.wait().await
149    }
150
151    /// Sends data on the socket to the remote address to which it is connected.
152    pub async fn send<T: IoBuf>(&self, buf: T) -> crate::BufResult<usize, T> {
153        let op = Op::send_msg_unix(self.fd.clone(), buf, None).unwrap();
154        op.wait().await
155    }
156
157    /// Receives a single datagram message on the socket from the remote address to
158    /// which it is connected. On success, returns the number of bytes read.
159    pub async fn recv<T: IoBufMut>(&self, buf: T) -> crate::BufResult<usize, T> {
160        let op = Op::recv(self.fd.clone(), buf).unwrap();
161        op.result().await
162    }
163}
164
165impl AsRawFd for UnixDatagram {
166    #[inline]
167    fn as_raw_fd(&self) -> RawFd {
168        self.fd.raw_fd()
169    }
170}
171
172impl std::fmt::Debug for UnixDatagram {
173    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
174        f.debug_struct("UnixDatagram")
175            .field("fd", &self.fd)
176            .finish()
177    }
178}