use super::swim::Packet;
use super::wire::{DEFAULT_MTU, EncodedDatagram, WireError, decode_packet, encode_packet};
use crate::net::UdpSocket;
use std::io;
use std::net::SocketAddr;
const RECV_BUFFER_BYTES: usize = 65_536;
#[derive(Debug)]
pub enum UdpMembershipError {
Io(io::Error),
Wire(WireError),
}
impl std::fmt::Display for UdpMembershipError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Io(e) => write!(f, "udp membership io error: {e}"),
Self::Wire(e) => write!(f, "udp membership wire error: {e}"),
}
}
}
impl std::error::Error for UdpMembershipError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Io(e) => Some(e),
Self::Wire(e) => Some(e),
}
}
}
impl From<io::Error> for UdpMembershipError {
fn from(e: io::Error) -> Self {
Self::Io(e)
}
}
impl From<WireError> for UdpMembershipError {
fn from(e: WireError) -> Self {
Self::Wire(e)
}
}
pub struct UdpMembershipTransport {
socket: UdpSocket,
mtu: usize,
recv_buffer: Vec<u8>,
}
impl UdpMembershipTransport {
#[must_use]
pub fn new(socket: UdpSocket) -> Self {
Self::with_mtu(socket, DEFAULT_MTU)
}
#[must_use]
pub fn with_mtu(socket: UdpSocket, mtu: usize) -> Self {
Self {
socket,
mtu,
recv_buffer: vec![0u8; RECV_BUFFER_BYTES],
}
}
pub fn local_addr(&self) -> io::Result<SocketAddr> {
self.socket.local_addr()
}
#[must_use]
pub const fn mtu(&self) -> usize {
self.mtu
}
pub async fn send(
&mut self,
target: SocketAddr,
packet: &Packet,
) -> Result<EncodedDatagram, UdpMembershipError> {
let datagram = encode_packet(packet, self.mtu)?;
self.socket.send_to(&datagram.bytes, target).await?;
Ok(datagram)
}
pub async fn recv(&mut self) -> Result<(SocketAddr, Packet), UdpMembershipError> {
let (len, from) = self.socket.recv_from(&mut self.recv_buffer).await?;
let packet = decode_packet(&self.recv_buffer[..len])?;
Ok((from, packet))
}
}