Skip to main content

leodos_protocols/datalink/link/cfs/
udp.rs

1use leodos_libcfs::error::CfsError as CfsError;
2use leodos_libcfs::os::net::SocketAddr;
3use leodos_libcfs::os::net::UdpSocket;
4
5use crate::datalink::{Datalink, DatalinkRead, DatalinkWrite};
6/// Sends frames over UDP.
7pub struct UdpFrameWriter<'a> {
8    socket: &'a UdpSocket,
9    target: &'a SocketAddr,
10}
11
12impl<'a> UdpFrameWriter<'a> {
13    /// Creates a new sender targeting the given address.
14    pub fn new(socket: &'a UdpSocket, target: &'a SocketAddr) -> Self {
15        Self { socket, target }
16    }
17}
18
19impl DatalinkWrite for UdpFrameWriter<'_> {
20    type Error = CfsError;
21
22    async fn write(&mut self, data: &[u8]) -> Result<(), Self::Error> {
23        self.socket.send(data, self.target).await?;
24        Ok(())
25    }
26}
27
28/// Receives frames over UDP.
29pub struct UdpFrameReader<'a> {
30    socket: &'a UdpSocket,
31}
32
33impl<'a> UdpFrameReader<'a> {
34    /// Creates a new receiver on the given socket.
35    pub fn new(socket: &'a UdpSocket) -> Self {
36        Self { socket }
37    }
38}
39
40impl DatalinkRead for UdpFrameReader<'_> {
41    type Error = CfsError;
42
43    async fn read(&mut self, buffer: &mut [u8]) -> Result<usize, Self::Error> {
44        let (len, _addr) = self.socket.recv(buffer).await?;
45        Ok(len)
46    }
47}
48
49/// A bidirectional UDP data link.
50pub struct UdpDatalink {
51    socket: UdpSocket,
52    remote: SocketAddr,
53}
54
55impl UdpDatalink {
56    /// Creates a new data link from an existing socket and remote address.
57    pub fn new(socket: UdpSocket, remote: SocketAddr) -> Self {
58        Self { socket, remote }
59    }
60
61    /// Binds a local socket and creates a data link to the remote address.
62    pub fn bind(local: SocketAddr, remote: SocketAddr) -> Result<Self, CfsError> {
63        let socket = UdpSocket::bind(local)?;
64        Ok(Self { socket, remote })
65    }
66
67    /// Splits into independent read and write halves.
68    ///
69    /// Both halves borrow the underlying socket. `send()` and
70    /// `recv()` on `UdpSocket` take `&self`, so concurrent
71    /// use is safe.
72    pub fn split(&self) -> (UdpFrameReader<'_>, UdpFrameWriter<'_>) {
73        (
74            UdpFrameReader::new(&self.socket),
75            UdpFrameWriter::new(&self.socket, &self.remote),
76        )
77    }
78}
79
80
81impl Datalink for UdpDatalink {
82    type ReadError = CfsError;
83    type WriteError = CfsError;
84    type Reader<'a> = UdpFrameReader<'a>;
85    type Writer<'a> = UdpFrameWriter<'a>;
86
87    fn split(&mut self) -> (UdpFrameReader<'_>, UdpFrameWriter<'_>) {
88        (
89            UdpFrameReader::new(&self.socket),
90            UdpFrameWriter::new(&self.socket, &self.remote),
91        )
92    }
93}
94
95impl DatalinkWrite for UdpDatalink {
96    type Error = CfsError;
97
98    async fn write(&mut self, data: &[u8]) -> Result<(), Self::Error> {
99        self.socket.send(data, &self.remote).await?;
100        Ok(())
101    }
102}
103
104impl DatalinkRead for UdpDatalink {
105    type Error = CfsError;
106
107    async fn read(&mut self, buffer: &mut [u8]) -> Result<usize, Self::Error> {
108        let (len, _addr) = self.socket.recv(buffer).await?;
109        Ok(len)
110    }
111}