embedded_nal/stack/
tcp.rs

1use core::net::SocketAddr;
2
3/// Represents specific errors encountered during TCP operations.
4#[non_exhaustive]
5#[derive(Copy, Clone, PartialEq, Debug)]
6pub enum TcpErrorKind {
7	/// The socket has been closed in the direction in which the failing operation was attempted.
8	PipeClosed,
9
10	/// Some other error has occurred.
11	Other,
12}
13
14/// Methods to resolve errors into identifiable, actionable codes on the client side.
15pub trait TcpError: core::fmt::Debug {
16	/// Determines the kind of error that occurred.
17	fn kind(&self) -> TcpErrorKind;
18}
19
20/// This trait is implemented by TCP/IP stacks. You could, for example, have an implementation
21/// which knows how to send AT commands to an ESP8266 WiFi module. You could have another implementation
22/// which knows how to driver the Rust Standard Library's `std::net` module. Given this trait, you can
23/// write a portable HTTP client which can work with either implementation.
24pub trait TcpClientStack {
25	/// The type returned when we create a new TCP socket
26	type TcpSocket;
27	/// The type returned when we have an error
28	type Error: TcpError;
29
30	/// Open a socket for usage as a TCP client.
31	///
32	/// The socket must be connected before it can be used.
33	///
34	/// Returns `Ok(socket)` if the socket was successfully created.
35	fn socket(&mut self) -> Result<Self::TcpSocket, Self::Error>;
36
37	/// Connect to the given remote host and port.
38	///
39	/// Returns `Ok` if the connection was successful. Otherwise, if the connection could not be
40	/// completed immediately, this function should return [`nb::Error::WouldBlock`].
41	fn connect(
42		&mut self,
43		socket: &mut Self::TcpSocket,
44		remote: SocketAddr,
45	) -> nb::Result<(), Self::Error>;
46
47	/// Write to the stream.
48	///
49	/// Returns the number of bytes written (which may be less than `buffer.len()`) or an error.
50	fn send(
51		&mut self,
52		socket: &mut Self::TcpSocket,
53		buffer: &[u8],
54	) -> nb::Result<usize, Self::Error>;
55
56	/// Receive data from the stream.
57	///
58	/// Returns `Ok(n)`, which means `n` bytes of data have been received and
59	/// they have been placed in `&buffer[0..n]`, or an error. If a packet has
60	/// not been received when called, then [`nb::Error::WouldBlock`]
61	/// should be returned.
62	fn receive(
63		&mut self,
64		socket: &mut Self::TcpSocket,
65		buffer: &mut [u8],
66	) -> nb::Result<usize, Self::Error>;
67
68	/// Close an existing TCP socket.
69	fn close(&mut self, socket: Self::TcpSocket) -> Result<(), Self::Error>;
70}
71
72/// This trait is implemented by TCP/IP stacks that expose TCP server functionality. TCP servers
73/// may listen for connection requests to establish multiple unique TCP connections with various
74/// clients.
75pub trait TcpFullStack: TcpClientStack {
76	/// Create a new TCP socket and bind it to the specified local port.
77	///
78	/// Returns `Ok` when a socket is successfully bound to the specified local port. Otherwise, an
79	/// `Err(e)` variant is returned.
80	fn bind(&mut self, socket: &mut Self::TcpSocket, local_port: u16) -> Result<(), Self::Error>;
81
82	/// Begin listening for connection requests on a previously-bound socket.
83	///
84	/// Returns `Ok` if the socket was successfully transitioned to the listening state. Otherwise,
85	/// an `Err(e)` variant is returned.
86	fn listen(&mut self, socket: &mut Self::TcpSocket) -> Result<(), Self::Error>;
87
88	/// Accept an active connection request on a listening socket.
89	///
90	/// Returns `Ok(connection)` if a new connection was created. If no pending connections are
91	/// available, this function should return [`nb::Error::WouldBlock`].
92	fn accept(
93		&mut self,
94		socket: &mut Self::TcpSocket,
95	) -> nb::Result<(Self::TcpSocket, SocketAddr), Self::Error>;
96}
97
98impl<T: TcpClientStack> TcpClientStack for &mut T {
99	type Error = T::Error;
100
101	type TcpSocket = T::TcpSocket;
102
103	fn socket(&mut self) -> Result<Self::TcpSocket, Self::Error> {
104		T::socket(self)
105	}
106
107	fn connect(
108		&mut self,
109		socket: &mut Self::TcpSocket,
110		remote: SocketAddr,
111	) -> nb::Result<(), Self::Error> {
112		T::connect(self, socket, remote)
113	}
114
115	fn send(
116		&mut self,
117		socket: &mut Self::TcpSocket,
118		buffer: &[u8],
119	) -> nb::Result<usize, Self::Error> {
120		T::send(self, socket, buffer)
121	}
122
123	fn receive(
124		&mut self,
125		socket: &mut Self::TcpSocket,
126		buffer: &mut [u8],
127	) -> nb::Result<usize, Self::Error> {
128		T::receive(self, socket, buffer)
129	}
130
131	fn close(&mut self, socket: Self::TcpSocket) -> Result<(), Self::Error> {
132		T::close(self, socket)
133	}
134}