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 const uint32_t timeoutStart = millis();
84 while (len > tcp_sndbuf(fpcb)) {
86 if (millis() - timeoutStart > serverConnectionTimeout) {
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 const uint32_t timerStart = millis();
139 while (fstate !=
nullptr && fstate->waiting_for_ack && !fstate->finished) {
140 if (millis() - timerStart > 5000) {
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->tot_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->tot_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) {
350 tcp_arg(tpcb,
nullptr);
357 return state->result;
361 if (state->backlogWasClosed ==
true) {
362 if (millis() - state->closeTimer > 5000) {
363 tcp_arg(tpcb,
nullptr);
370 return state->result;
377err_t RF24Client::closed_port(
void* arg,
struct tcp_pcb* tpcb)
382 if (state !=
nullptr) {
386 if (myPcb ==
nullptr) {
387 if (state !=
nullptr && tpcb !=
nullptr) {
389 if ((tpcb->state == ESTABLISHED || tpcb->state == SYN_SENT || tpcb->state == SYN_RCVD)) {
390 if (state->backlogWasAccepted ==
false && state->backlogWasClosed ==
false) {
392 state->backlogWasAccepted =
true;
393 state->connectTimestamp = millis();
394 state->connected =
true;
395 state->finished =
false;
400 tcp_backlog_accepted(tpcb);
408 if (tpcb !=
nullptr) {
409 if (state !=
nullptr) {
410 if (millis() - state->connectTimestamp > state->sConnectionTimeout) {
412 if ((tpcb->state == ESTABLISHED || tpcb->state == SYN_SENT || tpcb->state == SYN_RCVD)) {
413 if (state->backlogWasClosed ==
false) {
417 if (state->backlogWasAccepted ==
false) {
419 tcp_backlog_accepted(tpcb);
420 state->backlogWasAccepted =
true;
424 state->result = tcp_close(tpcb);
425 state->backlogWasClosed =
true;
426 if (state->result == ERR_OK) {
427 state->closeTimer = millis();
428 state->finished =
true;
436 return state->result;
441 if (state !=
nullptr) {
444 if (millis() - state->closeTimer > 5000) {
454 if (tpcb !=
nullptr) {
455 if (state !=
nullptr) {
456 if (millis() - state->connectTimestamp > state->sConnectionTimeout) {
457 if (state->backlogWasClosed ==
false) {
459 if (state->backlogWasAccepted ==
false) {
461 tcp_backlog_accepted(tpcb);
462 state->backlogWasAccepted =
true;
465 state->result = tcp_close(tpcb);
466 state->backlogWasClosed =
true;
467 if (state->result == ERR_OK) {
468 state->closeTimer = millis();
469 state->finished =
true;
476 return state->result;
480 if (state !=
nullptr) {
481 Serial.println(state->identifier);
482 if (millis() - state->closeTimer > 5000) {
498err_t RF24Client::accept(
void* arg,
struct tcp_pcb* tpcb, err_t err)
502 if (tpcb ==
nullptr) {
503 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print(
"Server: Accepted conn, but no tpcb from: "); Serial.println(ip4addr_ntoa(ip_2_ip4(&tpcb->remote_ip))););
507 if (tpcb !=
nullptr) {
512 if (myPcb !=
nullptr) {
514 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print(
"Server: Accept w/already connected: Accepted_Conns - Delayed_Conns == "); Serial.println(accepts););
515 tcp_backlog_delayed(tpcb);
517 tcp_poll(tpcb, closed_port, 5);
519 gState[actState]->connected =
false;
520 gState[actState]->backlogWasAccepted =
false;
524 tcp_poll(tpcb, serverTimeouts, 8);
527 gState[actState]->connected =
true;
528 gState[actState]->backlogWasAccepted =
true;
531 dataSize[actState] = 0;
534 gState[actState]->stateActiveID = actState;
535 gState[actState]->identifier = simpleCounter;
536 gState[actState]->finished =
false;
537 gState[actState]->sConnectionTimeout = serverConnectionTimeout;
538 gState[actState]->waiting_for_ack =
false;
539 gState[actState]->backlogWasClosed =
false;
540 gState[actState]->connectTimestamp = millis();
541 gState[actState]->serverTimer = millis();
552err_t RF24Client::closeConn(
void* arg,
struct tcp_pcb* tpcb)
555 if (tpcb !=
nullptr) {
566err_t RF24Client::on_connected(
void* arg,
struct tcp_pcb* tpcb, err_t err)
572 if (state !=
nullptr) {
583 state->cConnectionTimeout = clientConnectionTimeout;
584 state->clientTimer = millis();
586 state->finished =
true;
588 state->connected =
true;
591 state->connected =
false;
593 state->waiting_for_ack =
false;
630 return (data && (data->packets_in != 0 || (data->state & UIP_CLIENT_CONNECTED))) ? 1 : 0;
645 #if UIP_ACTIVE_OPEN > 0
651 uip_ip_addr(ipaddr, ip);
653 struct uip_conn* conn = uip_connect(&ipaddr, htons(port));
657 #if UIP_CONNECTION_TIMEOUT > 0
658 uint32_t timeout = millis();
661 while ((conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED)
665 if ((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED)
667 data = (uip_userdata_t*)conn->appstate;
668 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););
672 #if UIP_CONNECTION_TIMEOUT > 0
675 conn->tcpstateflags = UIP_CLOSED;
687 if (myPcb !=
nullptr) {
692 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
694 ETHERNET_APPLY_LOCK();
698 if (myPcb ==
nullptr) {
703 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
705 ETHERNET_REMOVE_LOCK();
727 IP_ADDR4(&myIp, ip[0], ip[1], ip[2], ip[3]);
729 err = tcp_connect(myPcb, &myIp, port, on_connected);
732 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
734 ETHERNET_REMOVE_LOCK();
742 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
744 ETHERNET_REMOVE_LOCK();
748 const uint32_t timeoutStart = millis();
754 if (clientConnectionTimeout > 0) {
767void dnsCallback(
const char* name,
const ip_addr_t* ipaddr,
void* callback_arg)
780 IPAddress remote_addr;
782 dns.
begin(RF24EthernetClass::_dnsServerAddress);
787 #if defined(ETH_DEBUG_L1) || defined(RF24ETHERNET_DEBUG_DNS)
788 Serial.println(F(
"*UIP Got DNS*"));
790 return connect(remote_addr, port);
792#elif RF24ETHERNET_USE_UDP
795 IPAddress remote_addr;
797 dns.
begin(RF24EthernetClass::_dnsServerAddress);
802 #if defined(ETH_DEBUG_L1) || defined(RF24ETHERNET_DEBUG_DNS)
803 Serial.println(F(
"*lwIP Got DNS*"));
805 return connect(remote_addr, port);
816#if defined(ETH_DEBUG_L1) || defined(RF24ETHERNET_DEBUG_DNS)
817 Serial.println(F(
"* DNS fail*"));
828 if (data && data->state)
833 data->packets_in = 0;
836 if (data->state & UIP_CLIENT_REMOTECLOSED)
842 data->state |= UIP_CLIENT_CLOSE;
863void RF24Client::_stop()
865 tcp_pcb* pcb = myPcb;
868 if (pcb !=
nullptr) {
869 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
871 ETHERNET_APPLY_LOCK();
874 if (pcb->state != CLOSED) {
880 err_t err = tcp_close(pcb);
885 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
887 ETHERNET_REMOVE_LOCK();
904 return data && rhs.data && (data == rhs.data);
912RF24Client::operator bool()
916 return data && (!(data->state & UIP_CLIENT_REMOTECLOSED) || data->packets_in != 0);
926 return _write(data, &c, 1);
933 return _write(data, buf, size);
938size_t RF24Client::_write(uip_userdata_t* u,
const uint8_t* buf,
size_t size)
940size_t RF24Client::_write(uint8_t* data,
const uint8_t* buf,
size_t size)
947 size_t total_written = 0;
948 size_t payloadSize = rf24_min(size, UIP_TCP_MSS);
949 uint32_t start = millis();
955 if (millis() - start > 5000)
960 return total_written;
963 if (u && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)) && (u->state & UIP_CLIENT_CONNECTED))
965 if (u->out_pos + payloadSize > UIP_TCP_MSS || u->hold)
972 Serial.print(millis());
973 Serial.print(F(
" UIPClient.write: writePacket("));
974 Serial.print(u->packets_out);
975 Serial.print(F(
") pos: "));
976 Serial.print(u->out_pos);
977 Serial.print(F(
", buf["));
978 Serial.print(size - total_written);
979 Serial.print(F(
"]: '"));
980 Serial.write((uint8_t*)buf + total_written, payloadSize);
981 Serial.println(F(
"'")););
983 memcpy(u->myData + u->out_pos, buf + total_written, payloadSize);
985 u->out_pos += payloadSize;
986 total_written += payloadSize;
988 if (total_written < size)
990 size_t remain = size - total_written;
991 payloadSize = rf24_min(remain, UIP_TCP_MSS);
1005 bool initialActiveState = activeState;
1006 size_t chunk = MAX_PAYLOAD_SIZE - 14;
1007 size_t position = 0;
1009 while (size > chunk) {
1010 if (myPcb ==
nullptr)
1012 gState[initialActiveState]->waiting_for_ack =
true;
1013 err_t write_err = blocking_write(myPcb, gState[initialActiveState],
reinterpret_cast<const char*
>(&buf[position]), chunk);
1014 if (write_err != ERR_OK) {
1015 gState[initialActiveState]->result = write_err;
1016 gState[initialActiveState]->connected =
false;
1025 if (myPcb ==
nullptr)
1027 gState[initialActiveState]->waiting_for_ack =
true;
1028 err_t write_err = blocking_write(myPcb, gState[initialActiveState],
reinterpret_cast<const char*
>(&buf[position]), size);
1030 if (write_err != ERR_OK) {
1031 gState[initialActiveState]->result = write_err;
1032 gState[initialActiveState]->connected =
false;
1037 return position + size;
1057 uip_userdata_t* u = (uip_userdata_t*)uip_conn->appstate;
1060 if (!u && uip_connected())
1064 u = (uip_userdata_t*)EthernetClient::_allocateData();
1068 uip_conn->appstate = u;
1077 #if UIP_CONNECTION_TIMEOUT > 0
1078 if (u && u->connectTimeout > 0) {
1079 if (millis() - u->connectTimer > u->connectTimeout) {
1080 u->state |= UIP_CLIENT_CLOSE;
1081 u->connectTimer = millis();
1092 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(); Serial.print(millis()); Serial.print(F(
" UIPClient uip_newdata, uip_len:")); Serial.println(uip_len););
1093 #if UIP_CONNECTION_TIMEOUT > 0
1094 u->connectTimer = millis();
1096 u->hold = (u->out_pos = (u->windowOpened = (u->packets_out =
false)));
1098 if (uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1101 u->state &= ~UIP_CLIENT_RESTART;
1102 u->windowOpened =
false;
1103 u->restartTime = millis();
1105 uint16_t writePos = u->in_pos + u->dataCnt;
1106 uint16_t incomingLen = uip_datalen();
1110 memcpy(&u->myData[writePos], uip_appdata, incomingLen);
1111 u->dataCnt += incomingLen;
1117 Serial.println(F(
"UIPClient RX overflow, closing connection")););
1118 u->state |= UIP_CLIENT_CLOSE;
1126 if (uip_closed() || uip_timedout() || uip_aborted())
1134 ((uip_userdata_closed_t*)u)->lport = uip_conn->lport;
1135 u->state |= UIP_CLIENT_REMOTECLOSED;
1145 uip_conn->appstate = NULL;
1153 u->state &= ~UIP_CLIENT_RESTART;
1154 u->hold = (u->out_pos = (u->windowOpened = (u->packets_out =
false)));
1155 u->restartTime = millis();
1156 #if UIP_CONNECTION_TIMEOUT > 0
1157 u->connectTimer = millis();
1162 if (uip_poll() || uip_rexmit())
1167 uip_len = u->out_pos;
1168 uip_send(u->myData, u->out_pos);
1174 if (u->packets_out != 0 && !u->hold)
1176 uip_len = u->out_pos;
1177 uip_send(u->myData, u->out_pos);
1185 if (!(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1188 if (u->windowOpened ==
true && u->state & UIP_CLIENT_RESTART && millis() - u->restartTime > u->restartInterval)
1190 u->restartTime = millis();
1191 #if defined RF24ETHERNET_DEBUG_CLIENT || defined ETH_DEBUG_L1
1193 Serial.print(millis());
1194 #if UIP_CONNECTION_TIMEOUT > 0
1195 Serial.print(F(
" UIPClient Re-Open TCP Window, time remaining before abort: "));
1199 u->restartInterval += 500;
1200 u->restartInterval = rf24_min(u->restartInterval, 7000);
1207 if (u->state & UIP_CLIENT_CLOSE)
1211 if (u->packets_out == 0)
1214 uip_conn->appstate = NULL;
1226 if (u->state & UIP_CLIENT_RESTART && !u->windowOpened)
1228 if (!(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1231 #if defined ETH_DEBUG_L1
1233 Serial.print(millis());
1234 Serial.println(F(
" UIPClient Re-Open TCP Window"));
1236 u->windowOpened =
true;
1238 u->restartTime = millis();
1246uip_userdata_t* RF24Client::_allocateData()
1248 for (uint8_t sock = 0; sock < UIP_CONNS; sock++)
1250 uip_userdata_t* data = &RF24Client::all_data[sock];
1253 data->state = sock | UIP_CLIENT_CONNECTED;
1254 data->packets_in = 0;
1255 data->packets_out = 0;
1260 data->restartTime = millis();
1261 data->restartInterval = 5000;
1262 #if (UIP_CONNECTION_TIMEOUT > 0)
1263 data->connectTimer = millis();
1275 uint32_t start = millis();
1278 if (millis() - start > timeout)
1295 return _available(data);
1298 return _available(data);
1305int RF24Client::_available(uip_userdata_t* u)
1307int RF24Client::_available(uint8_t* data)
1316 return dataSize[activeState];
1328 if (!data->packets_in)
1334 data->state |= UIP_CLIENT_CLOSE;
1339 size = rf24_min(data->dataCnt, size);
1340 memcpy(buf, &data->myData[data->in_pos], size);
1341 data->dataCnt -= size;
1343 data->in_pos += size;
1347 data->packets_in = 0;
1350 if (uip_stopped(&uip_conns[data->state & UIP_CLIENT_SOCKETS]) && !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1352 data->state |= UIP_CLIENT_RESTART;
1353 data->restartTime = 0;
1355 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(
"**")););
1359 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(
"**")););
1362 if (data->packets_in == 0)
1364 if (data->state & UIP_CLIENT_REMOTECLOSED)
1387 memcpy(&buf[0], &incomingData[
activeState][0], size);
1402 if (
read(&c, 1) < 0)
1414 return data->myData[data->in_pos];
1430 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 OUTPUT_BUFFER_SIZE
#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)