Skip to main content

moirai_async/net/
socket.rs

1use moirai_pal::net::AsyncUdpSocket;
2use std::io;
3use std::net::SocketAddr;
4use std::sync::Arc;
5
6use crate::net::types::{UdpConfig, UdpSocketStats, UdpStats};
7
8/// Native async UDP socket
9pub struct UdpSocket {
10    inner: AsyncUdpSocket,
11    stats: Arc<UdpStats>,
12    config: UdpConfig,
13}
14
15impl UdpSocket {
16    /// Bind UDP socket to an address
17    pub async fn bind(addr: &str) -> io::Result<Self> {
18        Self::bind_with_config(addr, UdpConfig::default()).await
19    }
20
21    /// Bind UDP socket with custom configuration
22    pub async fn bind_with_config(addr: &str, config: UdpConfig) -> io::Result<Self> {
23        let addr_parsed = crate::net::resolve::resolve(addr).await?.first();
24        let inner = AsyncUdpSocket::bind(addr_parsed).await?;
25        if config.broadcast {
26            inner.set_broadcast(true)?;
27        }
28
29        Ok(Self {
30            inner,
31            stats: Arc::new(UdpStats::default()),
32            config,
33        })
34    }
35
36    /// Send data to a specific address
37    pub async fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize> {
38        let bytes_sent = self.inner.send_to(buf, target).await?;
39        self.stats
40            .packets_sent
41            .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
42        self.stats
43            .bytes_sent
44            .fetch_add(bytes_sent as u64, std::sync::atomic::Ordering::Relaxed);
45        Ok(bytes_sent)
46    }
47
48    /// Receive data from any address
49    pub async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
50        let (bytes_received, addr) = self.inner.recv_from(buf).await?;
51        self.stats
52            .packets_received
53            .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
54        self.stats
55            .bytes_received
56            .fetch_add(bytes_received as u64, std::sync::atomic::Ordering::Relaxed);
57        Ok((bytes_received, addr))
58    }
59
60    /// Get UDP socket statistics
61    pub fn stats(&self) -> UdpSocketStats {
62        UdpSocketStats {
63            packets_sent: self
64                .stats
65                .packets_sent
66                .load(std::sync::atomic::Ordering::Relaxed),
67            packets_received: self
68                .stats
69                .packets_received
70                .load(std::sync::atomic::Ordering::Relaxed),
71            bytes_sent: self
72                .stats
73                .bytes_sent
74                .load(std::sync::atomic::Ordering::Relaxed),
75            bytes_received: self
76                .stats
77                .bytes_received
78                .load(std::sync::atomic::Ordering::Relaxed),
79        }
80    }
81
82    /// Return the local socket address this UDP socket is bound to.
83    pub fn local_addr(&self) -> io::Result<SocketAddr> {
84        self.inner.local_addr()
85    }
86
87    /// Return the socket configuration used at bind time.
88    pub fn config(&self) -> &UdpConfig {
89        &self.config
90    }
91}