Coverage Report

Created: 2025-07-01 06:44

/rust/registry/src/index.crates.io-6f17d22bba15001f/mio-1.0.4/src/net/udp.rs
Line
Count
Source (jump to first uncovered line)
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
/// // 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(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
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(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
0
    pub fn local_addr(&self) -> io::Result<SocketAddr> {
165
0
        self.inner.local_addr()
166
0
    }
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
0
    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
188
0
        self.inner.peer_addr()
189
0
    }
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
0
    pub fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize> {
216
0
        self.inner.do_io(|inner| inner.send_to(buf, target))
217
0
    }
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
0
    pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
251
0
        self.inner.do_io(|inner| inner.recv_from(buf))
252
0
    }
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
0
    pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
287
0
        self.inner.do_io(|inner| inner.peek_from(buf))
288
0
    }
289
290
    /// Sends data on the socket to the address previously bound via connect(). On success,
291
    /// returns the number of bytes written.
292
0
    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
293
0
        self.inner.do_io(|inner| inner.send(buf))
294
0
    }
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
0
    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
307
0
        self.inner.do_io(|inner| inner.recv(buf))
308
0
    }
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
0
    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
321
0
        self.inner.do_io(|inner| inner.peek(buf))
322
0
    }
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
0
    pub fn connect(&self, addr: SocketAddr) -> io::Result<()> {
332
0
        self.inner.connect(addr)
333
0
    }
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
0
    pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
360
0
        self.inner.set_broadcast(on)
361
0
    }
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
0
    pub fn broadcast(&self) -> io::Result<bool> {
386
0
        self.inner.broadcast()
387
0
    }
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
0
    pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> {
394
0
        self.inner.set_multicast_loop_v4(on)
395
0
    }
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
0
    pub fn multicast_loop_v4(&self) -> io::Result<bool> {
404
0
        self.inner.multicast_loop_v4()
405
0
    }
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
0
    pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
415
0
        self.inner.set_multicast_ttl_v4(ttl)
416
0
    }
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
0
    pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
425
0
        self.inner.multicast_ttl_v4()
426
0
    }
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
0
    pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> {
433
0
        self.inner.set_multicast_loop_v6(on)
434
0
    }
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
0
    pub fn multicast_loop_v6(&self) -> io::Result<bool> {
443
0
        self.inner.multicast_loop_v6()
444
0
    }
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
0
    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
471
0
        self.inner.set_ttl(ttl)
472
0
    }
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
0
    pub fn ttl(&self) -> io::Result<u32> {
498
0
        self.inner.ttl()
499
0
    }
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
0
    pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
510
0
        self.inner.join_multicast_v4(multiaddr, interface)
511
0
    }
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
0
    pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
520
0
        self.inner.join_multicast_v6(multiaddr, interface)
521
0
    }
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
0
    pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
531
0
        self.inner.leave_multicast_v4(multiaddr, interface)
532
0
    }
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
0
    pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
542
0
        self.inner.leave_multicast_v6(multiaddr, interface)
543
0
    }
544
545
    /// Get the value of the `IPV6_V6ONLY` option on this socket.
546
    #[allow(clippy::trivially_copy_pass_by_ref)]
547
0
    pub fn only_v6(&self) -> io::Result<bool> {
548
0
        sys::udp::only_v6(&self.inner)
549
0
    }
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
0
    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
557
0
        self.inner.take_error()
558
0
    }
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
0
    pub fn try_io<F, T>(&self, f: F) -> io::Result<T>
612
0
    where
613
0
        F: FnOnce() -> io::Result<T>,
614
0
    {
615
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}
616
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::<_, _>
617
}
618
619
impl event::Source for UdpSocket {
620
0
    fn register(
621
0
        &mut self,
622
0
        registry: &Registry,
623
0
        token: Token,
624
0
        interests: Interest,
625
0
    ) -> io::Result<()> {
626
0
        self.inner.register(registry, token, interests)
627
0
    }
628
629
0
    fn reregister(
630
0
        &mut self,
631
0
        registry: &Registry,
632
0
        token: Token,
633
0
        interests: Interest,
634
0
    ) -> io::Result<()> {
635
0
        self.inner.reregister(registry, token, interests)
636
0
    }
637
638
0
    fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
639
0
        self.inner.deregister(registry)
640
0
    }
641
}
642
643
impl fmt::Debug for UdpSocket {
644
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
645
0
        self.inner.fmt(f)
646
0
    }
647
}
648
649
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
650
impl IntoRawFd for UdpSocket {
651
0
    fn into_raw_fd(self) -> RawFd {
652
0
        self.inner.into_inner().into_raw_fd()
653
0
    }
654
}
655
656
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
657
impl AsRawFd for UdpSocket {
658
0
    fn as_raw_fd(&self) -> RawFd {
659
0
        self.inner.as_raw_fd()
660
0
    }
661
}
662
663
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
664
impl 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
0
    unsafe fn from_raw_fd(fd: RawFd) -> UdpSocket {
672
0
        UdpSocket::from_std(FromRawFd::from_raw_fd(fd))
673
0
    }
674
}
675
676
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
677
impl From<UdpSocket> for OwnedFd {
678
0
    fn from(udp_socket: UdpSocket) -> Self {
679
0
        udp_socket.inner.into_inner().into()
680
0
    }
681
}
682
683
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
684
impl AsFd for UdpSocket {
685
0
    fn as_fd(&self) -> BorrowedFd<'_> {
686
0
        self.inner.as_fd()
687
0
    }
688
}
689
690
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
691
impl 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
0
    fn from(fd: OwnedFd) -> Self {
699
0
        UdpSocket::from_std(From::from(fd))
700
0
    }
701
}
702
703
#[cfg(windows)]
704
impl IntoRawSocket for UdpSocket {
705
    fn into_raw_socket(self) -> RawSocket {
706
        self.inner.into_inner().into_raw_socket()
707
    }
708
}
709
710
#[cfg(windows)]
711
impl AsRawSocket for UdpSocket {
712
    fn as_raw_socket(&self) -> RawSocket {
713
        self.inner.as_raw_socket()
714
    }
715
}
716
717
#[cfg(windows)]
718
impl 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)]
731
impl From<UdpSocket> for OwnedSocket {
732
    fn from(udp_socket: UdpSocket) -> Self {
733
        udp_socket.inner.into_inner().into()
734
    }
735
}
736
737
#[cfg(windows)]
738
impl AsSocket for UdpSocket {
739
    fn as_socket(&self) -> BorrowedSocket<'_> {
740
        self.inner.as_socket()
741
    }
742
}
743
744
#[cfg(windows)]
745
impl 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
757
impl From<UdpSocket> for net::UdpSocket {
758
0
    fn from(socket: UdpSocket) -> Self {
759
0
        // Safety: This is safe since we are extracting the raw fd from a well-constructed
760
0
        // mio::net::UdpSocket which ensures that we actually pass in a valid file
761
0
        // descriptor/socket
762
0
        unsafe {
763
0
            #[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
764
0
            {
765
0
                net::UdpSocket::from_raw_fd(socket.into_raw_fd())
766
0
            }
767
0
            #[cfg(windows)]
768
0
            {
769
0
                net::UdpSocket::from_raw_socket(socket.into_raw_socket())
770
0
            }
771
0
        }
772
0
    }
773
}