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