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