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}