Coverage Report

Created: 2026-10-17 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/mio-1.2.4/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(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
/// ```
95
pub struct UdpSocket {
96
    inner: IoSource<net::UdpSocket>,
97
}
98
99
impl 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
0
    pub fn bind(addr: SocketAddr) -> io::Result<UdpSocket> {
126
0
        sys::udp::bind(addr).map(UdpSocket::from_std)
127
0
    }
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
0
    pub fn from_std(socket: net::UdpSocket) -> UdpSocket {
136
0
        UdpSocket {
137
0
            inner: IoSource::new(socket),
138
0
        }
139
0
    }
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
0
    pub fn local_addr(&self) -> io::Result<SocketAddr> {
168
0
        self.inner.local_addr()
169
0
    }
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
0
    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
191
0
        self.inner.peer_addr()
192
0
    }
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
0
    pub fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize> {
219
0
        self.inner.do_io(|inner| inner.send_to(buf, target))
220
0
    }
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
0
    pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
254
0
        self.inner.do_io(|inner| inner.recv_from(buf))
255
0
    }
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
0
    pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
290
0
        self.inner.do_io(|inner| inner.peek_from(buf))
291
0
    }
292
293
    /// Sends data on the socket to the address previously bound via connect(). On success,
294
    /// returns the number of bytes written.
295
0
    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
296
0
        self.inner.do_io(|inner| inner.send(buf))
297
0
    }
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
0
    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
310
0
        self.inner.do_io(|inner| inner.recv(buf))
311
0
    }
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
0
    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
324
0
        self.inner.do_io(|inner| inner.peek(buf))
325
0
    }
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
0
    pub fn connect(&self, addr: SocketAddr) -> io::Result<()> {
335
0
        self.inner.connect(addr)
336
0
    }
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
0
    pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
365
0
        self.inner.set_broadcast(on)
366
0
    }
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
0
    pub fn broadcast(&self) -> io::Result<bool> {
393
0
        self.inner.broadcast()
394
0
    }
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
0
    pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> {
401
0
        self.inner.set_multicast_loop_v4(on)
402
0
    }
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
0
    pub fn multicast_loop_v4(&self) -> io::Result<bool> {
411
0
        self.inner.multicast_loop_v4()
412
0
    }
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
0
    pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
422
0
        self.inner.set_multicast_ttl_v4(ttl)
423
0
    }
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
0
    pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
432
0
        self.inner.multicast_ttl_v4()
433
0
    }
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
0
    pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> {
440
0
        self.inner.set_multicast_loop_v6(on)
441
0
    }
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
0
    pub fn multicast_loop_v6(&self) -> io::Result<bool> {
450
0
        self.inner.multicast_loop_v6()
451
0
    }
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
0
    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
478
0
        self.inner.set_ttl(ttl)
479
0
    }
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
0
    pub fn ttl(&self) -> io::Result<u32> {
505
0
        self.inner.ttl()
506
0
    }
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
0
    pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
517
0
        self.inner.join_multicast_v4(multiaddr, interface)
518
0
    }
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
0
    pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
527
0
        self.inner.join_multicast_v6(multiaddr, interface)
528
0
    }
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
0
    pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
538
0
        self.inner.leave_multicast_v4(multiaddr, interface)
539
0
    }
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
0
    pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
549
0
        self.inner.leave_multicast_v6(multiaddr, interface)
550
0
    }
551
552
    /// Get the value of the `IPV6_V6ONLY` option on this socket.
553
    #[allow(clippy::trivially_copy_pass_by_ref)]
554
0
    pub fn only_v6(&self) -> io::Result<bool> {
555
0
        sys::udp::only_v6(&self.inner)
556
0
    }
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
0
    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
564
0
        self.inner.take_error()
565
0
    }
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
0
    pub fn try_io<F, T>(&self, f: F) -> io::Result<T>
619
0
    where
620
0
        F: FnOnce() -> io::Result<T>,
621
    {
622
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}
623
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::<_, _>
624
}
625
626
impl event::Source for UdpSocket {
627
0
    fn register(
628
0
        &mut self,
629
0
        registry: &Registry,
630
0
        token: Token,
631
0
        interests: Interest,
632
0
    ) -> io::Result<()> {
633
0
        self.inner.register(registry, token, interests)
634
0
    }
635
636
0
    fn reregister(
637
0
        &mut self,
638
0
        registry: &Registry,
639
0
        token: Token,
640
0
        interests: Interest,
641
0
    ) -> io::Result<()> {
642
0
        self.inner.reregister(registry, token, interests)
643
0
    }
644
645
0
    fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
646
0
        self.inner.deregister(registry)
647
0
    }
648
}
649
650
impl fmt::Debug for UdpSocket {
651
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
652
0
        self.inner.fmt(f)
653
0
    }
654
}
655
656
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
657
impl IntoRawFd for UdpSocket {
658
0
    fn into_raw_fd(self) -> RawFd {
659
0
        self.inner.into_inner().into_raw_fd()
660
0
    }
661
}
662
663
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
664
impl AsRawFd for UdpSocket {
665
0
    fn as_raw_fd(&self) -> RawFd {
666
0
        self.inner.as_raw_fd()
667
0
    }
668
}
669
670
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
671
impl 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
0
    unsafe fn from_raw_fd(fd: RawFd) -> UdpSocket {
679
0
        UdpSocket::from_std(FromRawFd::from_raw_fd(fd))
680
0
    }
681
}
682
683
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
684
impl From<UdpSocket> for OwnedFd {
685
0
    fn from(udp_socket: UdpSocket) -> Self {
686
0
        udp_socket.inner.into_inner().into()
687
0
    }
688
}
689
690
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
691
impl AsFd for UdpSocket {
692
0
    fn as_fd(&self) -> BorrowedFd<'_> {
693
0
        self.inner.as_fd()
694
0
    }
695
}
696
697
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
698
impl 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
0
    fn from(fd: OwnedFd) -> Self {
706
0
        UdpSocket::from_std(From::from(fd))
707
0
    }
708
}
709
710
#[cfg(windows)]
711
impl IntoRawSocket for UdpSocket {
712
    fn into_raw_socket(self) -> RawSocket {
713
        self.inner.into_inner().into_raw_socket()
714
    }
715
}
716
717
#[cfg(windows)]
718
impl AsRawSocket for UdpSocket {
719
    fn as_raw_socket(&self) -> RawSocket {
720
        self.inner.as_raw_socket()
721
    }
722
}
723
724
#[cfg(windows)]
725
impl 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)]
738
impl From<UdpSocket> for OwnedSocket {
739
    fn from(udp_socket: UdpSocket) -> Self {
740
        udp_socket.inner.into_inner().into()
741
    }
742
}
743
744
#[cfg(windows)]
745
impl AsSocket for UdpSocket {
746
    fn as_socket(&self) -> BorrowedSocket<'_> {
747
        self.inner.as_socket()
748
    }
749
}
750
751
#[cfg(windows)]
752
impl 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
764
impl From<UdpSocket> for net::UdpSocket {
765
0
    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
0
                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
0
    }
780
}