Skip to main content

edge_nal/stack/
tcp.rs

1//! Factory traits for creating TCP sockets on embedded devices
2
3use core::net::SocketAddr;
4
5use embedded_io_async::{Error, ErrorType, Read, Write};
6
7use crate::{Readable, TcpShutdown};
8
9/// This trait is implemented by TCP sockets that can be split into separate `send` and `receive` halves that can operate
10/// independently from each other (i.e., a full-duplex connection).
11pub trait TcpSplit: ErrorType {
12    type Read<'a>: Read<Error = Self::Error> + Readable<Error = Self::Error>
13    where
14        Self: 'a;
15    type Write<'a>: Write<Error = Self::Error>
16    where
17        Self: 'a;
18
19    fn split(&mut self) -> (Self::Read<'_>, Self::Write<'_>);
20}
21
22impl<T> TcpSplit for &mut T
23where
24    T: TcpSplit,
25{
26    type Read<'a>
27        = T::Read<'a>
28    where
29        Self: 'a;
30    type Write<'a>
31        = T::Write<'a>
32    where
33        Self: 'a;
34
35    fn split(&mut self) -> (Self::Read<'_>, Self::Write<'_>) {
36        (**self).split()
37    }
38}
39
40/// This is a factory trait for connecting to remote TCP peers
41pub trait TcpConnect {
42    /// Error type returned on socket creation failure
43    type Error: Error;
44
45    /// The socket type returned by the factory
46    type Socket<'a>: Read<Error = Self::Error>
47        + Write<Error = Self::Error>
48        + Readable<Error = Self::Error>
49        + TcpSplit<Error = Self::Error>
50        + TcpShutdown<Error = Self::Error>
51    where
52        Self: 'a;
53
54    /// Connect to a remote socket
55    async fn connect(&self, remote: SocketAddr) -> Result<Self::Socket<'_>, Self::Error>;
56}
57
58/// This is a factory trait for creating server-side TCP sockets
59pub trait TcpBind {
60    /// Error type returned on bind failure
61    type Error: Error;
62
63    /// The acceptor type returned by the factory
64    type Accept<'a>: TcpAccept<Error = Self::Error>
65    where
66        Self: 'a;
67
68    /// Bind to a local socket listening for incoming connections
69    ///
70    /// Depending on the platform, this method might actually be a no-op and just return a new acceptor
71    /// implementation, that does the actual binding.
72    /// Platforms that do not maintain internal acceptor queue (Embassy networking stack and `smoltcp`) are such examples.
73    async fn bind(&self, local: SocketAddr) -> Result<Self::Accept<'_>, Self::Error>;
74}
75
76/// This is a factory trait for accepting incoming connections on server-side TCP sockets
77pub trait TcpAccept {
78    /// Error type returned on socket creation failure
79    type Error: Error;
80
81    /// The socket type returned by the factory
82    type Socket<'a>: Read<Error = Self::Error>
83        + Write<Error = Self::Error>
84        + Readable<Error = Self::Error>
85        + TcpSplit<Error = Self::Error>
86        + TcpShutdown<Error = Self::Error>
87    where
88        Self: 'a;
89
90    /// Accepts an incoming connection
91    /// Returns the socket address of the remote peer, as well as the accepted socket.
92    async fn accept(&self) -> Result<(SocketAddr, Self::Socket<'_>), Self::Error>;
93}
94
95impl<T> TcpConnect for &T
96where
97    T: TcpConnect,
98{
99    type Error = T::Error;
100
101    type Socket<'a>
102        = T::Socket<'a>
103    where
104        Self: 'a;
105
106    async fn connect(&self, remote: SocketAddr) -> Result<Self::Socket<'_>, Self::Error> {
107        (*self).connect(remote).await
108    }
109}
110
111impl<T> TcpConnect for &mut T
112where
113    T: TcpConnect,
114{
115    type Error = T::Error;
116
117    type Socket<'a>
118        = T::Socket<'a>
119    where
120        Self: 'a;
121
122    async fn connect(&self, remote: SocketAddr) -> Result<Self::Socket<'_>, Self::Error> {
123        (**self).connect(remote).await
124    }
125}
126
127impl<T> TcpBind for &T
128where
129    T: TcpBind,
130{
131    type Error = T::Error;
132
133    type Accept<'a>
134        = T::Accept<'a>
135    where
136        Self: 'a;
137
138    async fn bind(&self, local: SocketAddr) -> Result<Self::Accept<'_>, Self::Error> {
139        (*self).bind(local).await
140    }
141}
142
143impl<T> TcpBind for &mut T
144where
145    T: TcpBind,
146{
147    type Error = T::Error;
148
149    type Accept<'a>
150        = T::Accept<'a>
151    where
152        Self: 'a;
153
154    async fn bind(&self, local: SocketAddr) -> Result<Self::Accept<'_>, Self::Error> {
155        (**self).bind(local).await
156    }
157}
158
159impl<T> TcpAccept for &T
160where
161    T: TcpAccept,
162{
163    type Error = T::Error;
164
165    type Socket<'a>
166        = T::Socket<'a>
167    where
168        Self: 'a;
169
170    async fn accept(&self) -> Result<(SocketAddr, Self::Socket<'_>), Self::Error> {
171        (*self).accept().await
172    }
173}
174
175impl<T> TcpAccept for &mut T
176where
177    T: TcpAccept,
178{
179    type Error = T::Error;
180
181    type Socket<'a>
182        = T::Socket<'a>
183    where
184        Self: 'a;
185
186    async fn accept(&self) -> Result<(SocketAddr, Self::Socket<'_>), Self::Error> {
187        (**self).accept().await
188    }
189}