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) {
210 const uint8_t* data =
static_cast<const uint8_t*
>(p->payload);
214 memcpy(&incomingData[state->stateActiveID][dataSize[state->stateActiveID]], data, p->len);
215 dataSize[state->stateActiveID] += p->len;
221 if (tpcb !=
nullptr) {
222 tcp_recved(tpcb, p->len);
239 if (state !=
nullptr) {
240 state->connected =
false;
241 state->finished =
true;
243 if (tpcb !=
nullptr) {
244 if (tcp_close(tpcb) != ERR_OK) {
259 if (err != ERR_OK || state ==
nullptr) {
265 if (state !=
nullptr) {
266 state->clientTimer = millis();
268 const uint8_t* data =
static_cast<const uint8_t*
>(p->payload);
277 if (tpcb !=
nullptr) {
278 tcp_recved(tpcb, p->len);
296err_t RF24Client::clientTimeouts(
void* arg,
struct tcp_pcb* tpcb)
301 if (state !=
nullptr) {
302 if (millis() - state->clientTimer > state->cConnectionTimeout) {
303 if (tpcb->state == ESTABLISHED || tpcb->state == SYN_SENT || tpcb->state == SYN_RCVD) {
305 err_t err = tcp_close(tpcb);
307 state->connected =
false;
308 state->finished =
true;
309 state->waiting_for_ack =
false;
318err_t RF24Client::serverTimeouts(
void* arg,
struct tcp_pcb* tpcb)
323 if (state !=
nullptr && tpcb !=
nullptr) {
326 state->result = ERR_OK;
328 if (millis() - state->serverTimer > state->sConnectionTimeout && state->backlogWasClosed ==
false) {
332 state->result = tcp_close(tpcb);
333 state->closeTimer = millis();
334 state->backlogWasClosed =
true;
336 state->connected =
false;
337 state->finished =
true;
338 if (state->result != ERR_OK) {
343 return state->result;
347 if (state->backlogWasClosed ==
true) {
348 if (millis() - state->closeTimer > 5000) {
360err_t RF24Client::closed_port(
void* arg,
struct tcp_pcb* tpcb)
365 if (state !=
nullptr) {
369 if (myPcb ==
nullptr) {
370 if (state !=
nullptr && tpcb !=
nullptr) {
372 if ((tpcb->state == ESTABLISHED || tpcb->state == SYN_SENT || tpcb->state == SYN_RCVD)) {
373 if (state->backlogWasAccepted ==
false && state->backlogWasClosed ==
false) {
375 state->backlogWasAccepted =
true;
376 state->connectTimestamp = millis();
377 state->connected =
true;
378 state->finished =
false;
383 tcp_backlog_accepted(tpcb);
391 if (tpcb !=
nullptr) {
392 if (state !=
nullptr) {
393 if (millis() - state->connectTimestamp > state->sConnectionTimeout) {
395 if ((tpcb->state == ESTABLISHED || tpcb->state == SYN_SENT || tpcb->state == SYN_RCVD)) {
396 if (state->backlogWasClosed ==
false) {
400 if (state->backlogWasAccepted ==
false) {
402 tcp_backlog_accepted(tpcb);
403 state->backlogWasAccepted =
true;
407 state->result = tcp_close(tpcb);
408 state->backlogWasClosed =
true;
409 if (state->result == ERR_OK) {
410 state->closeTimer = millis();
411 state->finished =
true;
419 return state->result;
424 if (state !=
nullptr) {
427 if (millis() - state->closeTimer > 5000) {
437 if (tpcb !=
nullptr) {
438 if (state !=
nullptr) {
439 if (millis() - state->connectTimestamp > state->sConnectionTimeout) {
440 if (state->backlogWasClosed ==
false) {
442 if (state->backlogWasAccepted ==
false) {
444 tcp_backlog_accepted(tpcb);
445 state->backlogWasAccepted =
true;
448 state->result = tcp_close(tpcb);
449 state->backlogWasClosed =
true;
450 if (state->result == ERR_OK) {
451 state->closeTimer = millis();
452 state->finished =
true;
459 return state->result;
463 if (state !=
nullptr) {
464 Serial.println(state->identifier);
465 if (millis() - state->closeTimer > 5000) {
481err_t RF24Client::accept(
void* arg,
struct tcp_pcb* tpcb, err_t err)
485 if (tpcb ==
nullptr) {
486 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print(
"Server: Accepted conn, but no tpcb from: "); Serial.println(ip4addr_ntoa(ip_2_ip4(&tpcb->remote_ip))););
490 if (tpcb !=
nullptr) {
495 if (myPcb !=
nullptr) {
497 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print(
"Server: Accept w/already connected: Accepted_Conns - Delayed_Conns == "); Serial.println(accepts););
498 tcp_backlog_delayed(tpcb);
500 tcp_poll(tpcb, closed_port, 5);
502 gState[actState]->connected =
false;
506 tcp_poll(tpcb, serverTimeouts, 8);
509 gState[actState]->connected =
true;
512 dataSize[actState] = 0;
515 gState[actState]->stateActiveID = actState;
516 gState[actState]->identifier = simpleCounter;
517 gState[actState]->finished =
false;
518 gState[actState]->sConnectionTimeout = serverConnectionTimeout;
519 gState[actState]->waiting_for_ack =
false;
520 gState[actState]->backlogWasAccepted =
false;
521 gState[actState]->backlogWasClosed =
false;
522 gState[actState]->connectTimestamp = millis();
523 gState[actState]->serverTimer = millis();
534err_t RF24Client::closeConn(
void* arg,
struct tcp_pcb* tpcb)
537 if (tpcb !=
nullptr) {
548err_t RF24Client::on_connected(
void* arg,
struct tcp_pcb* tpcb, err_t err)
554 if (state !=
nullptr) {
565 state->cConnectionTimeout = clientConnectionTimeout;
566 state->clientTimer = millis();
568 state->finished =
true;
570 state->connected =
true;
573 state->connected =
false;
575 state->waiting_for_ack =
false;
612 return (data && (data->packets_in != 0 || (data->state & UIP_CLIENT_CONNECTED))) ? 1 : 0;
627 #if UIP_ACTIVE_OPEN > 0
633 uip_ip_addr(ipaddr, ip);
635 struct uip_conn* conn = uip_connect(&ipaddr, htons(port));
639 #if UIP_CONNECTION_TIMEOUT > 0
640 uint32_t timeout = millis();
643 while ((conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED)
647 if ((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED)
649 data = (uip_userdata_t*)conn->appstate;
650 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););
654 #if UIP_CONNECTION_TIMEOUT > 0
657 conn->tcpstateflags = UIP_CLOSED;
669 if (myPcb !=
nullptr) {
670 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
672 ETHERNET_APPLY_LOCK();
675 if (myPcb->state == ESTABLISHED || myPcb->state == SYN_SENT || myPcb->state == SYN_RCVD) {
676 if (tcp_close(myPcb) != ERR_OK) {
680 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
682 ETHERNET_REMOVE_LOCK();
689 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
691 ETHERNET_REMOVE_LOCK();
698 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
700 ETHERNET_APPLY_LOCK();
704 if (myPcb ==
nullptr) {
710 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
712 ETHERNET_REMOVE_LOCK();
734 IP_ADDR4(&myIp, ip[0], ip[1], ip[2], ip[3]);
736 err = tcp_connect(myPcb, &myIp, port, on_connected);
739 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
741 ETHERNET_REMOVE_LOCK();
749 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
751 ETHERNET_REMOVE_LOCK();
755 uint32_t timeout = millis() + 5000;
761 if (clientConnectionTimeout > 0) {
774void dnsCallback(
const char* name,
const ip_addr_t* ipaddr,
void* callback_arg)
787 IPAddress remote_addr;
789 dns.
begin(RF24EthernetClass::_dnsServerAddress);
794 #if defined(ETH_DEBUG_L1) || defined(RF24ETHERNET_DEBUG_DNS)
795 Serial.println(F(
"*UIP Got DNS*"));
797 return connect(remote_addr, port);
799#elif RF24ETHERNET_USE_UDP
802 IPAddress remote_addr;
804 dns.
begin(RF24EthernetClass::_dnsServerAddress);
809 #if defined(ETH_DEBUG_L1) || defined(RF24ETHERNET_DEBUG_DNS)
810 Serial.println(F(
"*lwIP Got DNS*"));
812 return connect(remote_addr, port);
823#if defined(ETH_DEBUG_L1) || defined(RF24ETHERNET_DEBUG_DNS)
824 Serial.println(F(
"* DNS fail*"));
835 if (data && data->state)
840 data->packets_in = 0;
843 if (data->state & UIP_CLIENT_REMOTECLOSED)
849 data->state |= UIP_CLIENT_CLOSE;
870void RF24Client::_stop()
872 if (myPcb !=
nullptr) {
874 if (myPcb->state != CLOSED) {
876 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
878 ETHERNET_APPLY_LOCK();
881 err_t err = tcp_close(myPcb);
886 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
888 ETHERNET_REMOVE_LOCK();
906 return data && rhs.data && (data == rhs.data);
914RF24Client::operator bool()
918 return data && (!(data->state & UIP_CLIENT_REMOTECLOSED) || data->packets_in != 0);
928 return _write(data, &c, 1);
935 return _write(data, buf, size);
940size_t RF24Client::_write(uip_userdata_t* u,
const uint8_t* buf,
size_t size)
942size_t RF24Client::_write(uint8_t* data,
const uint8_t* buf,
size_t size)
949 size_t total_written = 0;
950 size_t payloadSize = rf24_min(size, UIP_TCP_MSS);
955 if (u && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)) && u->state & (UIP_CLIENT_CONNECTED))
958 if (u->out_pos + payloadSize > UIP_TCP_MSS || u->hold)
963 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(
"'")););
965 memcpy(u->myData + u->out_pos, buf + total_written, payloadSize);
967 u->out_pos += payloadSize;
969 total_written += payloadSize;
971 if (total_written < size)
973 size_t remain = size - total_written;
974 payloadSize = rf24_min(remain, UIP_TCP_MSS);
986 if (myPcb ==
nullptr) {
990 bool initialActiveState = activeState;
993 uint32_t position = 0;
994 uint32_t timeout1 = millis() + 3000;
996 while (size > MAX_PAYLOAD_SIZE - 14 && millis() < timeout1) {
997 memcpy(buffer, &buf[position], MAX_PAYLOAD_SIZE - 14);
999 if (myPcb ==
nullptr) {
1002 gState[initialActiveState]->waiting_for_ack =
true;
1003 err_t write_err = blocking_write(myPcb, gState[initialActiveState], buffer, MAX_PAYLOAD_SIZE - 14);
1005 if (write_err != ERR_OK) {
1006 gState[initialActiveState]->result = write_err;
1007 gState[initialActiveState]->connected =
false;
1011 position += MAX_PAYLOAD_SIZE - 14;
1012 size -= MAX_PAYLOAD_SIZE - 14;
1016 memcpy(buffer, &buf[position], size);
1018 if (myPcb ==
nullptr) {
1022 gState[initialActiveState]->waiting_for_ack =
true;
1023 err_t write_err = blocking_write(myPcb, gState[initialActiveState], buffer, size);
1025 if (write_err != ERR_OK) {
1026 gState[initialActiveState]->result = write_err;
1027 gState[initialActiveState]->connected =
false;
1052 uip_userdata_t* u = (uip_userdata_t*)uip_conn->appstate;
1055 if (!u && uip_connected())
1059 u = (uip_userdata_t*)EthernetClient::_allocateData();
1063 uip_conn->appstate = u;
1072 #if UIP_CONNECTION_TIMEOUT > 0
1073 if (u && u->connectTimeout > 0) {
1074 if (millis() - u->connectTimer > u->connectTimeout) {
1075 u->state |= UIP_CLIENT_CLOSE;
1076 u->connectTimer = millis();
1087 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(); Serial.print(millis()); Serial.print(F(
" UIPClient uip_newdata, uip_len:")); Serial.println(uip_len););
1088 #if UIP_CONNECTION_TIMEOUT > 0
1089 u->connectTimer = millis();
1091 u->hold = (u->out_pos = (u->windowOpened = (u->packets_out =
false)));
1093 if (uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1096 u->state &= ~UIP_CLIENT_RESTART;
1097 u->windowOpened =
false;
1098 u->restartTime = millis();
1099 memcpy(&u->myData[u->in_pos + u->dataCnt], uip_appdata, uip_datalen());
1100 u->dataCnt += uip_datalen();
1109 if (uip_closed() || uip_timedout() || uip_aborted())
1117 ((uip_userdata_closed_t*)u)->lport = uip_conn->lport;
1118 u->state |= UIP_CLIENT_REMOTECLOSED;
1128 uip_conn->appstate = NULL;
1136 u->state &= ~UIP_CLIENT_RESTART;
1137 u->hold = (u->out_pos = (u->windowOpened = (u->packets_out =
false)));
1138 u->restartTime = millis();
1139 #if UIP_CONNECTION_TIMEOUT > 0
1140 u->connectTimer = millis();
1145 if (uip_poll() || uip_rexmit())
1150 uip_len = u->out_pos;
1151 uip_send(u->myData, u->out_pos);
1157 if (u->packets_out != 0 && !u->hold)
1159 uip_len = u->out_pos;
1160 uip_send(u->myData, u->out_pos);
1168 if (!(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1171 if (u->windowOpened ==
true && u->state & UIP_CLIENT_RESTART && millis() - u->restartTime > u->restartInterval)
1173 u->restartTime = millis();
1174 #if defined RF24ETHERNET_DEBUG_CLIENT || defined ETH_DEBUG_L1
1176 Serial.print(millis());
1177 #if UIP_CONNECTION_TIMEOUT > 0
1178 Serial.print(F(
" UIPClient Re-Open TCP Window, time remaining before abort: "));
1182 u->restartInterval += 500;
1183 u->restartInterval = rf24_min(u->restartInterval, 7000);
1190 if (u->state & UIP_CLIENT_CLOSE)
1194 if (u->packets_out == 0)
1197 uip_conn->appstate = NULL;
1209 if (u->state & UIP_CLIENT_RESTART && !u->windowOpened)
1211 if (!(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1214 #if defined ETH_DEBUG_L1
1216 Serial.print(millis());
1217 Serial.println(F(
" UIPClient Re-Open TCP Window"));
1219 u->windowOpened =
true;
1221 u->restartTime = millis();
1229uip_userdata_t* RF24Client::_allocateData()
1231 for (uint8_t sock = 0; sock < UIP_CONNS; sock++)
1233 uip_userdata_t* data = &RF24Client::all_data[sock];
1236 data->state = sock | UIP_CLIENT_CONNECTED;
1237 data->packets_in = 0;
1238 data->packets_out = 0;
1243 data->restartTime = millis();
1244 data->restartInterval = 5000;
1245 #if (UIP_CONNECTION_TIMEOUT > 0)
1246 data->connectTimer = millis();
1258 uint32_t start = millis();
1261 if (millis() - start > timeout)
1278 return _available(data);
1281 return _available(data);
1288int RF24Client::_available(uip_userdata_t* u)
1290int RF24Client::_available(uint8_t* data)
1299 return dataSize[activeState];
1311 if (!data->packets_in)
1316 size = rf24_min(data->dataCnt, size);
1317 memcpy(buf, &data->myData[data->in_pos], size);
1318 data->dataCnt -= size;
1320 data->in_pos += size;
1324 data->packets_in = 0;
1327 if (uip_stopped(&uip_conns[data->state & UIP_CLIENT_SOCKETS]) && !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1329 data->state |= UIP_CLIENT_RESTART;
1330 data->restartTime = 0;
1332 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(
"**")););
1336 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(
"**")););
1339 if (data->packets_in == 0)
1341 if (data->state & UIP_CLIENT_REMOTECLOSED)
1364 memcpy(&buf[0], &incomingData[
activeState][0], size);
1379 if (
read(&c, 1) < 0)
1391 return data->myData[data->in_pos];
1407 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
uint16_t u16_t
16 bit datatype
void serialip_appcall(void)