use std::{future::Future, io, net::SocketAddr};
use compio_buf::{BufResult, IoBuf, IoBufMut, IoVectoredBuf, IoVectoredBufMut};
use compio_driver::impl_raw_fd;
use compio_runtime::{BorrowedBuffer, BufferPool};
use socket2::{Protocol, SockAddr, Socket as Socket2, Type};
use crate::{Socket, SocketOpts, ToSocketAddrsAsync};
#[derive(Debug, Clone)]
pub struct UdpSocket {
inner: Socket,
}
impl UdpSocket {
pub async fn bind(addr: impl ToSocketAddrsAsync) -> io::Result<Self> {
Self::bind_with_options(addr, &SocketOpts::default()).await
}
pub async fn bind_with_options(
addr: impl ToSocketAddrsAsync,
opts: &SocketOpts,
) -> io::Result<Self> {
super::each_addr(addr, |addr| async move {
let socket =
Socket::bind(&SockAddr::from(addr), Type::DGRAM, Some(Protocol::UDP)).await?;
opts.setup_socket(&socket)?;
Ok(Self { inner: socket })
})
.await
}
pub async fn connect(&self, addr: impl ToSocketAddrsAsync) -> io::Result<()> {
super::each_addr(addr, |addr| async move {
self.inner.connect(&SockAddr::from(addr))
})
.await
}
pub fn from_std(socket: std::net::UdpSocket) -> io::Result<Self> {
Ok(Self {
inner: Socket::from_socket2(Socket2::from(socket))?,
})
}
pub fn close(self) -> impl Future<Output = io::Result<()>> {
self.inner.close()
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
self.inner
.peer_addr()
.map(|addr| addr.as_socket().expect("should be SocketAddr"))
}
pub fn local_addr(&self) -> io::Result<SocketAddr> {
self.inner
.local_addr()
.map(|addr| addr.as_socket().expect("should be SocketAddr"))
}
pub async fn recv<T: IoBufMut>(&self, buffer: T) -> BufResult<usize, T> {
self.inner.recv(buffer, 0).await
}
pub async fn recv_vectored<T: IoVectoredBufMut>(&self, buffer: T) -> BufResult<usize, T> {
self.inner.recv_vectored(buffer, 0).await
}
pub async fn recv_managed<'a>(
&self,
buffer_pool: &'a BufferPool,
len: usize,
) -> io::Result<BorrowedBuffer<'a>> {
self.inner.recv_managed(buffer_pool, len, 0).await
}
pub async fn recv_from_managed<'a>(
&self,
buffer_pool: &'a BufferPool,
len: usize,
) -> io::Result<(BorrowedBuffer<'a>, SocketAddr)> {
self.inner
.recv_from_managed(buffer_pool, len, 0)
.await
.map(|(buffer, addr)| (buffer, addr.as_socket().expect("should be SocketAddr")))
}
pub async fn send<T: IoBuf>(&self, buffer: T) -> BufResult<usize, T> {
self.inner.send(buffer, 0).await
}
pub async fn send_vectored<T: IoVectoredBuf>(&self, buffer: T) -> BufResult<usize, T> {
self.inner.send_vectored(buffer, 0).await
}
pub async fn recv_from<T: IoBufMut>(&self, buffer: T) -> BufResult<(usize, SocketAddr), T> {
self.inner
.recv_from(buffer, 0)
.await
.map_res(|(n, addr)| (n, addr.as_socket().expect("should be SocketAddr")))
}
pub async fn recv_from_vectored<T: IoVectoredBufMut>(
&self,
buffer: T,
) -> BufResult<(usize, SocketAddr), T> {
self.inner
.recv_from_vectored(buffer, 0)
.await
.map_res(|(n, addr)| (n, addr.as_socket().expect("should be SocketAddr")))
}
pub async fn recv_msg<T: IoBufMut, C: IoBufMut>(
&self,
buffer: T,
control: C,
) -> BufResult<(usize, usize, SocketAddr), (T, C)> {
self.inner
.recv_msg(buffer, control, 0)
.await
.map_res(|(n, m, addr)| (n, m, addr.as_socket().expect("should be SocketAddr")))
}
pub async fn recv_msg_vectored<T: IoVectoredBufMut, C: IoBufMut>(
&self,
buffer: T,
control: C,
) -> BufResult<(usize, usize, SocketAddr), (T, C)> {
self.inner
.recv_msg_vectored(buffer, control, 0)
.await
.map_res(|(n, m, addr)| (n, m, addr.as_socket().expect("should be SocketAddr")))
}
pub async fn send_to<T: IoBuf>(
&self,
buffer: T,
addr: impl ToSocketAddrsAsync,
) -> BufResult<usize, T> {
super::first_addr_buf(addr, buffer, |addr, buffer| async move {
self.inner.send_to(buffer, &SockAddr::from(addr), 0).await
})
.await
}
pub async fn send_to_vectored<T: IoVectoredBuf>(
&self,
buffer: T,
addr: impl ToSocketAddrsAsync,
) -> BufResult<usize, T> {
super::first_addr_buf(addr, buffer, |addr, buffer| async move {
self.inner
.send_to_vectored(buffer, &SockAddr::from(addr), 0)
.await
})
.await
}
pub async fn send_msg<T: IoBuf, C: IoBuf>(
&self,
buffer: T,
control: C,
addr: impl ToSocketAddrsAsync,
) -> BufResult<usize, (T, C)> {
super::first_addr_buf(
addr,
(buffer, control),
|addr, (buffer, control)| async move {
self.inner
.send_msg(buffer, control, &SockAddr::from(addr), 0)
.await
},
)
.await
}
pub async fn send_msg_vectored<T: IoVectoredBuf, C: IoBuf>(
&self,
buffer: T,
control: C,
addr: impl ToSocketAddrsAsync,
) -> BufResult<usize, (T, C)> {
super::first_addr_buf(
addr,
(buffer, control),
|addr, (buffer, control)| async move {
self.inner
.send_msg_vectored(buffer, control, &SockAddr::from(addr), 0)
.await
},
)
.await
}
pub unsafe fn get_socket_option<T: Copy>(&self, level: i32, name: i32) -> io::Result<T> {
unsafe { self.inner.get_socket_option(level, name) }
}
pub unsafe fn set_socket_option<T: Copy>(
&self,
level: i32,
name: i32,
value: &T,
) -> io::Result<()> {
unsafe { self.inner.set_socket_option(level, name, value) }
}
}
impl_raw_fd!(UdpSocket, socket2::Socket, inner, socket);