veecle_osal_embassy/net/
udp.rs1use crate::IntoOsalError;
4use core::net::IpAddr;
5use core::net::SocketAddr;
6use embassy_net::IpAddress;
7use embassy_net::udp::{BindError, RecvError, SendError};
8use veecle_osal_api::net::udp::Error;
9
10pub struct UdpSocket<'a> {
12 socket: embassy_net::udp::UdpSocket<'a>,
13 is_bound: bool,
15}
16
17impl<'a> core::fmt::Debug for UdpSocket<'a> {
18 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
19 f.debug_struct("UdpSocket").finish()
20 }
21}
22
23impl<'a> UdpSocket<'a> {
24 pub fn new(socket: embassy_net::udp::UdpSocket<'a>) -> Result<Self, Error> {
28 if socket.is_open() {
29 return Err(Error::InvalidState);
30 }
31 Ok(Self {
32 socket,
33 is_bound: false,
34 })
35 }
36}
37
38impl<'a> veecle_osal_api::net::udp::UdpSocket for UdpSocket<'a> {
39 async fn bind(&mut self, address: SocketAddr) -> Result<(), Error> {
40 self.socket
41 .bind(address)
42 .map_err(IntoOsalError::into_osal_error)?;
43 self.is_bound = true;
44 Ok(())
45 }
46
47 fn local_addr(&self) -> Result<SocketAddr, Error> {
48 self.socket
49 .endpoint()
50 .addr
51 .ok_or(Error::SocketNotBound)
52 .map(|address| {
53 let address = match address {
54 IpAddress::Ipv4(address) => IpAddr::V4(address),
55 IpAddress::Ipv6(address) => IpAddr::V6(address),
56 };
57 SocketAddr::new(address, self.socket.endpoint().port)
58 })
59 }
60
61 async fn recv_from(&self, buffer: &mut [u8]) -> Result<(usize, SocketAddr), Error> {
62 if !self.is_bound {
63 return Err(Error::SocketNotBound);
64 }
65 let (read, metadata) = self
66 .socket
67 .recv_from(buffer)
68 .await
69 .map_err(IntoOsalError::into_osal_error)?;
70 let address = match metadata.endpoint.addr {
71 IpAddress::Ipv4(address) => IpAddr::V4(address),
72 IpAddress::Ipv6(address) => IpAddr::V6(address),
73 };
74 let address: SocketAddr = SocketAddr::new(address, metadata.endpoint.port);
75 Ok((read, address))
76 }
77
78 async fn send_to(&self, buffer: &[u8], address: SocketAddr) -> Result<usize, Error> {
79 if !self.is_bound {
80 return Err(Error::SocketNotBound);
81 }
82 self.socket
83 .send_to(buffer, address)
84 .await
85 .map_err(IntoOsalError::into_osal_error)?;
86 Ok(buffer.len())
87 }
88
89 fn close(&mut self) {
90 self.socket.close();
91 self.is_bound = false;
92 }
93}
94
95impl IntoOsalError<Error> for BindError {
96 fn into_osal_error(self) -> Error {
97 match self {
98 BindError::InvalidState => Error::InvalidState,
99 BindError::NoRoute => Error::NoRoute,
100 }
101 }
102}
103
104impl IntoOsalError<Error> for RecvError {
105 fn into_osal_error(self) -> Error {
106 match self {
107 RecvError::Truncated => Error::BufferTooSmall,
108 }
109 }
110}
111
112impl IntoOsalError<Error> for SendError {
113 fn into_osal_error(self) -> Error {
114 match self {
115 SendError::NoRoute => Error::NoRoute,
116 SendError::SocketNotBound => Error::SocketNotBound,
117 SendError::PacketTooLarge => Error::BufferTooLarge,
118 }
119 }
120}