use std::{
future::Future,
io,
net::{Ipv4Addr, Ipv6Addr, SocketAddr},
};
use crate::packet::{Packet, PacketBufPool};
pub mod buffer;
pub mod channel;
pub mod socket;
pub trait UdpTransportFactory: Send + Sync + 'static {
type SendV4: UdpSend + 'static;
type SendV6: UdpSend + 'static;
type RecvV4: UdpRecv + 'static;
type RecvV6: UdpRecv + 'static;
#[allow(clippy::type_complexity)]
fn bind(
&mut self,
params: &UdpTransportFactoryParams,
) -> impl Future<
Output = io::Result<((Self::SendV4, Self::RecvV4), (Self::SendV6, Self::RecvV6))>,
> + Send;
}
#[derive(Clone, Debug)]
pub struct UdpTransportFactoryParams {
pub addr_v4: Ipv4Addr,
pub addr_v6: Ipv6Addr,
pub port: u16,
#[cfg(target_os = "linux")]
pub fwmark: Option<u32>,
}
pub trait UdpRecv: Send + Sync {
fn recv_from(
&mut self,
pool: &mut PacketBufPool,
) -> impl Future<Output = io::Result<(Packet, SocketAddr)>> + Send;
type RecvManyBuf: Default + Send;
fn recv_many_from(
&mut self,
recv_buf: &mut Self::RecvManyBuf,
pool: &mut PacketBufPool,
packets: &mut Vec<(Packet, SocketAddr)>,
) -> impl Future<Output = io::Result<()>> + Send {
let _ = recv_buf;
async move {
let (packet, source_addr) = self.recv_from(pool).await?;
packets.push((packet, source_addr));
Ok(())
}
}
fn enable_udp_gro(&self) -> io::Result<()> {
Ok(())
}
}
pub trait UdpSend: Send + Sync + Clone {
type SendManyBuf: Default + Send + Sync;
fn send_to(
&self,
packet: Packet,
destination: SocketAddr,
) -> impl Future<Output = io::Result<()>> + Send;
fn max_number_of_packets_to_send(&self) -> usize {
1
}
fn send_many_to(
&self,
send_buf: &mut Self::SendManyBuf,
packets: &mut Vec<(Packet, SocketAddr)>,
) -> impl Future<Output = io::Result<()>> + Send {
let _ = send_buf;
generic_send_many_to(self, packets)
}
fn local_addr(&self) -> io::Result<Option<SocketAddr>> {
Ok(None)
}
#[cfg(target_os = "linux")]
fn set_fwmark(&self, _mark: u32) -> io::Result<()> {
Ok(())
}
}
#[cfg(not(target_os = "macos"))]
fn check_send_max_number_of_packets(
max_number_of_packets: usize,
packets: &[(Packet, SocketAddr)],
) -> io::Result<()> {
debug_assert!(packets.len() <= max_number_of_packets);
if packets.len() > max_number_of_packets {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!("send_many_to: Number of packets may not exceed {max_number_of_packets}"),
));
}
Ok(())
}
async fn generic_send_many_to<U: UdpSend>(
transport: &U,
packets: &mut Vec<(Packet, SocketAddr)>,
) -> io::Result<()> {
for (packet, target) in packets.drain(..) {
transport.send_to(packet, target).await?;
}
Ok(())
}