#[cfg(any(unix, target_os = "wasi"))]
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, RawFd};
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, AsSocket, BorrowedSocket, RawSocket};
use std::{
fmt, io,
net::{Ipv4Addr, Ipv6Addr, SocketAddr},
};
use crate::{AsyncIo, Local, Mode, Runtime};
pub struct UdpSocket<M = Local>
where
M: Mode,
{
io: AsyncIo<std::net::UdpSocket, M>,
}
impl<M> UdpSocket<M>
where
M: Mode,
{
pub fn bind<A>(runtime: &Runtime<M>, addr: A) -> io::Result<Self>
where
A: Into<SocketAddr>,
{
Self::from_std(runtime, std::net::UdpSocket::bind(addr.into())?)
}
pub fn from_std(runtime: &Runtime<M>, socket: std::net::UdpSocket) -> io::Result<Self> {
socket.set_nonblocking(true)?;
Ok(Self {
io: AsyncIo::from_nonblocking(runtime, socket)?,
})
}
pub fn local_addr(&self) -> io::Result<SocketAddr> {
self.io.get_ref().local_addr()
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
self.io.get_ref().peer_addr()
}
pub fn connect<A>(&self, addr: A) -> io::Result<()>
where
A: Into<SocketAddr>,
{
self.io.get_ref().connect(addr.into())
}
pub async fn send_to<A>(&self, buf: &[u8], addr: A) -> io::Result<usize>
where
A: Into<SocketAddr>,
{
let target = addr.into();
self.io
.write_with(|socket| socket.send_to(buf, target))
.await
}
pub async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
self.io.read_with(|socket| socket.recv_from(buf)).await
}
pub async fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
self.io.read_with(|socket| socket.peek_from(buf)).await
}
pub async fn send(&self, buf: &[u8]) -> io::Result<usize> {
self.io.write_with(|socket| socket.send(buf)).await
}
pub async fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
self.io.read_with(|socket| socket.recv(buf)).await
}
pub async fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
self.io.read_with(|socket| socket.peek(buf)).await
}
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 join_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()> {
self.io.get_ref().join_multicast_v4(&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 join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
self.io.get_ref().join_multicast_v6(multiaddr, interface)
}
pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
self.io.get_ref().leave_multicast_v6(multiaddr, interface)
}
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)
}
}
impl<M> fmt::Debug for UdpSocket<M>
where
M: Mode,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.io.get_ref(), f)
}
}
#[cfg(any(unix, target_os = "wasi"))]
impl<M> AsFd for UdpSocket<M>
where
M: Mode,
{
fn as_fd(&self) -> BorrowedFd<'_> {
self.io.get_ref().as_fd()
}
}
#[cfg(any(unix, target_os = "wasi"))]
impl<M> AsRawFd for UdpSocket<M>
where
M: Mode,
{
fn as_raw_fd(&self) -> RawFd {
self.io.get_ref().as_raw_fd()
}
}
#[cfg(windows)]
impl<M> AsSocket for UdpSocket<M>
where
M: Mode,
{
fn as_socket(&self) -> BorrowedSocket<'_> {
self.io.get_ref().as_socket()
}
}
#[cfg(windows)]
impl<M> AsRawSocket for UdpSocket<M>
where
M: Mode,
{
fn as_raw_socket(&self) -> RawSocket {
self.io.get_ref().as_raw_socket()
}
}