use std::cell::RefCell;
use std::io;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs, UdpSocket as StdUdpSocket};
#[cfg(unix)]
use std::os::fd::{AsRawFd, IntoRawFd, RawFd};
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, IntoRawSocket, RawSocket};
use std::pin::Pin;
use std::task::{Context, Poll};
use std::time::Duration;
use crate::driver::RegistrationMode;
use crate::fd_inner::InnerRawHandle;
use crate::io::{
AsInnerRawHandle, AsyncReadPoll, AsyncWritePoll, IoBuf, IoBufMut, IoBufTemporaryPoll,
};
use crate::op::{ReadinessOp, RecvOp, RecvfromOp, SendOp, SendtoOp};
use super::UdpSocket;
pub struct PollUdpSocket {
pub(crate) socket: UdpSocket,
pub(crate) read_ready: RefCell<bool>,
pub(crate) write_ready: RefCell<bool>,
}
impl PollUdpSocket {
#[inline]
pub fn bind(address: impl ToSocketAddrs) -> Result<Self, io::Error> {
let inner = StdUdpSocket::bind(address)?;
Self::from_std(inner)
}
#[inline]
pub fn from_std(inner: StdUdpSocket) -> Result<Self, io::Error> {
Ok(Self {
socket: UdpSocket::from_std_with_mode(inner, RegistrationMode::Poll)?,
read_ready: RefCell::new(false),
write_ready: RefCell::new(false),
})
}
#[inline]
pub fn into_adaptive(self) -> UdpSocket {
self.socket
}
#[inline]
pub fn into_completion(self) -> Result<UdpSocket, io::Error> {
let mut socket = self.socket;
socket.handle.rebind_mode(RegistrationMode::Completion)?;
socket
.inner
.set_nonblocking(!socket.handle.uses_completion())?;
Ok(socket)
}
#[inline]
pub async fn connect(&mut self, address: impl ToSocketAddrs) -> Result<(), io::Error> {
self.socket.connect(address).await
}
#[inline]
pub fn local_addr(&self) -> Result<SocketAddr, io::Error> {
self.socket.local_addr()
}
#[inline]
pub fn peer_addr(&self) -> Result<SocketAddr, io::Error> {
self.socket.peer_addr()
}
#[inline]
pub async fn recv<B: IoBufMut>(&self, buf: B) -> (Result<usize, io::Error>, B) {
self.socket.recv(buf).await
}
#[inline]
pub async fn recv_from<B: IoBufMut>(
&self,
buf: B,
) -> (Result<(usize, SocketAddr), io::Error>, B) {
self.socket.recv_from(buf).await
}
#[inline]
pub async fn send<B: IoBuf>(&self, buf: B) -> (Result<usize, io::Error>, B) {
self.socket.send(buf).await
}
#[inline]
pub async fn send_to<B: IoBuf>(
&self,
buf: B,
address: impl ToSocketAddrs,
) -> (Result<usize, io::Error>, B) {
self.socket.send_to(buf, address).await
}
#[inline]
pub async fn peek<B: IoBufMut>(&self, buf: B) -> (Result<usize, io::Error>, B) {
self.socket.peek(buf).await
}
#[inline]
pub async fn peek_from<B: IoBufMut>(
&self,
buf: B,
) -> (Result<(usize, SocketAddr), io::Error>, B) {
self.socket.peek_from(buf).await
}
#[inline]
pub fn try_clone(&self) -> Result<Self, io::Error> {
Ok(Self {
socket: self.socket.try_clone()?,
read_ready: RefCell::new(false),
write_ready: RefCell::new(false),
})
}
#[inline]
pub fn set_broadcast(&self, broadcast: bool) -> Result<(), io::Error> {
self.socket.set_broadcast(broadcast)
}
#[inline]
pub fn broadcast(&self) -> Result<bool, io::Error> {
self.socket.broadcast()
}
#[inline]
pub fn set_ttl(&self, ttl: u32) -> Result<(), io::Error> {
self.socket.set_ttl(ttl)
}
#[inline]
pub fn ttl(&self) -> Result<u32, io::Error> {
self.socket.ttl()
}
#[inline]
pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> Result<(), io::Error> {
self.socket.set_multicast_loop_v4(multicast_loop_v4)
}
#[inline]
pub fn multicast_loop_v4(&self) -> Result<bool, io::Error> {
self.socket.multicast_loop_v4()
}
#[inline]
pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> Result<(), io::Error> {
self.socket.set_multicast_ttl_v4(multicast_ttl_v4)
}
#[inline]
pub fn multicast_ttl_v4(&self) -> Result<u32, io::Error> {
self.socket.multicast_ttl_v4()
}
#[inline]
pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> Result<(), io::Error> {
self.socket.set_multicast_loop_v6(multicast_loop_v6)
}
#[inline]
pub fn multicast_loop_v6(&self) -> Result<bool, io::Error> {
self.socket.multicast_loop_v6()
}
#[inline]
pub fn join_multicast_v4(
&self,
multiaddr: &Ipv4Addr,
interface: &Ipv4Addr,
) -> Result<(), io::Error> {
self.socket.join_multicast_v4(multiaddr, interface)
}
#[inline]
pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> Result<(), io::Error> {
self.socket.join_multicast_v6(multiaddr, interface)
}
#[inline]
pub fn leave_multicast_v4(
&self,
multiaddr: &Ipv4Addr,
interface: &Ipv4Addr,
) -> Result<(), io::Error> {
self.socket.leave_multicast_v4(multiaddr, interface)
}
#[inline]
pub fn leave_multicast_v6(
&self,
multiaddr: &Ipv6Addr,
interface: u32,
) -> Result<(), io::Error> {
self.socket.leave_multicast_v6(multiaddr, interface)
}
#[inline]
pub fn take_error(&self) -> Result<Option<io::Error>, io::Error> {
self.socket.take_error()
}
#[inline]
pub fn set_read_timeout(&self, dur: Option<Duration>) -> Result<(), io::Error> {
self.socket.set_read_timeout(dur)
}
#[inline]
pub fn set_write_timeout(&self, dur: Option<Duration>) -> Result<(), io::Error> {
self.socket.set_write_timeout(dur)
}
#[inline]
pub fn read_timeout(&self) -> Result<Option<Duration>, io::Error> {
self.socket.read_timeout()
}
#[inline]
pub fn write_timeout(&self) -> Result<Option<Duration>, io::Error> {
self.socket.write_timeout()
}
#[inline]
pub fn poll_recv(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<Result<usize, io::Error>> {
let this = self.get_mut();
let handle = &this.socket.handle;
let buf_temp = unsafe { IoBufTemporaryPoll::new(buf.as_mut_ptr(), buf.len()) };
let mut op = RecvOp::new(handle, buf_temp);
handle.poll_op_poll(cx, &mut op)
}
#[inline]
pub fn poll_recv_from(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<Result<(usize, SocketAddr), io::Error>> {
let this = self.get_mut();
let handle = &this.socket.handle;
let buf_temp = unsafe { IoBufTemporaryPoll::new(buf.as_mut_ptr(), buf.len()) };
let mut op = RecvfromOp::new(handle, buf_temp);
handle.poll_op_poll(cx, &mut op)
}
#[inline]
pub fn poll_send(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<Result<usize, io::Error>> {
let this = self.get_mut();
let handle = &this.socket.handle;
let buf_temp = unsafe { IoBufTemporaryPoll::new(buf.as_ptr() as *mut u8, buf.len()) };
let mut op = SendOp::new(handle, buf_temp);
handle.poll_op_poll(cx, &mut op)
}
#[inline]
pub fn poll_send_to(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
target: SocketAddr,
) -> Poll<Result<usize, io::Error>> {
let this = self.get_mut();
let handle = &this.socket.handle;
let buf_temp = unsafe { IoBufTemporaryPoll::new(buf.as_ptr() as *mut u8, buf.len()) };
let mut op = SendtoOp::new(handle, buf_temp, target);
handle.poll_op_poll(cx, &mut op)
}
#[inline]
pub fn poll_peek(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<Result<usize, io::Error>> {
let this = self.get_mut();
let handle = &this.socket.handle;
let buf_temp = unsafe { IoBufTemporaryPoll::new(buf.as_mut_ptr(), buf.len()) };
let mut op = RecvOp::new_peek(handle, buf_temp);
handle.poll_op_poll(cx, &mut op)
}
#[inline]
pub fn poll_peek_from(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<Result<(usize, SocketAddr), io::Error>> {
let this = self.get_mut();
let handle = &this.socket.handle;
let buf_temp = unsafe { IoBufTemporaryPoll::new(buf.as_mut_ptr(), buf.len()) };
let mut op = RecvfromOp::new_peek(handle, buf_temp);
handle.poll_op_poll(cx, &mut op)
}
#[inline]
pub fn try_io_readable<Io, IoR>(&self, io: Io) -> io::Result<IoR>
where
Io: FnOnce() -> io::Result<IoR>,
{
if *self.read_ready.borrow() {
let result = io();
if result.is_err() {
*self.read_ready.borrow_mut() = false;
}
result
} else {
Err(io::Error::new(io::ErrorKind::WouldBlock, "read not ready"))
}
}
#[inline]
pub fn try_io_writable<Io, IoR>(&self, io: Io) -> io::Result<IoR>
where
Io: FnOnce() -> io::Result<IoR>,
{
if *self.write_ready.borrow() {
let result = io();
if result.is_err() {
*self.write_ready.borrow_mut() = false;
}
result
} else {
Err(io::Error::new(io::ErrorKind::WouldBlock, "write not ready"))
}
}
}
impl AsyncReadPoll for PollUdpSocket {
#[inline]
fn poll_readable(&self, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
if *self.read_ready.borrow() {
return Poll::Ready(Ok(()));
}
let poll = self
.socket
.handle
.poll_op_poll(cx, &mut ReadinessOp::new_readable(&self.socket.handle))?;
*self.read_ready.borrow_mut() = true;
poll.map(Ok)
}
}
impl AsyncWritePoll for PollUdpSocket {
#[inline]
fn poll_writable(&self, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
if *self.write_ready.borrow() {
return Poll::Ready(Ok(()));
}
let poll = self
.socket
.handle
.poll_op_poll(cx, &mut ReadinessOp::new_writable(&self.socket.handle))?;
*self.write_ready.borrow_mut() = true;
poll.map(Ok)
}
}
impl<'a> AsInnerRawHandle<'a> for PollUdpSocket {
#[inline]
fn as_inner_raw_handle(&'a self) -> &'a InnerRawHandle {
self.socket.as_inner_raw_handle()
}
}
#[cfg(unix)]
impl AsRawFd for PollUdpSocket {
#[inline]
fn as_raw_fd(&self) -> RawFd {
self.socket.inner.as_raw_fd()
}
}
#[cfg(unix)]
impl IntoRawFd for PollUdpSocket {
#[inline]
fn into_raw_fd(self) -> RawFd {
self.socket.into_std().into_raw_fd()
}
}
#[cfg(windows)]
impl AsRawSocket for PollUdpSocket {
#[inline]
fn as_raw_socket(&self) -> RawSocket {
self.socket.inner.as_raw_socket()
}
}
#[cfg(windows)]
impl IntoRawSocket for PollUdpSocket {
#[inline]
fn into_raw_socket(self) -> RawSocket {
self.socket.into_std().into_raw_socket()
}
}