use crate::UdpFramed;
use bytes::BufMut;
use rama_core::error::{BoxError, ErrorContext};
use rama_net::address::SocketAddress;
use std::{
io,
net::{Ipv4Addr, Ipv6Addr, SocketAddr},
};
use tokio::net::UdpSocket as TokioUdpSocket;
#[derive(Debug)]
pub struct UdpSocket {
inner: TokioUdpSocket,
}
impl UdpSocket {
pub async fn bind<A: TryInto<SocketAddress, Error: Into<BoxError>>>(
addr: A,
) -> Result<Self, BoxError> {
let socket_addr = addr.try_into().map_err(Into::into)?;
let tokio_socket_addr: SocketAddr = socket_addr.into();
let inner = TokioUdpSocket::bind(tokio_socket_addr)
.await
.context("bind to udp socket")?;
Ok(Self { inner })
}
#[inline]
pub fn from_std(socket: std::net::UdpSocket) -> io::Result<UdpSocket> {
socket.set_nonblocking(true)?;
Ok(TokioUdpSocket::from_std(socket)?.into())
}
#[inline]
pub fn into_std(self) -> io::Result<std::net::UdpSocket> {
self.inner.into_std()
}
#[cfg(any(windows, unix))]
#[inline]
pub fn as_socket(&self) -> rama_net::socket::SockRef<'_> {
rama_net::socket::SockRef::from(self)
}
#[inline]
pub fn local_addr(&self) -> io::Result<SocketAddr> {
self.inner.local_addr()
}
#[inline]
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
self.inner.peer_addr()
}
#[inline]
pub async fn connect<A: TryInto<SocketAddress, Error: Into<BoxError>>>(
&self,
addr: A,
) -> Result<(), BoxError> {
let socket_addr = addr.try_into().map_err(Into::into)?;
let tokio_socket_addr: SocketAddr = socket_addr.into();
self.inner.connect(tokio_socket_addr).await?;
Ok(())
}
#[inline]
pub async fn send(&self, buf: &[u8]) -> io::Result<usize> {
self.inner.send(buf).await
}
#[inline]
pub async fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.recv(buf).await
}
pub async fn recv_buf<B: BufMut>(&self, buf: &mut B) -> io::Result<usize> {
self.inner.recv_buf(buf).await
}
#[inline]
pub async fn recv_buf_from<B: BufMut>(
&self,
buf: &mut B,
) -> io::Result<(usize, SocketAddress)> {
let (n, addr) = self.inner.recv_buf_from(buf).await?;
Ok((n, addr.into()))
}
#[inline]
pub async fn send_to<A: TryInto<SocketAddress, Error: Into<BoxError>>>(
&self,
buf: &[u8],
addr: A,
) -> Result<usize, BoxError> {
let socket_addr = addr.try_into().map_err(Into::into)?;
let tokio_socket_addr: SocketAddr = socket_addr.into();
Ok(self.inner.send_to(buf, tokio_socket_addr).await?)
}
pub async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddress)> {
let (n, addr) = self.inner.recv_from(buf).await?;
Ok((n, addr.into()))
}
#[inline]
pub async fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.peek(buf).await
}
#[inline]
pub async fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddress)> {
let (n, addr) = self.inner.peek_from(buf).await?;
Ok((n, addr.into()))
}
#[inline]
pub async fn peek_sender(&self) -> io::Result<SocketAddress> {
Ok(self.inner.peek_sender().await?.into())
}
#[inline]
pub fn broadcast(&self) -> io::Result<bool> {
self.inner.broadcast()
}
#[inline]
pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
self.inner.set_broadcast(on)
}
#[inline]
pub fn multicast_loop_v4(&self) -> io::Result<bool> {
self.inner.multicast_loop_v4()
}
#[inline]
pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> {
self.inner.set_multicast_loop_v4(on)
}
#[inline]
pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
self.inner.multicast_ttl_v4()
}
#[inline]
pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
self.inner.set_multicast_ttl_v4(ttl)
}
#[inline]
pub fn multicast_loop_v6(&self) -> io::Result<bool> {
self.inner.multicast_loop_v6()
}
#[inline]
pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> {
self.inner.set_multicast_loop_v6(on)
}
#[inline]
pub fn ttl(&self) -> io::Result<u32> {
self.inner.ttl()
}
#[inline]
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
self.inner.set_ttl(ttl)
}
#[inline]
pub fn join_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()> {
self.inner.join_multicast_v4(multiaddr, interface)
}
#[inline]
pub fn join_multicast_v6(&self, multiaddr: Ipv6Addr, interface: u32) -> io::Result<()> {
self.inner.join_multicast_v6(&multiaddr, interface)
}
#[inline]
pub fn leave_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()> {
self.inner.leave_multicast_v4(multiaddr, interface)
}
#[inline]
pub fn leave_multicast_v6(&self, multiaddr: Ipv6Addr, interface: u32) -> io::Result<()> {
self.inner.leave_multicast_v6(&multiaddr, interface)
}
#[inline]
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
self.inner.take_error()
}
pub fn into_framed<C>(self, codec: C) -> UdpFramed<C> {
UdpFramed::new(self.inner, codec)
}
}
#[cfg(any(windows, unix))]
impl TryFrom<rama_net::socket::Socket> for UdpSocket {
type Error = std::io::Error;
#[inline]
fn try_from(value: rama_net::socket::Socket) -> Result<Self, Self::Error> {
let socket = std::net::UdpSocket::from(value);
socket.try_into()
}
}
impl TryFrom<std::net::UdpSocket> for UdpSocket {
type Error = io::Error;
#[inline]
fn try_from(stream: std::net::UdpSocket) -> Result<Self, Self::Error> {
Self::from_std(stream)
}
}
impl TryFrom<UdpSocket> for std::net::UdpSocket {
type Error = io::Error;
#[inline]
fn try_from(stream: UdpSocket) -> Result<Self, Self::Error> {
stream.into_std()
}
}
impl From<TokioUdpSocket> for UdpSocket {
fn from(value: TokioUdpSocket) -> Self {
Self { inner: value }
}
}
impl From<UdpSocket> for TokioUdpSocket {
fn from(value: UdpSocket) -> Self {
value.inner
}
}
#[cfg(unix)]
mod sys {
use super::UdpSocket;
use std::os::unix::prelude::*;
impl AsRawFd for UdpSocket {
#[inline]
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}
impl AsFd for UdpSocket {
#[inline]
fn as_fd(&self) -> BorrowedFd<'_> {
self.inner.as_fd()
}
}
}
#[cfg(windows)]
mod sys {
use super::UdpSocket;
use std::os::windows::prelude::*;
impl AsRawSocket for UdpSocket {
#[inline]
fn as_raw_socket(&self) -> RawSocket {
self.inner.as_raw_socket()
}
}
impl AsSocket for UdpSocket {
#[inline]
fn as_socket(&self) -> BorrowedSocket<'_> {
self.inner.as_socket()
}
}
}