mio/net/
udp.rs

1//! Primitives for working with UDP.
2//!
3//! The types provided in this module are non-blocking by default and are
4//! designed to be portable across all supported Mio platforms. As long as the
5//! [portability guidelines] are followed, the behavior should be identical no
6//! matter the target platform.
7//!
8//! [portability guidelines]: ../struct.Poll.html#portability
9
10use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
11#[cfg(any(unix, target_os = "wasi"))]
12use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
13// TODO: once <https://github.com/rust-lang/rust/issues/126198> is fixed this
14// can use `std::os::fd` and be merged with the above.
15#[cfg(target_os = "hermit")]
16use std::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
17#[cfg(windows)]
18use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
19use std::{fmt, io, net};
20
21use crate::io_source::IoSource;
22use crate::{event, sys, Interest, Registry, Token};
23
24/// A User Datagram Protocol socket.
25///
26/// This is an implementation of a bound UDP socket. This supports both IPv4 and
27/// IPv6 addresses, and there is no corresponding notion of a server because UDP
28/// is a datagram protocol.
29///
30/// # Examples
31///
32#[cfg_attr(feature = "os-poll", doc = "```")]
33#[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
34/// # use std::error::Error;
35/// #
36/// # fn main() -> Result<(), Box<dyn Error>> {
37/// // An Echo program:
38/// // SENDER -> sends a message.
39/// // ECHOER -> listens and prints the message received.
40///
41/// use mio::net::UdpSocket;
42/// use mio::{Events, Interest, Poll, Token};
43/// use std::time::Duration;
44///
45/// const SENDER: Token = Token(0);
46/// const ECHOER: Token = Token(1);
47///
48/// // This operation will fail if the address is in use, so we select different ports for each
49/// // socket.
50/// let mut sender_socket = UdpSocket::bind("127.0.0.1:0".parse()?)?;
51/// let mut echoer_socket = UdpSocket::bind("127.0.0.1:0".parse()?)?;
52///
53/// // If we do not use connect here, SENDER and ECHOER would need to call send_to and recv_from
54/// // respectively.
55/// sender_socket.connect(echoer_socket.local_addr()?)?;
56///
57/// // We need a Poll to check if SENDER is ready to be written into, and if ECHOER is ready to be
58/// // read from.
59/// let mut poll = Poll::new()?;
60///
61/// // We register our sockets here so that we can check if they are ready to be written/read.
62/// poll.registry().register(&mut sender_socket, SENDER, Interest::WRITABLE)?;
63/// poll.registry().register(&mut echoer_socket, ECHOER, Interest::READABLE)?;
64///
65/// let msg_to_send = [9; 9];
66/// let mut buffer = [0; 9];
67///
68/// let mut events = Events::with_capacity(128);
69/// loop {
70///     poll.poll(&mut events, Some(Duration::from_millis(100)))?;
71///     for event in events.iter() {
72///         match event.token() {
73///             // Our SENDER is ready to be written into.
74///             SENDER => {
75///                 let bytes_sent = sender_socket.send(&msg_to_send)?;
76///                 assert_eq!(bytes_sent, 9);
77///                 println!("sent {:?} -> {:?} bytes", msg_to_send, bytes_sent);
78///             },
79///             // Our ECHOER is ready to be read from.
80///             ECHOER => {
81///                 let num_recv = echoer_socket.recv(&mut buffer)?;
82///                 println!("echo {:?} -> {:?}", buffer, num_recv);
83///                 buffer = [0; 9];
84///                 # _ = buffer; // Silence unused assignment warning.
85///                 # return Ok(());
86///             }
87///             _ => unreachable!()
88///         }
89///     }
90/// }
91/// # }
92/// ```
93pub struct UdpSocket {
94    inner: IoSource<net::UdpSocket>,
95}
96
97impl UdpSocket {
98    /// Creates a UDP socket from the given address.
99    ///
100    /// # Examples
101    ///
102    #[cfg_attr(feature = "os-poll", doc = "```")]
103    #[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
104    /// # use std::error::Error;
105    /// #
106    /// # fn main() -> Result<(), Box<dyn Error>> {
107    /// use mio::net::UdpSocket;
108    ///
109    /// // We must bind it to an open address.
110    /// let socket = match UdpSocket::bind("127.0.0.1:0".parse()?) {
111    ///     Ok(new_socket) => new_socket,
112    ///     Err(fail) => {
113    ///         // We panic! here, but you could try to bind it again on another address.
114    ///         panic!("Failed to bind socket. {:?}", fail);
115    ///     }
116    /// };
117    ///
118    /// // Our socket was created, but we should not use it before checking it's readiness.
119    /// #    drop(socket); // Silence unused variable warning.
120    /// #    Ok(())
121    /// # }
122    /// ```
123    pub fn bind(addr: SocketAddr) -> io::Result<UdpSocket> {
124        sys::udp::bind(addr).map(UdpSocket::from_std)
125    }
126
127    /// Creates a new `UdpSocket` from a standard `net::UdpSocket`.
128    ///
129    /// This function is intended to be used to wrap a UDP socket from the
130    /// standard library in the Mio equivalent. The conversion assumes nothing
131    /// about the underlying socket; it is left up to the user to set it in
132    /// non-blocking mode.
133    pub fn from_std(socket: net::UdpSocket) -> UdpSocket {
134        UdpSocket {
135            inner: IoSource::new(socket),
136        }
137    }
138
139    /// Returns the socket address that this socket was created from.
140    ///
141    /// # Examples
142    ///
143    // This assertion is almost, but not quite, universal.  It fails on
144    // shared-IP FreeBSD jails.  It's hard for mio to know whether we're jailed,
145    // so simply disable the test on FreeBSD.
146    #[cfg_attr(all(feature = "os-poll", not(target_os = "freebsd")), doc = "```")]
147    #[cfg_attr(
148        any(not(feature = "os-poll"), target_os = "freebsd"),
149        doc = "```ignore"
150    )]
151    /// # use std::error::Error;
152    /// #
153    /// # fn main() -> Result<(), Box<dyn Error>> {
154    /// use mio::net::UdpSocket;
155    ///
156    /// let addr = "127.0.0.1:0".parse()?;
157    /// let socket = UdpSocket::bind(addr)?;
158    /// assert_eq!(socket.local_addr()?.ip(), addr.ip());
159    /// #    Ok(())
160    /// # }
161    /// ```
162    pub fn local_addr(&self) -> io::Result<SocketAddr> {
163        self.inner.local_addr()
164    }
165
166    /// Returns the socket address of the remote peer this socket was connected to.
167    ///
168    /// # Examples
169    ///
170    #[cfg_attr(feature = "os-poll", doc = "```")]
171    #[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
172    /// # use std::error::Error;
173    /// #
174    /// # fn main() -> Result<(), Box<dyn Error>> {
175    /// use mio::net::UdpSocket;
176    ///
177    /// let addr = "127.0.0.1:0".parse()?;
178    /// let peer_addr = "127.0.0.1:11100".parse()?;
179    /// let socket = UdpSocket::bind(addr)?;
180    /// socket.connect(peer_addr)?;
181    /// assert_eq!(socket.peer_addr()?.ip(), peer_addr.ip());
182    /// #    Ok(())
183    /// # }
184    /// ```
185    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
186        self.inner.peer_addr()
187    }
188
189    /// Sends data on the socket to the given address. On success, returns the
190    /// number of bytes written.
191    ///
192    /// Address type can be any implementor of `ToSocketAddrs` trait. See its
193    /// documentation for concrete examples.
194    ///
195    /// # Examples
196    ///
197    /// ```no_run
198    /// # use std::error::Error;
199    /// # fn main() -> Result<(), Box<dyn Error>> {
200    /// use mio::net::UdpSocket;
201    ///
202    /// let socket = UdpSocket::bind("127.0.0.1:0".parse()?)?;
203    ///
204    /// // We must check if the socket is writable before calling send_to,
205    /// // or we could run into a WouldBlock error.
206    ///
207    /// let bytes_sent = socket.send_to(&[9; 9], "127.0.0.1:11100".parse()?)?;
208    /// assert_eq!(bytes_sent, 9);
209    /// #
210    /// #    Ok(())
211    /// # }
212    /// ```
213    pub fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize> {
214        self.inner.do_io(|inner| inner.send_to(buf, target))
215    }
216
217    /// Receives data from the socket. On success, returns the number of bytes
218    /// read and the address from whence the data came.
219    ///
220    /// # Notes
221    ///
222    /// On Windows, if the data is larger than the buffer specified, the buffer
223    /// is filled with the first part of the data, and recv_from returns the error
224    /// WSAEMSGSIZE(10040). The excess data is lost.
225    /// Make sure to always use a sufficiently large buffer to hold the
226    /// maximum UDP packet size, which can be up to 65536 bytes in size.
227    ///
228    /// # Examples
229    ///
230    /// ```no_run
231    /// # use std::error::Error;
232    /// #
233    /// # fn main() -> Result<(), Box<dyn Error>> {
234    /// use mio::net::UdpSocket;
235    ///
236    /// let socket = UdpSocket::bind("127.0.0.1:0".parse()?)?;
237    ///
238    /// // We must check if the socket is readable before calling recv_from,
239    /// // or we could run into a WouldBlock error.
240    ///
241    /// let mut buf = [0; 9];
242    /// let (num_recv, from_addr) = socket.recv_from(&mut buf)?;
243    /// println!("Received {:?} -> {:?} bytes from {:?}", buf, num_recv, from_addr);
244    /// #
245    /// #    Ok(())
246    /// # }
247    /// ```
248    pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
249        self.inner.do_io(|inner| inner.recv_from(buf))
250    }
251
252    /// Receives data from the socket, without removing it from the input queue.
253    /// On success, returns the number of bytes read and the address from whence
254    /// the data came.
255    ///
256    /// # Notes
257    ///
258    /// On Windows, if the data is larger than the buffer specified, the buffer
259    /// is filled with the first part of the data, and peek_from returns the error
260    /// WSAEMSGSIZE(10040). The excess data is lost.
261    /// Make sure to always use a sufficiently large buffer to hold the
262    /// maximum UDP packet size, which can be up to 65536 bytes in size.
263    ///
264    /// # Examples
265    ///
266    /// ```no_run
267    /// # use std::error::Error;
268    /// #
269    /// # fn main() -> Result<(), Box<dyn Error>> {
270    /// use mio::net::UdpSocket;
271    ///
272    /// let socket = UdpSocket::bind("127.0.0.1:0".parse()?)?;
273    ///
274    /// // We must check if the socket is readable before calling recv_from,
275    /// // or we could run into a WouldBlock error.
276    ///
277    /// let mut buf = [0; 9];
278    /// let (num_recv, from_addr) = socket.peek_from(&mut buf)?;
279    /// println!("Received {:?} -> {:?} bytes from {:?}", buf, num_recv, from_addr);
280    /// #
281    /// #    Ok(())
282    /// # }
283    /// ```
284    pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
285        self.inner.do_io(|inner| inner.peek_from(buf))
286    }
287
288    /// Sends data on the socket to the address previously bound via connect(). On success,
289    /// returns the number of bytes written.
290    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
291        self.inner.do_io(|inner| inner.send(buf))
292    }
293
294    /// Receives data from the socket previously bound with connect(). On success, returns
295    /// the number of bytes read.
296    ///
297    /// # Notes
298    ///
299    /// On Windows, if the data is larger than the buffer specified, the buffer
300    /// is filled with the first part of the data, and recv returns the error
301    /// WSAEMSGSIZE(10040). The excess data is lost.
302    /// Make sure to always use a sufficiently large buffer to hold the
303    /// maximum UDP packet size, which can be up to 65536 bytes in size.
304    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
305        self.inner.do_io(|inner| inner.recv(buf))
306    }
307
308    /// Receives data from the socket, without removing it from the input queue.
309    /// On success, returns the number of bytes read.
310    ///
311    /// # Notes
312    ///
313    /// On Windows, if the data is larger than the buffer specified, the buffer
314    /// is filled with the first part of the data, and peek returns the error
315    /// WSAEMSGSIZE(10040). The excess data is lost.
316    /// Make sure to always use a sufficiently large buffer to hold the
317    /// maximum UDP packet size, which can be up to 65536 bytes in size.
318    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
319        self.inner.do_io(|inner| inner.peek(buf))
320    }
321
322    /// Connects the UDP socket setting the default destination for `send()`
323    /// and limiting packets that are read via `recv` from the address specified
324    /// in `addr`.
325    ///
326    /// This may return a `WouldBlock` in which case the socket connection
327    /// cannot be completed immediately, it usually means there are insufficient
328    /// entries in the routing cache.
329    pub fn connect(&self, addr: SocketAddr) -> io::Result<()> {
330        self.inner.connect(addr)
331    }
332
333    /// Sets the value of the `SO_BROADCAST` option for this socket.
334    ///
335    /// When enabled, this socket is allowed to send packets to a broadcast
336    /// address.
337    ///
338    /// # Examples
339    ///
340    #[cfg_attr(feature = "os-poll", doc = "```")]
341    #[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
342    /// # use std::error::Error;
343    /// #
344    /// # fn main() -> Result<(), Box<dyn Error>> {
345    /// use mio::net::UdpSocket;
346    ///
347    /// let broadcast_socket = UdpSocket::bind("127.0.0.1:0".parse()?)?;
348    /// if broadcast_socket.broadcast()? == false {
349    ///     broadcast_socket.set_broadcast(true)?;
350    /// }
351    ///
352    /// assert_eq!(broadcast_socket.broadcast()?, true);
353    /// #
354    /// #    Ok(())
355    /// # }
356    /// ```
357    pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
358        self.inner.set_broadcast(on)
359    }
360
361    /// Gets the value of the `SO_BROADCAST` option for this socket.
362    ///
363    /// For more information about this option, see
364    /// [`set_broadcast`][link].
365    ///
366    /// [link]: #method.set_broadcast
367    ///
368    /// # Examples
369    ///
370    #[cfg_attr(feature = "os-poll", doc = "```")]
371    #[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
372    /// # use std::error::Error;
373    /// #
374    /// # fn main() -> Result<(), Box<dyn Error>> {
375    /// use mio::net::UdpSocket;
376    ///
377    /// let broadcast_socket = UdpSocket::bind("127.0.0.1:0".parse()?)?;
378    /// assert_eq!(broadcast_socket.broadcast()?, false);
379    /// #
380    /// #    Ok(())
381    /// # }
382    /// ```
383    pub fn broadcast(&self) -> io::Result<bool> {
384        self.inner.broadcast()
385    }
386
387    /// Sets the value of the `IP_MULTICAST_LOOP` option for this socket.
388    ///
389    /// If enabled, multicast packets will be looped back to the local socket.
390    /// Note that this may not have any affect on IPv6 sockets.
391    pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> {
392        self.inner.set_multicast_loop_v4(on)
393    }
394
395    /// Gets the value of the `IP_MULTICAST_LOOP` option for this socket.
396    ///
397    /// For more information about this option, see
398    /// [`set_multicast_loop_v4`][link].
399    ///
400    /// [link]: #method.set_multicast_loop_v4
401    pub fn multicast_loop_v4(&self) -> io::Result<bool> {
402        self.inner.multicast_loop_v4()
403    }
404
405    /// Sets the value of the `IP_MULTICAST_TTL` option for this socket.
406    ///
407    /// Indicates the time-to-live value of outgoing multicast packets for
408    /// this socket. The default value is 1 which means that multicast packets
409    /// don't leave the local network unless explicitly requested.
410    ///
411    /// Note that this may not have any affect on IPv6 sockets.
412    pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
413        self.inner.set_multicast_ttl_v4(ttl)
414    }
415
416    /// Gets the value of the `IP_MULTICAST_TTL` option for this socket.
417    ///
418    /// For more information about this option, see
419    /// [`set_multicast_ttl_v4`][link].
420    ///
421    /// [link]: #method.set_multicast_ttl_v4
422    pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
423        self.inner.multicast_ttl_v4()
424    }
425
426    /// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
427    ///
428    /// Controls whether this socket sees the multicast packets it sends itself.
429    /// Note that this may not have any affect on IPv4 sockets.
430    pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> {
431        self.inner.set_multicast_loop_v6(on)
432    }
433
434    /// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
435    ///
436    /// For more information about this option, see
437    /// [`set_multicast_loop_v6`][link].
438    ///
439    /// [link]: #method.set_multicast_loop_v6
440    pub fn multicast_loop_v6(&self) -> io::Result<bool> {
441        self.inner.multicast_loop_v6()
442    }
443
444    /// Sets the value for the `IP_TTL` option on this socket.
445    ///
446    /// This value sets the time-to-live field that is used in every packet sent
447    /// from this socket.
448    ///
449    /// # Examples
450    ///
451    #[cfg_attr(feature = "os-poll", doc = "```")]
452    #[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
453    /// # use std::error::Error;
454    /// #
455    /// # fn main() -> Result<(), Box<dyn Error>> {
456    /// use mio::net::UdpSocket;
457    ///
458    /// let socket = UdpSocket::bind("127.0.0.1:0".parse()?)?;
459    /// if socket.ttl()? < 255 {
460    ///     socket.set_ttl(255)?;
461    /// }
462    ///
463    /// assert_eq!(socket.ttl()?, 255);
464    /// #
465    /// #    Ok(())
466    /// # }
467    /// ```
468    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
469        self.inner.set_ttl(ttl)
470    }
471
472    /// Gets the value of the `IP_TTL` option for this socket.
473    ///
474    /// For more information about this option, see [`set_ttl`][link].
475    ///
476    /// [link]: #method.set_ttl
477    ///
478    /// # Examples
479    ///
480    #[cfg_attr(feature = "os-poll", doc = "```")]
481    #[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
482    /// # use std::error::Error;
483    /// #
484    /// # fn main() -> Result<(), Box<dyn Error>> {
485    /// use mio::net::UdpSocket;
486    ///
487    /// let socket = UdpSocket::bind("127.0.0.1:0".parse()?)?;
488    /// socket.set_ttl(255)?;
489    ///
490    /// assert_eq!(socket.ttl()?, 255);
491    /// #
492    /// #    Ok(())
493    /// # }
494    /// ```
495    pub fn ttl(&self) -> io::Result<u32> {
496        self.inner.ttl()
497    }
498
499    /// Executes an operation of the `IP_ADD_MEMBERSHIP` type.
500    ///
501    /// This function specifies a new multicast group for this socket to join.
502    /// The address must be a valid multicast address, and `interface` is the
503    /// address of the local interface with which the system should join the
504    /// multicast group. If it's equal to `INADDR_ANY` then an appropriate
505    /// interface is chosen by the system.
506    #[allow(clippy::trivially_copy_pass_by_ref)]
507    pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
508        self.inner.join_multicast_v4(multiaddr, interface)
509    }
510
511    /// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type.
512    ///
513    /// This function specifies a new multicast group for this socket to join.
514    /// The address must be a valid multicast address, and `interface` is the
515    /// index of the interface to join/leave (or 0 to indicate any interface).
516    #[allow(clippy::trivially_copy_pass_by_ref)]
517    pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
518        self.inner.join_multicast_v6(multiaddr, interface)
519    }
520
521    /// Executes an operation of the `IP_DROP_MEMBERSHIP` type.
522    ///
523    /// For more information about this option, see
524    /// [`join_multicast_v4`][link].
525    ///
526    /// [link]: #method.join_multicast_v4
527    #[allow(clippy::trivially_copy_pass_by_ref)]
528    pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
529        self.inner.leave_multicast_v4(multiaddr, interface)
530    }
531
532    /// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type.
533    ///
534    /// For more information about this option, see
535    /// [`join_multicast_v6`][link].
536    ///
537    /// [link]: #method.join_multicast_v6
538    #[allow(clippy::trivially_copy_pass_by_ref)]
539    pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
540        self.inner.leave_multicast_v6(multiaddr, interface)
541    }
542
543    /// Get the value of the `IPV6_V6ONLY` option on this socket.
544    #[allow(clippy::trivially_copy_pass_by_ref)]
545    pub fn only_v6(&self) -> io::Result<bool> {
546        sys::udp::only_v6(&self.inner)
547    }
548
549    /// Get the value of the `SO_ERROR` option on this socket.
550    ///
551    /// This will retrieve the stored error in the underlying socket, clearing
552    /// the field in the process. This can be useful for checking errors between
553    /// calls.
554    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
555        self.inner.take_error()
556    }
557
558    /// Execute an I/O operation ensuring that the socket receives more events
559    /// if it hits a [`WouldBlock`] error.
560    ///
561    /// # Notes
562    ///
563    /// This method is required to be called for **all** I/O operations to
564    /// ensure the user will receive events once the socket is ready again after
565    /// returning a [`WouldBlock`] error.
566    ///
567    /// [`WouldBlock`]: io::ErrorKind::WouldBlock
568    ///
569    /// # Examples
570    ///
571    #[cfg_attr(unix, doc = "```no_run")]
572    #[cfg_attr(windows, doc = "```ignore")]
573    /// # use std::error::Error;
574    /// #
575    /// # fn main() -> Result<(), Box<dyn Error>> {
576    /// use std::io;
577    /// #[cfg(any(unix, target_os = "wasi"))]
578    /// use std::os::fd::AsRawFd;
579    /// #[cfg(windows)]
580    /// use std::os::windows::io::AsRawSocket;
581    /// use mio::net::UdpSocket;
582    ///
583    /// let address = "127.0.0.1:8080".parse().unwrap();
584    /// let dgram = UdpSocket::bind(address)?;
585    ///
586    /// // Wait until the dgram is readable...
587    ///
588    /// // Read from the dgram using a direct libc call, of course the
589    /// // `io::Read` implementation would be easier to use.
590    /// let mut buf = [0; 512];
591    /// let n = dgram.try_io(|| {
592    ///     let buf_ptr = &mut buf as *mut _ as *mut _;
593    ///     #[cfg(unix)]
594    ///     let res = unsafe { libc::recv(dgram.as_raw_fd(), buf_ptr, buf.len(), 0) };
595    ///     #[cfg(windows)]
596    ///     let res = unsafe { libc::recvfrom(dgram.as_raw_socket() as usize, buf_ptr, buf.len() as i32, 0, std::ptr::null_mut(), std::ptr::null_mut()) };
597    ///     if res != -1 {
598    ///         Ok(res as usize)
599    ///     } else {
600    ///         // If EAGAIN or EWOULDBLOCK is set by libc::recv, the closure
601    ///         // should return `WouldBlock` error.
602    ///         Err(io::Error::last_os_error())
603    ///     }
604    /// })?;
605    /// eprintln!("read {} bytes", n);
606    /// # Ok(())
607    /// # }
608    /// ```
609    pub fn try_io<F, T>(&self, f: F) -> io::Result<T>
610    where
611        F: FnOnce() -> io::Result<T>,
612    {
613        self.inner.do_io(|_| f())
614    }
615}
616
617impl event::Source for UdpSocket {
618    fn register(
619        &mut self,
620        registry: &Registry,
621        token: Token,
622        interests: Interest,
623    ) -> io::Result<()> {
624        self.inner.register(registry, token, interests)
625    }
626
627    fn reregister(
628        &mut self,
629        registry: &Registry,
630        token: Token,
631        interests: Interest,
632    ) -> io::Result<()> {
633        self.inner.reregister(registry, token, interests)
634    }
635
636    fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
637        self.inner.deregister(registry)
638    }
639}
640
641impl fmt::Debug for UdpSocket {
642    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
643        self.inner.fmt(f)
644    }
645}
646
647#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
648impl IntoRawFd for UdpSocket {
649    fn into_raw_fd(self) -> RawFd {
650        self.inner.into_inner().into_raw_fd()
651    }
652}
653
654#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
655impl AsRawFd for UdpSocket {
656    fn as_raw_fd(&self) -> RawFd {
657        self.inner.as_raw_fd()
658    }
659}
660
661#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
662impl FromRawFd for UdpSocket {
663    /// Converts a `RawFd` to a `UdpSocket`.
664    ///
665    /// # Notes
666    ///
667    /// The caller is responsible for ensuring that the socket is in
668    /// non-blocking mode.
669    unsafe fn from_raw_fd(fd: RawFd) -> UdpSocket {
670        UdpSocket::from_std(FromRawFd::from_raw_fd(fd))
671    }
672}
673
674#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
675impl AsFd for UdpSocket {
676    fn as_fd(&self) -> BorrowedFd<'_> {
677        self.inner.as_fd()
678    }
679}
680
681#[cfg(windows)]
682impl IntoRawSocket for UdpSocket {
683    fn into_raw_socket(self) -> RawSocket {
684        self.inner.into_inner().into_raw_socket()
685    }
686}
687
688#[cfg(windows)]
689impl AsRawSocket for UdpSocket {
690    fn as_raw_socket(&self) -> RawSocket {
691        self.inner.as_raw_socket()
692    }
693}
694
695#[cfg(windows)]
696impl FromRawSocket for UdpSocket {
697    /// Converts a `RawSocket` to a `UdpSocket`.
698    ///
699    /// # Notes
700    ///
701    /// The caller is responsible for ensuring that the socket is in
702    /// non-blocking mode.
703    unsafe fn from_raw_socket(socket: RawSocket) -> UdpSocket {
704        UdpSocket::from_std(FromRawSocket::from_raw_socket(socket))
705    }
706}
707
708impl From<UdpSocket> for net::UdpSocket {
709    fn from(socket: UdpSocket) -> Self {
710        // Safety: This is safe since we are extracting the raw fd from a well-constructed
711        // mio::net::UdpSocket which ensures that we actually pass in a valid file
712        // descriptor/socket
713        unsafe {
714            #[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
715            {
716                net::UdpSocket::from_raw_fd(socket.into_raw_fd())
717            }
718            #[cfg(windows)]
719            {
720                net::UdpSocket::from_raw_socket(socket.into_raw_socket())
721            }
722        }
723    }
724}