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 crate::io_source::IoSource; |
11 | use crate::{event, sys, Interest, Registry, Token}; |
12 | |
13 | use std::fmt; |
14 | use std::io; |
15 | use std::net; |
16 | use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr}; |
17 | #[cfg (unix)] |
18 | use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; |
19 | #[cfg (windows)] |
20 | use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket}; |
21 | |
22 | /// A User Datagram Protocol socket. |
23 | /// |
24 | /// This is an implementation of a bound UDP socket. This supports both IPv4 and |
25 | /// IPv6 addresses, and there is no corresponding notion of a server because UDP |
26 | /// is a datagram protocol. |
27 | /// |
28 | /// # Examples |
29 | /// |
30 | #[cfg_attr (feature = "os-poll" , doc = "```" )] |
31 | #[cfg_attr (not(feature = "os-poll" ), doc = "```ignore" )] |
32 | /// # use std::error::Error; |
33 | /// # |
34 | /// # fn main() -> Result<(), Box<dyn Error>> { |
35 | /// // An Echo program: |
36 | /// // SENDER -> sends a message. |
37 | /// // ECHOER -> listens and prints the message received. |
38 | /// |
39 | /// use mio::net::UdpSocket; |
40 | /// use mio::{Events, Interest, Poll, Token}; |
41 | /// use std::time::Duration; |
42 | /// |
43 | /// const SENDER: Token = Token(0); |
44 | /// const ECHOER: Token = Token(1); |
45 | /// |
46 | /// // This operation will fail if the address is in use, so we select different ports for each |
47 | /// // socket. |
48 | /// let mut sender_socket = UdpSocket::bind("127.0.0.1:0" .parse()?)?; |
49 | /// let mut echoer_socket = UdpSocket::bind("127.0.0.1:0" .parse()?)?; |
50 | /// |
51 | /// // If we do not use connect here, SENDER and ECHOER would need to call send_to and recv_from |
52 | /// // respectively. |
53 | /// sender_socket.connect(echoer_socket.local_addr()?)?; |
54 | /// |
55 | /// // We need a Poll to check if SENDER is ready to be written into, and if ECHOER is ready to be |
56 | /// // read from. |
57 | /// let mut poll = Poll::new()?; |
58 | /// |
59 | /// // We register our sockets here so that we can check if they are ready to be written/read. |
60 | /// poll.registry().register(&mut sender_socket, SENDER, Interest::WRITABLE)?; |
61 | /// poll.registry().register(&mut echoer_socket, ECHOER, Interest::READABLE)?; |
62 | /// |
63 | /// let msg_to_send = [9; 9]; |
64 | /// let mut buffer = [0; 9]; |
65 | /// |
66 | /// let mut events = Events::with_capacity(128); |
67 | /// loop { |
68 | /// poll.poll(&mut events, Some(Duration::from_millis(100)))?; |
69 | /// for event in events.iter() { |
70 | /// match event.token() { |
71 | /// // Our SENDER is ready to be written into. |
72 | /// SENDER => { |
73 | /// let bytes_sent = sender_socket.send(&msg_to_send)?; |
74 | /// assert_eq!(bytes_sent, 9); |
75 | /// println!("sent {:?} -> {:?} bytes" , msg_to_send, bytes_sent); |
76 | /// }, |
77 | /// // Our ECHOER is ready to be read from. |
78 | /// ECHOER => { |
79 | /// let num_recv = echoer_socket.recv(&mut buffer)?; |
80 | /// println!("echo {:?} -> {:?}" , buffer, num_recv); |
81 | /// buffer = [0; 9]; |
82 | /// # _ = buffer; // Silence unused assignment warning. |
83 | /// # return Ok(()); |
84 | /// } |
85 | /// _ => unreachable!() |
86 | /// } |
87 | /// } |
88 | /// } |
89 | /// # } |
90 | /// ``` |
91 | pub struct UdpSocket { |
92 | inner: IoSource<net::UdpSocket>, |
93 | } |
94 | |
95 | impl UdpSocket { |
96 | /// Creates a UDP socket from the given address. |
97 | /// |
98 | /// # Examples |
99 | /// |
100 | #[cfg_attr (feature = "os-poll" , doc = "```" )] |
101 | #[cfg_attr (not(feature = "os-poll" ), doc = "```ignore" )] |
102 | /// # use std::error::Error; |
103 | /// # |
104 | /// # fn main() -> Result<(), Box<dyn Error>> { |
105 | /// use mio::net::UdpSocket; |
106 | /// |
107 | /// // We must bind it to an open address. |
108 | /// let socket = match UdpSocket::bind("127.0.0.1:0" .parse()?) { |
109 | /// Ok(new_socket) => new_socket, |
110 | /// Err(fail) => { |
111 | /// // We panic! here, but you could try to bind it again on another address. |
112 | /// panic!("Failed to bind socket. {:?}" , fail); |
113 | /// } |
114 | /// }; |
115 | /// |
116 | /// // Our socket was created, but we should not use it before checking it's readiness. |
117 | /// # drop(socket); // Silence unused variable warning. |
118 | /// # Ok(()) |
119 | /// # } |
120 | /// ``` |
121 | pub fn bind(addr: SocketAddr) -> io::Result<UdpSocket> { |
122 | sys::udp::bind(addr).map(UdpSocket::from_std) |
123 | } |
124 | |
125 | /// Creates a new `UdpSocket` from a standard `net::UdpSocket`. |
126 | /// |
127 | /// This function is intended to be used to wrap a UDP socket from the |
128 | /// standard library in the Mio equivalent. The conversion assumes nothing |
129 | /// about the underlying socket; it is left up to the user to set it in |
130 | /// non-blocking mode. |
131 | pub fn from_std(socket: net::UdpSocket) -> UdpSocket { |
132 | UdpSocket { |
133 | inner: IoSource::new(socket), |
134 | } |
135 | } |
136 | |
137 | /// Returns the socket address that this socket was created from. |
138 | /// |
139 | /// # Examples |
140 | /// |
141 | // This assertion is almost, but not quite, universal. It fails on |
142 | // shared-IP FreeBSD jails. It's hard for mio to know whether we're jailed, |
143 | // so simply disable the test on FreeBSD. |
144 | #[cfg_attr (all(feature = "os-poll" , not(target_os = "freebsd" )), doc = "```" )] |
145 | #[cfg_attr ( |
146 | any(not(feature = "os-poll" ), target_os = "freebsd" ), |
147 | doc = "```ignore" |
148 | )] |
149 | /// # use std::error::Error; |
150 | /// # |
151 | /// # fn main() -> Result<(), Box<dyn Error>> { |
152 | /// use mio::net::UdpSocket; |
153 | /// |
154 | /// let addr = "127.0.0.1:0" .parse()?; |
155 | /// let socket = UdpSocket::bind(addr)?; |
156 | /// assert_eq!(socket.local_addr()?.ip(), addr.ip()); |
157 | /// # Ok(()) |
158 | /// # } |
159 | /// ``` |
160 | pub fn local_addr(&self) -> io::Result<SocketAddr> { |
161 | self.inner.local_addr() |
162 | } |
163 | |
164 | /// Returns the socket address of the remote peer this socket was connected to. |
165 | /// |
166 | /// # Examples |
167 | /// |
168 | #[cfg_attr (feature = "os-poll" , doc = "```" )] |
169 | #[cfg_attr (not(feature = "os-poll" ), doc = "```ignore" )] |
170 | /// # use std::error::Error; |
171 | /// # |
172 | /// # fn main() -> Result<(), Box<dyn Error>> { |
173 | /// use mio::net::UdpSocket; |
174 | /// |
175 | /// let addr = "127.0.0.1:0" .parse()?; |
176 | /// let peer_addr = "127.0.0.1:11100" .parse()?; |
177 | /// let socket = UdpSocket::bind(addr)?; |
178 | /// socket.connect(peer_addr)?; |
179 | /// assert_eq!(socket.peer_addr()?.ip(), peer_addr.ip()); |
180 | /// # Ok(()) |
181 | /// # } |
182 | /// ``` |
183 | pub fn peer_addr(&self) -> io::Result<SocketAddr> { |
184 | self.inner.peer_addr() |
185 | } |
186 | |
187 | /// Sends data on the socket to the given address. On success, returns the |
188 | /// number of bytes written. |
189 | /// |
190 | /// Address type can be any implementor of `ToSocketAddrs` trait. See its |
191 | /// documentation for concrete examples. |
192 | /// |
193 | /// # Examples |
194 | /// |
195 | /// ```no_run |
196 | /// # use std::error::Error; |
197 | /// # fn main() -> Result<(), Box<dyn Error>> { |
198 | /// use mio::net::UdpSocket; |
199 | /// |
200 | /// let socket = UdpSocket::bind("127.0.0.1:0" .parse()?)?; |
201 | /// |
202 | /// // We must check if the socket is writable before calling send_to, |
203 | /// // or we could run into a WouldBlock error. |
204 | /// |
205 | /// let bytes_sent = socket.send_to(&[9; 9], "127.0.0.1:11100" .parse()?)?; |
206 | /// assert_eq!(bytes_sent, 9); |
207 | /// # |
208 | /// # Ok(()) |
209 | /// # } |
210 | /// ``` |
211 | pub fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize> { |
212 | self.inner.do_io(|inner| inner.send_to(buf, target)) |
213 | } |
214 | |
215 | /// Receives data from the socket. On success, returns the number of bytes |
216 | /// read and the address from whence the data came. |
217 | /// |
218 | /// # Notes |
219 | /// |
220 | /// On Windows, if the data is larger than the buffer specified, the buffer |
221 | /// is filled with the first part of the data, and recv_from returns the error |
222 | /// WSAEMSGSIZE(10040). The excess data is lost. |
223 | /// Make sure to always use a sufficiently large buffer to hold the |
224 | /// maximum UDP packet size, which can be up to 65536 bytes in size. |
225 | /// |
226 | /// # Examples |
227 | /// |
228 | /// ```no_run |
229 | /// # use std::error::Error; |
230 | /// # |
231 | /// # fn main() -> Result<(), Box<dyn Error>> { |
232 | /// use mio::net::UdpSocket; |
233 | /// |
234 | /// let socket = UdpSocket::bind("127.0.0.1:0" .parse()?)?; |
235 | /// |
236 | /// // We must check if the socket is readable before calling recv_from, |
237 | /// // or we could run into a WouldBlock error. |
238 | /// |
239 | /// let mut buf = [0; 9]; |
240 | /// let (num_recv, from_addr) = socket.recv_from(&mut buf)?; |
241 | /// println!("Received {:?} -> {:?} bytes from {:?}" , buf, num_recv, from_addr); |
242 | /// # |
243 | /// # Ok(()) |
244 | /// # } |
245 | /// ``` |
246 | pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { |
247 | self.inner.do_io(|inner| inner.recv_from(buf)) |
248 | } |
249 | |
250 | /// Receives data from the socket, without removing it from the input queue. |
251 | /// On success, returns the number of bytes read and the address from whence |
252 | /// the data came. |
253 | /// |
254 | /// # Notes |
255 | /// |
256 | /// On Windows, if the data is larger than the buffer specified, the buffer |
257 | /// is filled with the first part of the data, and peek_from returns the error |
258 | /// WSAEMSGSIZE(10040). The excess data is lost. |
259 | /// Make sure to always use a sufficiently large buffer to hold the |
260 | /// maximum UDP packet size, which can be up to 65536 bytes in size. |
261 | /// |
262 | /// # Examples |
263 | /// |
264 | /// ```no_run |
265 | /// # use std::error::Error; |
266 | /// # |
267 | /// # fn main() -> Result<(), Box<dyn Error>> { |
268 | /// use mio::net::UdpSocket; |
269 | /// |
270 | /// let socket = UdpSocket::bind("127.0.0.1:0" .parse()?)?; |
271 | /// |
272 | /// // We must check if the socket is readable before calling recv_from, |
273 | /// // or we could run into a WouldBlock error. |
274 | /// |
275 | /// let mut buf = [0; 9]; |
276 | /// let (num_recv, from_addr) = socket.peek_from(&mut buf)?; |
277 | /// println!("Received {:?} -> {:?} bytes from {:?}" , buf, num_recv, from_addr); |
278 | /// # |
279 | /// # Ok(()) |
280 | /// # } |
281 | /// ``` |
282 | pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { |
283 | self.inner.do_io(|inner| inner.peek_from(buf)) |
284 | } |
285 | |
286 | /// Sends data on the socket to the address previously bound via connect(). On success, |
287 | /// returns the number of bytes written. |
288 | pub fn send(&self, buf: &[u8]) -> io::Result<usize> { |
289 | self.inner.do_io(|inner| inner.send(buf)) |
290 | } |
291 | |
292 | /// Receives data from the socket previously bound with connect(). On success, returns |
293 | /// the number of bytes read. |
294 | /// |
295 | /// # Notes |
296 | /// |
297 | /// On Windows, if the data is larger than the buffer specified, the buffer |
298 | /// is filled with the first part of the data, and recv returns the error |
299 | /// WSAEMSGSIZE(10040). The excess data is lost. |
300 | /// Make sure to always use a sufficiently large buffer to hold the |
301 | /// maximum UDP packet size, which can be up to 65536 bytes in size. |
302 | pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> { |
303 | self.inner.do_io(|inner| inner.recv(buf)) |
304 | } |
305 | |
306 | /// Receives data from the socket, without removing it from the input queue. |
307 | /// On success, returns the number of bytes read. |
308 | /// |
309 | /// # Notes |
310 | /// |
311 | /// On Windows, if the data is larger than the buffer specified, the buffer |
312 | /// is filled with the first part of the data, and peek returns the error |
313 | /// WSAEMSGSIZE(10040). The excess data is lost. |
314 | /// Make sure to always use a sufficiently large buffer to hold the |
315 | /// maximum UDP packet size, which can be up to 65536 bytes in size. |
316 | pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { |
317 | self.inner.do_io(|inner| inner.peek(buf)) |
318 | } |
319 | |
320 | /// Connects the UDP socket setting the default destination for `send()` |
321 | /// and limiting packets that are read via `recv` from the address specified |
322 | /// in `addr`. |
323 | /// |
324 | /// This may return a `WouldBlock` in which case the socket connection |
325 | /// cannot be completed immediately, it usually means there are insufficient |
326 | /// entries in the routing cache. |
327 | pub fn connect(&self, addr: SocketAddr) -> io::Result<()> { |
328 | self.inner.connect(addr) |
329 | } |
330 | |
331 | /// Sets the value of the `SO_BROADCAST` option for this socket. |
332 | /// |
333 | /// When enabled, this socket is allowed to send packets to a broadcast |
334 | /// address. |
335 | /// |
336 | /// # Examples |
337 | /// |
338 | #[cfg_attr (feature = "os-poll" , doc = "```" )] |
339 | #[cfg_attr (not(feature = "os-poll" ), doc = "```ignore" )] |
340 | /// # use std::error::Error; |
341 | /// # |
342 | /// # fn main() -> Result<(), Box<dyn Error>> { |
343 | /// use mio::net::UdpSocket; |
344 | /// |
345 | /// let broadcast_socket = UdpSocket::bind("127.0.0.1:0" .parse()?)?; |
346 | /// if broadcast_socket.broadcast()? == false { |
347 | /// broadcast_socket.set_broadcast(true)?; |
348 | /// } |
349 | /// |
350 | /// assert_eq!(broadcast_socket.broadcast()?, true); |
351 | /// # |
352 | /// # Ok(()) |
353 | /// # } |
354 | /// ``` |
355 | pub fn set_broadcast(&self, on: bool) -> io::Result<()> { |
356 | self.inner.set_broadcast(on) |
357 | } |
358 | |
359 | /// Gets the value of the `SO_BROADCAST` option for this socket. |
360 | /// |
361 | /// For more information about this option, see |
362 | /// [`set_broadcast`][link]. |
363 | /// |
364 | /// [link]: #method.set_broadcast |
365 | /// |
366 | /// # Examples |
367 | /// |
368 | #[cfg_attr (feature = "os-poll" , doc = "```" )] |
369 | #[cfg_attr (not(feature = "os-poll" ), doc = "```ignore" )] |
370 | /// # use std::error::Error; |
371 | /// # |
372 | /// # fn main() -> Result<(), Box<dyn Error>> { |
373 | /// use mio::net::UdpSocket; |
374 | /// |
375 | /// let broadcast_socket = UdpSocket::bind("127.0.0.1:0" .parse()?)?; |
376 | /// assert_eq!(broadcast_socket.broadcast()?, false); |
377 | /// # |
378 | /// # Ok(()) |
379 | /// # } |
380 | /// ``` |
381 | pub fn broadcast(&self) -> io::Result<bool> { |
382 | self.inner.broadcast() |
383 | } |
384 | |
385 | /// Sets the value of the `IP_MULTICAST_LOOP` option for this socket. |
386 | /// |
387 | /// If enabled, multicast packets will be looped back to the local socket. |
388 | /// Note that this may not have any affect on IPv6 sockets. |
389 | pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> { |
390 | self.inner.set_multicast_loop_v4(on) |
391 | } |
392 | |
393 | /// Gets the value of the `IP_MULTICAST_LOOP` option for this socket. |
394 | /// |
395 | /// For more information about this option, see |
396 | /// [`set_multicast_loop_v4`][link]. |
397 | /// |
398 | /// [link]: #method.set_multicast_loop_v4 |
399 | pub fn multicast_loop_v4(&self) -> io::Result<bool> { |
400 | self.inner.multicast_loop_v4() |
401 | } |
402 | |
403 | /// Sets the value of the `IP_MULTICAST_TTL` option for this socket. |
404 | /// |
405 | /// Indicates the time-to-live value of outgoing multicast packets for |
406 | /// this socket. The default value is 1 which means that multicast packets |
407 | /// don't leave the local network unless explicitly requested. |
408 | /// |
409 | /// Note that this may not have any affect on IPv6 sockets. |
410 | pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> { |
411 | self.inner.set_multicast_ttl_v4(ttl) |
412 | } |
413 | |
414 | /// Gets the value of the `IP_MULTICAST_TTL` option for this socket. |
415 | /// |
416 | /// For more information about this option, see |
417 | /// [`set_multicast_ttl_v4`][link]. |
418 | /// |
419 | /// [link]: #method.set_multicast_ttl_v4 |
420 | pub fn multicast_ttl_v4(&self) -> io::Result<u32> { |
421 | self.inner.multicast_ttl_v4() |
422 | } |
423 | |
424 | /// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket. |
425 | /// |
426 | /// Controls whether this socket sees the multicast packets it sends itself. |
427 | /// Note that this may not have any affect on IPv4 sockets. |
428 | pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> { |
429 | self.inner.set_multicast_loop_v6(on) |
430 | } |
431 | |
432 | /// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket. |
433 | /// |
434 | /// For more information about this option, see |
435 | /// [`set_multicast_loop_v6`][link]. |
436 | /// |
437 | /// [link]: #method.set_multicast_loop_v6 |
438 | pub fn multicast_loop_v6(&self) -> io::Result<bool> { |
439 | self.inner.multicast_loop_v6() |
440 | } |
441 | |
442 | /// Sets the value for the `IP_TTL` option on this socket. |
443 | /// |
444 | /// This value sets the time-to-live field that is used in every packet sent |
445 | /// from this socket. |
446 | /// |
447 | /// # Examples |
448 | /// |
449 | #[cfg_attr (feature = "os-poll" , doc = "```" )] |
450 | #[cfg_attr (not(feature = "os-poll" ), doc = "```ignore" )] |
451 | /// # use std::error::Error; |
452 | /// # |
453 | /// # fn main() -> Result<(), Box<dyn Error>> { |
454 | /// use mio::net::UdpSocket; |
455 | /// |
456 | /// let socket = UdpSocket::bind("127.0.0.1:0" .parse()?)?; |
457 | /// if socket.ttl()? < 255 { |
458 | /// socket.set_ttl(255)?; |
459 | /// } |
460 | /// |
461 | /// assert_eq!(socket.ttl()?, 255); |
462 | /// # |
463 | /// # Ok(()) |
464 | /// # } |
465 | /// ``` |
466 | pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { |
467 | self.inner.set_ttl(ttl) |
468 | } |
469 | |
470 | /// Gets the value of the `IP_TTL` option for this socket. |
471 | /// |
472 | /// For more information about this option, see [`set_ttl`][link]. |
473 | /// |
474 | /// [link]: #method.set_ttl |
475 | /// |
476 | /// # Examples |
477 | /// |
478 | #[cfg_attr (feature = "os-poll" , doc = "```" )] |
479 | #[cfg_attr (not(feature = "os-poll" ), doc = "```ignore" )] |
480 | /// # use std::error::Error; |
481 | /// # |
482 | /// # fn main() -> Result<(), Box<dyn Error>> { |
483 | /// use mio::net::UdpSocket; |
484 | /// |
485 | /// let socket = UdpSocket::bind("127.0.0.1:0" .parse()?)?; |
486 | /// socket.set_ttl(255)?; |
487 | /// |
488 | /// assert_eq!(socket.ttl()?, 255); |
489 | /// # |
490 | /// # Ok(()) |
491 | /// # } |
492 | /// ``` |
493 | pub fn ttl(&self) -> io::Result<u32> { |
494 | self.inner.ttl() |
495 | } |
496 | |
497 | /// Executes an operation of the `IP_ADD_MEMBERSHIP` type. |
498 | /// |
499 | /// This function specifies a new multicast group for this socket to join. |
500 | /// The address must be a valid multicast address, and `interface` is the |
501 | /// address of the local interface with which the system should join the |
502 | /// multicast group. If it's equal to `INADDR_ANY` then an appropriate |
503 | /// interface is chosen by the system. |
504 | #[allow (clippy::trivially_copy_pass_by_ref)] |
505 | pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> { |
506 | self.inner.join_multicast_v4(multiaddr, interface) |
507 | } |
508 | |
509 | /// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type. |
510 | /// |
511 | /// This function specifies a new multicast group for this socket to join. |
512 | /// The address must be a valid multicast address, and `interface` is the |
513 | /// index of the interface to join/leave (or 0 to indicate any interface). |
514 | #[allow (clippy::trivially_copy_pass_by_ref)] |
515 | pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { |
516 | self.inner.join_multicast_v6(multiaddr, interface) |
517 | } |
518 | |
519 | /// Executes an operation of the `IP_DROP_MEMBERSHIP` type. |
520 | /// |
521 | /// For more information about this option, see |
522 | /// [`join_multicast_v4`][link]. |
523 | /// |
524 | /// [link]: #method.join_multicast_v4 |
525 | #[allow (clippy::trivially_copy_pass_by_ref)] |
526 | pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> { |
527 | self.inner.leave_multicast_v4(multiaddr, interface) |
528 | } |
529 | |
530 | /// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type. |
531 | /// |
532 | /// For more information about this option, see |
533 | /// [`join_multicast_v6`][link]. |
534 | /// |
535 | /// [link]: #method.join_multicast_v6 |
536 | #[allow (clippy::trivially_copy_pass_by_ref)] |
537 | pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { |
538 | self.inner.leave_multicast_v6(multiaddr, interface) |
539 | } |
540 | |
541 | /// Get the value of the `IPV6_V6ONLY` option on this socket. |
542 | #[allow (clippy::trivially_copy_pass_by_ref)] |
543 | pub fn only_v6(&self) -> io::Result<bool> { |
544 | sys::udp::only_v6(&self.inner) |
545 | } |
546 | |
547 | /// Get the value of the `SO_ERROR` option on this socket. |
548 | /// |
549 | /// This will retrieve the stored error in the underlying socket, clearing |
550 | /// the field in the process. This can be useful for checking errors between |
551 | /// calls. |
552 | pub fn take_error(&self) -> io::Result<Option<io::Error>> { |
553 | self.inner.take_error() |
554 | } |
555 | |
556 | /// Execute an I/O operation ensuring that the socket receives more events |
557 | /// if it hits a [`WouldBlock`] error. |
558 | /// |
559 | /// # Notes |
560 | /// |
561 | /// This method is required to be called for **all** I/O operations to |
562 | /// ensure the user will receive events once the socket is ready again after |
563 | /// returning a [`WouldBlock`] error. |
564 | /// |
565 | /// [`WouldBlock`]: io::ErrorKind::WouldBlock |
566 | /// |
567 | /// # Examples |
568 | /// |
569 | #[cfg_attr (unix, doc = "```no_run" )] |
570 | #[cfg_attr (windows, doc = "```ignore" )] |
571 | /// # use std::error::Error; |
572 | /// # |
573 | /// # fn main() -> Result<(), Box<dyn Error>> { |
574 | /// use std::io; |
575 | /// #[cfg(unix)] |
576 | /// use std::os::unix::io::AsRawFd; |
577 | /// #[cfg(windows)] |
578 | /// use std::os::windows::io::AsRawSocket; |
579 | /// use mio::net::UdpSocket; |
580 | /// |
581 | /// let address = "127.0.0.1:8080" .parse().unwrap(); |
582 | /// let dgram = UdpSocket::bind(address)?; |
583 | /// |
584 | /// // Wait until the dgram is readable... |
585 | /// |
586 | /// // Read from the dgram using a direct libc call, of course the |
587 | /// // `io::Read` implementation would be easier to use. |
588 | /// let mut buf = [0; 512]; |
589 | /// let n = dgram.try_io(|| { |
590 | /// let buf_ptr = &mut buf as *mut _ as *mut _; |
591 | /// #[cfg (unix)] |
592 | /// let res = unsafe { libc::recv(dgram.as_raw_fd(), buf_ptr, buf.len(), 0) }; |
593 | /// #[cfg (windows)] |
594 | /// 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()) }; |
595 | /// if res != -1 { |
596 | /// Ok(res as usize) |
597 | /// } else { |
598 | /// // If EAGAIN or EWOULDBLOCK is set by libc::recv, the closure |
599 | /// // should return `WouldBlock` error. |
600 | /// Err(io::Error::last_os_error()) |
601 | /// } |
602 | /// })?; |
603 | /// eprintln!("read {} bytes" , n); |
604 | /// # Ok(()) |
605 | /// # } |
606 | /// ``` |
607 | pub fn try_io<F, T>(&self, f: F) -> io::Result<T> |
608 | where |
609 | F: FnOnce() -> io::Result<T>, |
610 | { |
611 | self.inner.do_io(|_| f()) |
612 | } |
613 | } |
614 | |
615 | impl event::Source for UdpSocket { |
616 | fn register( |
617 | &mut self, |
618 | registry: &Registry, |
619 | token: Token, |
620 | interests: Interest, |
621 | ) -> io::Result<()> { |
622 | self.inner.register(registry, token, interests) |
623 | } |
624 | |
625 | fn reregister( |
626 | &mut self, |
627 | registry: &Registry, |
628 | token: Token, |
629 | interests: Interest, |
630 | ) -> io::Result<()> { |
631 | self.inner.reregister(registry, token, interests) |
632 | } |
633 | |
634 | fn deregister(&mut self, registry: &Registry) -> io::Result<()> { |
635 | self.inner.deregister(registry) |
636 | } |
637 | } |
638 | |
639 | impl fmt::Debug for UdpSocket { |
640 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
641 | self.inner.fmt(f) |
642 | } |
643 | } |
644 | |
645 | #[cfg (unix)] |
646 | impl IntoRawFd for UdpSocket { |
647 | fn into_raw_fd(self) -> RawFd { |
648 | self.inner.into_inner().into_raw_fd() |
649 | } |
650 | } |
651 | |
652 | #[cfg (unix)] |
653 | impl AsRawFd for UdpSocket { |
654 | fn as_raw_fd(&self) -> RawFd { |
655 | self.inner.as_raw_fd() |
656 | } |
657 | } |
658 | |
659 | #[cfg (unix)] |
660 | impl FromRawFd for UdpSocket { |
661 | /// Converts a `RawFd` to a `UdpSocket`. |
662 | /// |
663 | /// # Notes |
664 | /// |
665 | /// The caller is responsible for ensuring that the socket is in |
666 | /// non-blocking mode. |
667 | unsafe fn from_raw_fd(fd: RawFd) -> UdpSocket { |
668 | UdpSocket::from_std(socket:FromRawFd::from_raw_fd(fd)) |
669 | } |
670 | } |
671 | |
672 | #[cfg (windows)] |
673 | impl IntoRawSocket for UdpSocket { |
674 | fn into_raw_socket(self) -> RawSocket { |
675 | self.inner.into_inner().into_raw_socket() |
676 | } |
677 | } |
678 | |
679 | #[cfg (windows)] |
680 | impl AsRawSocket for UdpSocket { |
681 | fn as_raw_socket(&self) -> RawSocket { |
682 | self.inner.as_raw_socket() |
683 | } |
684 | } |
685 | |
686 | #[cfg (windows)] |
687 | impl FromRawSocket for UdpSocket { |
688 | /// Converts a `RawSocket` to a `UdpSocket`. |
689 | /// |
690 | /// # Notes |
691 | /// |
692 | /// The caller is responsible for ensuring that the socket is in |
693 | /// non-blocking mode. |
694 | unsafe fn from_raw_socket(socket: RawSocket) -> UdpSocket { |
695 | UdpSocket::from_std(FromRawSocket::from_raw_socket(socket)) |
696 | } |
697 | } |
698 | |