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