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