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