1use crate::SocketState;
2use embedded_nal::nb;
3use embedded_nal::{TcpClientStack, TcpFullStack};
4use std::io::{Error, Read, Write};
5use std::net::{IpAddr, Ipv6Addr, SocketAddr, TcpListener, TcpStream};
6
7#[derive(Debug)]
8pub struct TcpError(pub Error);
9
10impl From<Error> for TcpError {
11 fn from(e: Error) -> Self {
12 Self(e)
13 }
14}
15
16impl TcpError {
17 fn to_nb(e: Error) -> nb::Error<Self> {
18 use std::io::ErrorKind::{TimedOut, WouldBlock};
19 match e.kind() {
20 WouldBlock | TimedOut => nb::Error::WouldBlock,
21 _ => nb::Error::Other(Self(e)),
22 }
23 }
24}
25
26impl embedded_nal::TcpError for TcpError {
27 fn kind(&self) -> embedded_nal::TcpErrorKind {
28 match self.0.kind() {
29 std::io::ErrorKind::BrokenPipe => embedded_nal::TcpErrorKind::PipeClosed,
30 _ => embedded_nal::TcpErrorKind::Other,
31 }
32 }
33}
34
35pub struct TcpSocket {
36 state: SocketState<TcpStream, TcpListener>,
37}
38
39impl TcpSocket {
40 fn new() -> Self {
41 Self {
42 state: SocketState::new(),
43 }
44 }
45
46 fn connected(s: TcpStream) -> Self {
47 Self {
48 state: SocketState::Connected(s),
49 }
50 }
51
52 #[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
64 pub fn as_raw_fd(&self) -> Option<std::os::fd::RawFd> {
65 use std::os::fd::AsRawFd;
66
67 match &self.state {
68 SocketState::Connected(s) => Some(s.as_raw_fd()),
69 SocketState::Bound(s) => Some(s.as_raw_fd()),
70 SocketState::Building => None,
71 }
72 }
73}
74
75impl TcpClientStack for crate::Stack {
76 type TcpSocket = TcpSocket;
77 type Error = TcpError;
78
79 fn socket(&mut self) -> Result<TcpSocket, Self::Error> {
80 Ok(TcpSocket::new())
81 }
82
83 fn connect(
84 &mut self,
85 socket: &mut TcpSocket,
86 remote: SocketAddr,
87 ) -> nb::Result<(), Self::Error> {
88 let soc = TcpStream::connect(remote).map_err(Self::Error::from)?;
89
90 soc.set_nonblocking(true).map_err(Self::Error::from)?;
91
92 socket.state = SocketState::Connected(soc);
93 Ok(())
94 }
95
96 fn send(&mut self, socket: &mut TcpSocket, buffer: &[u8]) -> nb::Result<usize, Self::Error> {
97 let socket = socket.state.get_running().map_err(Self::Error::from)?;
98 socket.write(buffer).map_err(Self::Error::to_nb)
99 }
100
101 fn receive(
102 &mut self,
103 socket: &mut TcpSocket,
104 buffer: &mut [u8],
105 ) -> nb::Result<usize, Self::Error> {
106 let socket = socket.state.get_running().map_err(Self::Error::from)?;
107 socket.read(buffer).map_err(Self::Error::to_nb)
108 }
109
110 fn close(&mut self, _: TcpSocket) -> Result<(), Self::Error> {
111 Ok(())
117 }
118}
119
120impl TcpFullStack for crate::Stack {
121 fn bind(&mut self, socket: &mut TcpSocket, port: u16) -> Result<(), Self::Error> {
122 let anyaddressthisport = SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), port);
123
124 let sock = TcpListener::bind(anyaddressthisport)?;
125
126 sock.set_nonblocking(true)?;
127
128 socket.state = SocketState::Bound(sock);
129 Ok(())
130 }
131
132 fn listen(&mut self, _: &mut TcpSocket) -> Result<(), Self::Error> {
133 Ok(())
135 }
136
137 fn accept(
138 &mut self,
139 socket: &mut TcpSocket,
140 ) -> nb::Result<(TcpSocket, SocketAddr), Self::Error> {
141 let sock = socket.state.get_bound().map_err(Self::Error::from)?;
142 sock.accept()
143 .map_err(Self::Error::to_nb)
144 .map(|(s, a)| (TcpSocket::connected(s), a))
145 }
146}