use bytes::Bytes;
use std::net::SocketAddr;
use std::sync::Arc;
use tokio::net::UdpSocket;
use tokio::sync::mpsc;
use crate::dtls::Result;
pub struct UdpTransport {
socket: Arc<UdpSocket>,
mtu: usize,
rx: mpsc::Receiver<(Bytes, SocketAddr)>,
tx: mpsc::Sender<(Bytes, SocketAddr)>,
running: bool,
}
impl UdpTransport {
pub async fn new(socket: Arc<UdpSocket>, mtu: usize) -> Result<Self> {
let (tx, rx) = mpsc::channel(100);
let transport = Self {
socket,
mtu,
rx,
tx,
running: false,
};
Ok(transport)
}
pub async fn start(&mut self) -> Result<()> {
if self.running {
return Ok(());
}
self.running = true;
let socket = self.socket.clone();
let tx = self.tx.clone();
let mtu = self.mtu;
tokio::spawn(async move {
let mut buf = vec![0u8; mtu];
loop {
match socket.recv_from(&mut buf).await {
Ok((n, addr)) => {
let packet = Bytes::copy_from_slice(&buf[..n]);
if tx.send((packet, addr)).await.is_err() {
break;
}
}
Err(err) => {
tracing::error!("DTLS UDP transport error: {}", err);
}
}
}
});
Ok(())
}
pub async fn stop(&mut self) {
self.running = false;
}
pub async fn send(&self, data: &[u8], addr: SocketAddr) -> Result<usize> {
match self.socket.send_to(data, addr).await {
Ok(n) => Ok(n),
Err(err) => Err(crate::error::Error::IoError(err.to_string())),
}
}
pub async fn recv(&mut self) -> Option<(Bytes, SocketAddr)> {
self.rx.recv().await
}
pub fn local_addr(&self) -> Result<SocketAddr> {
match self.socket.local_addr() {
Ok(addr) => Ok(addr),
Err(err) => Err(crate::error::Error::IoError(err.to_string())),
}
}
pub fn mtu(&self) -> usize {
self.mtu
}
}