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/// // 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/// ```
95pub struct UdpSocket {
96 inner: IoSource<net::UdpSocket>,
97}
98
99impl 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 /// ```
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.
135 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 /// ```
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 /// ```
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 /// ```
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 /// ```
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 /// ```
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.
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.
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.
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.
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 /// ```
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 /// ```
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.
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
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.
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
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.
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
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 /// ```
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 /// ```
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)]
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)]
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)]
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)]
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)]
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.
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 /// ```
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
619impl event::Source for UdpSocket {
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
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
638 fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
639 self.inner.deregister(registry)
640 }
641}
642
643impl fmt::Debug for UdpSocket {
644 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"))]
650impl IntoRawFd for UdpSocket {
651 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"))]
657impl AsRawFd for UdpSocket {
658 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"))]
664impl 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.
671 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"))]
677impl From<UdpSocket> for OwnedFd {
678 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"))]
684impl AsFd for UdpSocket {
685 fn as_fd(&self) -> BorrowedFd<'_> {
686 self.inner.as_fd()
687 }
688}
689
690#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
691impl 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.
698 fn from(fd: OwnedFd) -> Self {
699 UdpSocket::from_std(From::from(fd))
700 }
701}
702
703#[cfg(windows)]
704impl IntoRawSocket for UdpSocket {
705 fn into_raw_socket(self) -> RawSocket {
706 self.inner.into_inner().into_raw_socket()
707 }
708}
709
710#[cfg(windows)]
711impl AsRawSocket for UdpSocket {
712 fn as_raw_socket(&self) -> RawSocket {
713 self.inner.as_raw_socket()
714 }
715}
716
717#[cfg(windows)]
718impl 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.
725 unsafe fn from_raw_socket(socket: RawSocket) -> UdpSocket {
726 UdpSocket::from_std(FromRawSocket::from_raw_socket(socket))
727 }
728}
729
730#[cfg(windows)]
731impl From<UdpSocket> for OwnedSocket {
732 fn from(udp_socket: UdpSocket) -> Self {
733 udp_socket.inner.into_inner().into()
734 }
735}
736
737#[cfg(windows)]
738impl AsSocket for UdpSocket {
739 fn as_socket(&self) -> BorrowedSocket<'_> {
740 self.inner.as_socket()
741 }
742}
743
744#[cfg(windows)]
745impl 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.
752 fn from(socket: OwnedSocket) -> Self {
753 UdpSocket::from_std(From::from(socket))
754 }
755}
756
757impl From<UdpSocket> for net::UdpSocket {
758 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}