veecle_osal_embassy/net/
tcp.rs1use crate::IntoOsalError;
4use core::net::IpAddr;
5use core::net::SocketAddr;
6use embassy_net::tcp::{AcceptError, ConnectError, State};
7use embassy_net::{IpAddress, IpEndpoint, IpListenEndpoint};
8use veecle_osal_api::net::tcp::Error;
9
10pub struct TcpSocket<'a> {
15 socket: embassy_net::tcp::TcpSocket<'a>,
16}
17
18impl<'a> core::fmt::Debug for TcpSocket<'a> {
19 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
20 f.debug_struct("TcpSocket").finish()
21 }
22}
23
24impl<'a> TcpSocket<'a> {
25 pub fn new(socket: embassy_net::tcp::TcpSocket<'a>) -> Result<Self, Error> {
29 if socket.state() != State::Closed {
30 return Err(Error::InvalidState);
31 }
32 Ok(Self { socket })
33 }
34}
35
36pub struct TcpConnection<'a, 's> {
44 socket: &'s mut embassy_net::tcp::TcpSocket<'a>,
45}
46
47impl<'a, 's> core::fmt::Debug for TcpConnection<'a, 's> {
48 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
49 f.debug_struct("TcpConnection").finish()
50 }
51}
52
53impl Drop for TcpConnection<'_, '_> {
54 fn drop(&mut self) {
55 if self.socket.state() != State::Closed {
56 self.socket.close();
57 self.socket.abort();
58 }
59 }
60}
61
62impl<'a, 's> embedded_io_async::Read for TcpConnection<'a, 's> {
63 async fn read(&mut self, buffer: &mut [u8]) -> Result<usize, Self::Error> {
64 self.socket
65 .read(buffer)
66 .await
67 .map_err(IntoOsalError::into_osal_error)
68 }
69}
70
71impl<'a, 's> embedded_io::ErrorType for TcpConnection<'a, 's> {
72 type Error = Error;
73}
74
75impl<'a, 's> embedded_io_async::Write for TcpConnection<'a, 's> {
76 async fn write(&mut self, buffer: &[u8]) -> Result<usize, Self::Error> {
77 self.socket
78 .write(buffer)
79 .await
80 .map_err(IntoOsalError::into_osal_error)
81 }
82
83 async fn flush(&mut self) -> Result<(), Self::Error> {
84 embedded_io_async::Write::flush(self.socket)
85 .await
86 .map_err(IntoOsalError::into_osal_error)
87 }
88}
89
90impl<'a, 's> veecle_osal_api::net::tcp::TcpConnection for TcpConnection<'a, 's> {
91 async fn close(self) {
92 self.socket.close();
93 let _ = self.socket.flush().await;
96 }
97}
98
99impl<'a> veecle_osal_api::net::tcp::TcpSocket for TcpSocket<'a> {
100 async fn connect(
101 &mut self,
102 address: SocketAddr,
103 ) -> Result<impl veecle_osal_api::net::tcp::TcpConnection, Error> {
104 self.socket
105 .connect(address)
106 .await
107 .map_err(IntoOsalError::into_osal_error)?;
108 Ok(TcpConnection {
109 socket: &mut self.socket,
110 })
111 }
112
113 async fn accept(
114 &mut self,
115 address: SocketAddr,
116 ) -> Result<(impl veecle_osal_api::net::tcp::TcpConnection, SocketAddr), Error> {
117 let listen_endpoint = if address.ip().is_unspecified() {
119 IpListenEndpoint {
120 addr: None,
121 port: address.port(),
122 }
123 } else {
124 address.into()
125 };
126
127 self.socket
128 .accept(listen_endpoint)
129 .await
130 .map_err(IntoOsalError::into_osal_error)?;
131 let IpEndpoint {
132 addr: address,
133 port,
134 } = self
135 .socket
136 .remote_endpoint()
137 .expect("The endpoint should be set after accepting a connection.");
138
139 let address = match address {
140 IpAddress::Ipv4(address) => IpAddr::V4(address),
141 IpAddress::Ipv6(address) => IpAddr::V6(address),
142 };
143 let address: SocketAddr = SocketAddr::new(address, port);
144 Ok((
145 TcpConnection {
146 socket: &mut self.socket,
147 },
148 address,
149 ))
150 }
151}
152
153impl IntoOsalError<Error> for AcceptError {
154 fn into_osal_error(self) -> Error {
155 match self {
156 AcceptError::ConnectionReset => Error::ConnectionReset,
157 AcceptError::InvalidState => Error::InvalidState,
158 AcceptError::InvalidPort => Error::InvalidPort,
159 }
160 }
161}
162
163impl IntoOsalError<Error> for ConnectError {
164 fn into_osal_error(self) -> Error {
165 match self {
166 ConnectError::InvalidState => Error::InvalidState,
167 ConnectError::ConnectionReset => Error::ConnectionReset,
168 ConnectError::TimedOut => Error::TimedOut,
169 ConnectError::NoRoute => Error::NoRoute,
170 }
171 }
172}
173
174impl IntoOsalError<Error> for embassy_net::tcp::Error {
175 fn into_osal_error(self) -> Error {
176 match self {
177 embassy_net::tcp::Error::ConnectionReset => Error::ConnectionReset,
178 }
179 }
180}