|
|
|
@ -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,14 @@ 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
|
|
|
|
|
.context(|| String::from("could not resolve addresses"))?;
|
|
|
|
|
|
|
|
|
|
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 +111,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 +159,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 +187,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.
|
|
|
|
@ -195,7 +215,7 @@ impl UdpSocket {
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
|
|
|
|
/// #
|
|
|
|
|
/// use async_std::net::UdpSocket;
|
|
|
|
|
/// use async_std::net::UdpSocket;
|
|
|
|
|
///
|
|
|
|
|
/// let socket = UdpSocket::bind("127.0.0.1:0").await?;
|
|
|
|
|
/// socket.connect("127.0.0.1:8080").await?;
|
|
|
|
@ -204,8 +224,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 +272,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 +307,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.
|
|
|
|
@ -415,7 +463,7 @@ impl UdpSocket {
|
|
|
|
|
/// use async_std::net::UdpSocket;
|
|
|
|
|
///
|
|
|
|
|
/// let socket_addr = SocketAddr::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).into(), 0);
|
|
|
|
|
/// let mdns_addr = Ipv6Addr::new(0xFF02, 0, 0, 0, 0, 0, 0, 0x0123) ;
|
|
|
|
|
/// let mdns_addr = Ipv6Addr::new(0xFF02, 0, 0, 0, 0, 0, 0, 0x0123);
|
|
|
|
|
/// let socket = UdpSocket::bind(&socket_addr).await?;
|
|
|
|
|
///
|
|
|
|
|
/// socket.join_multicast_v6(&mdns_addr, 0)?;
|
|
|
|
|