interprocess_docfix/os/unix/udsocket/tokio/
socket.rs

1#[cfg(uds_peercred)]
2use super::c_wrappers;
3use {
4    crate::os::unix::{imports::*, udsocket},
5    std::{
6        convert::TryFrom,
7        future::Future,
8        io,
9        net::Shutdown,
10        pin::Pin,
11        task::{Context, Poll},
12    },
13    udsocket::{ToUdSocketPath, UdSocket as SyncUdSocket, UdSocketPath},
14};
15
16/// A Unix domain datagram socket, obtained either from [`UdSocketListener`](super::UdSocketListener) or by connecting to an existing server.
17///
18/// # Examples
19/// - [Basic packet exchange](https://github.com/kotauskas/interprocess/blob/main/examples/tokio_udsocket/inner.rs)
20#[derive(Debug)]
21pub struct UdSocket(TokioUdSocket);
22impl UdSocket {
23    /// Creates an unnamed datagram socket.
24    pub fn unbound() -> io::Result<Self> {
25        let socket = TokioUdSocket::unbound()?;
26        Ok(Self(socket))
27    }
28    /// Creates a named datagram socket assigned to the specified path. This will be the "home" of this socket. Then, packets from somewhere else directed to this socket with [`.send_to()`] or [`.connect()`](Self::connect) will go here.
29    ///
30    /// See [`ToUdSocketPath`] for an example of using various string types to specify socket paths.
31    pub fn bind<'a>(path: impl ToUdSocketPath<'a>) -> io::Result<Self> {
32        Self::_bind(path.to_socket_path()?)
33    }
34    fn _bind(path: UdSocketPath<'_>) -> io::Result<Self> {
35        let socket = TokioUdSocket::bind(path.as_osstr())?;
36        Ok(Self(socket))
37    }
38    /// Selects the Unix domain socket to send packets to. You can also just use [`.send_to()`](Self::send_to) instead, but supplying the address to the kernel once is more efficient.
39    ///
40    /// See [`ToUdSocketPath`] for an example of using various string types to specify socket paths.
41    pub fn set_destination<'a>(&self, path: impl ToUdSocketPath<'a>) -> io::Result<()> {
42        self._set_destination(path.to_socket_path()?)
43    }
44    fn _set_destination(&self, path: UdSocketPath<'_>) -> io::Result<()> {
45        self.0.connect(path.as_osstr())
46    }
47    /// Shuts down the read, write, or both halves of the socket. See [`Shutdown`].
48    ///
49    /// Attempting to call this method with the same `how` argument multiple times may return `Ok(())` every time or it may return an error the second time it is called, depending on the platform. You must either avoid using the same value twice or ignore the error entirely.
50    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
51        self.0.shutdown(how)
52    }
53    /// Receives a single datagram from the socket, advancing the `ReadBuf` cursor by the datagram length.
54    ///
55    /// Uses Tokio's [`ReadBuf`] interface. See `.recv_stdbuf()` for a `&mut [u8]` version.
56    pub async fn recv(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
57        // Tokio's .recv() uses &mut [u8] instead of &mut ReadBuf<'_> for some
58        // reason, this works around that
59        struct WrapperFuture<'a, 'b, 'c>(&'a UdSocket, &'b mut ReadBuf<'c>);
60        impl Future for WrapperFuture<'_, '_, '_> {
61            type Output = io::Result<()>;
62            fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
63                self.0 .0.poll_recv(cx, self.1)
64            }
65        }
66        WrapperFuture(self, buf).await
67    }
68    /// Receives a single datagram from the socket, advancing the `ReadBuf` cursor by the datagram length.
69    ///
70    /// Uses an `std`-like `&mut [u8]` interface. See `.recv()` for a version which uses Tokio's [`ReadBuf`] instead.
71    pub async fn recv_stdbuf(&self, buf: &mut [u8]) -> io::Result<usize> {
72        self.0.recv(buf).await
73    }
74    /// Asynchronously waits until readable data arrives to the socket.
75    ///
76    /// May finish spuriously – *do not* perform a blocking read when this future finishes and *do* handle a [`WouldBlock`](io::ErrorKind::WouldBlock) or [`Poll::Pending`].
77    pub async fn recv_ready(&self) -> io::Result<()> {
78        self.0.readable().await
79    }
80    /// Sends a single datagram into the socket, returning how many bytes were actually sent.
81    pub async fn send(&self, buf: &[u8]) -> io::Result<usize> {
82        self.0.send(buf).await
83    }
84    /// Sends a single datagram to the given address, returning how many bytes were actually sent.
85    pub async fn send_to(&self, buf: &[u8], path: impl ToUdSocketPath<'_>) -> io::Result<usize> {
86        let path = path.to_socket_path()?;
87        self._send_to(buf, &path).await
88    }
89    async fn _send_to(&self, buf: &[u8], path: &UdSocketPath<'_>) -> io::Result<usize> {
90        self.0.send_to(buf, path.as_osstr()).await
91    }
92    /// Asynchronously waits until the socket becomes writable due to the other side freeing up space in its OS receive buffer.
93    ///
94    /// May finish spuriously – *do not* perform a blocking write when this future finishes and *do* handle a [`WouldBlock`](io::ErrorKind::WouldBlock) or [`Poll::Pending`].
95    pub async fn send_ready(&self) -> io::Result<()> {
96        self.0.writable().await
97    }
98    /// Raw polling interface for receiving datagrams. You probably want `.recv()` instead.
99    pub fn poll_recv(&self, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll<io::Result<()>> {
100        self.0.poll_recv(cx, buf)
101    }
102    /// Raw polling interface for receiving datagrams with an `std`-like receive buffer. You probably want `.recv_stdbuf()` instead.
103    pub fn poll_recv_stdbuf(&self, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<io::Result<()>> {
104        let mut readbuf = ReadBuf::new(buf);
105        self.0.poll_recv(cx, &mut readbuf)
106    }
107    /// Raw polling interface for sending datagrams. You probably want `.send()` instead.
108    pub fn poll_send(&self, cx: &mut Context<'_>, buf: &[u8]) -> Poll<io::Result<usize>> {
109        self.0.poll_send(cx, buf)
110    }
111    /// Raw polling interface for sending datagrams. You probably want `.send_to()` instead.
112    pub fn poll_send_to<'a>(
113        &self,
114        cx: &mut Context<'_>,
115        buf: &[u8],
116        path: impl ToUdSocketPath<'a>,
117    ) -> Poll<io::Result<usize>> {
118        let path = path.to_socket_path()?;
119        self._poll_send_to(cx, buf, &path)
120    }
121    fn _poll_send_to(
122        &self,
123        cx: &mut Context<'_>,
124        buf: &[u8],
125        path: &UdSocketPath<'_>,
126    ) -> Poll<io::Result<usize>> {
127        self.0.poll_send_to(cx, buf, path.as_osstr())
128    }
129    /// Fetches the credentials of the other end of the connection without using ancillary data. The returned structure contains the process identifier, user identifier and group identifier of the peer.
130    #[cfg(any(doc, uds_peercred))]
131    #[cfg_attr( // uds_peercred template
132        feature = "doc_cfg",
133        doc(cfg(any(
134            all(
135                target_os = "linux",
136                any(
137                    target_env = "gnu",
138                    target_env = "musl",
139                    target_env = "musleabi",
140                    target_env = "musleabihf"
141                )
142            ),
143            target_os = "emscripten",
144            target_os = "redox",
145            target_os = "haiku"
146        )))
147    )]
148    pub fn get_peer_credentials(&self) -> io::Result<ucred> {
149        c_wrappers::get_peer_ucred(self.as_raw_fd().as_ref())
150    }
151    tokio_wrapper_conversion_methods!(
152        sync SyncUdSocket,
153        std StdUdSocket,
154        tokio TokioUdSocket);
155}
156
157tokio_wrapper_trait_impls!(
158    for UdSocket,
159    sync SyncUdSocket,
160    std StdUdSocket,
161    tokio TokioUdSocket);