async_std/os/unix/net/
datagram.rs

1//! Unix-specific networking extensions.
2
3use std::fmt;
4use std::net::Shutdown;
5use std::os::unix::net::UnixDatagram as StdUnixDatagram;
6
7use async_io::Async;
8
9use super::SocketAddr;
10use crate::io;
11use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
12use crate::path::Path;
13
14/// A Unix datagram socket.
15///
16/// After creating a `UnixDatagram` by [`bind`]ing it to a path, data can be [sent to] and
17/// [received from] any other socket address.
18///
19/// This type is an async version of [`std::os::unix::net::UnixDatagram`].
20///
21/// [`std::os::unix::net::UnixDatagram`]:
22/// https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html
23/// [`bind`]: #method.bind
24/// [received from]: #method.recv_from
25/// [sent to]: #method.send_to
26///
27/// ## Examples
28///
29/// ```no_run
30/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
31/// #
32/// use async_std::os::unix::net::UnixDatagram;
33///
34/// let socket = UnixDatagram::bind("/tmp/socket1").await?;
35/// socket.send_to(b"hello world", "/tmp/socket2").await?;
36///
37/// let mut buf = vec![0u8; 1024];
38/// let (n, peer) = socket.recv_from(&mut buf).await?;
39/// #
40/// # Ok(()) }) }
41/// ```
42pub struct UnixDatagram {
43    watcher: Async<StdUnixDatagram>,
44}
45
46impl UnixDatagram {
47    fn new(socket: StdUnixDatagram) -> UnixDatagram {
48        UnixDatagram {
49            watcher: Async::new(socket).expect("UnixDatagram is known to be good"),
50        }
51    }
52
53    /// Creates a Unix datagram socket bound to the given path.
54    ///
55    /// # Examples
56    ///
57    /// ```no_run
58    /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
59    /// #
60    /// use async_std::os::unix::net::UnixDatagram;
61    ///
62    /// let socket = UnixDatagram::bind("/tmp/socket").await?;
63    /// #
64    /// # Ok(()) }) }
65    /// ```
66    pub async fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram> {
67        let path = path.as_ref().to_owned();
68        let socket = Async::<StdUnixDatagram>::bind(path)?;
69        Ok(UnixDatagram { watcher: socket })
70    }
71
72    /// Creates a Unix datagram which is not bound to any address.
73    ///
74    /// # Examples
75    ///
76    /// ```no_run
77    /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
78    /// #
79    /// use async_std::os::unix::net::UnixDatagram;
80    ///
81    /// let socket = UnixDatagram::unbound()?;
82    /// #
83    /// # Ok(()) }) }
84    /// ```
85    pub fn unbound() -> io::Result<UnixDatagram> {
86        let socket = StdUnixDatagram::unbound()?;
87        Ok(UnixDatagram::new(socket))
88    }
89
90    /// Creates an unnamed pair of connected sockets.
91    ///
92    /// Returns two sockets which are connected to each other.
93    ///
94    /// # Examples
95    ///
96    /// ```no_run
97    /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
98    /// #
99    /// use async_std::os::unix::net::UnixDatagram;
100    ///
101    /// let (socket1, socket2) = UnixDatagram::pair()?;
102    /// #
103    /// # Ok(()) }) }
104    /// ```
105    pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> {
106        let (a, b) = StdUnixDatagram::pair()?;
107        let a = UnixDatagram::new(a);
108        let b = UnixDatagram::new(b);
109        Ok((a, b))
110    }
111
112    /// Connects the socket to the specified address.
113    ///
114    /// The [`send`] method may be used to send data to the specified address. [`recv`] and
115    /// [`recv_from`] will only receive data from that address.
116    ///
117    /// [`send`]: #method.send
118    /// [`recv`]: #method.recv
119    /// [`recv_from`]: #method.recv_from
120    ///
121    /// # Examples
122    ///
123    /// ```no_run
124    /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
125    /// #
126    /// use async_std::os::unix::net::UnixDatagram;
127    ///
128    /// let socket = UnixDatagram::unbound()?;
129    /// socket.connect("/tmp/socket").await?;
130    /// #
131    /// # Ok(()) }) }
132    /// ```
133    pub async fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
134        // TODO(stjepang): Connect the socket on a blocking pool.
135        let p = path.as_ref();
136        self.watcher.get_ref().connect(p)
137    }
138
139    /// Returns the address of this socket.
140    ///
141    /// # Examples
142    ///
143    /// ```no_run
144    /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
145    /// #
146    /// use async_std::os::unix::net::UnixDatagram;
147    ///
148    /// let socket = UnixDatagram::bind("/tmp/socket").await?;
149    /// let addr = socket.local_addr()?;
150    /// #
151    /// # Ok(()) }) }
152    /// ```
153    pub fn local_addr(&self) -> io::Result<SocketAddr> {
154        self.watcher.get_ref().local_addr()
155    }
156
157    /// Returns the address of this socket's peer.
158    ///
159    /// The [`connect`] method will connect the socket to a peer.
160    ///
161    /// [`connect`]: #method.connect
162    ///
163    /// # Examples
164    ///
165    /// ```no_run
166    /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
167    /// #
168    /// use async_std::os::unix::net::UnixDatagram;
169    ///
170    /// let socket = UnixDatagram::unbound()?;
171    /// socket.connect("/tmp/socket").await?;
172    /// let peer = socket.peer_addr()?;
173    /// #
174    /// # Ok(()) }) }
175    /// ```
176    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
177        self.watcher.get_ref().peer_addr()
178    }
179
180    /// Receives data from the socket.
181    ///
182    /// On success, returns the number of bytes read and the address from where the data came.
183    ///
184    /// # Examples
185    ///
186    /// ```no_run
187    /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
188    /// #
189    /// use async_std::os::unix::net::UnixDatagram;
190    ///
191    /// let socket = UnixDatagram::unbound()?;
192    /// let mut buf = vec![0; 1024];
193    /// let (n, peer) = socket.recv_from(&mut buf).await?;
194    /// #
195    /// # Ok(()) }) }
196    /// ```
197    pub async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
198        self.watcher.recv_from(buf).await
199    }
200
201    /// Receives data from the socket.
202    ///
203    /// On success, returns the number of bytes read.
204    ///
205    /// # Examples
206    ///
207    /// ```no_run
208    /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
209    /// #
210    /// use async_std::os::unix::net::UnixDatagram;
211    ///
212    /// let socket = UnixDatagram::bind("/tmp/socket").await?;
213    /// let mut buf = vec![0; 1024];
214    /// let n = socket.recv(&mut buf).await?;
215    /// #
216    /// # Ok(()) }) }
217    /// ```
218    pub async fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
219        self.watcher.recv(buf).await
220    }
221
222    /// Sends data on the socket to the specified address.
223    ///
224    /// On success, returns the number of bytes written.
225    ///
226    /// # Examples
227    ///
228    /// ```no_run
229    /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
230    /// #
231    /// use async_std::os::unix::net::UnixDatagram;
232    ///
233    /// let socket = UnixDatagram::unbound()?;
234    /// socket.send_to(b"hello world", "/tmp/socket").await?;
235    /// #
236    /// # Ok(()) }) }
237    /// ```
238    pub async fn send_to<P: AsRef<Path>>(&self, buf: &[u8], path: P) -> io::Result<usize> {
239        self.watcher.send_to(buf, path.as_ref()).await
240    }
241
242    /// Sends data on the socket to the socket's peer.
243    ///
244    /// On success, returns the number of bytes written.
245    ///
246    /// # Examples
247    ///
248    /// ```no_run
249    /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
250    /// #
251    /// use async_std::os::unix::net::UnixDatagram;
252    ///
253    /// let socket = UnixDatagram::unbound()?;
254    /// socket.connect("/tmp/socket").await?;
255    /// socket.send(b"hello world").await?;
256    /// #
257    /// # Ok(()) }) }
258    /// ```
259    pub async fn send(&self, buf: &[u8]) -> io::Result<usize> {
260        self.watcher.send(buf).await
261    }
262
263    /// Shut down the read, write, or both halves of this connection.
264    ///
265    /// This function will cause all pending and future I/O calls on the specified portions to
266    /// immediately return with an appropriate value (see the documentation of [`Shutdown`]).
267    ///
268    /// [`Shutdown`]: https://doc.rust-lang.org/std/net/enum.Shutdown.html
269    ///
270    /// ## Examples
271    ///
272    /// ```no_run
273    /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
274    /// #
275    /// use async_std::os::unix::net::UnixDatagram;
276    /// use std::net::Shutdown;
277    ///
278    /// let socket = UnixDatagram::unbound()?;
279    /// socket.shutdown(Shutdown::Both)?;
280    /// #
281    /// # Ok(()) }) }
282    /// ```
283    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
284        self.watcher.get_ref().shutdown(how)
285    }
286}
287
288impl fmt::Debug for UnixDatagram {
289    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
290        let mut builder = f.debug_struct("UnixDatagram");
291        builder.field("fd", &self.as_raw_fd());
292
293        if let Ok(addr) = self.local_addr() {
294            builder.field("local", &addr);
295        }
296
297        if let Ok(addr) = self.peer_addr() {
298            builder.field("peer", &addr);
299        }
300
301        builder.finish()
302    }
303}
304
305impl From<StdUnixDatagram> for UnixDatagram {
306    /// Converts a `std::os::unix::net::UnixDatagram` into its asynchronous equivalent.
307    fn from(datagram: StdUnixDatagram) -> UnixDatagram {
308        UnixDatagram {
309            watcher: Async::new(datagram).expect("UnixDatagram is known to be good"),
310        }
311    }
312}
313
314impl std::convert::TryFrom<UnixDatagram> for StdUnixDatagram {
315    type Error = io::Error;
316    /// Converts a `UnixDatagram` into its synchronous equivalent.
317    fn try_from(listener: UnixDatagram) -> io::Result<StdUnixDatagram> {
318        let inner = listener.watcher.into_inner()?;
319        inner.set_nonblocking(false)?;
320        Ok(inner)
321    }
322}
323
324impl AsRawFd for UnixDatagram {
325    fn as_raw_fd(&self) -> RawFd {
326        self.watcher.as_raw_fd()
327    }
328}
329
330impl FromRawFd for UnixDatagram {
331    unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram {
332        let raw = StdUnixDatagram::from_raw_fd(fd);
333        let datagram = Async::<StdUnixDatagram>::new(raw).expect("invalid file descriptor");
334        UnixDatagram { watcher: datagram }
335    }
336}
337
338impl IntoRawFd for UnixDatagram {
339    fn into_raw_fd(self) -> RawFd {
340        self.watcher.into_inner().unwrap().into_raw_fd()
341    }
342}
343
344cfg_io_safety! {
345    use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
346
347    impl AsFd for UnixDatagram {
348        fn as_fd(&self) -> BorrowedFd<'_> {
349            self.watcher.get_ref().as_fd()
350        }
351    }
352
353    impl From<OwnedFd> for UnixDatagram {
354        fn from(fd: OwnedFd) -> UnixDatagram {
355            StdUnixDatagram::from(fd).into()
356        }
357    }
358
359    impl From<UnixDatagram> for OwnedFd {
360        fn from(stream: UnixDatagram) -> OwnedFd {
361            stream.watcher.into_inner().unwrap().into()
362        }
363    }
364}