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);
355 return state->result;
359 if (state->backlogWasClosed ==
true) {
360 if (millis() - state->closeTimer > 5000) {
361 tcp_arg(tpcb,
nullptr);
367 return state->result;
374err_t RF24Client::closed_port(
void* arg,
struct tcp_pcb* tpcb)
379 if (state !=
nullptr) {
383 if (myPcb ==
nullptr) {
384 if (state !=
nullptr && tpcb !=
nullptr) {
386 if ((tpcb->state == ESTABLISHED || tpcb->state == SYN_SENT || tpcb->state == SYN_RCVD)) {
387 if (state->backlogWasAccepted ==
false && state->backlogWasClosed ==
false) {
389 state->backlogWasAccepted =
true;
390 state->connectTimestamp = millis();
391 state->connected =
true;
392 state->finished =
false;
397 tcp_backlog_accepted(tpcb);
405 if (tpcb !=
nullptr) {
406 if (state !=
nullptr) {
407 if (millis() - state->connectTimestamp > state->sConnectionTimeout) {
409 if ((tpcb->state == ESTABLISHED || tpcb->state == SYN_SENT || tpcb->state == SYN_RCVD)) {
410 if (state->backlogWasClosed ==
false) {
414 if (state->backlogWasAccepted ==
false) {
416 tcp_backlog_accepted(tpcb);
417 state->backlogWasAccepted =
true;
421 state->result = tcp_close(tpcb);
422 state->backlogWasClosed =
true;
423 if (state->result == ERR_OK) {
424 state->closeTimer = millis();
425 state->finished =
true;
433 return state->result;
438 if (state !=
nullptr) {
441 if (millis() - state->closeTimer > 5000) {
451 if (tpcb !=
nullptr) {
452 if (state !=
nullptr) {
453 if (millis() - state->connectTimestamp > state->sConnectionTimeout) {
454 if (state->backlogWasClosed ==
false) {
456 if (state->backlogWasAccepted ==
false) {
458 tcp_backlog_accepted(tpcb);
459 state->backlogWasAccepted =
true;
462 state->result = tcp_close(tpcb);
463 state->backlogWasClosed =
true;
464 if (state->result == ERR_OK) {
465 state->closeTimer = millis();
466 state->finished =
true;
473 return state->result;
477 if (state !=
nullptr) {
478 Serial.println(state->identifier);
479 if (millis() - state->closeTimer > 5000) {
495err_t RF24Client::accept(
void* arg,
struct tcp_pcb* tpcb, err_t err)
499 if (tpcb ==
nullptr) {
500 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print(
"Server: Accepted conn, but no tpcb from: "); Serial.println(ip4addr_ntoa(ip_2_ip4(&tpcb->remote_ip))););
504 if (tpcb !=
nullptr) {
509 if (myPcb !=
nullptr) {
511 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print(
"Server: Accept w/already connected: Accepted_Conns - Delayed_Conns == "); Serial.println(accepts););
512 tcp_backlog_delayed(tpcb);
514 tcp_poll(tpcb, closed_port, 5);
516 gState[actState]->connected =
false;
517 gState[actState]->backlogWasAccepted =
false;
521 tcp_poll(tpcb, serverTimeouts, 8);
524 gState[actState]->connected =
true;
525 gState[actState]->backlogWasAccepted =
true;
528 dataSize[actState] = 0;
531 gState[actState]->stateActiveID = actState;
532 gState[actState]->identifier = simpleCounter;
533 gState[actState]->finished =
false;
534 gState[actState]->sConnectionTimeout = serverConnectionTimeout;
535 gState[actState]->waiting_for_ack =
false;
536 gState[actState]->backlogWasClosed =
false;
537 gState[actState]->connectTimestamp = millis();
538 gState[actState]->serverTimer = millis();
549err_t RF24Client::closeConn(
void* arg,
struct tcp_pcb* tpcb)
552 if (tpcb !=
nullptr) {
563err_t RF24Client::on_connected(
void* arg,
struct tcp_pcb* tpcb, err_t err)
569 if (state !=
nullptr) {
580 state->cConnectionTimeout = clientConnectionTimeout;
581 state->clientTimer = millis();
583 state->finished =
true;
585 state->connected =
true;
588 state->connected =
false;
590 state->waiting_for_ack =
false;
627 return (data && (data->packets_in != 0 || (data->state & UIP_CLIENT_CONNECTED))) ? 1 : 0;
642 #if UIP_ACTIVE_OPEN > 0
648 uip_ip_addr(ipaddr, ip);
650 struct uip_conn* conn = uip_connect(&ipaddr, htons(port));
654 #if UIP_CONNECTION_TIMEOUT > 0
655 uint32_t timeout = millis();
658 while ((conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED)
662 if ((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED)
664 data = (uip_userdata_t*)conn->appstate;
665 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););
669 #if UIP_CONNECTION_TIMEOUT > 0
672 conn->tcpstateflags = UIP_CLOSED;
684 if (myPcb !=
nullptr) {
689 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
691 ETHERNET_APPLY_LOCK();
695 if (myPcb ==
nullptr) {
700 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
702 ETHERNET_REMOVE_LOCK();
724 IP_ADDR4(&myIp, ip[0], ip[1], ip[2], ip[3]);
726 err = tcp_connect(myPcb, &myIp, port, on_connected);
729 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
731 ETHERNET_REMOVE_LOCK();
739 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
741 ETHERNET_REMOVE_LOCK();
745 const uint32_t timeoutStart = millis();
751 if (clientConnectionTimeout > 0) {
764void dnsCallback(
const char* name,
const ip_addr_t* ipaddr,
void* callback_arg)
777 IPAddress remote_addr;
779 dns.
begin(RF24EthernetClass::_dnsServerAddress);
784 #if defined(ETH_DEBUG_L1) || defined(RF24ETHERNET_DEBUG_DNS)
785 Serial.println(F(
"*UIP Got DNS*"));
787 return connect(remote_addr, port);
789#elif RF24ETHERNET_USE_UDP
792 IPAddress remote_addr;
794 dns.
begin(RF24EthernetClass::_dnsServerAddress);
799 #if defined(ETH_DEBUG_L1) || defined(RF24ETHERNET_DEBUG_DNS)
800 Serial.println(F(
"*lwIP Got DNS*"));
802 return connect(remote_addr, port);
813#if defined(ETH_DEBUG_L1) || defined(RF24ETHERNET_DEBUG_DNS)
814 Serial.println(F(
"* DNS fail*"));
825 if (data && data->state)
830 data->packets_in = 0;
833 if (data->state & UIP_CLIENT_REMOTECLOSED)
839 data->state |= UIP_CLIENT_CLOSE;
860void RF24Client::_stop()
862 tcp_pcb* pcb = myPcb;
865 if (pcb !=
nullptr) {
866 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
868 ETHERNET_APPLY_LOCK();
871 if (pcb->state != CLOSED) {
877 err_t err = tcp_close(pcb);
882 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
884 ETHERNET_REMOVE_LOCK();
901 return data && rhs.data && (data == rhs.data);
909RF24Client::operator bool()
913 return data && (!(data->state & UIP_CLIENT_REMOTECLOSED) || data->packets_in != 0);
923 return _write(data, &c, 1);
930 return _write(data, buf, size);
935size_t RF24Client::_write(uip_userdata_t* u,
const uint8_t* buf,
size_t size)
937size_t RF24Client::_write(uint8_t* data,
const uint8_t* buf,
size_t size)
944 size_t total_written = 0;
945 size_t payloadSize = rf24_min(size, UIP_TCP_MSS);
946 uint32_t start = millis();
952 if (millis() - start > 5000)
957 return total_written;
960 if (u && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)) && (u->state & UIP_CLIENT_CONNECTED))
962 if (u->out_pos + payloadSize > UIP_TCP_MSS || u->hold)
969 Serial.print(millis());
970 Serial.print(F(
" UIPClient.write: writePacket("));
971 Serial.print(u->packets_out);
972 Serial.print(F(
") pos: "));
973 Serial.print(u->out_pos);
974 Serial.print(F(
", buf["));
975 Serial.print(size - total_written);
976 Serial.print(F(
"]: '"));
977 Serial.write((uint8_t*)buf + total_written, payloadSize);
978 Serial.println(F(
"'")););
980 memcpy(u->myData + u->out_pos, buf + total_written, payloadSize);
982 u->out_pos += payloadSize;
983 total_written += payloadSize;
985 if (total_written < size)
987 size_t remain = size - total_written;
988 payloadSize = rf24_min(remain, UIP_TCP_MSS);
1002 bool initialActiveState = activeState;
1003 size_t chunk = MAX_PAYLOAD_SIZE - 14;
1004 size_t position = 0;
1006 while (size > chunk) {
1007 if (myPcb ==
nullptr)
1009 gState[initialActiveState]->waiting_for_ack =
true;
1010 err_t write_err = blocking_write(myPcb, gState[initialActiveState],
reinterpret_cast<const char*
>(&buf[position]), chunk);
1011 if (write_err != ERR_OK) {
1012 gState[initialActiveState]->result = write_err;
1013 gState[initialActiveState]->connected =
false;
1022 if (myPcb ==
nullptr)
1024 gState[initialActiveState]->waiting_for_ack =
true;
1025 err_t write_err = blocking_write(myPcb, gState[initialActiveState],
reinterpret_cast<const char*
>(&buf[position]), size);
1027 if (write_err != ERR_OK) {
1028 gState[initialActiveState]->result = write_err;
1029 gState[initialActiveState]->connected =
false;
1034 return position + size;
1054 uip_userdata_t* u = (uip_userdata_t*)uip_conn->appstate;
1057 if (!u && uip_connected())
1061 u = (uip_userdata_t*)EthernetClient::_allocateData();
1065 uip_conn->appstate = u;
1074 #if UIP_CONNECTION_TIMEOUT > 0
1075 if (u && u->connectTimeout > 0) {
1076 if (millis() - u->connectTimer > u->connectTimeout) {
1077 u->state |= UIP_CLIENT_CLOSE;
1078 u->connectTimer = millis();
1089 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(); Serial.print(millis()); Serial.print(F(
" UIPClient uip_newdata, uip_len:")); Serial.println(uip_len););
1090 #if UIP_CONNECTION_TIMEOUT > 0
1091 u->connectTimer = millis();
1093 u->hold = (u->out_pos = (u->windowOpened = (u->packets_out =
false)));
1095 if (uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1098 u->state &= ~UIP_CLIENT_RESTART;
1099 u->windowOpened =
false;
1100 u->restartTime = millis();
1102 uint16_t writePos = u->in_pos + u->dataCnt;
1103 uint16_t incomingLen = uip_datalen();
1107 memcpy(&u->myData[writePos], uip_appdata, incomingLen);
1108 u->dataCnt += incomingLen;
1114 Serial.println(F(
"UIPClient RX overflow, closing connection")););
1115 u->state |= UIP_CLIENT_CLOSE;
1123 if (uip_closed() || uip_timedout() || uip_aborted())
1131 ((uip_userdata_closed_t*)u)->lport = uip_conn->lport;
1132 u->state |= UIP_CLIENT_REMOTECLOSED;
1142 uip_conn->appstate = NULL;
1150 u->state &= ~UIP_CLIENT_RESTART;
1151 u->hold = (u->out_pos = (u->windowOpened = (u->packets_out =
false)));
1152 u->restartTime = millis();
1153 #if UIP_CONNECTION_TIMEOUT > 0
1154 u->connectTimer = millis();
1159 if (uip_poll() || uip_rexmit())
1164 uip_len = u->out_pos;
1165 uip_send(u->myData, u->out_pos);
1171 if (u->packets_out != 0 && !u->hold)
1173 uip_len = u->out_pos;
1174 uip_send(u->myData, u->out_pos);
1182 if (!(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1185 if (u->windowOpened ==
true && u->state & UIP_CLIENT_RESTART && millis() - u->restartTime > u->restartInterval)
1187 u->restartTime = millis();
1188 #if defined RF24ETHERNET_DEBUG_CLIENT || defined ETH_DEBUG_L1
1190 Serial.print(millis());
1191 #if UIP_CONNECTION_TIMEOUT > 0
1192 Serial.print(F(
" UIPClient Re-Open TCP Window, time remaining before abort: "));
1196 u->restartInterval += 500;
1197 u->restartInterval = rf24_min(u->restartInterval, 7000);
1204 if (u->state & UIP_CLIENT_CLOSE)
1208 if (u->packets_out == 0)
1211 uip_conn->appstate = NULL;
1223 if (u->state & UIP_CLIENT_RESTART && !u->windowOpened)
1225 if (!(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1228 #if defined ETH_DEBUG_L1
1230 Serial.print(millis());
1231 Serial.println(F(
" UIPClient Re-Open TCP Window"));
1233 u->windowOpened =
true;
1235 u->restartTime = millis();
1243uip_userdata_t* RF24Client::_allocateData()
1245 for (uint8_t sock = 0; sock < UIP_CONNS; sock++)
1247 uip_userdata_t* data = &RF24Client::all_data[sock];
1250 data->state = sock | UIP_CLIENT_CONNECTED;
1251 data->packets_in = 0;
1252 data->packets_out = 0;
1257 data->restartTime = millis();
1258 data->restartInterval = 5000;
1259 #if (UIP_CONNECTION_TIMEOUT > 0)
1260 data->connectTimer = millis();
1272 uint32_t start = millis();
1275 if (millis() - start > timeout)
1292 return _available(data);
1295 return _available(data);
1302int RF24Client::_available(uip_userdata_t* u)
1304int RF24Client::_available(uint8_t* data)
1313 return dataSize[activeState];
1325 if (!data->packets_in)
1331 data->state |= UIP_CLIENT_CLOSE;
1336 size = rf24_min(data->dataCnt, size);
1337 memcpy(buf, &data->myData[data->in_pos], size);
1338 data->dataCnt -= size;
1340 data->in_pos += size;
1344 data->packets_in = 0;
1347 if (uip_stopped(&uip_conns[data->state & UIP_CLIENT_SOCKETS]) && !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1349 data->state |= UIP_CLIENT_RESTART;
1350 data->restartTime = 0;
1352 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(
"**")););
1356 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(
"**")););
1359 if (data->packets_in == 0)
1361 if (data->state & UIP_CLIENT_REMOTECLOSED)
1384 memcpy(&buf[0], &incomingData[
activeState][0], size);
1399 if (
read(&c, 1) < 0)
1411 return data->myData[data->in_pos];
1427 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)