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