Coverage Report

Created: 2026-07-16 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/mio-1.2.2/src/net/udp.rs
Line
Count
Source
1
//! Primitives for working with UDP.
2
//!
3
//! The types provided in this module are non-blocking by default and are
4
//! designed to be portable across all supported Mio platforms. As long as the
5
//! [portability guidelines] are followed, the behavior should be identical no
6
//! matter the target platform.
7
//!
8
//! [portability guidelines]: ../struct.Poll.html#portability
9
10
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
11
#[cfg(any(unix, target_os = "wasi"))]
12
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
13
// TODO: once <https://github.com/rust-lang/rust/issues/126198> is fixed this
14
// can use `std::os::fd` and be merged with the above.
15
#[cfg(target_os = "hermit")]
16
use std::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
17
#[cfg(windows)]
18
use std::os::windows::io::{
19
    AsRawSocket, AsSocket, BorrowedSocket, FromRawSocket, IntoRawSocket, OwnedSocket, RawSocket,
20
};
21
use std::{fmt, io, net};
22
23
use crate::io_source::IoSource;
24
use crate::{event, sys, Interest, Registry, Token};
25
26
/// A User Datagram Protocol socket.
27
///
28
/// This is an implementation of a bound UDP socket. This supports both IPv4 and
29
/// IPv6 addresses, and there is no corresponding notion of a server because UDP
30
/// is a datagram protocol.
31
///
32
/// # Examples
33
///
34
#[cfg_attr(feature = "os-poll", doc = "```")]
35
#[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
36
/// # use std::error::Error;
37
/// #
38
/// # fn main() -> Result<(), Box<dyn Error>> {
39
/// # // 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
/// ```
97
pub struct UdpSocket {
98
    inner: IoSource<net::UdpSocket>,
99
}
100
101
impl 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
0
    pub fn bind(addr: SocketAddr) -> io::Result<UdpSocket> {
128
0
        sys::udp::bind(addr).map(UdpSocket::from_std)
129
0
    }
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
0
    pub fn from_std(socket: net::UdpSocket) -> UdpSocket {
138
0
        UdpSocket {
139
0
            inner: IoSource::new(socket),
140
0
        }
141
0
    }
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
0
    pub fn local_addr(&self) -> io::Result<SocketAddr> {
167
0
        self.inner.local_addr()
168
0
    }
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
0
    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
190
0
        self.inner.peer_addr()
191
0
    }
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
0
    pub fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize> {
218
0
        self.inner.do_io(|inner| inner.send_to(buf, target))
219
0
    }
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
0
    pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
253
0
        self.inner.do_io(|inner| inner.recv_from(buf))
254
0
    }
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
0
    pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
289
0
        self.inner.do_io(|inner| inner.peek_from(buf))
290
0
    }
291
292
    /// Sends data on the socket to the address previously bound via connect(). On success,
293
    /// returns the number of bytes written.
294
0
    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
295
0
        self.inner.do_io(|inner| inner.send(buf))
296
0
    }
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
0
    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
309
0
        self.inner.do_io(|inner| inner.recv(buf))
310
0
    }
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
0
    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
323
0
        self.inner.do_io(|inner| inner.peek(buf))
324
0
    }
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
0
    pub fn connect(&self, addr: SocketAddr) -> io::Result<()> {
334
0
        self.inner.connect(addr)
335
0
    }
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
0
    pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
364
0
        self.inner.set_broadcast(on)
365
0
    }
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
0
    pub fn broadcast(&self) -> io::Result<bool> {
392
0
        self.inner.broadcast()
393
0
    }
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
0
    pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> {
400
0
        self.inner.set_multicast_loop_v4(on)
401
0
    }
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
0
    pub fn multicast_loop_v4(&self) -> io::Result<bool> {
410
0
        self.inner.multicast_loop_v4()
411
0
    }
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
0
    pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
421
0
        self.inner.set_multicast_ttl_v4(ttl)
422
0
    }
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
0
    pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
431
0
        self.inner.multicast_ttl_v4()
432
0
    }
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
0
    pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> {
439
0
        self.inner.set_multicast_loop_v6(on)
440
0
    }
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
0
    pub fn multicast_loop_v6(&self) -> io::Result<bool> {
449
0
        self.inner.multicast_loop_v6()
450
0
    }
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
0
    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
477
0
        self.inner.set_ttl(ttl)
478
0
    }
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
0
    pub fn ttl(&self) -> io::Result<u32> {
504
0
        self.inner.ttl()
505
0
    }
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
0
    pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
516
0
        self.inner.join_multicast_v4(multiaddr, interface)
517
0
    }
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
0
    pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
526
0
        self.inner.join_multicast_v6(multiaddr, interface)
527
0
    }
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
0
    pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
537
0
        self.inner.leave_multicast_v4(multiaddr, interface)
538
0
    }
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
0
    pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
548
0
        self.inner.leave_multicast_v6(multiaddr, interface)
549
0
    }
550
551
    /// Get the value of the `IPV6_V6ONLY` option on this socket.
552
    #[allow(clippy::trivially_copy_pass_by_ref)]
553
0
    pub fn only_v6(&self) -> io::Result<bool> {
554
0
        sys::udp::only_v6(&self.inner)
555
0
    }
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
0
    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
563
0
        self.inner.take_error()
564
0
    }
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
0
    pub fn try_io<F, T>(&self, f: F) -> io::Result<T>
618
0
    where
619
0
        F: FnOnce() -> io::Result<T>,
620
    {
621
0
        self.inner.do_io(|_| f())
Unexecuted instantiation: <mio::net::udp::UdpSocket>::try_io::<<tokio::net::udp::UdpSocket>::peek_sender_inner::{closure#0}, core::net::socket_addr::SocketAddr>::{closure#0}
Unexecuted instantiation: <mio::net::udp::UdpSocket>::try_io::<_, _>::{closure#0}
622
0
    }
Unexecuted instantiation: <mio::net::udp::UdpSocket>::try_io::<<tokio::net::udp::UdpSocket>::peek_sender_inner::{closure#0}, core::net::socket_addr::SocketAddr>
Unexecuted instantiation: <mio::net::udp::UdpSocket>::try_io::<_, _>
623
}
624
625
impl event::Source for UdpSocket {
626
0
    fn register(
627
0
        &mut self,
628
0
        registry: &Registry,
629
0
        token: Token,
630
0
        interests: Interest,
631
0
    ) -> io::Result<()> {
632
0
        self.inner.register(registry, token, interests)
633
0
    }
634
635
0
    fn reregister(
636
0
        &mut self,
637
0
        registry: &Registry,
638
0
        token: Token,
639
0
        interests: Interest,
640
0
    ) -> io::Result<()> {
641
0
        self.inner.reregister(registry, token, interests)
642
0
    }
643
644
0
    fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
645
0
        self.inner.deregister(registry)
646
0
    }
647
}
648
649
impl fmt::Debug for UdpSocket {
650
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
651
0
        self.inner.fmt(f)
652
0
    }
653
}
654
655
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
656
impl IntoRawFd for UdpSocket {
657
0
    fn into_raw_fd(self) -> RawFd {
658
0
        self.inner.into_inner().into_raw_fd()
659
0
    }
660
}
661
662
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
663
impl AsRawFd for UdpSocket {
664
0
    fn as_raw_fd(&self) -> RawFd {
665
0
        self.inner.as_raw_fd()
666
0
    }
667
}
668
669
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
670
impl 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
0
    unsafe fn from_raw_fd(fd: RawFd) -> UdpSocket {
678
0
        UdpSocket::from_std(FromRawFd::from_raw_fd(fd))
679
0
    }
680
}
681
682
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
683
impl From<UdpSocket> for OwnedFd {
684
0
    fn from(udp_socket: UdpSocket) -> Self {
685
0
        udp_socket.inner.into_inner().into()
686
0
    }
687
}
688
689
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
690
impl AsFd for UdpSocket {
691
0
    fn as_fd(&self) -> BorrowedFd<'_> {
692
0
        self.inner.as_fd()
693
0
    }
694
}
695
696
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
697
impl 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
0
    fn from(fd: OwnedFd) -> Self {
705
0
        UdpSocket::from_std(From::from(fd))
706
0
    }
707
}
708
709
#[cfg(windows)]
710
impl IntoRawSocket for UdpSocket {
711
    fn into_raw_socket(self) -> RawSocket {
712
        self.inner.into_inner().into_raw_socket()
713
    }
714
}
715
716
#[cfg(windows)]
717
impl AsRawSocket for UdpSocket {
718
    fn as_raw_socket(&self) -> RawSocket {
719
        self.inner.as_raw_socket()
720
    }
721
}
722
723
#[cfg(windows)]
724
impl 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)]
737
impl From<UdpSocket> for OwnedSocket {
738
    fn from(udp_socket: UdpSocket) -> Self {
739
        udp_socket.inner.into_inner().into()
740
    }
741
}
742
743
#[cfg(windows)]
744
impl AsSocket for UdpSocket {
745
    fn as_socket(&self) -> BorrowedSocket<'_> {
746
        self.inner.as_socket()
747
    }
748
}
749
750
#[cfg(windows)]
751
impl 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
763
impl From<UdpSocket> for net::UdpSocket {
764
0
    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
0
                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
0
    }
779
}