use futures::prelude::*;
use std::io;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs};
use std::pin::Pin;
use std::task::{Context, Poll};
#[derive(Debug)]
pub struct UdpSocket {
inner: Pin<Box<dyn runtime_raw::UdpSocket>>,
}
impl UdpSocket {
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<Self> {
let mut last_err = None;
for addr in addr.to_socket_addrs()? {
match runtime_raw::current_runtime().bind_udp_socket(&addr) {
Ok(inner) => return Ok(UdpSocket { inner }),
Err(e) => last_err = Some(e),
}
}
Err(last_err.unwrap_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidInput,
"could not resolve to any addresses",
)
}))
}
pub fn local_addr(&self) -> io::Result<SocketAddr> {
self.inner.local_addr()
}
pub fn send_to<'socket, 'buf, A: ToSocketAddrs>(
&'socket mut self,
buf: &'buf [u8],
addr: A,
) -> SendToFuture<'socket, 'buf> {
let addr = addr
.to_socket_addrs()
.map(|mut iter| iter.next())
.transpose();
SendToFuture {
buf,
addr,
socket: self,
}
}
pub fn recv_from<'socket, 'buf>(
&'socket mut self,
buf: &'buf mut [u8],
) -> RecvFromFuture<'socket, 'buf> {
RecvFromFuture { buf, socket: self }
}
pub fn broadcast(&self) -> io::Result<bool> {
self.inner.broadcast()
}
pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
self.inner.set_broadcast(on)
}
pub fn multicast_loop_v4(&self) -> io::Result<bool> {
self.inner.multicast_loop_v4()
}
pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> {
self.inner.set_multicast_loop_v4(on)
}
pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
self.inner.multicast_ttl_v4()
}
pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
self.inner.set_multicast_ttl_v4(ttl)
}
pub fn multicast_loop_v6(&self) -> io::Result<bool> {
self.inner.multicast_loop_v6()
}
pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> {
self.inner.set_multicast_loop_v6(on)
}
pub fn ttl(&self) -> io::Result<u32> {
self.inner.ttl()
}
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
self.inner.set_ttl(ttl)
}
pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
self.inner.join_multicast_v4(multiaddr, interface)
}
pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
self.inner.join_multicast_v6(multiaddr, interface)
}
pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
self.inner.leave_multicast_v4(multiaddr, interface)
}
pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
self.inner.leave_multicast_v6(multiaddr, interface)
}
}
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[derive(Debug)]
pub struct SendToFuture<'socket, 'buf> {
socket: &'socket mut UdpSocket,
buf: &'buf [u8],
addr: Option<io::Result<SocketAddr>>,
}
impl<'socket, 'buf> Future for SendToFuture<'socket, 'buf> {
type Output = io::Result<usize>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let SendToFuture { socket, buf, addr } = &mut *self;
let addr = match addr.take() {
Some(addr) => addr?,
None => {
let err_msg = "no addresses to send data to";
let err = io::Error::new(io::ErrorKind::InvalidInput, err_msg);
return Poll::Ready(Err(err));
}
};
let poll = socket.inner.as_mut().poll_send_to(cx, buf, &addr);
self.addr = Some(Ok(addr));
poll
}
}
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[derive(Debug)]
pub struct RecvFromFuture<'socket, 'buf> {
socket: &'socket mut UdpSocket,
buf: &'buf mut [u8],
}
impl<'socket, 'buf> Future for RecvFromFuture<'socket, 'buf> {
type Output = io::Result<(usize, SocketAddr)>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let RecvFromFuture { socket, buf } = &mut *self;
socket.inner.as_mut().poll_recv_from(cx, buf)
}
}
#[cfg(unix)]
mod sys {
use super::UdpSocket;
use std::os::unix::prelude::*;
impl AsRawFd for UdpSocket {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}
}