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 /// # drop(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 /// ``` bind(addr: SocketAddr) -> io::Result<UdpSocket>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. from_std(socket: net::UdpSocket) -> UdpSocket131 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 /// ``` local_addr(&self) -> io::Result<SocketAddr>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 /// ``` peer_addr(&self) -> io::Result<SocketAddr>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 /// ``` send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize>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 /// ``` recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)>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 /// ``` peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)>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. send(&self, buf: &[u8]) -> io::Result<usize>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. recv(&self, buf: &mut [u8]) -> io::Result<usize>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. peek(&self, buf: &mut [u8]) -> io::Result<usize>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. connect(&self, addr: SocketAddr) -> io::Result<()>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 /// ``` set_broadcast(&self, on: bool) -> io::Result<()>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 /// ``` broadcast(&self) -> io::Result<bool>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. set_multicast_loop_v4(&self, on: bool) -> io::Result<()>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 multicast_loop_v4(&self) -> io::Result<bool>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. set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()>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 multicast_ttl_v4(&self) -> io::Result<u32>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. set_multicast_loop_v6(&self, on: bool) -> io::Result<()>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 multicast_loop_v6(&self) -> io::Result<bool>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 /// ``` set_ttl(&self, ttl: u32) -> io::Result<()>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 /// ``` ttl(&self) -> io::Result<u32>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)] join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()>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)] join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>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)] leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()>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)] leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>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)] only_v6(&self) -> io::Result<bool>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. take_error(&self) -> io::Result<Option<io::Error>>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 /// ``` try_io<F, T>(&self, f: F) -> io::Result<T> where F: FnOnce() -> io::Result<T>,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 { register( &mut self, registry: &Registry, token: Token, interests: Interest, ) -> io::Result<()>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 reregister( &mut self, registry: &Registry, token: Token, interests: Interest, ) -> io::Result<()>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 deregister(&mut self, registry: &Registry) -> io::Result<()>634 fn deregister(&mut self, registry: &Registry) -> io::Result<()> { 635 self.inner.deregister(registry) 636 } 637 } 638 639 impl fmt::Debug for UdpSocket { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result640 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 { into_raw_fd(self) -> RawFd647 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 { as_raw_fd(&self) -> RawFd654 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. from_raw_fd(fd: RawFd) -> UdpSocket667 unsafe fn from_raw_fd(fd: RawFd) -> UdpSocket { 668 UdpSocket::from_std(FromRawFd::from_raw_fd(fd)) 669 } 670 } 671 672 #[cfg(windows)] 673 impl IntoRawSocket for UdpSocket { into_raw_socket(self) -> RawSocket674 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 { as_raw_socket(&self) -> RawSocket681 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. from_raw_socket(socket: RawSocket) -> UdpSocket694 unsafe fn from_raw_socket(socket: RawSocket) -> UdpSocket { 695 UdpSocket::from_std(FromRawSocket::from_raw_socket(socket)) 696 } 697 } 698