veecle_osal_std/net/
udp.rs1use crate::IntoOsalError;
4use core::net::SocketAddr;
5use socket2::{Protocol, SockAddr, Type};
6use std::io::ErrorKind;
7use veecle_osal_api::net::udp::Error;
8
9#[derive(Default)]
11pub struct UdpSocket {
12 socket: Option<tokio::net::UdpSocket>,
16}
17
18impl core::fmt::Debug for UdpSocket {
19 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
20 f.debug_struct("UdpSocket").finish()
21 }
22}
23
24impl UdpSocket {
25 pub fn new() -> Self {
27 Self { socket: None }
28 }
29}
30
31impl veecle_osal_api::net::udp::UdpSocket for UdpSocket {
32 async fn bind(&mut self, address: SocketAddr) -> Result<(), Error> {
33 if self.socket.is_some() {
34 return Err(Error::InvalidState);
35 }
36
37 let socket2_socket = socket2::Socket::new(
42 socket2::Domain::for_address(address),
43 Type::DGRAM,
44 Some(Protocol::UDP),
45 )
46 .map_err(IntoOsalError::into_osal_error)?;
47
48 socket2_socket
49 .set_reuse_address(true)
50 .map_err(IntoOsalError::into_osal_error)?;
51 socket2_socket
52 .set_reuse_port(true)
53 .map_err(IntoOsalError::into_osal_error)?;
54 socket2_socket
55 .set_nonblocking(true)
56 .map_err(IntoOsalError::into_osal_error)?;
57
58 let socket2_addr: SockAddr = address.into();
59 socket2_socket
60 .bind(&socket2_addr)
61 .map_err(IntoOsalError::into_osal_error)?;
62
63 let tokio_socket = tokio::net::UdpSocket::from_std(socket2_socket.into())
64 .map_err(IntoOsalError::into_osal_error)?;
65
66 self.socket = Some(tokio_socket);
67 Ok(())
68 }
69
70 fn local_addr(&self) -> Result<SocketAddr, Error> {
71 self.socket
72 .as_ref()
73 .ok_or(Error::SocketNotBound)?
74 .local_addr()
75 .map_err(IntoOsalError::into_osal_error)
76 }
77
78 async fn recv_from(&self, buffer: &mut [u8]) -> Result<(usize, SocketAddr), Error> {
79 let Some(socket) = self.socket.as_ref() else {
80 return Err(Error::SocketNotBound);
81 };
82
83 let (read, address) = socket
84 .recv_from(buffer)
85 .await
86 .map_err(IntoOsalError::into_osal_error)?;
87
88 Ok((read, address))
89 }
90
91 async fn send_to(&self, buffer: &[u8], address: SocketAddr) -> Result<usize, Error> {
92 let Some(socket) = self.socket.as_ref() else {
93 return Err(Error::SocketNotBound);
94 };
95
96 let read = socket
97 .send_to(buffer, address)
98 .await
99 .map_err(IntoOsalError::into_osal_error)?;
100
101 Ok(read)
102 }
103
104 fn close(&mut self) {
105 self.socket = None;
106 }
107}
108
109impl IntoOsalError<Error> for std::io::Error {
110 fn into_osal_error(self) -> Error {
111 match self.kind() {
112 ErrorKind::PermissionDenied => Error::PermissionDenied,
113 ErrorKind::HostUnreachable => Error::NoRoute,
114 ErrorKind::NetworkUnreachable => Error::NoRoute,
115 ErrorKind::AddrInUse => Error::InvalidAddress,
116 ErrorKind::AddrNotAvailable => Error::InvalidAddress,
117 ErrorKind::NetworkDown => Error::NetworkDown,
118 _ => Error::Other,
119 }
120 }
121}