21 #define UIP_TCP_PHYH_LEN UIP_LLH_LEN + UIP_IPTCPH_LEN
22uip_userdata_t RF24Client::all_data[UIP_CONNS];
28 #if !defined ETHERNET_USING_LWIP_ARDUINO
30 #include "lwip/tcpip.h"
31 #include "lwip/timeouts.h"
33 #include "lwip/include/lwip/tcp.h"
34 #include "lwip/include/lwip/tcpip.h"
40char* RF24Client::incomingData[2];
41uint16_t RF24Client::dataSize[2];
42struct tcp_pcb* RF24Client::myPcb;
43uint32_t RF24Client::clientConnectionTimeout;
44uint32_t RF24Client::serverConnectionTimeout;
45uint32_t RF24Client::simpleCounter;
47int32_t RF24Client::accepts;
56 if (state !=
nullptr) {
57 state->serverTimer = millis();
58 state->clientTimer = millis();
61 state->waiting_for_ack =
false;
62 state->finished =
true;
70err_t RF24Client::blocking_write(
struct tcp_pcb* fpcb, ConnectState* fstate,
const char* data,
size_t len)
73 if (fpcb ==
nullptr) {
78 if (!fstate->connected) {
83 uint32_t timeout = millis() + serverConnectionTimeout;
84 while (len > tcp_sndbuf(fpcb)) {
86 if (millis() > timeout) {
92 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
94 ETHERNET_APPLY_LOCK();
99 if (fpcb !=
nullptr) {
100 err = tcp_write(fpcb, data, len, TCP_WRITE_FLAG_COPY);
105 if (fstate !=
nullptr) {
106 fstate->waiting_for_ack =
false;
107 fstate->finished =
true;
111 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
113 ETHERNET_REMOVE_LOCK();
119 if (fpcb !=
nullptr && fpcb->state != CLOSED && fstate->connected) {
125 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
127 ETHERNET_REMOVE_LOCK();
132 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
134 ETHERNET_REMOVE_LOCK();
138 volatile uint32_t timer = millis() + 5000;
139 while (fstate !=
nullptr && fstate->waiting_for_ack && !fstate->finished) {
140 if (millis() > timer) {
141 if (fstate !=
nullptr) {
142 fstate->finished =
true;
159 if (state !=
nullptr) {
161 state->connected =
false;
162 state->finished =
true;
163 state->waiting_for_ack =
false;
164 dataSize[state->stateActiveID] = 0;
179 if (state !=
nullptr) {
180 state->serverTimer = millis();
184 if (state !=
nullptr) {
185 state->connected =
false;
186 state->finished =
true;
188 if (tpcb !=
nullptr) {
189 if (tcp_close(tpcb) != ERR_OK) {
204 if (err != ERR_OK || state ==
nullptr) {
214 while (q !=
nullptr) {
215 const uint8_t* data =
static_cast<const uint8_t*
>(q->payload);
217 memcpy(&incomingData[
id][dataSize[
id]], data, q->len);
218 dataSize[id] += q->len;
226 if (tpcb !=
nullptr) {
227 tcp_recved(tpcb, p->len);
244 if (state !=
nullptr) {
245 state->connected =
false;
246 state->finished =
true;
248 if (tpcb !=
nullptr) {
249 if (tcp_close(tpcb) != ERR_OK) {
264 if (err != ERR_OK || state ==
nullptr) {
270 if (state !=
nullptr) {
271 state->clientTimer = millis();
276 while (q !=
nullptr) {
277 const uint8_t* data =
static_cast<const uint8_t*
>(q->payload);
279 memcpy(&incomingData[
id][dataSize[
id]], data, q->len);
280 dataSize[id] += q->len;
288 if (tpcb !=
nullptr) {
289 tcp_recved(tpcb, p->len);
307err_t RF24Client::clientTimeouts(
void* arg,
struct tcp_pcb* tpcb)
312 if (state !=
nullptr) {
313 if (millis() - state->clientTimer > state->cConnectionTimeout) {
314 if (tpcb->state == ESTABLISHED || tpcb->state == SYN_SENT || tpcb->state == SYN_RCVD) {
316 err_t err = tcp_close(tpcb);
318 state->connected =
false;
319 state->finished =
true;
320 state->waiting_for_ack =
false;
329err_t RF24Client::serverTimeouts(
void* arg,
struct tcp_pcb* tpcb)
334 if (state !=
nullptr && tpcb !=
nullptr) {
337 state->result = ERR_OK;
339 if (millis() - state->serverTimer > state->sConnectionTimeout && state->backlogWasClosed ==
false) {
343 state->result = tcp_close(tpcb);
344 state->closeTimer = millis();
345 state->backlogWasClosed =
true;
347 state->connected =
false;
348 state->finished =
true;
349 if (state->result != ERR_OK) {
354 return state->result;
358 if (state->backlogWasClosed ==
true) {
359 if (millis() - state->closeTimer > 5000) {
371err_t RF24Client::closed_port(
void* arg,
struct tcp_pcb* tpcb)
376 if (state !=
nullptr) {
380 if (myPcb ==
nullptr) {
381 if (state !=
nullptr && tpcb !=
nullptr) {
383 if ((tpcb->state == ESTABLISHED || tpcb->state == SYN_SENT || tpcb->state == SYN_RCVD)) {
384 if (state->backlogWasAccepted ==
false && state->backlogWasClosed ==
false) {
386 state->backlogWasAccepted =
true;
387 state->connectTimestamp = millis();
388 state->connected =
true;
389 state->finished =
false;
394 tcp_backlog_accepted(tpcb);
402 if (tpcb !=
nullptr) {
403 if (state !=
nullptr) {
404 if (millis() - state->connectTimestamp > state->sConnectionTimeout) {
406 if ((tpcb->state == ESTABLISHED || tpcb->state == SYN_SENT || tpcb->state == SYN_RCVD)) {
407 if (state->backlogWasClosed ==
false) {
411 if (state->backlogWasAccepted ==
false) {
413 tcp_backlog_accepted(tpcb);
414 state->backlogWasAccepted =
true;
418 state->result = tcp_close(tpcb);
419 state->backlogWasClosed =
true;
420 if (state->result == ERR_OK) {
421 state->closeTimer = millis();
422 state->finished =
true;
430 return state->result;
435 if (state !=
nullptr) {
438 if (millis() - state->closeTimer > 5000) {
448 if (tpcb !=
nullptr) {
449 if (state !=
nullptr) {
450 if (millis() - state->connectTimestamp > state->sConnectionTimeout) {
451 if (state->backlogWasClosed ==
false) {
453 if (state->backlogWasAccepted ==
false) {
455 tcp_backlog_accepted(tpcb);
456 state->backlogWasAccepted =
true;
459 state->result = tcp_close(tpcb);
460 state->backlogWasClosed =
true;
461 if (state->result == ERR_OK) {
462 state->closeTimer = millis();
463 state->finished =
true;
470 return state->result;
474 if (state !=
nullptr) {
475 Serial.println(state->identifier);
476 if (millis() - state->closeTimer > 5000) {
492err_t RF24Client::accept(
void* arg,
struct tcp_pcb* tpcb, err_t err)
496 if (tpcb ==
nullptr) {
497 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print(
"Server: Accepted conn, but no tpcb from: "); Serial.println(ip4addr_ntoa(ip_2_ip4(&tpcb->remote_ip))););
501 if (tpcb !=
nullptr) {
506 if (myPcb !=
nullptr) {
508 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print(
"Server: Accept w/already connected: Accepted_Conns - Delayed_Conns == "); Serial.println(accepts););
509 tcp_backlog_delayed(tpcb);
511 tcp_poll(tpcb, closed_port, 5);
513 gState[actState]->connected =
false;
514 gState[actState]->backlogWasAccepted =
false;
518 tcp_poll(tpcb, serverTimeouts, 8);
521 gState[actState]->connected =
true;
522 gState[actState]->backlogWasAccepted =
true;
525 dataSize[actState] = 0;
528 gState[actState]->stateActiveID = actState;
529 gState[actState]->identifier = simpleCounter;
530 gState[actState]->finished =
false;
531 gState[actState]->sConnectionTimeout = serverConnectionTimeout;
532 gState[actState]->waiting_for_ack =
false;
533 gState[actState]->backlogWasClosed =
false;
534 gState[actState]->connectTimestamp = millis();
535 gState[actState]->serverTimer = millis();
546err_t RF24Client::closeConn(
void* arg,
struct tcp_pcb* tpcb)
549 if (tpcb !=
nullptr) {
560err_t RF24Client::on_connected(
void* arg,
struct tcp_pcb* tpcb, err_t err)
566 if (state !=
nullptr) {
577 state->cConnectionTimeout = clientConnectionTimeout;
578 state->clientTimer = millis();
580 state->finished =
true;
582 state->connected =
true;
585 state->connected =
false;
587 state->waiting_for_ack =
false;
624 return (data && (data->packets_in != 0 || (data->state & UIP_CLIENT_CONNECTED))) ? 1 : 0;
639 #if UIP_ACTIVE_OPEN > 0
645 uip_ip_addr(ipaddr, ip);
647 struct uip_conn* conn = uip_connect(&ipaddr, htons(port));
651 #if UIP_CONNECTION_TIMEOUT > 0
652 uint32_t timeout = millis();
655 while ((conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED)
659 if ((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED)
661 data = (uip_userdata_t*)conn->appstate;
662 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print(millis()); Serial.print(F(
" connected, state: ")); Serial.print(data->state); Serial.print(F(
", first packet in: ")); Serial.println(data->packets_in););
666 #if UIP_CONNECTION_TIMEOUT > 0
669 conn->tcpstateflags = UIP_CLOSED;
681 if (myPcb !=
nullptr) {
682 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
684 ETHERNET_APPLY_LOCK();
687 if (myPcb->state == ESTABLISHED || myPcb->state == SYN_SENT || myPcb->state == SYN_RCVD) {
688 if (tcp_close(myPcb) != ERR_OK) {
692 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
694 ETHERNET_REMOVE_LOCK();
701 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
703 ETHERNET_REMOVE_LOCK();
710 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
712 ETHERNET_APPLY_LOCK();
716 if (myPcb ==
nullptr) {
722 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
724 ETHERNET_REMOVE_LOCK();
746 IP_ADDR4(&myIp, ip[0], ip[1], ip[2], ip[3]);
748 err = tcp_connect(myPcb, &myIp, port, on_connected);
751 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
753 ETHERNET_REMOVE_LOCK();
761 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
763 ETHERNET_REMOVE_LOCK();
767 uint32_t timeout = millis() + 5000;
773 if (clientConnectionTimeout > 0) {
786void dnsCallback(
const char* name,
const ip_addr_t* ipaddr,
void* callback_arg)
799 IPAddress remote_addr;
801 dns.
begin(RF24EthernetClass::_dnsServerAddress);
806 #if defined(ETH_DEBUG_L1) || defined(RF24ETHERNET_DEBUG_DNS)
807 Serial.println(F(
"*UIP Got DNS*"));
809 return connect(remote_addr, port);
811#elif RF24ETHERNET_USE_UDP
814 IPAddress remote_addr;
816 dns.
begin(RF24EthernetClass::_dnsServerAddress);
821 #if defined(ETH_DEBUG_L1) || defined(RF24ETHERNET_DEBUG_DNS)
822 Serial.println(F(
"*lwIP Got DNS*"));
824 return connect(remote_addr, port);
835#if defined(ETH_DEBUG_L1) || defined(RF24ETHERNET_DEBUG_DNS)
836 Serial.println(F(
"* DNS fail*"));
847 if (data && data->state)
852 data->packets_in = 0;
855 if (data->state & UIP_CLIENT_REMOTECLOSED)
861 data->state |= UIP_CLIENT_CLOSE;
882void RF24Client::_stop()
884 if (myPcb !=
nullptr) {
886 if (myPcb->state != CLOSED) {
888 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
890 ETHERNET_APPLY_LOCK();
893 err_t err = tcp_close(myPcb);
898 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
900 ETHERNET_REMOVE_LOCK();
918 return data && rhs.data && (data == rhs.data);
926RF24Client::operator bool()
930 return data && (!(data->state & UIP_CLIENT_REMOTECLOSED) || data->packets_in != 0);
940 return _write(data, &c, 1);
947 return _write(data, buf, size);
952size_t RF24Client::_write(uip_userdata_t* u,
const uint8_t* buf,
size_t size)
954size_t RF24Client::_write(uint8_t* data,
const uint8_t* buf,
size_t size)
961 size_t total_written = 0;
962 size_t payloadSize = rf24_min(size, UIP_TCP_MSS);
967 if (u && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)) && u->state & (UIP_CLIENT_CONNECTED))
970 if (u->out_pos + payloadSize > UIP_TCP_MSS || u->hold)
975 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(); Serial.print(millis()); Serial.print(F(
" UIPClient.write: writePacket(")); Serial.print(u->packets_out); Serial.print(F(
") pos: ")); Serial.print(u->out_pos); Serial.print(F(
", buf[")); Serial.print(size - total_written); Serial.print(F(
"]: '")); Serial.write((uint8_t*)buf + total_written, payloadSize); Serial.println(F(
"'")););
977 memcpy(u->myData + u->out_pos, buf + total_written, payloadSize);
979 u->out_pos += payloadSize;
981 total_written += payloadSize;
983 if (total_written < size)
985 size_t remain = size - total_written;
986 payloadSize = rf24_min(remain, UIP_TCP_MSS);
998 if (myPcb ==
nullptr) {
1002 bool initialActiveState = activeState;
1005 uint32_t position = 0;
1006 uint32_t timeout1 = millis() + 3000;
1008 while (size > MAX_PAYLOAD_SIZE - 14 && millis() < timeout1) {
1009 memcpy(buffer, &buf[position], MAX_PAYLOAD_SIZE - 14);
1011 if (myPcb ==
nullptr) {
1014 gState[initialActiveState]->waiting_for_ack =
true;
1015 err_t write_err = blocking_write(myPcb, gState[initialActiveState], buffer, MAX_PAYLOAD_SIZE - 14);
1017 if (write_err != ERR_OK) {
1018 gState[initialActiveState]->result = write_err;
1019 gState[initialActiveState]->connected =
false;
1023 position += MAX_PAYLOAD_SIZE - 14;
1024 size -= MAX_PAYLOAD_SIZE - 14;
1028 memcpy(buffer, &buf[position], size);
1030 if (myPcb ==
nullptr) {
1034 gState[initialActiveState]->waiting_for_ack =
true;
1035 err_t write_err = blocking_write(myPcb, gState[initialActiveState], buffer, size);
1037 if (write_err != ERR_OK) {
1038 gState[initialActiveState]->result = write_err;
1039 gState[initialActiveState]->connected =
false;
1064 uip_userdata_t* u = (uip_userdata_t*)uip_conn->appstate;
1067 if (!u && uip_connected())
1071 u = (uip_userdata_t*)EthernetClient::_allocateData();
1075 uip_conn->appstate = u;
1084 #if UIP_CONNECTION_TIMEOUT > 0
1085 if (u && u->connectTimeout > 0) {
1086 if (millis() - u->connectTimer > u->connectTimeout) {
1087 u->state |= UIP_CLIENT_CLOSE;
1088 u->connectTimer = millis();
1099 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(); Serial.print(millis()); Serial.print(F(
" UIPClient uip_newdata, uip_len:")); Serial.println(uip_len););
1100 #if UIP_CONNECTION_TIMEOUT > 0
1101 u->connectTimer = millis();
1103 u->hold = (u->out_pos = (u->windowOpened = (u->packets_out =
false)));
1105 if (uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1108 u->state &= ~UIP_CLIENT_RESTART;
1109 u->windowOpened =
false;
1110 u->restartTime = millis();
1111 memcpy(&u->myData[u->in_pos + u->dataCnt], uip_appdata, uip_datalen());
1112 u->dataCnt += uip_datalen();
1121 if (uip_closed() || uip_timedout() || uip_aborted())
1129 ((uip_userdata_closed_t*)u)->lport = uip_conn->lport;
1130 u->state |= UIP_CLIENT_REMOTECLOSED;
1140 uip_conn->appstate = NULL;
1148 u->state &= ~UIP_CLIENT_RESTART;
1149 u->hold = (u->out_pos = (u->windowOpened = (u->packets_out =
false)));
1150 u->restartTime = millis();
1151 #if UIP_CONNECTION_TIMEOUT > 0
1152 u->connectTimer = millis();
1157 if (uip_poll() || uip_rexmit())
1162 uip_len = u->out_pos;
1163 uip_send(u->myData, u->out_pos);
1169 if (u->packets_out != 0 && !u->hold)
1171 uip_len = u->out_pos;
1172 uip_send(u->myData, u->out_pos);
1180 if (!(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1183 if (u->windowOpened ==
true && u->state & UIP_CLIENT_RESTART && millis() - u->restartTime > u->restartInterval)
1185 u->restartTime = millis();
1186 #if defined RF24ETHERNET_DEBUG_CLIENT || defined ETH_DEBUG_L1
1188 Serial.print(millis());
1189 #if UIP_CONNECTION_TIMEOUT > 0
1190 Serial.print(F(
" UIPClient Re-Open TCP Window, time remaining before abort: "));
1194 u->restartInterval += 500;
1195 u->restartInterval = rf24_min(u->restartInterval, 7000);
1202 if (u->state & UIP_CLIENT_CLOSE)
1206 if (u->packets_out == 0)
1209 uip_conn->appstate = NULL;
1221 if (u->state & UIP_CLIENT_RESTART && !u->windowOpened)
1223 if (!(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1226 #if defined ETH_DEBUG_L1
1228 Serial.print(millis());
1229 Serial.println(F(
" UIPClient Re-Open TCP Window"));
1231 u->windowOpened =
true;
1233 u->restartTime = millis();
1241uip_userdata_t* RF24Client::_allocateData()
1243 for (uint8_t sock = 0; sock < UIP_CONNS; sock++)
1245 uip_userdata_t* data = &RF24Client::all_data[sock];
1248 data->state = sock | UIP_CLIENT_CONNECTED;
1249 data->packets_in = 0;
1250 data->packets_out = 0;
1255 data->restartTime = millis();
1256 data->restartInterval = 5000;
1257 #if (UIP_CONNECTION_TIMEOUT > 0)
1258 data->connectTimer = millis();
1270 uint32_t start = millis();
1273 if (millis() - start > timeout)
1290 return _available(data);
1293 return _available(data);
1300int RF24Client::_available(uip_userdata_t* u)
1302int RF24Client::_available(uint8_t* data)
1311 return dataSize[activeState];
1323 if (!data->packets_in)
1328 size = rf24_min(data->dataCnt, size);
1329 memcpy(buf, &data->myData[data->in_pos], size);
1330 data->dataCnt -= size;
1332 data->in_pos += size;
1336 data->packets_in = 0;
1339 if (uip_stopped(&uip_conns[data->state & UIP_CLIENT_SOCKETS]) && !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1341 data->state |= UIP_CLIENT_RESTART;
1342 data->restartTime = 0;
1344 IF_ETH_DEBUG_L2(Serial.print(F(
"UIPClient set restart ")); Serial.println(data->state & UIP_CLIENT_SOCKETS); Serial.println(F(
"**")); Serial.println(data->state, BIN); Serial.println(F(
"**")); Serial.println(UIP_CLIENT_SOCKETS, BIN); Serial.println(F(
"**")););
1348 IF_ETH_DEBUG_L2(Serial.print(F(
"UIPClient stop?????? ")); Serial.println(data->state & UIP_CLIENT_SOCKETS); Serial.println(F(
"**")); Serial.println(data->state, BIN); Serial.println(F(
"**")); Serial.println(UIP_CLIENT_SOCKETS, BIN); Serial.println(F(
"**")););
1351 if (data->packets_in == 0)
1353 if (data->state & UIP_CLIENT_REMOTECLOSED)
1376 memcpy(&buf[0], &incomingData[
activeState][0], size);
1391 if (
read(&c, 1) < 0)
1403 return data->myData[data->in_pos];
1419 data->packets_in = 0;
#define INCOMING_DATA_SIZE
RF24EthernetClass RF24Ethernet
void begin(const IPAddress &aDNSServer)
int getHostByName(const char *aHostname, IPAddress &aResult)
virtual bool operator==(const EthernetClient &)
int connect(IPAddress ip, uint16_t port)
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]
static err_t recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
static err_t sent_callback(void *arg, struct tcp_pcb *tpcb, uint16_t len)
#define IF_ETH_DEBUG_L2(x)
#define IF_RF24ETHERNET_DEBUG_CLIENT(x)
#define IF_ETH_DEBUG_L1(x)
#define UIP_CONNECTION_TIMEOUT
Optional: Uncomment to disable
#define UIP_WINDOW_REOPEN_DELAY
Optional: Used with UIP_CONNECTION_TIMEOUT
volatile bool stateActiveID
uint16_t u16_t
16 bit datatype
void serialip_appcall(void)