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
84impl<'a, 's> veecle_osal_api::net::tcp::TcpConnection for TcpConnection<'a, 's> {
85 async fn close(self) {
86 self.socket.close();
87 let _ = self.socket.flush().await;
90 }
91}
92
93impl<'a> veecle_osal_api::net::tcp::TcpSocket for TcpSocket<'a> {
94 async fn connect(
95 &mut self,
96 address: SocketAddr,
97 ) -> Result<impl veecle_osal_api::net::tcp::TcpConnection, Error> {
98 self.socket
99 .connect(address)
100 .await
101 .map_err(IntoOsalError::into_osal_error)?;
102 Ok(TcpConnection {
103 socket: &mut self.socket,
104 })
105 }
106
107 async fn accept(
108 &mut self,
109 address: SocketAddr,
110 ) -> Result<(impl veecle_osal_api::net::tcp::TcpConnection, SocketAddr), Error> {
111 let listen_endpoint = if address.ip().is_unspecified() {
113 IpListenEndpoint {
114 addr: None,
115 port: address.port(),
116 }
117 } else {
118 address.into()
119 };
120
121 self.socket
122 .accept(listen_endpoint)
123 .await
124 .map_err(IntoOsalError::into_osal_error)?;
125 let IpEndpoint {
126 addr: address,
127 port,
128 } = self
129 .socket
130 .remote_endpoint()
131 .expect("The endpoint should be set after accepting a connection.");
132
133 let address = match address {
134 IpAddress::Ipv4(address) => IpAddr::V4(address),
135 IpAddress::Ipv6(address) => IpAddr::V6(address),
136 };
137 let address: SocketAddr = SocketAddr::new(address, port);
138 Ok((
139 TcpConnection {
140 socket: &mut self.socket,
141 },
142 address,
143 ))
144 }
145}
146
147impl IntoOsalError<Error> for AcceptError {
148 fn into_osal_error(self) -> Error {
149 match self {
150 AcceptError::ConnectionReset => Error::ConnectionReset,
151 AcceptError::InvalidState => Error::InvalidState,
152 AcceptError::InvalidPort => Error::InvalidPort,
153 }
154 }
155}
156
157impl IntoOsalError<Error> for ConnectError {
158 fn into_osal_error(self) -> Error {
159 match self {
160 ConnectError::InvalidState => Error::InvalidState,
161 ConnectError::ConnectionReset => Error::ConnectionReset,
162 ConnectError::TimedOut => Error::TimedOut,
163 ConnectError::NoRoute => Error::NoRoute,
164 }
165 }
166}
167
168impl IntoOsalError<Error> for embassy_net::tcp::Error {
169 fn into_osal_error(self) -> Error {
170 match self {
171 embassy_net::tcp::Error::ConnectionReset => Error::ConnectionReset,
172 }
173 }
174}