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