async_std/net/udp/mod.rs
1use std::io;
2use std::net::SocketAddr;
3use std::net::{Ipv4Addr, Ipv6Addr};
4
5use async_io::Async;
6
7use crate::net::ToSocketAddrs;
8use crate::utils::Context as _;
9
10/// A UDP socket.
11///
12/// After creating a `UdpSocket` by [`bind`]ing it to a socket address, data can be [sent to] and
13/// [received from] any other socket address.
14///
15/// As stated in the User Datagram Protocol's specification in [IETF RFC 768], UDP is an unordered,
16/// unreliable protocol. Refer to [`TcpListener`] and [`TcpStream`] for async TCP primitives.
17///
18/// This type is an async version of [`std::net::UdpSocket`].
19///
20/// [`bind`]: #method.bind
21/// [received from]: #method.recv_from
22/// [sent to]: #method.send_to
23/// [`TcpListener`]: struct.TcpListener.html
24/// [`TcpStream`]: struct.TcpStream.html
25/// [`std::net`]: https://doc.rust-lang.org/std/net/index.html
26/// [IETF RFC 768]: https://tools.ietf.org/html/rfc768
27/// [`std::net::UdpSocket`]: https://doc.rust-lang.org/std/net/struct.UdpSocket.html
28///
29/// ## Examples
30///
31/// ```no_run
32/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
33/// #
34/// use async_std::net::UdpSocket;
35///
36/// let socket = UdpSocket::bind("127.0.0.1:8080").await?;
37/// let mut buf = vec![0u8; 1024];
38///
39/// loop {
40/// let (n, peer) = socket.recv_from(&mut buf).await?;
41/// socket.send_to(&buf[..n], &peer).await?;
42/// }
43/// #
44/// # }) }
45/// ```
46#[derive(Debug)]
47pub struct UdpSocket {
48 watcher: Async<std::net::UdpSocket>,
49}
50
51impl UdpSocket {
52 /// Creates a UDP socket from the given address.
53 ///
54 /// Binding with a port number of 0 will request that the OS assigns a port to this socket. The
55 /// port allocated can be queried via the [`local_addr`] method.
56 ///
57 /// [`local_addr`]: #method.local_addr
58 ///
59 /// # Examples
60 ///
61 /// ```no_run
62 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
63 /// #
64 /// use async_std::net::UdpSocket;
65 ///
66 /// let socket = UdpSocket::bind("127.0.0.1:0").await?;
67 /// #
68 /// # Ok(()) }) }
69 /// ```
70 pub async fn bind<A: ToSocketAddrs>(addrs: A) -> io::Result<UdpSocket> {
71 let mut last_err = None;
72 let addrs = addrs.to_socket_addrs().await?;
73
74 for addr in addrs {
75 match Async::<std::net::UdpSocket>::bind(addr) {
76 Ok(socket) => {
77 return Ok(UdpSocket { watcher: socket });
78 }
79 Err(err) => last_err = Some(err),
80 }
81 }
82
83 Err(last_err.unwrap_or_else(|| {
84 io::Error::new(
85 io::ErrorKind::InvalidInput,
86 "could not resolve to any addresses",
87 )
88 }))
89 }
90
91 /// Returns the peer address that this listener is connected to.
92 ///
93 /// This can be useful, for example, when connect to port 0 to figure out which port was
94 /// actually connected.
95 ///
96 /// # Examples
97 ///
98 /// ```no_run
99 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
100 /// #
101 /// use async_std::net::UdpSocket;
102 ///
103 /// let socket1 = UdpSocket::bind("127.0.0.1:0").await?;
104 /// let socket2 = UdpSocket::bind("127.0.0.1:0").await?;
105 /// socket1.connect(socket2.local_addr()?).await?;
106 /// let addr = socket1.peer_addr()?;
107 /// #
108 /// # Ok(()) }) }
109 /// ```
110 pub fn peer_addr(&self) -> io::Result<SocketAddr> {
111 self.watcher
112 .get_ref()
113 .peer_addr()
114 .context(|| String::from("could not get peer address"))
115 }
116
117 /// Returns the local address that this listener is bound to.
118 ///
119 /// This can be useful, for example, when binding to port 0 to figure out which port was
120 /// actually bound.
121 ///
122 /// # Examples
123 ///
124 /// ```no_run
125 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
126 /// #
127 /// use async_std::net::UdpSocket;
128 ///
129 /// let socket = UdpSocket::bind("127.0.0.1:0").await?;
130 /// let addr = socket.local_addr()?;
131 /// #
132 /// # Ok(()) }) }
133 /// ```
134 pub fn local_addr(&self) -> io::Result<SocketAddr> {
135 self.watcher
136 .get_ref()
137 .local_addr()
138 .context(|| String::from("could not get local address"))
139 }
140
141 /// Sends data on the socket to the given address.
142 ///
143 /// On success, returns the number of bytes written.
144 ///
145 /// # Examples
146 ///
147 /// ```no_run
148 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
149 /// #
150 /// use async_std::net::UdpSocket;
151 ///
152 /// const THE_MERCHANT_OF_VENICE: &[u8] = b"
153 /// If you prick us, do we not bleed?
154 /// If you tickle us, do we not laugh?
155 /// If you poison us, do we not die?
156 /// And if you wrong us, shall we not revenge?
157 /// ";
158 ///
159 /// let socket = UdpSocket::bind("127.0.0.1:0").await?;
160 ///
161 /// let addr = "127.0.0.1:7878";
162 /// let sent = socket.send_to(THE_MERCHANT_OF_VENICE, &addr).await?;
163 /// println!("Sent {} bytes to {}", sent, addr);
164 /// #
165 /// # Ok(()) }) }
166 /// ```
167 pub async fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addrs: A) -> io::Result<usize> {
168 let addr = match addrs.to_socket_addrs().await?.next() {
169 Some(addr) => addr,
170 None => {
171 return Err(io::Error::new(
172 io::ErrorKind::InvalidInput,
173 "no addresses to send data to",
174 ));
175 }
176 };
177
178 self.watcher
179 .send_to(buf, addr)
180 .await
181 .context(|| format!("could not send packet to {}", addr))
182 }
183
184 /// Receives data from the socket.
185 ///
186 /// On success, returns the number of bytes read and the origin.
187 ///
188 /// # Examples
189 ///
190 /// ```no_run
191 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
192 /// #
193 /// use async_std::net::UdpSocket;
194 ///
195 /// let socket = UdpSocket::bind("127.0.0.1:0").await?;
196 ///
197 /// let mut buf = vec![0; 1024];
198 /// let (n, peer) = socket.recv_from(&mut buf).await?;
199 /// println!("Received {} bytes from {}", n, peer);
200 /// #
201 /// # Ok(()) }) }
202 /// ```
203 pub async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
204 self.watcher.recv_from(buf).await
205 }
206
207 /// Receives data from socket without removing it from the queue.
208 ///
209 /// On success, returns the number of bytes peeked and the origin.
210 ///
211 /// # Examples
212 ///
213 /// ```no_run
214 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
215 /// #
216 /// use async_std::net::UdpSocket;
217 ///
218 /// let socket = UdpSocket::bind("127.0.0.1:0").await?;
219 ///
220 /// let mut buf = vec![0; 1024];
221 /// let (n, peer) = socket.peek_from(&mut buf).await?;
222 /// println!("Peeked {} bytes from {}", n, peer);
223 /// #
224 /// # Ok (()) }) }
225 /// ```
226 pub async fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
227 self.watcher.peek_from(buf).await
228 }
229
230 /// Connects the UDP socket to a remote address.
231 ///
232 /// When connected, methods [`send`] and [`recv`] will use the specified address for sending
233 /// and receiving messages. Additionally, a filter will be applied to [`recv_from`] so that it
234 /// only receives messages from that same address.
235 ///
236 /// [`send`]: #method.send
237 /// [`recv`]: #method.recv
238 /// [`recv_from`]: #method.recv_from
239 ///
240 /// # Examples
241 ///
242 /// ```no_run
243 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
244 /// #
245 /// use async_std::net::UdpSocket;
246 ///
247 /// let socket = UdpSocket::bind("127.0.0.1:0").await?;
248 /// socket.connect("127.0.0.1:8080").await?;
249 /// #
250 /// # Ok(()) }) }
251 /// ```
252 pub async fn connect<A: ToSocketAddrs>(&self, addrs: A) -> io::Result<()> {
253 let mut last_err = None;
254 let addrs = addrs
255 .to_socket_addrs()
256 .await
257 .context(|| String::from("could not resolve addresses"))?;
258
259 for addr in addrs {
260 // TODO(stjepang): connect on the blocking pool
261 match self.watcher.get_ref().connect(addr) {
262 Ok(()) => return Ok(()),
263 Err(err) => last_err = Some(err),
264 }
265 }
266
267 Err(last_err.unwrap_or_else(|| {
268 io::Error::new(
269 io::ErrorKind::InvalidInput,
270 "could not resolve to any addresses",
271 )
272 }))
273 }
274
275 /// Sends data on the socket to the remote address to which it is connected.
276 ///
277 /// The [`connect`] method will connect this socket to a remote address.
278 /// This method will fail if the socket is not connected.
279 ///
280 /// [`connect`]: #method.connect
281 ///
282 /// # Examples
283 ///
284 /// ```no_run
285 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
286 /// #
287 /// use async_std::net::UdpSocket;
288 ///
289 /// let socket = UdpSocket::bind("127.0.0.1:34254").await?;
290 /// socket.connect("127.0.0.1:8080").await?;
291 /// let bytes = socket.send(b"Hi there!").await?;
292 ///
293 /// println!("Sent {} bytes", bytes);
294 /// #
295 /// # Ok(()) }) }
296 /// ```
297 pub async fn send(&self, buf: &[u8]) -> io::Result<usize> {
298 self.watcher.send(buf).await
299 }
300
301 /// Receives data from the socket.
302 ///
303 /// On success, returns the number of bytes read.
304 ///
305 /// # Examples
306 ///
307 /// ```no_run
308 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
309 /// #
310 /// use async_std::net::UdpSocket;
311 ///
312 /// let socket = UdpSocket::bind("127.0.0.1:0").await?;
313 /// socket.connect("127.0.0.1:8080").await?;
314 ///
315 /// let mut buf = vec![0; 1024];
316 /// let n = socket.recv(&mut buf).await?;
317 /// println!("Received {} bytes", n);
318 /// #
319 /// # Ok(()) }) }
320 /// ```
321 pub async fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
322 self.watcher.recv(buf).await
323 }
324
325 /// Receives data from the socket without removing it from the queue.
326 ///
327 /// On success, returns the number of bytes peeked.
328 ///
329 /// # Examples
330 ///
331 /// ```no_run
332 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
333 /// #
334 /// use async_std::net::UdpSocket;
335 ///
336 /// let socket = UdpSocket::bind("127.0.0.1:0").await?;
337 /// socket.connect("127.0.0.1:8080").await?;
338 ///
339 /// let mut buf = vec![0; 1024];
340 /// let n = socket.peek(&mut buf).await?;
341 /// println!("Peeked {} bytes", n);
342 /// #
343 /// # Ok(()) }) }
344 /// ```
345 pub async fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
346 self.watcher.peek(buf).await
347 }
348
349 /// Gets the value of the `SO_BROADCAST` option for this socket.
350 ///
351 /// For more information about this option, see [`set_broadcast`].
352 ///
353 /// [`set_broadcast`]: #method.set_broadcast
354 pub fn broadcast(&self) -> io::Result<bool> {
355 self.watcher.get_ref().broadcast()
356 }
357
358 /// Sets the value of the `SO_BROADCAST` option for this socket.
359 ///
360 /// When enabled, this socket is allowed to send packets to a broadcast address.
361 pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
362 self.watcher.get_ref().set_broadcast(on)
363 }
364
365 /// Gets the value of the `IP_MULTICAST_LOOP` option for this socket.
366 ///
367 /// For more information about this option, see [`set_multicast_loop_v4`].
368 ///
369 /// [`set_multicast_loop_v4`]: #method.set_multicast_loop_v4
370 pub fn multicast_loop_v4(&self) -> io::Result<bool> {
371 self.watcher.get_ref().multicast_loop_v4()
372 }
373
374 /// Sets the value of the `IP_MULTICAST_LOOP` option for this socket.
375 ///
376 /// If enabled, multicast packets will be looped back to the local socket.
377 ///
378 /// # Note
379 ///
380 /// This may not have any affect on IPv6 sockets.
381 pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> {
382 self.watcher.get_ref().set_multicast_loop_v4(on)
383 }
384
385 /// Gets the value of the `IP_MULTICAST_TTL` option for this socket.
386 ///
387 /// For more information about this option, see [`set_multicast_ttl_v4`].
388 ///
389 /// [`set_multicast_ttl_v4`]: #method.set_multicast_ttl_v4
390 pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
391 self.watcher.get_ref().multicast_ttl_v4()
392 }
393
394 /// Sets the value of the `IP_MULTICAST_TTL` option for this socket.
395 ///
396 /// Indicates the time-to-live value of outgoing multicast packets for this socket. The default
397 /// value is 1 which means that multicast packets don't leave the local network unless
398 /// explicitly requested.
399 ///
400 /// # Note
401 ///
402 /// This may not have any affect on IPv6 sockets.
403 pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
404 self.watcher.get_ref().set_multicast_ttl_v4(ttl)
405 }
406
407 /// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
408 ///
409 /// For more information about this option, see [`set_multicast_loop_v6`].
410 ///
411 /// [`set_multicast_loop_v6`]: #method.set_multicast_loop_v6
412 pub fn multicast_loop_v6(&self) -> io::Result<bool> {
413 self.watcher.get_ref().multicast_loop_v6()
414 }
415
416 /// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
417 ///
418 /// Controls whether this socket sees the multicast packets it sends itself.
419 ///
420 /// # Note
421 ///
422 /// This may not have any affect on IPv4 sockets.
423 pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> {
424 self.watcher.get_ref().set_multicast_loop_v6(on)
425 }
426
427 /// Gets the value of the `IP_TTL` option for this socket.
428 ///
429 /// For more information about this option, see [`set_ttl`].
430 ///
431 /// [`set_ttl`]: #method.set_ttl
432 pub fn ttl(&self) -> io::Result<u32> {
433 self.watcher.get_ref().ttl()
434 }
435
436 /// Sets the value for the `IP_TTL` option on this socket.
437 ///
438 /// This value sets the time-to-live field that is used in every packet sent
439 /// from this socket.
440 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
441 self.watcher.get_ref().set_ttl(ttl)
442 }
443
444 /// Executes an operation of the `IP_ADD_MEMBERSHIP` type.
445 ///
446 /// This method specifies a new multicast group for this socket to join. The address must be
447 /// a valid multicast address, and `interface` is the address of the local interface with which
448 /// the system should join the multicast group. If it's equal to `INADDR_ANY` then an
449 /// appropriate interface is chosen by the system.
450 ///
451 /// # Examples
452 ///
453 /// ```no_run
454 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
455 /// #
456 /// use std::net::Ipv4Addr;
457 ///
458 /// use async_std::net::UdpSocket;
459 ///
460 /// let interface = Ipv4Addr::new(0, 0, 0, 0);
461 /// let mdns_addr = Ipv4Addr::new(224, 0, 0, 123);
462 ///
463 /// let socket = UdpSocket::bind("127.0.0.1:0").await?;
464 /// socket.join_multicast_v4(mdns_addr, interface)?;
465 /// #
466 /// # Ok(()) }) }
467 /// ```
468 pub fn join_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()> {
469 self.watcher
470 .get_ref()
471 .join_multicast_v4(&multiaddr, &interface)
472 }
473
474 /// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type.
475 ///
476 /// This method specifies a new multicast group for this socket to join. The address must be
477 /// a valid multicast address, and `interface` is the index of the interface to join/leave (or
478 /// 0 to indicate any interface).
479 ///
480 /// # Examples
481 ///
482 /// ```no_run
483 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
484 /// #
485 /// use std::net::{Ipv6Addr, SocketAddr};
486 ///
487 /// use async_std::net::UdpSocket;
488 ///
489 /// let socket_addr = SocketAddr::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).into(), 0);
490 /// let mdns_addr = Ipv6Addr::new(0xFF02, 0, 0, 0, 0, 0, 0, 0x0123);
491 /// let socket = UdpSocket::bind(&socket_addr).await?;
492 ///
493 /// socket.join_multicast_v6(&mdns_addr, 0)?;
494 /// #
495 /// # Ok(()) }) }
496 /// ```
497 pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
498 self.watcher
499 .get_ref()
500 .join_multicast_v6(multiaddr, interface)
501 }
502
503 /// Executes an operation of the `IP_DROP_MEMBERSHIP` type.
504 ///
505 /// For more information about this option, see [`join_multicast_v4`].
506 ///
507 /// [`join_multicast_v4`]: #method.join_multicast_v4
508 pub fn leave_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()> {
509 self.watcher
510 .get_ref()
511 .leave_multicast_v4(&multiaddr, &interface)
512 }
513
514 /// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type.
515 ///
516 /// For more information about this option, see [`join_multicast_v6`].
517 ///
518 /// [`join_multicast_v6`]: #method.join_multicast_v6
519 pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
520 self.watcher
521 .get_ref()
522 .leave_multicast_v6(multiaddr, interface)
523 }
524}
525
526impl From<std::net::UdpSocket> for UdpSocket {
527 /// Converts a `std::net::UdpSocket` into its asynchronous equivalent.
528 fn from(socket: std::net::UdpSocket) -> UdpSocket {
529 UdpSocket {
530 watcher: Async::new(socket).expect("UdpSocket is known to be good"),
531 }
532 }
533}
534
535impl std::convert::TryFrom<UdpSocket> for std::net::UdpSocket {
536 type Error = io::Error;
537 /// Converts a `UdpSocket` into its synchronous equivalent.
538 fn try_from(listener: UdpSocket) -> io::Result<std::net::UdpSocket> {
539 let inner = listener.watcher.into_inner()?;
540 inner.set_nonblocking(false)?;
541 Ok(inner)
542 }
543}
544
545cfg_unix! {
546 use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
547
548 impl AsRawFd for UdpSocket {
549 fn as_raw_fd(&self) -> RawFd {
550 self.watcher.get_ref().as_raw_fd()
551 }
552 }
553
554 impl FromRawFd for UdpSocket {
555 unsafe fn from_raw_fd(fd: RawFd) -> UdpSocket {
556 std::net::UdpSocket::from_raw_fd(fd).into()
557 }
558 }
559
560 impl IntoRawFd for UdpSocket {
561 fn into_raw_fd(self) -> RawFd {
562 self.watcher.into_inner().unwrap().into_raw_fd()
563 }
564 }
565
566 cfg_io_safety! {
567 use crate::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
568
569 impl AsFd for UdpSocket {
570 fn as_fd(&self) -> BorrowedFd<'_> {
571 self.watcher.get_ref().as_fd()
572 }
573 }
574
575 impl From<OwnedFd> for UdpSocket {
576 fn from(fd: OwnedFd) -> UdpSocket {
577 std::net::UdpSocket::from(fd).into()
578 }
579 }
580
581 impl From<UdpSocket> for OwnedFd {
582 fn from(stream: UdpSocket) -> OwnedFd {
583 stream.watcher.into_inner().unwrap().into()
584 }
585 }
586 }
587}
588
589cfg_windows! {
590 use crate::os::windows::io::{
591 RawSocket, AsRawSocket, IntoRawSocket, FromRawSocket
592 };
593
594 impl AsRawSocket for UdpSocket {
595 fn as_raw_socket(&self) -> RawSocket {
596 self.watcher.get_ref().as_raw_socket()
597 }
598 }
599
600 impl FromRawSocket for UdpSocket {
601 unsafe fn from_raw_socket(handle: RawSocket) -> UdpSocket {
602 std::net::UdpSocket::from_raw_socket(handle).into()
603 }
604 }
605
606 impl IntoRawSocket for UdpSocket {
607 fn into_raw_socket(self) -> RawSocket {
608 self.watcher.into_inner().unwrap().into_raw_socket()
609 }
610 }
611
612 cfg_io_safety! {
613 use crate::os::windows::io::{AsSocket, BorrowedSocket, OwnedSocket};
614
615 impl AsSocket for UdpSocket {
616 fn as_socket(&self) -> BorrowedSocket<'_> {
617 self.watcher.get_ref().as_socket()
618 }
619 }
620
621 impl From<OwnedSocket> for UdpSocket {
622 fn from(fd: OwnedSocket) -> UdpSocket {
623 std::net::UdpSocket::from(fd).into()
624 }
625 }
626
627 impl From<UdpSocket> for OwnedSocket {
628 fn from(stream: UdpSocket) -> OwnedSocket {
629 stream.watcher.into_inner().unwrap().into()
630 }
631 }
632 }
633}