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 /// ``` bind(addr: SocketAddr) -> io::Result<UdpSocket>125 pub fn bind(addr: SocketAddr) -> io::Result<UdpSocket> { 126 sys::udp::bind(addr).map(UdpSocket::from_std) 127 } 128 129 /// Creates a new `UdpSocket` from a standard `net::UdpSocket`. 130 /// 131 /// This function is intended to be used to wrap a UDP socket from the 132 /// standard library in the Mio equivalent. The conversion assumes nothing 133 /// about the underlying socket; it is left up to the user to set it in 134 /// non-blocking mode. from_std(socket: net::UdpSocket) -> UdpSocket135 pub fn from_std(socket: net::UdpSocket) -> UdpSocket { 136 UdpSocket { 137 inner: IoSource::new(socket), 138 } 139 } 140 141 /// Returns the socket address that this socket was created from. 142 /// 143 /// # Examples 144 /// 145 // This assertion is almost, but not quite, universal. It fails on 146 // shared-IP FreeBSD jails. It's hard for mio to know whether we're jailed, 147 // so simply disable the test on FreeBSD. 148 #[cfg_attr(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 /// ``` local_addr(&self) -> io::Result<SocketAddr>164 pub fn local_addr(&self) -> io::Result<SocketAddr> { 165 self.inner.local_addr() 166 } 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 /// ``` peer_addr(&self) -> io::Result<SocketAddr>187 pub fn peer_addr(&self) -> io::Result<SocketAddr> { 188 self.inner.peer_addr() 189 } 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 /// ``` send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize>215 pub fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize> { 216 self.inner.do_io(|inner| inner.send_to(buf, target)) 217 } 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 /// ``` recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)>250 pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { 251 self.inner.do_io(|inner| inner.recv_from(buf)) 252 } 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 /// ``` peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)>286 pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { 287 self.inner.do_io(|inner| inner.peek_from(buf)) 288 } 289 290 /// Sends data on the socket to the address previously bound via connect(). On success, 291 /// returns the number of bytes written. send(&self, buf: &[u8]) -> io::Result<usize>292 pub fn send(&self, buf: &[u8]) -> io::Result<usize> { 293 self.inner.do_io(|inner| inner.send(buf)) 294 } 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. recv(&self, buf: &mut [u8]) -> io::Result<usize>306 pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> { 307 self.inner.do_io(|inner| inner.recv(buf)) 308 } 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. peek(&self, buf: &mut [u8]) -> io::Result<usize>320 pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { 321 self.inner.do_io(|inner| inner.peek(buf)) 322 } 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. connect(&self, addr: SocketAddr) -> io::Result<()>331 pub fn connect(&self, addr: SocketAddr) -> io::Result<()> { 332 self.inner.connect(addr) 333 } 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 /// ``` set_broadcast(&self, on: bool) -> io::Result<()>359 pub fn set_broadcast(&self, on: bool) -> io::Result<()> { 360 self.inner.set_broadcast(on) 361 } 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 /// ``` broadcast(&self) -> io::Result<bool>385 pub fn broadcast(&self) -> io::Result<bool> { 386 self.inner.broadcast() 387 } 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. set_multicast_loop_v4(&self, on: bool) -> io::Result<()>393 pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> { 394 self.inner.set_multicast_loop_v4(on) 395 } 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 multicast_loop_v4(&self) -> io::Result<bool>403 pub fn multicast_loop_v4(&self) -> io::Result<bool> { 404 self.inner.multicast_loop_v4() 405 } 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. set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()>414 pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> { 415 self.inner.set_multicast_ttl_v4(ttl) 416 } 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 multicast_ttl_v4(&self) -> io::Result<u32>424 pub fn multicast_ttl_v4(&self) -> io::Result<u32> { 425 self.inner.multicast_ttl_v4() 426 } 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. set_multicast_loop_v6(&self, on: bool) -> io::Result<()>432 pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> { 433 self.inner.set_multicast_loop_v6(on) 434 } 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 multicast_loop_v6(&self) -> io::Result<bool>442 pub fn multicast_loop_v6(&self) -> io::Result<bool> { 443 self.inner.multicast_loop_v6() 444 } 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 /// ``` set_ttl(&self, ttl: u32) -> io::Result<()>470 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { 471 self.inner.set_ttl(ttl) 472 } 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 /// ``` ttl(&self) -> io::Result<u32>497 pub fn ttl(&self) -> io::Result<u32> { 498 self.inner.ttl() 499 } 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)] join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()>509 pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> { 510 self.inner.join_multicast_v4(multiaddr, interface) 511 } 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)] join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>519 pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { 520 self.inner.join_multicast_v6(multiaddr, interface) 521 } 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)] leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()>530 pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> { 531 self.inner.leave_multicast_v4(multiaddr, interface) 532 } 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)] leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>541 pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { 542 self.inner.leave_multicast_v6(multiaddr, interface) 543 } 544 545 /// Get the value of the `IPV6_V6ONLY` option on this socket. 546 #[allow(clippy::trivially_copy_pass_by_ref)] only_v6(&self) -> io::Result<bool>547 pub fn only_v6(&self) -> io::Result<bool> { 548 sys::udp::only_v6(&self.inner) 549 } 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. take_error(&self) -> io::Result<Option<io::Error>>556 pub fn take_error(&self) -> io::Result<Option<io::Error>> { 557 self.inner.take_error() 558 } 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 /// ``` try_io<F, T>(&self, f: F) -> io::Result<T> where F: FnOnce() -> io::Result<T>,611 pub fn try_io<F, T>(&self, f: F) -> io::Result<T> 612 where 613 F: FnOnce() -> io::Result<T>, 614 { 615 self.inner.do_io(|_| f()) 616 } 617 } 618 619 impl event::Source for UdpSocket { register( &mut self, registry: &Registry, token: Token, interests: Interest, ) -> io::Result<()>620 fn register( 621 &mut self, 622 registry: &Registry, 623 token: Token, 624 interests: Interest, 625 ) -> io::Result<()> { 626 self.inner.register(registry, token, interests) 627 } 628 reregister( &mut self, registry: &Registry, token: Token, interests: Interest, ) -> io::Result<()>629 fn reregister( 630 &mut self, 631 registry: &Registry, 632 token: Token, 633 interests: Interest, 634 ) -> io::Result<()> { 635 self.inner.reregister(registry, token, interests) 636 } 637 deregister(&mut self, registry: &Registry) -> io::Result<()>638 fn deregister(&mut self, registry: &Registry) -> io::Result<()> { 639 self.inner.deregister(registry) 640 } 641 } 642 643 impl fmt::Debug for UdpSocket { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result644 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 645 self.inner.fmt(f) 646 } 647 } 648 649 #[cfg(any(unix, target_os = "hermit", target_os = "wasi"))] 650 impl IntoRawFd for UdpSocket { into_raw_fd(self) -> RawFd651 fn into_raw_fd(self) -> RawFd { 652 self.inner.into_inner().into_raw_fd() 653 } 654 } 655 656 #[cfg(any(unix, target_os = "hermit", target_os = "wasi"))] 657 impl AsRawFd for UdpSocket { as_raw_fd(&self) -> RawFd658 fn as_raw_fd(&self) -> RawFd { 659 self.inner.as_raw_fd() 660 } 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. from_raw_fd(fd: RawFd) -> UdpSocket671 unsafe fn from_raw_fd(fd: RawFd) -> UdpSocket { 672 UdpSocket::from_std(FromRawFd::from_raw_fd(fd)) 673 } 674 } 675 676 #[cfg(any(unix, target_os = "hermit", target_os = "wasi"))] 677 impl From<UdpSocket> for OwnedFd { from(udp_socket: UdpSocket) -> Self678 fn from(udp_socket: UdpSocket) -> Self { 679 udp_socket.inner.into_inner().into() 680 } 681 } 682 683 #[cfg(any(unix, target_os = "hermit", target_os = "wasi"))] 684 impl AsFd for UdpSocket { as_fd(&self) -> BorrowedFd<'_>685 fn as_fd(&self) -> BorrowedFd<'_> { 686 self.inner.as_fd() 687 } 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. from(fd: OwnedFd) -> Self698 fn from(fd: OwnedFd) -> Self { 699 UdpSocket::from_std(From::from(fd)) 700 } 701 } 702 703 #[cfg(windows)] 704 impl IntoRawSocket for UdpSocket { into_raw_socket(self) -> RawSocket705 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 { as_raw_socket(&self) -> RawSocket712 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. from_raw_socket(socket: RawSocket) -> UdpSocket725 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 { from(udp_socket: UdpSocket) -> Self732 fn from(udp_socket: UdpSocket) -> Self { 733 udp_socket.inner.into_inner().into() 734 } 735 } 736 737 #[cfg(windows)] 738 impl AsSocket for UdpSocket { as_socket(&self) -> BorrowedSocket<'_>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. from(socket: OwnedSocket) -> Self752 fn from(socket: OwnedSocket) -> Self { 753 UdpSocket::from_std(From::from(socket)) 754 } 755 } 756 757 impl From<UdpSocket> for net::UdpSocket { from(socket: UdpSocket) -> Self758 fn from(socket: UdpSocket) -> Self { 759 // Safety: This is safe since we are extracting the raw fd from a well-constructed 760 // mio::net::UdpSocket which ensures that we actually pass in a valid file 761 // descriptor/socket 762 unsafe { 763 #[cfg(any(unix, target_os = "hermit", target_os = "wasi"))] 764 { 765 net::UdpSocket::from_raw_fd(socket.into_raw_fd()) 766 } 767 #[cfg(windows)] 768 { 769 net::UdpSocket::from_raw_socket(socket.into_raw_socket()) 770 } 771 } 772 } 773 } 774