veecle_osal_std/net/
tcp.rs1use crate::IntoOsalError;
4use embedded_io_adapters::tokio_1::FromTokio;
5use std::io::ErrorKind;
6use std::net::SocketAddr;
7use tokio::io::AsyncWriteExt;
8use veecle_osal_api::net::tcp::Error;
9
10#[derive(Default)]
15pub struct TcpSocket;
16
17impl TcpSocket {
18 pub fn new() -> Self {
20 Self
21 }
22}
23
24impl core::fmt::Debug for TcpSocket {
25 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
26 f.debug_struct("TcpSocket").finish()
27 }
28}
29
30pub struct TcpConnection<'s> {
35 stream: FromTokio<tokio::net::TcpStream>,
36 _socket: &'s mut TcpSocket,
38}
39
40impl<'s> core::fmt::Debug for TcpConnection<'s> {
41 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
42 f.debug_struct("TcpConnection").finish()
43 }
44}
45
46impl<'s> veecle_osal_api::net::tcp::TcpConnection for TcpConnection<'s> {
47 async fn close(self) {
48 let _ = self.stream.into_inner().shutdown().await;
50 }
51}
52
53impl<'s> embedded_io_async::Read for TcpConnection<'s> {
54 async fn read(&mut self, buffer: &mut [u8]) -> Result<usize, Self::Error> {
55 self.stream
56 .read(buffer)
57 .await
58 .map_err(IntoOsalError::into_osal_error)
59 }
60}
61
62impl<'s> embedded_io::ErrorType for TcpConnection<'s> {
63 type Error = Error;
64}
65
66impl<'s> embedded_io_async::Write for TcpConnection<'s> {
67 async fn write(&mut self, buffer: &[u8]) -> Result<usize, Self::Error> {
68 self.stream
69 .write(buffer)
70 .await
71 .map_err(IntoOsalError::into_osal_error)
72 }
73
74 async fn flush(&mut self) -> Result<(), Self::Error> {
75 embedded_io_async::Write::flush(&mut self.stream)
76 .await
77 .map_err(IntoOsalError::into_osal_error)
78 }
79}
80
81impl veecle_osal_api::net::tcp::TcpSocket for TcpSocket {
82 async fn connect(
83 &mut self,
84 address: SocketAddr,
85 ) -> Result<impl veecle_osal_api::net::tcp::TcpConnection, Error> {
86 let stream = tokio::net::TcpStream::connect(address)
87 .await
88 .map_err(IntoOsalError::into_osal_error)?;
89 Ok(TcpConnection {
90 stream: FromTokio::new(stream),
91 _socket: self,
92 })
93 }
94
95 async fn accept(
96 &mut self,
97 address: SocketAddr,
98 ) -> Result<(impl veecle_osal_api::net::tcp::TcpConnection, SocketAddr), Error> {
99 if address.port() == 0 {
101 return Err(Error::InvalidPort);
102 }
103
104 let socket = if address.ip().is_ipv4() {
105 tokio::net::TcpSocket::new_v4().map_err(IntoOsalError::into_osal_error)?
106 } else {
107 tokio::net::TcpSocket::new_v6().map_err(IntoOsalError::into_osal_error)?
108 };
109
110 socket
112 .set_reuseaddr(true)
113 .map_err(IntoOsalError::into_osal_error)?;
114 socket
115 .set_reuseport(true)
116 .map_err(IntoOsalError::into_osal_error)?;
117
118 socket
119 .bind(address)
120 .map_err(IntoOsalError::into_osal_error)?;
121
122 let listener = socket.listen(1).map_err(IntoOsalError::into_osal_error)?;
123
124 let (stream, address) = listener
125 .accept()
126 .await
127 .map_err(IntoOsalError::into_osal_error)?;
128 Ok((
129 TcpConnection {
130 stream: FromTokio::new(stream),
131 _socket: self,
132 },
133 address,
134 ))
135 }
136}
137
138impl IntoOsalError<Error> for std::io::Error {
139 fn into_osal_error(self) -> Error {
140 match self.kind() {
141 ErrorKind::PermissionDenied => Error::PermissionDenied,
142 ErrorKind::ConnectionRefused => Error::ConnectionReset,
143 ErrorKind::ConnectionReset => Error::ConnectionReset,
144 ErrorKind::HostUnreachable => Error::NoRoute,
145 ErrorKind::NetworkUnreachable => Error::NoRoute,
146 ErrorKind::ConnectionAborted => Error::ConnectionReset,
147 ErrorKind::AddrInUse => Error::InvalidAddress,
148 ErrorKind::AddrNotAvailable => Error::InvalidAddress,
149 ErrorKind::NetworkDown => Error::NetworkDown,
150 ErrorKind::TimedOut => Error::TimedOut,
151 _ => Error::Other,
152 }
153 }
154}