RF24Ethernet - TCP/IP over RF24Network v2.2.0
TMRh20 - Pushing the practical limits of RF24 modules
Loading...
Searching...
No Matches
RF24Client.cpp
Go to the documentation of this file.
1/*
2 RF24Client.cpp - Arduino implementation of a uIP wrapper class.
3 Copyright (c) 2014 tmrh20@gmail.com, github.com/TMRh20
4 Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
5 All rights reserved.
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17#include "RF24Ethernet.h"
18
19#if USE_LWIP < 1
20
21 #define UIP_TCP_PHYH_LEN UIP_LLH_LEN + UIP_IPTCPH_LEN
22uip_userdata_t RF24Client::all_data[UIP_CONNS];
23
24#else
25// #define LWIP_ERR_T uint32_t
26
27 //
28 #if !defined ETHERNET_USING_LWIP_ARDUINO
29 #include <lwip/tcp.h>
30 #include "lwip/tcpip.h"
31 #include "lwip/timeouts.h"
32 #else
33 #include "lwip/include/lwip/tcp.h"
34 #include "lwip/include/lwip/tcpip.h"
35 #endif
36
37 #include "RF24Ethernet.h"
38/** \cond */
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;
48
49/***************************************************************************************************/
50
51// Called when the remote host acknowledges receipt of data
52err_t RF24Client::sent_callback(void* arg, struct tcp_pcb* tpcb, u16_t len)
53{
54
55 ConnectState* state = (ConnectState*)arg;
56 if (state != nullptr) {
57 state->serverTimer = millis();
58 state->clientTimer = millis();
59 IF_ETH_DEBUG_L1(Serial.println("Client: Sent cb"););
60
61 state->waiting_for_ack = false; // Data is successfully out
62 state->finished = true;
63 }
64
65 return ERR_OK;
66}
67
68/***************************************************************************************************/
69
70err_t RF24Client::blocking_write(struct tcp_pcb* fpcb, ConnectState* fstate, const char* data, size_t len)
71{
72
73 if (fpcb == nullptr) {
74 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Client: Tx with no fpcb"););
75 return ERR_CLSD;
76 }
77
78 if (!fstate->connected) {
79 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Client: Tx with no connection"););
80 return ERR_CLSD;
81 }
82
83 const uint32_t timeoutStart = millis();
84 while (len > tcp_sndbuf(fpcb)) {
85 Ethernet.update();
86 if (millis() - timeoutStart > serverConnectionTimeout) {
87 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Client: TCP Send Buffer full"););
88 return ERR_BUF;
89 }
90 }
91
92 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
93 if (Ethernet.useCoreLocking) {
94 ETHERNET_APPLY_LOCK();
95 }
96 #endif
97
98 err_t err = ERR_CLSD;
99 if (fpcb != nullptr) {
100 err = tcp_write(fpcb, data, len, TCP_WRITE_FLAG_COPY);
101 }
102
103 //Ethernet.update();
104 if (err != ERR_OK) {
105 if (fstate != nullptr) {
106 fstate->waiting_for_ack = false;
107 fstate->finished = true;
108 }
109 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Client: BLK Write fail 2: "); Serial.println((int)err););
110
111 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
112 if (Ethernet.useCoreLocking) {
113 ETHERNET_REMOVE_LOCK();
114 }
115 #endif
116 return err;
117 }
118
119 if (fpcb != nullptr && fpcb->state != CLOSED && fstate->connected) {
120 tcp_sent(fpcb, sent_callback);
121 }
122 else {
123 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Client: TCP OUT FAIL"););
124
125 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
126 if (Ethernet.useCoreLocking) {
127 ETHERNET_REMOVE_LOCK();
128 }
129 #endif
130 return ERR_BUF;
131 }
132 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
133 if (Ethernet.useCoreLocking) {
134 ETHERNET_REMOVE_LOCK();
135 }
136 #endif
137
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;
143 return ERR_CLSD;
144 }
145 break;
146 }
147 Ethernet.update();
148 }
149
150 return ERR_OK;
151}
152
153/***************************************************************************************************/
154
155void RF24Client::error_callback(void* arg, err_t err)
156{
157
158 ConnectState* state = (ConnectState*)arg;
159 if (state != nullptr) {
160 state->result = err;
161 state->connected = false;
162 state->finished = true; // Break the blocking loop
163 state->waiting_for_ack = false;
164 dataSize[state->stateActiveID] = 0;
165 if (state->stateActiveID == activeState) {
166 myPcb = nullptr;
167 }
168 }
169 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Client: Err cb: "); Serial.println((int)err););
170}
171
172/***************************************************************************************************/
173
174err_t RF24Client::srecv_callback(void* arg, struct tcp_pcb* tpcb, struct pbuf* p, err_t err)
175{
176
177 ConnectState* state = (ConnectState*)arg;
178
179 if (state != nullptr) {
180 state->serverTimer = millis();
181 }
182
183 if (p == nullptr) {
184 if (state != nullptr) {
185 state->connected = false;
186 state->finished = true; // Break the loop
187 }
188 if (tpcb != nullptr) {
189 if (tcp_close(tpcb) != ERR_OK) {
190 tcp_abort(tpcb);
191 tpcb = nullptr;
192 if (state->stateActiveID == activeState) {
193 myPcb = nullptr;
194 }
195 return ERR_ABRT;
196 }
197 tpcb = nullptr;
198 if (state->stateActiveID == activeState) {
199 myPcb = nullptr;
200 }
201 }
202 return ERR_OK;
203 }
204 if (err != ERR_OK || state == nullptr) {
205 if (p)
206 pbuf_free(p);
207 return ERR_OK;
208 }
209
210 bool id = state->stateActiveID;
211 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Copy data to "); Serial.println(state->stateActiveID););
212
213 struct pbuf* q = p;
214 while (q != nullptr) {
215 const uint8_t* data = static_cast<const uint8_t*>(q->payload);
216 if (dataSize[id] + q->len < INCOMING_DATA_SIZE) {
217 memcpy(&incomingData[id][dataSize[id]], data, q->len);
218 dataSize[id] += q->len;
219 }
220 else {
221 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Server: srecv - Out of incoming buffer space"););
222 }
223 q = q->next;
224 }
225
226 if (tpcb != nullptr) {
227 tcp_recved(tpcb, p->tot_len);
228 }
229 if (p) {
230 pbuf_free(p);
231 }
232 return ERR_OK;
233}
234
235/***************************************************************************************************/
236
237err_t RF24Client::recv_callback(void* arg, struct tcp_pcb* tpcb, struct pbuf* p, err_t err)
238{
239
240 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Client: Recv cb"););
241
242 ConnectState* state = (ConnectState*)arg;
243 if (p == nullptr) {
244 if (state != nullptr) {
245 state->connected = false;
246 state->finished = true; // Break the loop
247 }
248 if (tpcb != nullptr) {
249 if (tcp_close(tpcb) != ERR_OK) {
250 tcp_abort(tpcb);
251 tpcb = nullptr;
252 if (state->stateActiveID == activeState) {
253 myPcb = nullptr;
254 }
255 return ERR_ABRT;
256 }
257 tpcb = nullptr;
258 if (state->stateActiveID == activeState) {
259 myPcb = nullptr;
260 }
261 }
262 return err;
263 }
264 if (err != ERR_OK || state == nullptr) {
265 if (p)
266 pbuf_free(p);
267 return err;
268 }
269
270 if (state != nullptr) {
271 state->clientTimer = millis();
272 }
273
274 bool id = state->stateActiveID;
275 struct pbuf* q = p;
276 while (q != nullptr) {
277 const uint8_t* data = static_cast<const uint8_t*>(q->payload);
278 if (dataSize[id] + q->len < INCOMING_DATA_SIZE) {
279 memcpy(&incomingData[id][dataSize[id]], data, q->len);
280 dataSize[id] += q->len;
281 }
282 else {
283 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Client: recv - Out of incoming buffer space"););
284 }
285 q = q->next;
286 }
287
288 if (tpcb != nullptr) {
289 tcp_recved(tpcb, p->tot_len);
290 }
291 if (p) {
292 pbuf_free(p);
293 }
294 return ERR_OK;
295}
296
297/***************************************************************************************************/
298
299//void RF24Client::setConnectionTimeout(uint32_t timeout)
300//{
301
302// clientConnectionTimeout = timeout;
303//}
304
305/***************************************************************************************************/
306
307err_t RF24Client::clientTimeouts(void* arg, struct tcp_pcb* tpcb)
308{
309
310 ConnectState* state = (ConnectState*)arg;
311
312 if (state != nullptr) {
313 if (millis() - state->clientTimer > state->cConnectionTimeout) {
314 if (tpcb->state == ESTABLISHED || tpcb->state == SYN_SENT || tpcb->state == SYN_RCVD) {
315 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Client: Closed Client PCB TIMEOUT"););
316 err_t err = tcp_close(tpcb);
317 state->result = err;
318 state->connected = false;
319 state->finished = true; // Break the blocking loop
320 state->waiting_for_ack = false;
321 }
322 }
323 }
324 return ERR_OK;
325}
326
327/***************************************************************************************************/
328
329err_t RF24Client::serverTimeouts(void* arg, struct tcp_pcb* tpcb)
330{
331
332 ConnectState* state = (ConnectState*)arg;
333
334 if (state != nullptr && tpcb != nullptr) {
335 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Stimeout cb "); Serial.println(millis() - state->serverTimer););
336
337 state->result = ERR_OK;
338
339 if (millis() - state->serverTimer > state->sConnectionTimeout && state->backlogWasClosed == false) {
340 //if (tpcb->state == ESTABLISHED || tpcb->state == SYN_SENT || tpcb->state == SYN_RCVD) {
341 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Server: Closed Server PCB TIMEOUT "););
342
343 state->result = tcp_close(tpcb);
344 state->closeTimer = millis();
345 state->backlogWasClosed = true;
346 dataSize[activeState] = 0;
347 state->connected = false;
348 state->finished = true;
349 if (state->result != ERR_OK) {
350 tcp_arg(tpcb, nullptr);
351 tcp_abort(tpcb);
352 tpcb = nullptr;
353 myPcb = nullptr;
354 return ERR_ABRT;
355 }
356 myPcb = nullptr;
357 return state->result;
358
359 // }
360 }
361 if (state->backlogWasClosed == true) {
362 if (millis() - state->closeTimer > 5000) {
363 tcp_arg(tpcb, nullptr);
364 tcp_abort(tpcb);
365 tpcb = nullptr;
366 myPcb = nullptr;
367 return ERR_ABRT;
368 }
369 }
370 return state->result;
371 }
372 return ERR_CLSD;
373}
374
375/***************************************************************************************************/
376
377err_t RF24Client::closed_port(void* arg, struct tcp_pcb* tpcb)
378{
379
380 ConnectState* state = (ConnectState*)arg;
381
382 if (state != nullptr) {
383 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Client Poll Cb ID: "); Serial.println(state->identifier));
384 }
385
386 if (myPcb == nullptr) {
387 if (state != nullptr && tpcb != nullptr) {
388
389 if ((tpcb->state == ESTABLISHED || tpcb->state == SYN_SENT || tpcb->state == SYN_RCVD)) {
390 if (state->backlogWasAccepted == false && state->backlogWasClosed == false) {
391
392 state->backlogWasAccepted = true;
393 state->connectTimestamp = millis();
394 state->connected = true;
395 state->finished = false;
396 accepts--;
397 myPcb = tpcb;
398 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: ACCEPT delayed PCB "); Serial.println(state->identifier););
399
400 tcp_backlog_accepted(tpcb);
401 activeState = state->stateActiveID;
402 return ERR_OK;
403 }
404 }
405 }
406 }
407
408 if (tpcb != nullptr) {
409 if (state != nullptr) {
410 if (millis() - state->connectTimestamp > state->sConnectionTimeout) {
411
412 if ((tpcb->state == ESTABLISHED || tpcb->state == SYN_SENT || tpcb->state == SYN_RCVD)) {
413 if (state->backlogWasClosed == false) {
414
415 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Close off delayed PCB function 1, ID: "); Serial.println(state->identifier););
416
417 if (state->backlogWasAccepted == false) {
418 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Server: With backlog accepted"););
419 tcp_backlog_accepted(tpcb);
420 state->backlogWasAccepted = true;
421 accepts--;
422 }
423
424 state->result = tcp_close(tpcb);
425 state->backlogWasClosed = true;
426 if (state->result == ERR_OK) {
427 state->closeTimer = millis();
428 state->finished = true;
429 }
430 else {
431 tcp_abort(tpcb);
432 tpcb = nullptr;
433 return ERR_ABRT;
434 }
435
436 return state->result;
437 }
438 else {
439 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Killing off TPCB already closed function 1, ID: "););
440
441 if (state != nullptr) {
442 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(state->identifier););
443 }
444 if (millis() - state->closeTimer > 5000) {
445 tcp_abort(tpcb);
446 tpcb = nullptr;
447 return ERR_ABRT;
448 }
449 }
450 }
451 }
452 }
453 }
454 if (tpcb != nullptr) {
455 if (state != nullptr) {
456 if (millis() - state->connectTimestamp > state->sConnectionTimeout) {
457 if (state->backlogWasClosed == false) {
458 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Close off delayed PCB function 2, ID "); Serial.println(state->identifier););
459 if (state->backlogWasAccepted == false) {
460 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Server: With backlog accepted"););
461 tcp_backlog_accepted(tpcb);
462 state->backlogWasAccepted = true;
463 accepts--;
464 }
465 state->result = tcp_close(tpcb);
466 state->backlogWasClosed = true;
467 if (state->result == ERR_OK) {
468 state->closeTimer = millis();
469 state->finished = true;
470 }
471 else {
472 tcp_abort(tpcb);
473 tpcb = nullptr;
474 return ERR_ABRT;
475 }
476 return state->result;
477 }
478 else {
479 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Killing off TPCB already closed function 2, ID: "););
480 if (state != nullptr) {
481 Serial.println(state->identifier);
482 if (millis() - state->closeTimer > 5000) {
483 tcp_abort(tpcb);
484 tpcb = nullptr;
485 return ERR_ABRT;
486 }
487 }
488 }
489 }
490 }
491 }
492
493 return ERR_OK;
494}
495
496/**************************************************************************************************/
497
498err_t RF24Client::accept(void* arg, struct tcp_pcb* tpcb, err_t err)
499{
500 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Accept cb, ID: "); Serial.println(simpleCounter + 1););
501
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))););
504 return ERR_CLSD;
505 }
506
507 if (tpcb != nullptr) {
508 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Client connect from: "); Serial.println(ip4addr_ntoa(ip_2_ip4(&tpcb->remote_ip))););
509 }
510 bool actState = activeState;
511
512 if (myPcb != nullptr) {
513
514 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Accept w/already connected: Accepted_Conns - Delayed_Conns == "); Serial.println(accepts););
515 tcp_backlog_delayed(tpcb);
516 accepts++;
517 tcp_poll(tpcb, closed_port, 5);
518 actState = !activeState;
519 gState[actState]->connected = false;
520 gState[actState]->backlogWasAccepted = false;
521 }
522 else {
523 myPcb = tpcb;
524 tcp_poll(tpcb, serverTimeouts, 8);
526 actState = activeState;
527 gState[actState]->connected = true;
528 gState[actState]->backlogWasAccepted = true;
529 }
530
531 dataSize[actState] = 0;
532
533 simpleCounter += 1;
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();
542
543 tcp_arg(tpcb, RF24Client::gState[actState]);
544 tcp_recv(tpcb, srecv_callback);
545 tcp_sent(tpcb, sent_callback);
546 tcp_err(tpcb, error_callback);
547
548 return ERR_OK;
549}
550
551/***************************************************************************************************/
552err_t RF24Client::closeConn(void* arg, struct tcp_pcb* tpcb)
553{
554 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Client: Immediate close"););
555 if (tpcb != nullptr) {
556 tcp_close(tpcb);
557 }
558
559 return ERR_OK;
560}
561
562/***************************************************************************************************/
563
564// Callback triggered by lwIP when handshake completes
565
566err_t RF24Client::on_connected(void* arg, struct tcp_pcb* tpcb, err_t err)
567{
568 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Client: Conn cb"););
569
570 ConnectState* state = (ConnectState*)arg;
571
572 if (state != nullptr) {
573 /*if (state->cConnectionTimeout > 0) {
574 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
575 if(Ethernet.useCoreLocking){if(Ethernet.useCoreLocking){ ETHERNET_APPLY_LOCK(); } }
576 #endif
577 tcp_poll(tpcb, clientTimeouts, 30);
578 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
579 if(Ethernet.useCoreLocking){ ETHERNET_REMOVE_LOCK(); }
580 #endif
581 }*/
582
583 state->cConnectionTimeout = clientConnectionTimeout;
584 state->clientTimer = millis();
585 state->result = err;
586 state->finished = true;
587 if (err == ERR_OK) {
588 state->connected = true;
589 }
590 else {
591 state->connected = false;
592 }
593 state->waiting_for_ack = false;
594 }
595 return err;
596}
597/** \endcond */
598#endif // USE_LWIP > 1
599
600/***************************************************************************************************/
601
602#if USE_LWIP < 1
603RF24Client::RF24Client() : data(NULL)
604{
605}
606#else
608{
609}
610
611#endif
612/*************************************************************/
613
614#if USE_LWIP < 1
615RF24Client::RF24Client(uip_userdata_t* conn_data) : data(conn_data)
616{
617}
618#else
619/** \cond */
620RF24Client::RF24Client(uint32_t data) : data(0)
621{
622}
623/** \endcond */
624#endif
625/*************************************************************/
626
628{
629#if USE_LWIP < 1
630 return (data && (data->packets_in != 0 || (data->state & UIP_CLIENT_CONNECTED))) ? 1 : 0;
631#else
632 if (gState[activeState] != nullptr) {
633 return gState[activeState]->connected;
634 }
635 return 0;
636#endif
637}
638
639/*************************************************************/
640
641int RF24Client::connect(IPAddress ip, uint16_t port)
642{
643
644#if USE_LWIP < 1
645 #if UIP_ACTIVE_OPEN > 0
646
647 // do{
648
649 stop();
650 uip_ipaddr_t ipaddr;
651 uip_ip_addr(ipaddr, ip);
652
653 struct uip_conn* conn = uip_connect(&ipaddr, htons(port));
654
655 if (conn)
656 {
657 #if UIP_CONNECTION_TIMEOUT > 0
658 uint32_t timeout = millis();
659 #endif
660
661 while ((conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED)
662 {
663 Ethernet.update();
664
665 if ((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED)
666 {
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););
669 return 1;
670 }
671
672 #if UIP_CONNECTION_TIMEOUT > 0
673 if ((millis() - timeout) > UIP_CONNECTION_TIMEOUT)
674 {
675 conn->tcpstateflags = UIP_CLOSED;
676 break;
677 }
678 #endif
679 }
680 }
681 // delay(25);
682 // }while(millis()-timer < 175);
683
684 #endif // Active open enabled
685#else
686
687 if (myPcb != nullptr) {
688 _stop();
689 return ERR_CLSD;
690 }
691
692 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
693 if (Ethernet.useCoreLocking) {
694 ETHERNET_APPLY_LOCK();
695 }
696 #endif
697
698 if (myPcb == nullptr) {
699 myPcb = tcp_new();
700 }
701
702 if (!myPcb) {
703 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
704 if (Ethernet.useCoreLocking) {
705 ETHERNET_REMOVE_LOCK();
706 }
707 #endif
708 return 0;
709 }
710
711 dataSize[activeState] = 0;
712 memset(incomingData[activeState], 0, INCOMING_DATA_SIZE);
713
714 gState[activeState]->finished = false;
715 gState[activeState]->connected = false;
716 gState[activeState]->result = 0;
717 gState[activeState]->waiting_for_ack = false;
718
719 tcp_arg(myPcb, gState[activeState]);
720 tcp_err(myPcb, error_callback);
721 tcp_recv(myPcb, recv_callback);
722 //tcp_poll(myPcb, clientTimeouts, 30);
723
724 err_t err = ERR_OK;
725
726 ip_addr_t myIp;
727 IP_ADDR4(&myIp, ip[0], ip[1], ip[2], ip[3]);
728
729 err = tcp_connect(myPcb, &myIp, port, on_connected);
730
731 if (err != ERR_OK || gState[activeState]->result != ERR_OK) {
732 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
733 if (Ethernet.useCoreLocking) {
734 ETHERNET_REMOVE_LOCK();
735 }
736 #endif
737
738 stop();
739 return ERR_CLSD;
740 }
741
742 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
743 if (Ethernet.useCoreLocking) {
744 ETHERNET_REMOVE_LOCK();
745 }
746 #endif
747
748 const uint32_t timeoutStart = millis();
749 // Simulate blocking by looping until the callback sets 'finished'
750 while (!gState[activeState]->finished && millis() - timeoutStart < 5000) {
751 Ethernet.update();
752 }
753
754 if (clientConnectionTimeout > 0) {
755 gState[activeState]->clientPollingSetup = 1;
756 }
757
758 return gState[activeState]->connected;
759
760#endif
761 return 0;
762}
763
764/*************************************************************/
765
766#if USE_LWIP > 1
767void dnsCallback(const char* name, const ip_addr_t* ipaddr, void* callback_arg)
768{
769}
770#endif
771/*************************************************************/
772
773int RF24Client::connect(const char* host, uint16_t port)
774{
775 // Look up the host first
776 int ret = 0;
777
778#if UIP_UDP
779 DNSClient dns;
780 IPAddress remote_addr;
781
782 dns.begin(RF24EthernetClass::_dnsServerAddress);
783 ret = dns.getHostByName(host, remote_addr);
784
785 if (ret == 1)
786 {
787 #if defined(ETH_DEBUG_L1) || defined(RF24ETHERNET_DEBUG_DNS)
788 Serial.println(F("*UIP Got DNS*"));
789 #endif
790 return connect(remote_addr, port);
791 }
792#elif RF24ETHERNET_USE_UDP
793
794 DNSClient dns;
795 IPAddress remote_addr;
796
797 dns.begin(RF24EthernetClass::_dnsServerAddress);
798 ret = dns.getHostByName(host, remote_addr);
799
800 if (ret == 1)
801 {
802 #if defined(ETH_DEBUG_L1) || defined(RF24ETHERNET_DEBUG_DNS)
803 Serial.println(F("*lwIP Got DNS*"));
804 #endif
805 return connect(remote_addr, port);
806 }
807
808#else // ! UIP_UDP
809 // Do something with the input parameters to prevent compile time warnings
810 if (host) {
811 };
812 if (port) {
813 };
814#endif // ! UIP_UDP
815
816#if defined(ETH_DEBUG_L1) || defined(RF24ETHERNET_DEBUG_DNS)
817 Serial.println(F("* DNS fail*"));
818#endif
819
820 return ret;
821}
822
823/*************************************************************/
824
826{
827#if USE_LWIP < 1
828 if (data && data->state)
829 {
830
831 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print(millis()); Serial.println(F(" before stop(), with data")););
832
833 data->packets_in = 0;
834 data->dataCnt = 0;
835
836 if (data->state & UIP_CLIENT_REMOTECLOSED)
837 {
838 data->state = 0;
839 }
840 else
841 {
842 data->state |= UIP_CLIENT_CLOSE;
843 }
844
845 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(F("after stop()")););
846 }
847 else
848 {
849 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print(millis()); Serial.println(F(" stop(), data: NULL")););
850 }
851
852 data = NULL;
853 RF24Ethernet.update();
854#else
855
856 _stop();
857
858#endif
859}
860
861/***************************************************************************************************/
862#if USE_LWIP > 0
863void RF24Client::_stop()
864{
865 tcp_pcb* pcb = myPcb;
866 myPcb = nullptr;
867
868 if (pcb != nullptr) {
869 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
870 if (Ethernet.useCoreLocking) {
871 ETHERNET_APPLY_LOCK();
872 }
873 #endif
874 if (pcb->state != CLOSED) {
875 tcp_arg(pcb, NULL);
876 tcp_recv(pcb, NULL);
877 tcp_sent(pcb, NULL);
878 tcp_err(pcb, NULL);
879
880 err_t err = tcp_close(pcb);
881 if (err != ERR_OK) {
882 tcp_abort(pcb);
883 }
884 }
885 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
886 if (Ethernet.useCoreLocking) {
887 ETHERNET_REMOVE_LOCK();
888 }
889 #endif
890 }
891
892 gState[activeState]->connected = false;
893 gState[activeState]->finished = true;
894 dataSize[activeState] = 0;
895}
896#endif
897/*************************************************************/
898
899// the next function allows us to use the client returned by
900// EthernetServer::available() as the condition in an if-statement.
902{
903#if USE_LWIP < 1
904 return data && rhs.data && (data == rhs.data);
905#else
906 return dataSize[activeState] > 0 ? true : false;
907#endif
908}
909
910/*************************************************************/
911
912RF24Client::operator bool()
913{
914 Ethernet.update();
915#if USE_LWIP < 1
916 return data && (!(data->state & UIP_CLIENT_REMOTECLOSED) || data->packets_in != 0);
917#else
918 return dataSize[activeState] > 0 ? true : false;
919#endif
920}
921
922/*************************************************************/
923
924size_t RF24Client::write(uint8_t c)
925{
926 return _write(data, &c, 1);
927}
928
929/*************************************************************/
930
931size_t RF24Client::write(const uint8_t* buf, size_t size)
932{
933 return _write(data, buf, size);
934}
935
936/*************************************************************/
937#if USE_LWIP < 1
938size_t RF24Client::_write(uip_userdata_t* u, const uint8_t* buf, size_t size)
939#else
940size_t RF24Client::_write(uint8_t* data, const uint8_t* buf, size_t size)
941
942#endif
943
944{
945
946#if USE_LWIP < 1
947 size_t total_written = 0;
948 size_t payloadSize = rf24_min(size, UIP_TCP_MSS);
949 uint32_t start = millis();
950
951test2:
952
953 Ethernet.update();
954
955 if (millis() - start > 5000)
956 {
957 if (u) {
958 u->hold = false;
959 }
960 return total_written;
961 }
962
963 if (u && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)) && (u->state & UIP_CLIENT_CONNECTED))
964 {
965 if (u->out_pos + payloadSize > UIP_TCP_MSS || u->hold)
966 {
967 goto test2;
968 }
969
971 Serial.println();
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("'")););
982
983 memcpy(u->myData + u->out_pos, buf + total_written, payloadSize);
984 u->packets_out = 1;
985 u->out_pos += payloadSize;
986 total_written += payloadSize;
987
988 if (total_written < size)
989 {
990 size_t remain = size - total_written;
991 payloadSize = rf24_min(remain, UIP_TCP_MSS);
992 goto test2;
993 }
994
995 u->hold = false;
996 return u->out_pos;
997 }
998
999 if (u) {
1000 u->hold = false;
1001 }
1002 return 0;
1003#else
1004
1005 bool initialActiveState = activeState;
1006 size_t chunk = MAX_PAYLOAD_SIZE - 14; // 14 = Ethernet/link-layer header bytes reserved per frame
1007 size_t position = 0;
1008
1009 while (size > chunk) {
1010 if (myPcb == nullptr)
1011 return 0;
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;
1017 _stop();
1018 return 0;
1019 }
1020 position += chunk;
1021 size -= chunk;
1022 Ethernet.update();
1023 }
1024
1025 if (myPcb == nullptr)
1026 return 0;
1027 gState[initialActiveState]->waiting_for_ack = true;
1028 err_t write_err = blocking_write(myPcb, gState[initialActiveState], reinterpret_cast<const char*>(&buf[position]), size);
1029
1030 if (write_err != ERR_OK) {
1031 gState[initialActiveState]->result = write_err;
1032 gState[initialActiveState]->connected = false;
1033 _stop();
1034 return 0;
1035 }
1036
1037 return position + size;
1038#endif
1039}
1040
1041/*************************************************************/
1042
1043void uip_log(char* msg)
1044{
1045 // Serial.println();
1046 // Serial.println("** UIP LOG **");
1047 // Serial.println(msg);
1048 if (msg)
1049 {
1050 };
1051}
1052
1053/*************************************************************/
1054#if USE_LWIP < 1
1055void serialip_appcall(void)
1056{
1057 uip_userdata_t* u = (uip_userdata_t*)uip_conn->appstate;
1058
1059 /*******Connected**********/
1060 if (!u && uip_connected())
1061 {
1062 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(); Serial.print(millis()); Serial.println(F(" UIPClient uip_connected")););
1063
1064 u = (uip_userdata_t*)EthernetClient::_allocateData();
1065
1066 if (u)
1067 {
1068 uip_conn->appstate = u;
1069 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print(F("UIPClient allocated state: ")); Serial.println(u->state, BIN););
1070 }
1071 else
1072 {
1073 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(F("UIPClient allocation failed")););
1074 }
1075 }
1076
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();
1082 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(); Serial.print(millis()); Serial.println("UIP Client close(timeout)"););
1083 }
1084 }
1085 #endif
1086
1087 /*******User Data RX**********/
1088 if (u)
1089 {
1090 if (uip_newdata())
1091 {
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();
1095 #endif
1096 u->hold = (u->out_pos = (u->windowOpened = (u->packets_out = false)));
1097
1098 if (uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1099 {
1100 uip_stop();
1101 u->state &= ~UIP_CLIENT_RESTART;
1102 u->windowOpened = false;
1103 u->restartTime = millis();
1104
1105 uint16_t writePos = u->in_pos + u->dataCnt;
1106 uint16_t incomingLen = uip_datalen();
1107
1108 if (writePos <= OUTPUT_BUFFER_SIZE && incomingLen <= (OUTPUT_BUFFER_SIZE - writePos))
1109 {
1110 memcpy(&u->myData[writePos], uip_appdata, incomingLen);
1111 u->dataCnt += incomingLen;
1112 u->packets_in = 1;
1113 }
1114 else
1115 {
1117 Serial.println(F("UIPClient RX overflow, closing connection")););
1118 u->state |= UIP_CLIENT_CLOSE;
1119 }
1120 }
1121 goto finish;
1122 }
1123
1124 /*******Closed/Timed-out/Aborted**********/
1125 // If the connection has been closed, save received but unread data.
1126 if (uip_closed() || uip_timedout() || uip_aborted())
1127 {
1128 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(); Serial.print(millis()); Serial.println(F(" UIPClient uip_closed")););
1129 // drop outgoing packets not sent yet:
1130 u->packets_out = 0;
1131
1132 if (u->packets_in)
1133 {
1134 ((uip_userdata_closed_t*)u)->lport = uip_conn->lport;
1135 u->state |= UIP_CLIENT_REMOTECLOSED;
1136 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(F("UIPClient close 1")););
1137 }
1138 else
1139 {
1140 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(F("UIPClient close 2")););
1141 u->state = 0;
1142 }
1143
1144 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(F("after UIPClient uip_closed")););
1145 uip_conn->appstate = NULL;
1146 goto finish;
1147 }
1148
1149 /*******ACKED**********/
1150 if (uip_acked())
1151 {
1152 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(); Serial.print(millis()); Serial.println(F(" UIPClient uip_acked")););
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();
1158 #endif
1159 }
1160
1161 /*******Polling**********/
1162 if (uip_poll() || uip_rexmit())
1163 {
1164 if (uip_rexmit()) {
1165 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print(F("ReXmit, Len: ")););
1166 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(u->out_pos));
1167 uip_len = u->out_pos;
1168 uip_send(u->myData, u->out_pos);
1169 u->hold = true;
1170 goto finish;
1171 }
1172 // IF_RF24ETHERNET_DEBUG_CLIENT( Serial.println(); Serial.println(F("UIPClient uip_poll")); );
1173
1174 if (u->packets_out != 0 && !u->hold)
1175 {
1176 uip_len = u->out_pos;
1177 uip_send(u->myData, u->out_pos);
1178 u->hold = true;
1179 goto finish;
1180 }
1181
1182 // Restart mechanism to keep connections going
1183 // Only call this if the TCP window has already been re-opened, the connection is being polled, but no data
1184 // has been acked
1185 if (!(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1186 {
1187
1188 if (u->windowOpened == true && u->state & UIP_CLIENT_RESTART && millis() - u->restartTime > u->restartInterval)
1189 {
1190 u->restartTime = millis();
1191 #if defined RF24ETHERNET_DEBUG_CLIENT || defined ETH_DEBUG_L1
1192 Serial.println();
1193 Serial.print(millis());
1194 #if UIP_CONNECTION_TIMEOUT > 0
1195 Serial.print(F(" UIPClient Re-Open TCP Window, time remaining before abort: "));
1196 Serial.println(UIP_CONNECTION_TIMEOUT - (millis() - u->connectTimer));
1197 #endif
1198 #endif
1199 u->restartInterval += 500;
1200 u->restartInterval = rf24_min(u->restartInterval, 7000);
1201 uip_restart();
1202 }
1203 }
1204 }
1205
1206 /*******Close**********/
1207 if (u->state & UIP_CLIENT_CLOSE)
1208 {
1209 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(); Serial.print(millis()); Serial.println(F(" UIPClient state UIP_CLIENT_CLOSE")););
1210
1211 if (u->packets_out == 0)
1212 {
1213 u->state = 0;
1214 uip_conn->appstate = NULL;
1215 uip_close();
1216 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(F("no blocks out -> free userdata")););
1217 }
1218 else
1219 {
1220 uip_stop();
1221 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(F("blocks outstanding transfer -> uip_stop()")););
1222 }
1223 }
1224finish:;
1225
1226 if (u->state & UIP_CLIENT_RESTART && !u->windowOpened)
1227 {
1228 if (!(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1229 {
1230 uip_restart();
1231 #if defined ETH_DEBUG_L1
1232 Serial.println();
1233 Serial.print(millis());
1234 Serial.println(F(" UIPClient Re-Open TCP Window"));
1235 #endif
1236 u->windowOpened = true;
1237 u->restartInterval = UIP_WINDOW_REOPEN_DELAY; //.75 seconds
1238 u->restartTime = millis();
1239 }
1240 }
1241 }
1242}
1243#endif
1244/*******************************************************/
1245#if USE_LWIP < 1
1246uip_userdata_t* RF24Client::_allocateData()
1247{
1248 for (uint8_t sock = 0; sock < UIP_CONNS; sock++)
1249 {
1250 uip_userdata_t* data = &RF24Client::all_data[sock];
1251 if (!data->state)
1252 {
1253 data->state = sock | UIP_CLIENT_CONNECTED;
1254 data->packets_in = 0;
1255 data->packets_out = 0;
1256 data->dataCnt = 0;
1257 data->in_pos = 0;
1258 data->out_pos = 0;
1259 data->hold = 0;
1260 data->restartTime = millis();
1261 data->restartInterval = 5000;
1262 #if (UIP_CONNECTION_TIMEOUT > 0)
1263 data->connectTimer = millis();
1264 data->connectTimeout = UIP_CONNECTION_TIMEOUT;
1265 #endif
1266 return data;
1267 }
1268 }
1269 return NULL;
1270}
1271#endif
1272
1273int RF24Client::waitAvailable(uint32_t timeout)
1274{
1275 uint32_t start = millis();
1276 while (available() < 1)
1277 {
1278 if (millis() - start > timeout)
1279 {
1280 return 0;
1281 }
1282 RF24Ethernet.update();
1283 }
1284 return available();
1285}
1286
1287/*************************************************************/
1288
1290{
1291 RF24Ethernet.update();
1292#if USE_LWIP < 1
1293 if (*this)
1294 {
1295 return _available(data);
1296 }
1297#else
1298 return _available(data);
1299#endif
1300 return 0;
1301}
1302
1303/*************************************************************/
1304#if USE_LWIP < 1
1305int RF24Client::_available(uip_userdata_t* u)
1306#else
1307int RF24Client::_available(uint8_t* data)
1308#endif
1309{
1310#if USE_LWIP < 1
1311 if (u->packets_in)
1312 {
1313 return u->dataCnt;
1314 }
1315#else
1316 return dataSize[activeState];
1317#endif
1318 return 0;
1319}
1320
1321/*************************************************************/
1322
1323int RF24Client::read(uint8_t* buf, size_t size)
1324{
1325#if USE_LWIP < 1
1326 if (*this)
1327 {
1328 if (!data->packets_in)
1329 {
1330 return -1;
1331 }
1332 if (data->in_pos > OUTPUT_BUFFER_SIZE || data->dataCnt > OUTPUT_BUFFER_SIZE || (data->in_pos + data->dataCnt) > OUTPUT_BUFFER_SIZE)
1333 {
1334 data->state |= UIP_CLIENT_CLOSE;
1335 data->in_pos = 0;
1336 data->dataCnt = 0;
1337 return -1;
1338 }
1339 size = rf24_min(data->dataCnt, size);
1340 memcpy(buf, &data->myData[data->in_pos], size);
1341 data->dataCnt -= size;
1342
1343 data->in_pos += size;
1344
1345 if (!data->dataCnt)
1346 {
1347 data->packets_in = 0;
1348 data->in_pos = 0;
1349
1350 if (uip_stopped(&uip_conns[data->state & UIP_CLIENT_SOCKETS]) && !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1351 {
1352 data->state |= UIP_CLIENT_RESTART;
1353 data->restartTime = 0;
1354
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("**")););
1356 }
1357 else
1358 {
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("**")););
1360 }
1361
1362 if (data->packets_in == 0)
1363 {
1364 if (data->state & UIP_CLIENT_REMOTECLOSED)
1365 {
1366 data->state = 0;
1367 data = NULL;
1368 }
1369 }
1370 }
1371 return size;
1372 }
1373
1374 return -1;
1375#else
1376
1377 if (available()) {
1378
1379 if (size >= dataSize[activeState]) {
1380 memcpy(&buf[0], &incomingData[activeState][0], dataSize[activeState]);
1381 memmove(&incomingData[activeState][0], &incomingData[activeState][dataSize[activeState]], dataSize[activeState]);
1382 size = dataSize[activeState];
1383 dataSize[activeState] = 0;
1384 return size;
1385 }
1386 else {
1387 memcpy(&buf[0], &incomingData[activeState][0], size);
1388 memmove(&incomingData[activeState][0], &incomingData[activeState][size], dataSize[activeState] - size);
1389 dataSize[activeState] -= size;
1390 return size;
1391 }
1392 }
1393 return -1;
1394#endif
1395}
1396
1397/*************************************************************/
1398
1400{
1401 uint8_t c;
1402 if (read(&c, 1) < 0)
1403 return -1;
1404 return c;
1405}
1406
1407/*************************************************************/
1408
1410{
1411 if (available())
1412 {
1413#if USE_LWIP < 1
1414 return data->myData[data->in_pos];
1415#else
1416 return incomingData[activeState][0];
1417#endif
1418 }
1419 return -1;
1420}
1421
1422/*************************************************************/
1423
1425{
1426#if USE_LWIP < 1
1427 if (*this)
1428 {
1429 #if USE_LWIP < 1
1430 data->packets_in = 0;
1431 data->dataCnt = 0;
1432 #else
1433 data = 0;
1434 #endif
1435 }
1436#else
1437 dataSize[activeState] = 0;
1438#endif
1439}
void uip_log(char *msg)
volatile err_t result
Definition RF24Client.h:8
#define INCOMING_DATA_SIZE
Definition RF24Client.h:78
volatile bool finished
Definition RF24Client.h:0
RF24EthernetClass RF24Ethernet
void begin(const IPAddress &aDNSServer)
Definition Dns.cpp:45
int getHostByName(const char *aHostname, IPAddress &aResult)
Definition Dns.cpp:110
virtual bool operator==(const EthernetClient &)
size_t write(uint8_t)
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]
Definition RF24Client.h:218
static bool activeState
Definition RF24Client.h:233
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)
uint8_t connected()
#define Ethernet
#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
Definition uip-conf.h:90
#define OUTPUT_BUFFER_SIZE
Definition uip-conf.h:153
#define UIP_WINDOW_REOPEN_DELAY
Optional: Used with UIP_CONNECTION_TIMEOUT
Definition uip-conf.h:167
volatile bool stateActiveID
Definition RF24Client.h:205
uint16_t u16_t
16 bit datatype
Definition uip-conf.h:245
void serialip_appcall(void)