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