use crate::{
UnsubmittedWrite,
buf::fixed::FixedBuf,
buf::{BoundedBuf, BoundedBufMut},
io::{SharedFd, Socket},
};
use socket2::SockAddr;
use std::{
io,
net::SocketAddr,
os::unix::prelude::{AsRawFd, FromRawFd, RawFd},
};
pub struct UdpSocket {
pub(super) inner: Socket,
}
impl UdpSocket {
pub async fn bind(socket_addr: SocketAddr) -> io::Result<UdpSocket> {
let socket = Socket::bind(socket_addr, libc::SOCK_DGRAM)?;
Ok(UdpSocket { inner: socket })
}
pub fn local_addr(&self) -> io::Result<SocketAddr> {
let fd = self.inner.as_raw_fd();
let s = unsafe { std::net::UdpSocket::from_raw_fd(fd) };
let local_addr = s.local_addr();
std::mem::forget(s);
local_addr
}
pub fn from_std(socket: std::net::UdpSocket) -> Self {
let inner = Socket::from_std(socket);
Self { inner }
}
pub(crate) fn from_socket(inner: Socket) -> Self {
Self { inner }
}
pub async fn connect(&self, socket_addr: SocketAddr) -> io::Result<()> {
self.inner.connect(SockAddr::from(socket_addr)).await
}
pub async fn send<T: BoundedBuf>(&self, buf: T) -> crate::BufResult<usize, T> {
self.inner.send_to(buf, None).await
}
pub async fn send_to<T: BoundedBuf>(&self, buf: T, socket_addr: SocketAddr) -> crate::BufResult<usize, T> {
self.inner.send_to(buf, Some(socket_addr)).await
}
pub async fn send_zc<T: BoundedBuf>(&self, buf: T) -> crate::BufResult<usize, T> {
self.inner.send_zc(buf).await
}
pub async fn sendmsg<T: BoundedBuf, U: BoundedBuf>(
&self,
io_slices: Vec<T>,
socket_addr: Option<SocketAddr>,
msg_control: Option<U>,
) -> (io::Result<usize>, Vec<T>, Option<U>) {
self.inner.sendmsg(io_slices, socket_addr, msg_control).await
}
pub async fn sendmsg_zc<T: BoundedBuf, U: BoundedBuf>(
&self,
io_slices: Vec<T>,
socket_addr: Option<SocketAddr>,
msg_control: Option<U>,
) -> (io::Result<usize>, Vec<T>, Option<U>) {
self.inner.sendmsg_zc(io_slices, socket_addr, msg_control).await
}
pub async fn recv_from<T: BoundedBufMut>(&self, buf: T) -> crate::BufResult<(usize, SocketAddr), T> {
self.inner.recv_from(buf).await
}
pub async fn recvmsg<T: BoundedBufMut>(&self, buf: Vec<T>) -> crate::BufResult<(usize, SocketAddr), Vec<T>> {
self.inner.recvmsg(buf).await
}
pub async fn read<T: BoundedBufMut>(&self, buf: T) -> crate::BufResult<usize, T> {
self.inner.read(buf).await
}
pub async fn read_fixed<T>(&self, buf: T) -> crate::BufResult<usize, T>
where
T: BoundedBufMut<BufMut = FixedBuf>,
{
self.inner.read_fixed(buf).await
}
pub fn write<T: BoundedBuf>(&self, buf: T) -> UnsubmittedWrite<T> {
self.inner.write(buf)
}
pub async fn write_fixed<T>(&self, buf: T) -> crate::BufResult<usize, T>
where
T: BoundedBuf<Buf = FixedBuf>,
{
self.inner.write_fixed(buf).await
}
pub fn shutdown(&self, how: std::net::Shutdown) -> io::Result<()> {
self.inner.shutdown(how)
}
}
impl FromRawFd for UdpSocket {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
UdpSocket::from_socket(Socket::from_shared_fd(SharedFd::new(fd)))
}
}
impl AsRawFd for UdpSocket {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}