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 std::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
11 #[cfg(any(unix, target_os = "wasi"))]
12 use 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")]
16 use std::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
17 #[cfg(windows)]
18 use std::os::windows::io::{
19     AsRawSocket, AsSocket, BorrowedSocket, FromRawSocket, IntoRawSocket, OwnedSocket, RawSocket,
20 };
21 use std::{fmt, io, net};
22 
23 use crate::io_source::IoSource;
24 use 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 /// ```
95 pub struct UdpSocket {
96     inner: IoSource<net::UdpSocket>,
97 }
98 
99 impl 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     /// ```
bind(addr: SocketAddr) -> io::Result<UdpSocket>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.
from_std(socket: net::UdpSocket) -> UdpSocket135     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     /// ```
local_addr(&self) -> io::Result<SocketAddr>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     /// ```
peer_addr(&self) -> io::Result<SocketAddr>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     /// ```
send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize>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     /// ```
recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)>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     /// ```
peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)>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.
send(&self, buf: &[u8]) -> io::Result<usize>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.
recv(&self, buf: &mut [u8]) -> io::Result<usize>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.
peek(&self, buf: &mut [u8]) -> io::Result<usize>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.
connect(&self, addr: SocketAddr) -> io::Result<()>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     /// ```
set_broadcast(&self, on: bool) -> io::Result<()>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     /// ```
broadcast(&self) -> io::Result<bool>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.
set_multicast_loop_v4(&self, on: bool) -> io::Result<()>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
multicast_loop_v4(&self) -> io::Result<bool>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.
set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()>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
multicast_ttl_v4(&self) -> io::Result<u32>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.
set_multicast_loop_v6(&self, on: bool) -> io::Result<()>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
multicast_loop_v6(&self) -> io::Result<bool>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     /// ```
set_ttl(&self, ttl: u32) -> io::Result<()>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     /// ```
ttl(&self) -> io::Result<u32>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)]
join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()>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)]
join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>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)]
leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()>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)]
leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>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)]
only_v6(&self) -> io::Result<bool>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.
take_error(&self) -> io::Result<Option<io::Error>>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     /// ```
try_io<F, T>(&self, f: F) -> io::Result<T> where F: FnOnce() -> io::Result<T>,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 
619 impl event::Source for UdpSocket {
register( &mut self, registry: &Registry, token: Token, interests: Interest, ) -> io::Result<()>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 
reregister( &mut self, registry: &Registry, token: Token, interests: Interest, ) -> io::Result<()>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 
deregister(&mut self, registry: &Registry) -> io::Result<()>638     fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
639         self.inner.deregister(registry)
640     }
641 }
642 
643 impl fmt::Debug for UdpSocket {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result644     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"))]
650 impl IntoRawFd for UdpSocket {
into_raw_fd(self) -> RawFd651     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"))]
657 impl AsRawFd for UdpSocket {
as_raw_fd(&self) -> RawFd658     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"))]
664 impl 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.
from_raw_fd(fd: RawFd) -> UdpSocket671     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"))]
677 impl From<UdpSocket> for OwnedFd {
from(udp_socket: UdpSocket) -> Self678     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"))]
684 impl AsFd for UdpSocket {
as_fd(&self) -> BorrowedFd<'_>685     fn as_fd(&self) -> BorrowedFd<'_> {
686         self.inner.as_fd()
687     }
688 }
689 
690 #[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
691 impl 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.
from(fd: OwnedFd) -> Self698     fn from(fd: OwnedFd) -> Self {
699         UdpSocket::from_std(From::from(fd))
700     }
701 }
702 
703 #[cfg(windows)]
704 impl IntoRawSocket for UdpSocket {
into_raw_socket(self) -> RawSocket705     fn into_raw_socket(self) -> RawSocket {
706         self.inner.into_inner().into_raw_socket()
707     }
708 }
709 
710 #[cfg(windows)]
711 impl AsRawSocket for UdpSocket {
as_raw_socket(&self) -> RawSocket712     fn as_raw_socket(&self) -> RawSocket {
713         self.inner.as_raw_socket()
714     }
715 }
716 
717 #[cfg(windows)]
718 impl 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.
from_raw_socket(socket: RawSocket) -> UdpSocket725     unsafe fn from_raw_socket(socket: RawSocket) -> UdpSocket {
726         UdpSocket::from_std(FromRawSocket::from_raw_socket(socket))
727     }
728 }
729 
730 #[cfg(windows)]
731 impl From<UdpSocket> for OwnedSocket {
from(udp_socket: UdpSocket) -> Self732     fn from(udp_socket: UdpSocket) -> Self {
733         udp_socket.inner.into_inner().into()
734     }
735 }
736 
737 #[cfg(windows)]
738 impl AsSocket for UdpSocket {
as_socket(&self) -> BorrowedSocket<'_>739     fn as_socket(&self) -> BorrowedSocket<'_> {
740         self.inner.as_socket()
741     }
742 }
743 
744 #[cfg(windows)]
745 impl 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.
from(socket: OwnedSocket) -> Self752     fn from(socket: OwnedSocket) -> Self {
753         UdpSocket::from_std(From::from(socket))
754     }
755 }
756 
757 impl From<UdpSocket> for net::UdpSocket {
from(socket: UdpSocket) -> Self758     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 }
774