use std::fmt;
use std::io;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
use std::pin::Pin;
use std::task::Context;
use async_datagram::AsyncDatagram;
use async_ready::{AsyncReadReady, AsyncWriteReady};
use futures::Future;
use futures::{ready, Poll};
use mio;
use crate::raw::PollEvented;
pub struct UdpSocket {
io: PollEvented<mio::net::UdpSocket>,
}
impl UdpSocket {
pub fn bind(addr: &SocketAddr) -> io::Result<UdpSocket> {
mio::net::UdpSocket::bind(addr).map(UdpSocket::new)
}
fn new(socket: mio::net::UdpSocket) -> UdpSocket {
let io = PollEvented::new(socket);
UdpSocket { io: io }
}
pub fn local_addr(&self) -> io::Result<SocketAddr> {
self.io.get_ref().local_addr()
}
pub fn send_to<'a, 'b>(&'a mut self, buf: &'b [u8], target: &'b SocketAddr) -> SendTo<'a, 'b> {
SendTo {
buf,
target,
socket: self,
}
}
pub fn recv_from<'a, 'b>(&'a mut self, buf: &'b mut [u8]) -> RecvFrom<'a, 'b> {
RecvFrom { buf, socket: self }
}
pub fn broadcast(&self) -> io::Result<bool> {
self.io.get_ref().broadcast()
}
pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
self.io.get_ref().set_broadcast(on)
}
pub fn multicast_loop_v4(&self) -> io::Result<bool> {
self.io.get_ref().multicast_loop_v4()
}
pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> {
self.io.get_ref().set_multicast_loop_v4(on)
}
pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
self.io.get_ref().multicast_ttl_v4()
}
pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
self.io.get_ref().set_multicast_ttl_v4(ttl)
}
pub fn multicast_loop_v6(&self) -> io::Result<bool> {
self.io.get_ref().multicast_loop_v6()
}
pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> {
self.io.get_ref().set_multicast_loop_v6(on)
}
pub fn ttl(&self) -> io::Result<u32> {
self.io.get_ref().ttl()
}
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
self.io.get_ref().set_ttl(ttl)
}
pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
self.io.get_ref().join_multicast_v4(multiaddr, interface)
}
pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
self.io.get_ref().join_multicast_v6(multiaddr, interface)
}
pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
self.io.get_ref().leave_multicast_v4(multiaddr, interface)
}
pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
self.io.get_ref().leave_multicast_v6(multiaddr, interface)
}
}
impl AsyncDatagram for UdpSocket {
type Sender = SocketAddr;
type Receiver = SocketAddr;
type Err = io::Error;
fn poll_send_to(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
receiver: &Self::Receiver,
) -> Poll<io::Result<usize>> {
ready!(self.io.poll_write_ready(cx)?);
match self.io.get_ref().send_to(buf, receiver) {
Ok(n) => Poll::Ready(Ok(n)),
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
Pin::new(&mut self.io).clear_write_ready(cx)?;
Poll::Pending
}
Err(e) => Poll::Ready(Err(e)),
}
}
fn poll_recv_from(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<(usize, Self::Sender)>> {
ready!(Pin::new(&mut self.io).poll_read_ready(cx)?);
match self.io.get_ref().recv_from(buf) {
Ok(n) => Poll::Ready(Ok(n)),
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
Pin::new(&mut self.io).clear_read_ready(cx)?;
Poll::Pending
}
Err(e) => Poll::Ready(Err(e)),
}
}
}
impl AsyncReadReady for UdpSocket
where
Self: Unpin,
{
type Ok = mio::Ready;
type Err = io::Error;
fn poll_read_ready(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Result<Self::Ok, Self::Err>> {
Pin::new(&mut self.io).poll_read_ready(cx)
}
}
impl AsyncWriteReady for UdpSocket {
type Ok = mio::Ready;
type Err = io::Error;
fn poll_write_ready(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Result<Self::Ok, Self::Err>> {
self.io.poll_write_ready(cx)
}
}
impl fmt::Debug for UdpSocket {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.io.get_ref().fmt(f)
}
}
#[cfg(all(unix))]
mod sys {
use super::UdpSocket;
use std::os::unix::prelude::*;
impl AsRawFd for UdpSocket {
fn as_raw_fd(&self) -> RawFd {
self.io.get_ref().as_raw_fd()
}
}
}
#[derive(Debug)]
pub struct SendTo<'a, 'b> {
socket: &'a mut UdpSocket,
buf: &'b [u8],
target: &'b SocketAddr,
}
impl<'a, 'b> Future for SendTo<'a, 'b> {
type Output = io::Result<usize>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let SendTo {
socket,
buf,
target,
} = &mut *self;
Pin::new(&mut **socket).poll_send_to(cx, buf, target)
}
}
#[derive(Debug)]
pub struct RecvFrom<'a, 'b> {
socket: &'a mut UdpSocket,
buf: &'b mut [u8],
}
impl<'a, 'b> Future for RecvFrom<'a, 'b> {
type Output = io::Result<(usize, SocketAddr)>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let RecvFrom { socket, buf } = &mut *self;
Pin::new(&mut **socket).poll_recv_from(cx, buf)
}
}