• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
10 use crate::io_source::IoSource;
11 use crate::{event, sys, Interest, Registry, Token};
12 
13 use std::fmt;
14 use std::io;
15 use std::net;
16 use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
17 #[cfg(unix)]
18 use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
19 #[cfg(windows)]
20 use 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 ///                 # drop(buffer); // Silence unused assignment warning.
83 ///                 # return Ok(());
84 ///             }
85 ///             _ => unreachable!()
86 ///         }
87 ///     }
88 /// }
89 /// # }
90 /// ```
91 pub struct UdpSocket {
92     inner: IoSource<net::UdpSocket>,
93 }
94 
95 impl 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     /// ```
bind(addr: SocketAddr) -> io::Result<UdpSocket>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.
from_std(socket: net::UdpSocket) -> UdpSocket131     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     /// ```
local_addr(&self) -> io::Result<SocketAddr>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     /// ```
peer_addr(&self) -> io::Result<SocketAddr>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     /// ```
send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize>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     /// ```
recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)>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     /// ```
peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)>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.
send(&self, buf: &[u8]) -> io::Result<usize>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.
recv(&self, buf: &mut [u8]) -> io::Result<usize>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.
peek(&self, buf: &mut [u8]) -> io::Result<usize>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.
connect(&self, addr: SocketAddr) -> io::Result<()>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     /// ```
set_broadcast(&self, on: bool) -> io::Result<()>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     /// ```
broadcast(&self) -> io::Result<bool>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.
set_multicast_loop_v4(&self, on: bool) -> io::Result<()>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
multicast_loop_v4(&self) -> io::Result<bool>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.
set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()>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
multicast_ttl_v4(&self) -> io::Result<u32>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.
set_multicast_loop_v6(&self, on: bool) -> io::Result<()>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
multicast_loop_v6(&self) -> io::Result<bool>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     /// ```
set_ttl(&self, ttl: u32) -> io::Result<()>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     /// ```
ttl(&self) -> io::Result<u32>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)]
join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()>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)]
join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>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)]
leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()>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)]
leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>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)]
only_v6(&self) -> io::Result<bool>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.
take_error(&self) -> io::Result<Option<io::Error>>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     /// ```
try_io<F, T>(&self, f: F) -> io::Result<T> where F: FnOnce() -> io::Result<T>,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 
615 impl event::Source for UdpSocket {
register( &mut self, registry: &Registry, token: Token, interests: Interest, ) -> io::Result<()>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 
reregister( &mut self, registry: &Registry, token: Token, interests: Interest, ) -> io::Result<()>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 
deregister(&mut self, registry: &Registry) -> io::Result<()>634     fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
635         self.inner.deregister(registry)
636     }
637 }
638 
639 impl fmt::Debug for UdpSocket {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result640     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
641         self.inner.fmt(f)
642     }
643 }
644 
645 #[cfg(unix)]
646 impl IntoRawFd for UdpSocket {
into_raw_fd(self) -> RawFd647     fn into_raw_fd(self) -> RawFd {
648         self.inner.into_inner().into_raw_fd()
649     }
650 }
651 
652 #[cfg(unix)]
653 impl AsRawFd for UdpSocket {
as_raw_fd(&self) -> RawFd654     fn as_raw_fd(&self) -> RawFd {
655         self.inner.as_raw_fd()
656     }
657 }
658 
659 #[cfg(unix)]
660 impl 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.
from_raw_fd(fd: RawFd) -> UdpSocket667     unsafe fn from_raw_fd(fd: RawFd) -> UdpSocket {
668         UdpSocket::from_std(FromRawFd::from_raw_fd(fd))
669     }
670 }
671 
672 #[cfg(windows)]
673 impl IntoRawSocket for UdpSocket {
into_raw_socket(self) -> RawSocket674     fn into_raw_socket(self) -> RawSocket {
675         self.inner.into_inner().into_raw_socket()
676     }
677 }
678 
679 #[cfg(windows)]
680 impl AsRawSocket for UdpSocket {
as_raw_socket(&self) -> RawSocket681     fn as_raw_socket(&self) -> RawSocket {
682         self.inner.as_raw_socket()
683     }
684 }
685 
686 #[cfg(windows)]
687 impl 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.
from_raw_socket(socket: RawSocket) -> UdpSocket694     unsafe fn from_raw_socket(socket: RawSocket) -> UdpSocket {
695         UdpSocket::from_std(FromRawSocket::from_raw_socket(socket))
696     }
697 }
698