|
|
|
@ -5,6 +5,7 @@ use std::net::{Ipv4Addr, Ipv6Addr};
|
|
|
|
|
use crate::future;
|
|
|
|
|
use crate::net::driver::Watcher;
|
|
|
|
|
use crate::net::ToSocketAddrs;
|
|
|
|
|
use crate::utils::Context as _;
|
|
|
|
|
|
|
|
|
|
/// A UDP socket.
|
|
|
|
|
///
|
|
|
|
@ -66,10 +67,13 @@ impl UdpSocket {
|
|
|
|
|
/// #
|
|
|
|
|
/// # Ok(()) }) }
|
|
|
|
|
/// ```
|
|
|
|
|
pub async fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
|
|
|
|
|
pub async fn bind<A: ToSocketAddrs>(addrs: A) -> io::Result<UdpSocket> {
|
|
|
|
|
let mut last_err = None;
|
|
|
|
|
let addrs = addrs
|
|
|
|
|
.to_socket_addrs()
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
for addr in addr.to_socket_addrs().await? {
|
|
|
|
|
for addr in addrs {
|
|
|
|
|
match mio::net::UdpSocket::bind(&addr) {
|
|
|
|
|
Ok(mio_socket) => {
|
|
|
|
|
return Ok(UdpSocket {
|
|
|
|
@ -106,7 +110,10 @@ impl UdpSocket {
|
|
|
|
|
/// # Ok(()) }) }
|
|
|
|
|
/// ```
|
|
|
|
|
pub fn local_addr(&self) -> io::Result<SocketAddr> {
|
|
|
|
|
self.watcher.get_ref().local_addr()
|
|
|
|
|
self.watcher
|
|
|
|
|
.get_ref()
|
|
|
|
|
.local_addr()
|
|
|
|
|
.context(|| String::from("could not get local address"))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Sends data on the socket to the given address.
|
|
|
|
@ -151,6 +158,7 @@ impl UdpSocket {
|
|
|
|
|
.poll_write_with(cx, |inner| inner.send_to(buf, &addr))
|
|
|
|
|
})
|
|
|
|
|
.await
|
|
|
|
|
.context(|| format!("could not send packet to {}", addr))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Receives data from the socket.
|
|
|
|
@ -178,6 +186,17 @@ impl UdpSocket {
|
|
|
|
|
.poll_read_with(cx, |inner| inner.recv_from(buf))
|
|
|
|
|
})
|
|
|
|
|
.await
|
|
|
|
|
.context(|| {
|
|
|
|
|
use std::fmt::Write;
|
|
|
|
|
|
|
|
|
|
let mut error = String::from("could not receive data on ");
|
|
|
|
|
if let Ok(addr) = self.local_addr() {
|
|
|
|
|
let _ = write!(&mut error, "{}", addr);
|
|
|
|
|
} else {
|
|
|
|
|
error.push_str("socket");
|
|
|
|
|
}
|
|
|
|
|
error
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Connects the UDP socket to a remote address.
|
|
|
|
@ -204,8 +223,12 @@ impl UdpSocket {
|
|
|
|
|
/// ```
|
|
|
|
|
pub async fn connect<A: ToSocketAddrs>(&self, addrs: A) -> io::Result<()> {
|
|
|
|
|
let mut last_err = None;
|
|
|
|
|
let addrs = addrs
|
|
|
|
|
.to_socket_addrs()
|
|
|
|
|
.await
|
|
|
|
|
.context(|| String::from("could not resolve addresses"))?;
|
|
|
|
|
|
|
|
|
|
for addr in addrs.to_socket_addrs().await? {
|
|
|
|
|
for addr in addrs {
|
|
|
|
|
// TODO(stjepang): connect on the blocking pool
|
|
|
|
|
match self.watcher.get_ref().connect(addr) {
|
|
|
|
|
Ok(()) => return Ok(()),
|
|
|
|
@ -248,7 +271,19 @@ impl UdpSocket {
|
|
|
|
|
/// # Ok(()) }) }
|
|
|
|
|
/// ```
|
|
|
|
|
pub async fn send(&self, buf: &[u8]) -> io::Result<usize> {
|
|
|
|
|
future::poll_fn(|cx| self.watcher.poll_write_with(cx, |inner| inner.send(buf))).await
|
|
|
|
|
future::poll_fn(|cx| self.watcher.poll_write_with(cx, |inner| inner.send(buf)))
|
|
|
|
|
.await
|
|
|
|
|
.context(|| {
|
|
|
|
|
use std::fmt::Write;
|
|
|
|
|
|
|
|
|
|
let mut error = String::from("could not send data on ");
|
|
|
|
|
if let Ok(addr) = self.local_addr() {
|
|
|
|
|
let _ = write!(&mut error, "{}", addr);
|
|
|
|
|
} else {
|
|
|
|
|
error.push_str("socket");
|
|
|
|
|
}
|
|
|
|
|
error
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Receives data from the socket.
|
|
|
|
@ -271,7 +306,19 @@ impl UdpSocket {
|
|
|
|
|
/// # Ok(()) }) }
|
|
|
|
|
/// ```
|
|
|
|
|
pub async fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
|
|
|
|
|
future::poll_fn(|cx| self.watcher.poll_read_with(cx, |inner| inner.recv(buf))).await
|
|
|
|
|
future::poll_fn(|cx| self.watcher.poll_read_with(cx, |inner| inner.recv(buf)))
|
|
|
|
|
.await
|
|
|
|
|
.context(|| {
|
|
|
|
|
use std::fmt::Write;
|
|
|
|
|
|
|
|
|
|
let mut error = String::from("could not receive data on ");
|
|
|
|
|
if let Ok(addr) = self.local_addr() {
|
|
|
|
|
let _ = write!(&mut error, "{}", addr);
|
|
|
|
|
} else {
|
|
|
|
|
error.push_str("socket");
|
|
|
|
|
}
|
|
|
|
|
error
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Gets the value of the `SO_BROADCAST` option for this socket.
|
|
|
|
|