diff options
Diffstat (limited to 'src/net/udp.rs')
-rw-r--r-- | src/net/udp.rs | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/net/udp.rs b/src/net/udp.rs index c5c3ba9..5abe12e 100644 --- a/src/net/udp.rs +++ b/src/net/udp.rs @@ -161,6 +161,29 @@ impl UdpSocket { self.inner.local_addr() } + /// Returns the socket address of the remote peer this socket was connected to. + /// + /// # Examples + /// + #[cfg_attr(feature = "os-poll", doc = "```")] + #[cfg_attr(not(feature = "os-poll"), doc = "```ignore")] + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box<dyn Error>> { + /// use mio::net::UdpSocket; + /// + /// let addr = "127.0.0.1:0".parse()?; + /// let peer_addr = "127.0.0.1:11100".parse()?; + /// let socket = UdpSocket::bind(addr)?; + /// socket.connect(peer_addr)?; + /// assert_eq!(socket.peer_addr()?.ip(), peer_addr.ip()); + /// # Ok(()) + /// # } + /// ``` + pub fn peer_addr(&self) -> io::Result<SocketAddr> { + self.inner.peer_addr() + } + /// Sends data on the socket to the given address. On success, returns the /// number of bytes written. /// @@ -297,6 +320,10 @@ impl UdpSocket { /// Connects the UDP socket setting the default destination for `send()` /// and limiting packets that are read via `recv` from the address specified /// in `addr`. + /// + /// This may return a `WouldBlock` in which case the socket connection + /// cannot be completed immediately, it usually means there are insufficient + /// entries in the routing cache. pub fn connect(&self, addr: SocketAddr) -> io::Result<()> { self.inner.connect(addr) } @@ -525,6 +552,64 @@ impl UdpSocket { pub fn take_error(&self) -> io::Result<Option<io::Error>> { self.inner.take_error() } + + /// Execute an I/O operation ensuring that the socket receives more events + /// if it hits a [`WouldBlock`] error. + /// + /// # Notes + /// + /// This method is required to be called for **all** I/O operations to + /// ensure the user will receive events once the socket is ready again after + /// returning a [`WouldBlock`] error. + /// + /// [`WouldBlock`]: io::ErrorKind::WouldBlock + /// + /// # Examples + /// + #[cfg_attr(unix, doc = "```no_run")] + #[cfg_attr(windows, doc = "```ignore")] + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box<dyn Error>> { + /// use std::io; + /// #[cfg(unix)] + /// use std::os::unix::io::AsRawFd; + /// #[cfg(windows)] + /// use std::os::windows::io::AsRawSocket; + /// use mio::net::UdpSocket; + /// + /// let address = "127.0.0.1:8080".parse().unwrap(); + /// let dgram = UdpSocket::bind(address)?; + /// + /// // Wait until the dgram is readable... + /// + /// // Read from the dgram using a direct libc call, of course the + /// // `io::Read` implementation would be easier to use. + /// let mut buf = [0; 512]; + /// let n = dgram.try_io(|| { + /// let buf_ptr = &mut buf as *mut _ as *mut _; + /// #[cfg(unix)] + /// let res = unsafe { libc::recv(dgram.as_raw_fd(), buf_ptr, buf.len(), 0) }; + /// #[cfg(windows)] + /// 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()) }; + /// if res != -1 { + /// Ok(res as usize) + /// } else { + /// // If EAGAIN or EWOULDBLOCK is set by libc::recv, the closure + /// // should return `WouldBlock` error. + /// Err(io::Error::last_os_error()) + /// } + /// })?; + /// eprintln!("read {} bytes", n); + /// # Ok(()) + /// # } + /// ``` + pub fn try_io<F, T>(&self, f: F) -> io::Result<T> + where + F: FnOnce() -> io::Result<T>, + { + self.inner.do_io(|_| f()) + } } impl event::Source for UdpSocket { |