RF24Ethernet - TCP/IP over RF24Network v2.2.0
TMRh20 - Pushing the practical limits of RF24 modules
Loading...
Searching...
No Matches
RF24Client.h
Go to the documentation of this file.
2/*
3 RF24Client.h - Arduino implementation of a uIP wrapper class.
4 lwIP - Copyright (c) 2025 tmrh20@gmail.com, github.com/TMRh20
5 uIP - Copyright (c) 2014 tmrh20@gmail.com, github.com/TMRh20
6 uIP - Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
7 All rights reserved.
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifndef RF24CLIENT_H
21#define RF24CLIENT_H
22
23#if __has_include(<Print.h>)
24 #include <Print.h>
25 #include <Client.h>
26#elif __has_include("Print.h")
27 #include "Print.h"
28 #include "Client.h"
29#else
30 #include <Arduino.h>
31#endif
32
33//#define UIP_SOCKET_DATALEN UIP_TCP_MSS
34//#define UIP_SOCKET_NUMPACKETS UIP_RECEIVE_WINDOW/UIP_TCP_MSS+1
35//#ifndef UIP_SOCKET_NUMPACKETS
36//#define UIP_SOCKET_NUMPACKETS 5
37//#endif
38
39#if USE_LWIP < 1
40 #define UIP_CLIENT_CONNECTED 0x10
41 #define UIP_CLIENT_CLOSE 0x20
42 #define UIP_CLIENT_REMOTECLOSED 0x40
43 #define UIP_CLIENT_RESTART 0x80
44 #define UIP_CLIENT_STATEFLAGS (UIP_CLIENT_CONNECTED | UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED | UIP_CLIENT_RESTART)
45 #define UIP_CLIENT_SOCKETS ~UIP_CLIENT_STATEFLAGS
46
47/**
48 * @warning <b> This is used internally and should not be accessed directly by users </b>
49 */
50typedef struct
51{
52 uint8_t state;
53 uint8_t packets_in[UIP_SOCKET_NUMPACKETS];
54 /** The local TCP port, in network byte order. */
55 uint16_t lport;
56} uip_userdata_closed_t;
57
58/**
59 * Data structure for holding per connection data
60 * @warning <b> This is used internally and should not be accessed directly by users </b>
61 */
62typedef struct __attribute__((__packed__))
63{
64 bool hold;
65 bool packets_in;
66 bool packets_out;
67 bool windowOpened;
68 uint8_t state;
69 uint16_t in_pos;
70 uint16_t out_pos;
71 uint16_t dataCnt;
72 #if UIP_CLIENT_TIMER >= 0
73 uint32_t timer;
74 #endif
75 uint32_t restartTime;
76 uint32_t restartInterval;
77 #if UIP_CONNECTION_TIMEOUT > 0
78 uint32_t connectTimeout;
79 uint32_t connectTimer;
80 #endif
81 uint8_t myData[OUTPUT_BUFFER_SIZE];
82} uip_userdata_t;
83#else
84 #include "RF24Network_config.h"
85 #define INCOMING_DATA_SIZE MAX_PAYLOAD_SIZE * 2
86
87 // ESP32 and ESP8266 use internal IP stack
88 #ifndef ETHERNET_USING_LWIP_ARDUINO
89 #define LWIP_DNS 1
90extern "C" {
91 #include "lwip/tcp.h"
92 #include "lwip/tcpip.h"
93 #include "lwip/raw.h"
94}
95 #else
96 #include <lwIP_Arduino.h>
97 #include "lwip/include/lwip/tcp.h"
98 #include "lwip/include/lwip/raw.h"
99 #endif
100#endif
101
102class RF24Client : public Client
103{
104
105public:
106 /** Basic constructor */
107 RF24Client();
108
109 /** Establish a connection to a specified IP address and port */
110 int connect(IPAddress ip, uint16_t port);
111
112 /**
113 * Establish a connection to a given hostname and port
114 * @note With slower devices < 50Mhz, or if using the uIP stack, UDP must be enabled in uip-conf.h for DNS lookups to work
115 *
116 * @note Tip: DNS lookups generally require a buffer size of 250-300 bytes or greater.
117 * Lookups will generally return responses with a single A record if using hostnames like
118 * "www.google.com" instead of "google.com" which works well with the default buffer size
119 */
120 int connect(const char* host, uint16_t port);
121
122 /**
123 * Read available data into a buffer
124 * @code
125 * uint8_t buf[size];
126 * client.read(buf,size);
127 * @endcode
128 */
129 int read(uint8_t* buf, size_t size);
130
131 /**
132 * Read data one byte at a time
133 * @code
134 * char c = client.read();
135 * @endcode
136 */
137 int read();
138
139 /** Disconnects from the current active connection */
140 void stop();
141
142 /**
143 * Indicates whether the client is connected or not
144 * When using slower devices < 50MHz (uIP stack) there is a default connection timeout of 45 seconds. If data is not received or sent successfully
145 * within that timeframe the client will be disconnected.
146 * With faster devices > 50Mhz (lwIP stack), there is NO default connection timeout. Use the clientConnectionTimeout functions to set the timeout on
147 * connect or disconnect, and utilize application side timeouts to disconnect as necessary after a connection has been established.
148 */
149 uint8_t connected();
150
151 /**
152 * Write a single byte of data to the stream
153 * @note This will write an entire TCP payload with only 1 byte in it
154 */
155 size_t write(uint8_t);
156
157 /** Write a buffer of data, to be sent in a single TCP packet */
158 size_t write(const uint8_t* buf, size_t size);
159
160 /**
161 * Indicates whether data is available to be read by the client.
162 * @return Returns the number of bytes available to be read
163 * @note Calling client or server available() keeps the IP stack and RF24Network layer running, so needs to be called regularly,
164 * even when disconnected or delaying for extended periods.
165 */
166 int available();
167
168 /**
169 * Wait Available
170 *
171 * Helps to ensure all incoming data has been received, prior to writing data back to the client, etc.
172 *
173 * Indicates whether data is available to be read by the client, after waiting a maximum period of time.
174 * @return Returns the number of bytes available to be read or 0 if timed out
175 * @note Calling client or server available() keeps the IP stack and RF24Network layer running, so needs to be called regularly,
176 * even when disconnected or delaying for extended periods.
177 */
178 int waitAvailable(uint32_t timeout = 750);
179
180 /** Read a byte from the incoming buffer without advancing the point of reading */
181 int peek();
182
183 /** Flush all incoming client data from the current connection/buffer */
184 void flush();
185
186 using Print::write;
187
188 operator bool();
189 virtual bool operator==(const EthernetClient&);
190 virtual bool operator!=(const EthernetClient& rhs)
191 {
192 return !this->operator==(rhs);
193 };
194
195protected:
196#if USE_LWIP < 1
197 static uip_userdata_t all_data[UIP_CONNS];
198#else
199
200 /**
201 * Connection state structure, used internally to monitor the state of connections
202 */
204 {
205 volatile bool finished = false;
206 volatile bool connected = false;
207 volatile bool waiting_for_ack = false;
208 volatile bool backlogWasClosed = false;
209
210 volatile bool backlogWasAccepted = false;
211 volatile bool clientPollingSetup = 0;
212 volatile bool stateActiveID = 0;
213 volatile err_t result = 0;
214
215 volatile uint32_t connectTimestamp = millis();
216 volatile uint32_t sConnectionTimeout = serverConnectionTimeout;
217 volatile uint32_t serverTimer = millis();
218 volatile uint32_t cConnectionTimeout = clientConnectionTimeout;
219 volatile uint32_t clientTimer = millis();
220 volatile uint32_t closeTimer = millis();
221 volatile uint32_t identifier = 0;
222 } __attribute__((packed));
223
224 /** Connection states */
226
227 /** Used internally when data is ACKed */
228 static err_t sent_callback(void* arg, struct tcp_pcb* tpcb, uint16_t len);
229 /** Used internally for receiving data via the client functions */
230 static err_t recv_callback(void* arg, struct tcp_pcb* tpcb, struct pbuf* p, err_t err);
231 /** Used internally for receiving data via the server functions */
232 static err_t srecv_callback(void* arg, struct tcp_pcb* tpcb, struct pbuf* p, err_t err);
233 /** Used internally when there is an error */
234 static void error_callback(void* arg, err_t err);
235
236 /** Used to set client timeouts. Whenever there is no data sent, received, or acked in
237 * the given timeout period (mS) the connection will be closed. Set to 0 to disable
238 **/
239 //static void setConnectionTimeout(uint32_t timeout);
240 static bool activeState;
241
242#endif
243
244private:
245#if USE_LWIP < 1
246
247 RF24Client(struct uip_conn* _conn);
248 RF24Client(uip_userdata_t* conn_data);
249
250 uip_userdata_t* data;
251
252 static int _available(uip_userdata_t*);
253 static uip_userdata_t* _allocateData();
254 static size_t _write(uip_userdata_t*, const uint8_t* buf, size_t size);
255
256 friend void serialip_appcall(void);
257 friend void uip_log(char* msg);
258
259#else
260 RF24Client(uint32_t data);
261 RF24Client(uint8_t data);
262 uint8_t* data;
263 static size_t _write(uint8_t* data, const uint8_t* buf, size_t size);
264 static int _available(uint8_t* data);
265
266 static err_t accept(void* arg, struct tcp_pcb* tpcb, err_t err);
267 static err_t closed(void* arg, struct tcp_pcb* tpcb, err_t err);
268 static err_t closed_port(void* arg, struct tcp_pcb* tpcb);
269 static err_t closeConn(void* arg, struct tcp_pcb* tpcb);
270 static err_t serverTimeouts(void* arg, struct tcp_pcb* tpcb);
271 static err_t clientTimeouts(void* arg, struct tcp_pcb* tpcb);
272 static err_t on_connected(void* arg, struct tcp_pcb* tpcb, err_t err);
273 static err_t blocking_write(struct tcp_pcb* pcb, ConnectState* fstate, const char* data, size_t len);
274 static void dnsCallback(const char* name, const ip_addr_t* ipaddr, void* callback_arg);
275 static void _stop();
276
277 static uint32_t clientConnectionTimeout;
278 static uint32_t serverConnectionTimeout;
279 static uint16_t dataSize[2];
280 static struct tcp_pcb* myPcb; // = nullptr;//tcp_new();// = nullptr;//tcp_new();
281
282 static char* incomingData[2];
283 static uint32_t simpleCounter;
284 static int32_t accepts;
285
286#endif
287
288 friend class RF24EthernetClass;
289 friend class RF24Server;
290};
291
292#endif // RF24CLIENT_H
void uip_log(char *msg)
virtual bool operator==(const EthernetClient &)
size_t write(uint8_t)
int connect(IPAddress ip, uint16_t port)
friend class RF24EthernetClass
Definition RF24Client.h:288
static void error_callback(void *arg, err_t err)
struct RF24Client::ConnectState __attribute__((packed))
static err_t srecv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
int waitAvailable(uint32_t timeout=750)
static ConnectState * gState[2]
Definition RF24Client.h:225
static bool activeState
Definition RF24Client.h:240
virtual bool operator!=(const EthernetClient &rhs)
Definition RF24Client.h:190
static err_t recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
friend class RF24Server
Definition RF24Client.h:289
static err_t sent_callback(void *arg, struct tcp_pcb *tpcb, uint16_t len)
uint8_t connected()
#define EthernetClient
#define OUTPUT_BUFFER_SIZE
Definition uip-conf.h:153
volatile bool backlogWasClosed
Definition RF24Client.h:208
volatile uint32_t clientTimer
Definition RF24Client.h:219
volatile uint32_t sConnectionTimeout
Definition RF24Client.h:216
volatile bool backlogWasAccepted
Definition RF24Client.h:210
volatile bool connected
Definition RF24Client.h:206
volatile bool clientPollingSetup
Definition RF24Client.h:211
volatile uint32_t identifier
Definition RF24Client.h:221
volatile uint32_t closeTimer
Definition RF24Client.h:220
volatile uint32_t cConnectionTimeout
Definition RF24Client.h:218
volatile bool waiting_for_ack
Definition RF24Client.h:207
volatile err_t result
Definition RF24Client.h:213
volatile bool stateActiveID
Definition RF24Client.h:212
volatile uint32_t connectTimestamp
Definition RF24Client.h:215
volatile uint32_t serverTimer
Definition RF24Client.h:217
void serialip_appcall(void)
#define UIP_SOCKET_NUMPACKETS
Definition uip-conf.h:175