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}