Subversion Repositories ESP8266_P1_Meter

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 raymond 1
/*
2
  Asynchronous TCP library for Espressif MCUs
3
 
4
  Copyright (c) 2016 Hristo Gochkov. All rights reserved.
5
  This file is part of the esp8266 core for Arduino environment.
6
 
7
  This library is free software; you can redistribute it and/or
8
  modify it under the terms of the GNU Lesser General Public
9
  License as published by the Free Software Foundation; either
10
  version 2.1 of the License, or (at your option) any later version.
11
 
12
  This library is distributed in the hope that it will be useful,
13
  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
  Lesser General Public License for more details.
16
 
17
  You should have received a copy of the GNU Lesser General Public
18
  License along with this library; if not, write to the Free Software
19
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20
*/
21
/*
22
Changes for July 2019
23
 
24
The operator "new ..." was changed to "new (std::nothrow) ...", which will
25
return NULL when the heap is out of memory. Without the change "soft WDT"
26
was the result, starting with Arduino ESP8266 Core 2.5.0. (Note, RE:"soft
27
WDT" - the error  reporting may improve with core 2.6.) With proir core
28
versions the library appears to work fine.
29
ref: https://github.com/esp8266/Arduino/issues/6269#issue-464978944
30
 
31
To support newer lwIP versions and buffer models. All references to 1460
32
were replaced with TCP_MSS. If TCP_MSS is not defined (exp. 1.4v lwIP)
33
1460 is assumed.
34
 
35
The ESPAsyncTCP library should build for Arduino ESP8266 Core releases:
36
2.3.0, 2.4.1, 2.4.2, 2.5.1, 2.5.2. It may still build with core versions
37
2.4.0 and 2.5.0. I did not do any regression testing with these, since
38
they had too many issues and were quickly superseded.
39
 
40
lwIP tcp_err() callback often resulted in crashes. The problem was a
41
tcp_err() would come in, while processing a send or receive in the
42
forground. The tcp_err() callback would be passed down to a client's
43
registered disconnect CB. A common problem with SyncClient and other
44
modules as well as some client code was: the freeing of ESPAsyncTCP
45
AsyncClient objects via disconnect CB handlers while the library was
46
waiting for an operstion to  finished. Attempts to access bad pointers
47
followed. For SyncClient this commonly occured during a call to delay().
48
On return to SyncClient _client was invalid. Also the problem described by
49
issue #94 also surfaced
50
 
51
Use of tcp_abort() required some very special handling and was very
52
challenging to make work without changing client API. ERR_ABRT can only be
53
used once on a return to lwIP for a given connection and since the
54
AsyncClient structure was sometimes deleted before returning to lwIP, the
55
state tracking became tricky. While ugly, a global variable for this
56
seemed to work; however, I  abanded it when I saw a possible
57
reentrancy/concurrency issue. After several approaches I settled the
58
problem by creating "class ACErrorTracker" to manage the issue.
59
 
60
 
61
Additional Async Client considerations:
62
 
63
The client sketch must always test if the connection is still up at loop()
64
entry and after the return of any function call, that may have done a
65
delay() or yield() or any ESPAsyncTCP library family call. For example,
66
the connection could be lost during a call to _client->write(...). Client
67
sketches that delete _client as part of their onDisconnect() handler must
68
be very careful as _client will become invalid after calls to delay(),
69
yield(), etc.
70
 
71
 
72
 */
73
 
74
#include "Arduino.h"
75
 
76
#include "ESPAsyncTCP.h"
77
extern "C"{
78
  #include "lwip/opt.h"
79
  #include "lwip/tcp.h"
80
  #include "lwip/inet.h"
81
  #include "lwip/dns.h"
82
  #include "lwip/init.h"
83
}
84
#include <tcp_axtls.h>
85
 
86
/*
87
  Async Client Error Return Tracker
88
*/
89
// Assumption: callbacks are never called with err == ERR_ABRT; however,
90
// they may return ERR_ABRT.
91
 
92
ACErrorTracker::ACErrorTracker(AsyncClient *c):
93
    _client(c)
94
  , _close_error(ERR_OK)
95
  , _errored(EE_OK)
96
#ifdef DEBUG_MORE
97
  , _error_event_cb(NULL)
98
  , _error_event_cb_arg(NULL)
99
#endif
100
{}
101
 
102
#ifdef DEBUG_MORE
103
/**
104
 * This is not necessary, but a start at gathering some statistics on
105
 * errored out connections. Used from AsyncServer.
106
 */
107
void ACErrorTracker::onErrorEvent(AsNotifyHandler cb, void *arg) {
108
  _error_event_cb = cb;
109
  _error_event_cb_arg = arg;
110
}
111
#endif
112
 
113
void ACErrorTracker::setCloseError(err_t e) {
114
  if (e != ERR_OK)
115
    ASYNC_TCP_DEBUG("setCloseError() to: %s(%ld)\n", _client->errorToString(e), e);
116
  if(_errored == EE_OK)
117
    _close_error = e;
118
}
119
/**
120
 * Called mainly by callback routines, called when err is not ERR_OK.
121
 * This prevents the possiblity of aborting an already errored out
122
 * connection.
123
 */
124
void ACErrorTracker::setErrored(size_t errorEvent){
125
  if(EE_OK == _errored)
126
    _errored = errorEvent;
127
#ifdef DEBUG_MORE
128
  if (_error_event_cb)
129
    _error_event_cb(_error_event_cb_arg, errorEvent);
130
#endif
131
}
132
/**
133
 * Used by callback functions only. Used for proper ERR_ABRT return value
134
 * reporting. ERR_ABRT is only reported/returned once; thereafter ERR_OK
135
 * is always returned.
136
 */
137
err_t ACErrorTracker::getCallbackCloseError(void){
138
  if (EE_OK != _errored)
139
    return ERR_OK;
140
  if (ERR_ABRT == _close_error)
141
    setErrored(EE_ABORTED);
142
  return _close_error;
143
}
144
 
145
/*
146
  Async TCP Client
147
*/
148
#if DEBUG_ESP_ASYNC_TCP
149
static size_t _connectionCount=0;
150
#endif
151
 
152
#if ASYNC_TCP_SSL_ENABLED
153
AsyncClient::AsyncClient(tcp_pcb* pcb, SSL_CTX * ssl_ctx):
154
#else
155
AsyncClient::AsyncClient(tcp_pcb* pcb):
156
#endif
157
  _connect_cb(0)
158
  , _connect_cb_arg(0)
159
  , _discard_cb(0)
160
  , _discard_cb_arg(0)
161
  , _sent_cb(0)
162
  , _sent_cb_arg(0)
163
  , _error_cb(0)
164
  , _error_cb_arg(0)
165
  , _recv_cb(0)
166
  , _recv_cb_arg(0)
167
  , _pb_cb(0)
168
  , _pb_cb_arg(0)
169
  , _timeout_cb(0)
170
  , _timeout_cb_arg(0)
171
  , _poll_cb(0)
172
  , _poll_cb_arg(0)
173
  , _pcb_busy(false)
174
#if ASYNC_TCP_SSL_ENABLED
175
  , _pcb_secure(false)
176
  , _handshake_done(true)
177
#endif
178
  , _pcb_sent_at(0)
179
  , _close_pcb(false)
180
  , _ack_pcb(true)
181
  , _tx_unacked_len(0)
182
  , _tx_acked_len(0)
183
  , _rx_ack_len(0)
184
  , _rx_last_packet(0)
185
  , _rx_since_timeout(0)
186
  , _ack_timeout(ASYNC_MAX_ACK_TIME)
187
  , _connect_port(0)
188
  , _recv_pbuf_flags(0)
189
  , _errorTracker(NULL)
190
  , prev(NULL)
191
  , next(NULL)
192
{
193
  _pcb = pcb;
194
  if(_pcb){
195
    _rx_last_packet = millis();
196
    tcp_setprio(_pcb, TCP_PRIO_MIN);
197
    tcp_arg(_pcb, this);
198
    tcp_recv(_pcb, &_s_recv);
199
    tcp_sent(_pcb, &_s_sent);
200
    tcp_err(_pcb, &_s_error);
201
    tcp_poll(_pcb, &_s_poll, 1);
202
#if ASYNC_TCP_SSL_ENABLED
203
    if(ssl_ctx){
204
      if(tcp_ssl_new_server(_pcb, ssl_ctx) < 0){
205
        _close();
206
        return;
207
      }
208
      tcp_ssl_arg(_pcb, this);
209
      tcp_ssl_data(_pcb, &_s_data);
210
      tcp_ssl_handshake(_pcb, &_s_handshake);
211
      tcp_ssl_err(_pcb, &_s_ssl_error);
212
 
213
      _pcb_secure = true;
214
      _handshake_done = false;
215
    }
216
#endif
217
  }
218
 
219
  _errorTracker = std::make_shared<ACErrorTracker>(this);
220
#if DEBUG_ESP_ASYNC_TCP
221
  _errorTracker->setConnectionId(++_connectionCount);
222
#endif
223
}
224
 
225
AsyncClient::~AsyncClient(){
226
  if(_pcb)
227
    _close();
228
 
229
  _errorTracker->clearClient();
230
}
231
 
232
inline void clearTcpCallbacks(tcp_pcb* pcb){
233
      tcp_arg(pcb, NULL);
234
      tcp_sent(pcb, NULL);
235
      tcp_recv(pcb, NULL);
236
      tcp_err(pcb, NULL);
237
      tcp_poll(pcb, NULL, 0);
238
}
239
 
240
#if ASYNC_TCP_SSL_ENABLED
241
bool AsyncClient::connect(IPAddress ip, uint16_t port, bool secure){
242
#else
243
bool AsyncClient::connect(IPAddress ip, uint16_t port){
244
#endif
245
  if (_pcb) //already connected
246
    return false;
247
  IPAddress addr;
248
  addr = ip;
249
#if LWIP_VERSION_MAJOR == 1
250
  netif* interface = ip_route(&addr);
251
  if (!interface){ //no route to host
252
    return false;
253
  }
254
#endif
255
  tcp_pcb* pcb = tcp_new();
256
  if (!pcb){ //could not allocate pcb
257
    return false;
258
  }
259
 
260
  tcp_setprio(pcb, TCP_PRIO_MIN);
261
#if ASYNC_TCP_SSL_ENABLED
262
  _pcb_secure = secure;
263
  _handshake_done = !secure;
264
#endif
265
  tcp_arg(pcb, this);
266
  tcp_err(pcb, &_s_error);
267
  size_t err = tcp_connect(pcb, addr, port,(tcp_connected_fn)&_s_connected);
268
  return (ERR_OK == err);
269
}
270
 
271
#if ASYNC_TCP_SSL_ENABLED
272
bool AsyncClient::connect(const char* host, uint16_t port, bool secure){
273
#else
274
bool AsyncClient::connect(const char* host, uint16_t port){
275
#endif
276
  IPAddress addr;
277
  err_t err = dns_gethostbyname(host, addr, (dns_found_callback)&_s_dns_found, this);
278
  if(err == ERR_OK) {
279
#if ASYNC_TCP_SSL_ENABLED
280
    return connect(addr, port, secure);
281
#else
282
    return connect(addr, port);
283
#endif
284
  } else if(err == ERR_INPROGRESS) {
285
#if ASYNC_TCP_SSL_ENABLED
286
    _pcb_secure = secure;
287
    _handshake_done = !secure;
288
#endif
289
    _connect_port = port;
290
    return true;
291
  }
292
  return false;
293
}
294
 
295
AsyncClient& AsyncClient::operator=(const AsyncClient& other){
296
  if (_pcb) {
297
    ASYNC_TCP_DEBUG("operator=[%u]: Abandoned _pcb(0x%" PRIXPTR ") forced close.\n", getConnectionId(), uintptr_t(_pcb));
298
    _close();
299
  }
300
  _errorTracker = other._errorTracker;
301
 
302
  // I am confused when "other._pcb" falls out of scope the destructor will
303
  // close it? TODO: Look to see where this is used and how it might work.
304
  _pcb = other._pcb;
305
  if (_pcb) {
306
    _rx_last_packet = millis();
307
    tcp_setprio(_pcb, TCP_PRIO_MIN);
308
    tcp_arg(_pcb, this);
309
    tcp_recv(_pcb, &_s_recv);
310
    tcp_sent(_pcb, &_s_sent);
311
    tcp_err(_pcb, &_s_error);
312
    tcp_poll(_pcb, &_s_poll, 1);
313
#if ASYNC_TCP_SSL_ENABLED
314
    if(tcp_ssl_has(_pcb)){
315
      _pcb_secure = true;
316
      _handshake_done = false;
317
      tcp_ssl_arg(_pcb, this);
318
      tcp_ssl_data(_pcb, &_s_data);
319
      tcp_ssl_handshake(_pcb, &_s_handshake);
320
      tcp_ssl_err(_pcb, &_s_ssl_error);
321
    } else {
322
      _pcb_secure = false;
323
      _handshake_done = true;
324
    }
325
#endif
326
  }
327
  return *this;
328
}
329
 
330
bool AsyncClient::operator==(const AsyncClient &other) {
331
  return (_pcb != NULL && other._pcb != NULL && (IPAddress(_pcb->remote_ip) ==  IPAddress(other._pcb->remote_ip)) && (_pcb->remote_port == other._pcb->remote_port));
332
}
333
 
334
void AsyncClient::abort(){
335
  // Notes:
336
  // 1) _pcb is set to NULL, so we cannot call tcp_abort() more than once.
337
  // 2) setCloseError(ERR_ABRT) is only done here!
338
  // 3) Using this abort() function guarantees only one tcp_abort() call is
339
  //    made and only one CB returns with ERR_ABORT.
340
  // 4) After abort() is called from _close(), no callbacks with an err
341
  //    parameter will be called.  eg. _recv(), _error(), _connected().
342
  //    _close() will reset there CB handlers before calling.
343
  // 5) A callback to _error(), will set _pcb to NULL, thus avoiding the
344
  //    of a 2nd call to tcp_abort().
345
  // 6) Callbacks to _recv() or _connected() with err set, will result in _pcb
346
  //    set to NULL. Thus, preventing possible calls later to tcp_abort().
347
  if(_pcb) {
348
    tcp_abort(_pcb);
349
    _pcb = NULL;
350
    setCloseError(ERR_ABRT);
351
  }
352
  return;
353
}
354
 
355
void AsyncClient::close(bool now){
356
  if(_pcb)
357
    tcp_recved(_pcb, _rx_ack_len);
358
  if(now) {
359
    ASYNC_TCP_DEBUG("close[%u]: AsyncClient 0x%" PRIXPTR "\n", getConnectionId(), uintptr_t(this));
360
    _close();
361
  } else {
362
    _close_pcb = true;
363
  }
364
}
365
 
366
void AsyncClient::stop() {
367
  close(false);
368
}
369
 
370
bool AsyncClient::free(){
371
  if(!_pcb)
372
    return true;
373
  if(_pcb->state == 0 || _pcb->state > 4)
374
    return true;
375
  return false;
376
}
377
 
378
size_t AsyncClient::write(const char* data) {
379
  if(data == NULL)
380
    return 0;
381
  return write(data, strlen(data));
382
}
383
 
384
size_t AsyncClient::write(const char* data, size_t size, uint8_t apiflags) {
385
  size_t will_send = add(data, size, apiflags);
386
 
387
  if(!will_send || !send())
388
    return 0;
389
  return will_send;
390
}
391
 
392
size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) {
393
  if(!_pcb || size == 0 || data == NULL)
394
    return 0;
395
  size_t room = space();
396
  if(!room)
397
    return 0;
398
#if ASYNC_TCP_SSL_ENABLED
399
  if(_pcb_secure){
400
    int sent = tcp_ssl_write(_pcb, (uint8_t*)data, size);
401
    if(sent >= 0){
402
      _tx_unacked_len += sent;
403
      return sent;
404
    }
405
    _close();
406
    return 0;
407
  }
408
#endif
409
  size_t will_send = (room < size) ? room : size;
410
  err_t err = tcp_write(_pcb, data, will_send, apiflags);
411
  if(err != ERR_OK) {
412
    ASYNC_TCP_DEBUG("_add[%u]: tcp_write() returned err: %s(%ld)\n", getConnectionId(), errorToString(err), err);
413
    return 0;
414
  }
415
  _tx_unacked_len += will_send;
416
  return will_send;
417
}
418
 
419
bool AsyncClient::send(){
420
#if ASYNC_TCP_SSL_ENABLED
421
  if(_pcb_secure)
422
    return true;
423
#endif
424
  err_t err = tcp_output(_pcb);
425
  if(err == ERR_OK){
426
    _pcb_busy = true;
427
    _pcb_sent_at = millis();
428
    return true;
429
  }
430
 
431
  ASYNC_TCP_DEBUG("send[%u]: tcp_output() returned err: %s(%ld)", getConnectionId(), errorToString(err), err);
432
  return false;
433
}
434
 
435
size_t AsyncClient::ack(size_t len){
436
  if(len > _rx_ack_len)
437
    len = _rx_ack_len;
438
  if(len)
439
    tcp_recved(_pcb, len);
440
  _rx_ack_len -= len;
441
  return len;
442
}
443
 
444
// Private Callbacks
445
 
446
void AsyncClient::_connected(std::shared_ptr<ACErrorTracker>& errorTracker, void* pcb, err_t err){
447
  //(void)err; // LWIP v1.4 appears to always call with ERR_OK
448
  // Documentation for 2.1.0 also says:
449
  //   "err	- An unused error code, always ERR_OK currently ;-)"
450
  // https://www.nongnu.org/lwip/2_1_x/tcp_8h.html#a939867106bd492caf2d85852fb7f6ae8
451
  // Based on that wording and emoji lets just handle it now.
452
  // After all, the API does allow for an err != ERR_OK.
453
  if(NULL == pcb || ERR_OK != err) {
454
    ASYNC_TCP_DEBUG("_connected[%u]:%s err: %s(%ld)\n", errorTracker->getConnectionId(), ((NULL == pcb) ? " NULL == pcb!," : ""), errorToString(err), err);
455
    errorTracker->setCloseError(err);
456
    errorTracker->setErrored(EE_CONNECTED_CB);
457
    _pcb = reinterpret_cast<tcp_pcb*>(pcb);
458
    if (_pcb)
459
      clearTcpCallbacks(_pcb);
460
    _pcb = NULL;
461
    _error(err);
462
    return;
463
  }
464
 
465
  _pcb = reinterpret_cast<tcp_pcb*>(pcb);
466
  if(_pcb){
467
    _pcb_busy = false;
468
    _rx_last_packet = millis();
469
    tcp_setprio(_pcb, TCP_PRIO_MIN);
470
    tcp_recv(_pcb, &_s_recv);
471
    tcp_sent(_pcb, &_s_sent);
472
    tcp_poll(_pcb, &_s_poll, 1);
473
#if ASYNC_TCP_SSL_ENABLED
474
    if(_pcb_secure){
475
      if(tcp_ssl_new_client(_pcb) < 0){
476
        _close();
477
        return;
478
      }
479
      tcp_ssl_arg(_pcb, this);
480
      tcp_ssl_data(_pcb, &_s_data);
481
      tcp_ssl_handshake(_pcb, &_s_handshake);
482
      tcp_ssl_err(_pcb, &_s_ssl_error);
483
    }
484
  }
485
  if(!_pcb_secure && _connect_cb)
486
#else
487
  }
488
  if(_connect_cb)
489
#endif
490
    _connect_cb(_connect_cb_arg, this);
491
  return;
492
}
493
 
494
void AsyncClient::_close(){
495
  if(_pcb) {
496
#if ASYNC_TCP_SSL_ENABLED
497
    if(_pcb_secure){
498
      tcp_ssl_free(_pcb);
499
    }
500
#endif
501
    clearTcpCallbacks(_pcb);
502
    err_t err = tcp_close(_pcb);
503
    if(ERR_OK == err) {
504
      setCloseError(err);
505
      ASYNC_TCP_DEBUG("_close[%u]: AsyncClient 0x%" PRIXPTR "\n", getConnectionId(), uintptr_t(this));
506
    } else {
507
      ASYNC_TCP_DEBUG("_close[%u]: abort() called for AsyncClient 0x%" PRIXPTR "\n", getConnectionId(), uintptr_t(this));
508
      abort();
509
    }
510
    _pcb = NULL;
511
    if(_discard_cb)
512
      _discard_cb(_discard_cb_arg, this);
513
  }
514
  return;
515
}
516
 
517
void AsyncClient::_error(err_t err) {
518
  ASYNC_TCP_DEBUG("_error[%u]:%s err: %s(%ld)\n", getConnectionId(), ((NULL == _pcb) ? " NULL == _pcb!," : ""), errorToString(err), err);
519
  if(_pcb){
520
#if ASYNC_TCP_SSL_ENABLED
521
    if(_pcb_secure){
522
      tcp_ssl_free(_pcb);
523
    }
524
#endif
525
    // At this callback _pcb is possible already freed. Thus, no calls are
526
    // made to set to NULL other callbacks.
527
    _pcb = NULL;
528
  }
529
  if(_error_cb)
530
    _error_cb(_error_cb_arg, this, err);
531
  if(_discard_cb)
532
    _discard_cb(_discard_cb_arg, this);
533
}
534
 
535
#if ASYNC_TCP_SSL_ENABLED
536
void AsyncClient::_ssl_error(int8_t err){
537
  if(_error_cb)
538
    _error_cb(_error_cb_arg, this, err+64);
539
}
540
#endif
541
 
542
void AsyncClient::_sent(std::shared_ptr<ACErrorTracker>& errorTracker, tcp_pcb* pcb, uint16_t len) {
543
  (void)pcb;
544
#if ASYNC_TCP_SSL_ENABLED
545
  if (_pcb_secure && !_handshake_done)
546
    return;
547
#endif
548
  _rx_last_packet = millis();
549
  _tx_unacked_len -= len;
550
  _tx_acked_len += len;
551
  ASYNC_TCP_DEBUG("_sent[%u]: %4u, unacked=%4u, acked=%4u, space=%4u\n", errorTracker->getConnectionId(), len, _tx_unacked_len, _tx_acked_len, space());
552
  if(_tx_unacked_len == 0){
553
    _pcb_busy = false;
554
    errorTracker->setCloseError(ERR_OK);
555
    if(_sent_cb) {
556
      _sent_cb(_sent_cb_arg, this, _tx_acked_len, (millis() - _pcb_sent_at));
557
      if(!errorTracker->hasClient())
558
        return;
559
    }
560
    _tx_acked_len = 0;
561
  }
562
  return;
563
}
564
 
565
void AsyncClient::_recv(std::shared_ptr<ACErrorTracker>& errorTracker, tcp_pcb* pcb, pbuf* pb, err_t err) {
566
  // While lwIP v1.4 appears to always call with ERR_OK, 2.x lwIP may present
567
  // a non-ERR_OK value.
568
  // https://www.nongnu.org/lwip/2_1_x/tcp_8h.html#a780cfac08b02c66948ab94ea974202e8
569
  if(NULL == pcb || ERR_OK != err){
570
    ASYNC_TCP_DEBUG("_recv[%u]:%s err: %s(%ld)\n", errorTracker->getConnectionId(), ((NULL == pcb) ? " NULL == pcb!," : ""), errorToString(err), err);
571
    ASYNC_TCP_ASSERT(ERR_ABRT != err);
572
    errorTracker->setCloseError(err);
573
    errorTracker->setErrored(EE_RECV_CB);
574
    _pcb = pcb;
575
    if(_pcb)
576
      clearTcpCallbacks(_pcb);
577
    _pcb = NULL;
578
    // I think we are safe from being called from an interrupt context.
579
    // Best Hint that calling _error() is safe:
580
    //    https://www.nongnu.org/lwip/2_1_x/group__lwip__nosys.html
581
    // "Feed incoming packets to netif->input(pbuf, netif) function from
582
    // mainloop, not from interrupt context. You can allocate a Packet buffers
583
    // (PBUF) in interrupt context and put them into a queue which is processed
584
    // from mainloop."
585
    // And the description of "Mainloop Mode" option 2:
586
    //    https://www.nongnu.org/lwip/2_1_x/pitfalls.html
587
    // "2) Run lwIP in a mainloop. ... lwIP is ONLY called from mainloop
588
    // callstacks here. The ethernet IRQ has to put received telegrams into a
589
    // queue which is polled in the mainloop. Ensure lwIP is NEVER called from
590
    // an interrupt, ...!"
591
    // Based on these comments I am thinking tcp_recv_fn() is called
592
    // from somebody's mainloop(), which could only have been reached from a
593
    // delay like function or the Arduino sketch loop() function has returned.
594
    // What I don't want is for the client sketch to delete the AsyncClient
595
    // object via _error() while it is in the middle of using it. However,
596
    // the client sketch must always test that the connection is still up
597
    // at loop() entry and after the return of any function call, that may
598
    // have done a delay() or yield().
599
    _error(err);
600
    return;
601
  }
602
 
603
  if(pb == NULL){
604
    ASYNC_TCP_DEBUG("_recv[%u]: pb == NULL! Closing... %ld\n", errorTracker->getConnectionId(), err);
605
    _close();
606
    return;
607
  }
608
  _rx_last_packet = millis();
609
  errorTracker->setCloseError(ERR_OK);
610
#if ASYNC_TCP_SSL_ENABLED
611
  if(_pcb_secure){
612
    ASYNC_TCP_DEBUG("_recv[%u]: %d\n", getConnectionId(), pb->tot_len);
613
    int read_bytes = tcp_ssl_read(pcb, pb);
614
    if(read_bytes < 0){
615
      if (read_bytes != SSL_CLOSE_NOTIFY) {
616
        ASYNC_TCP_DEBUG("_recv[%u] err: %d\n", getConnectionId(), read_bytes);
617
        _close();
618
      }
619
    }
620
    return;
621
  }
622
#endif
623
  while(pb != NULL){
624
    // IF this callback function returns ERR_OK or ERR_ABRT
625
    // then it is assummed we freed the pbufs.
626
    // https://www.nongnu.org/lwip/2_1_x/group__tcp__raw.html#ga8afd0b316a87a5eeff4726dc95006ed0
627
    if(!errorTracker->hasClient()){
628
      while(pb != NULL){
629
        pbuf *b = pb;
630
        pb = b->next;
631
        b->next = NULL;
632
        pbuf_free(b);
633
      }
634
      return;
635
    }
636
    //we should not ack before we assimilate the data
637
    _ack_pcb = true;
638
    pbuf *b = pb;
639
    pb = b->next;
640
    b->next = NULL;
641
    ASYNC_TCP_DEBUG("_recv[%u]: %d%s\n", errorTracker->getConnectionId(), b->len, (b->flags&PBUF_FLAG_PUSH)?", PBUF_FLAG_PUSH":"");
642
    if(_pb_cb){
643
      _pb_cb(_pb_cb_arg, this, b);
644
    } else {
645
      if(_recv_cb){
646
        _recv_pbuf_flags = b->flags;
647
        _recv_cb(_recv_cb_arg, this, b->payload, b->len);
648
      }
649
      if(errorTracker->hasClient()){
650
        if(!_ack_pcb)
651
          _rx_ack_len += b->len;
652
        else
653
          tcp_recved(pcb, b->len);
654
      }
655
      pbuf_free(b);
656
    }
657
  }
658
  return;
659
}
660
 
661
void AsyncClient::_poll(std::shared_ptr<ACErrorTracker>& errorTracker, tcp_pcb* pcb){
662
  (void)pcb;
663
  errorTracker->setCloseError(ERR_OK);
664
 
665
  // Close requested
666
  if(_close_pcb){
667
    ASYNC_TCP_DEBUG("_poll[%u]: Process _close_pcb.\n", errorTracker->getConnectionId() );
668
    _close_pcb = false;
669
    _close();
670
    return;
671
  }
672
  uint32_t now = millis();
673
 
674
  // ACK Timeout
675
  if(_pcb_busy && _ack_timeout && (now - _pcb_sent_at) >= _ack_timeout){
676
    _pcb_busy = false;
677
    if(_timeout_cb)
678
      _timeout_cb(_timeout_cb_arg, this, (now - _pcb_sent_at));
679
    return;
680
  }
681
  // RX Timeout
682
  if(_rx_since_timeout && (now - _rx_last_packet) >= (_rx_since_timeout * 1000)){
683
    ASYNC_TCP_DEBUG("_poll[%u]: RX Timeout.\n", errorTracker->getConnectionId() );
684
    _close();
685
    return;
686
  }
687
#if ASYNC_TCP_SSL_ENABLED
688
  // SSL Handshake Timeout
689
  if(_pcb_secure && !_handshake_done && (now - _rx_last_packet) >= 2000){
690
    ASYNC_TCP_DEBUG("_poll[%u]: SSL Handshake Timeout.\n", errorTracker->getConnectionId() );
691
    _close();
692
    return;
693
  }
694
#endif
695
  // Everything is fine
696
  if(_poll_cb)
697
    _poll_cb(_poll_cb_arg, this);
698
  return;
699
}
700
 
701
#if LWIP_VERSION_MAJOR == 1
702
void AsyncClient::_dns_found(struct ip_addr *ipaddr){
703
#else
704
void AsyncClient::_dns_found(const ip_addr *ipaddr){
705
#endif
706
  if(ipaddr){
707
#if ASYNC_TCP_SSL_ENABLED
708
    connect(ipaddr, _connect_port, _pcb_secure);
709
#else
710
    connect(ipaddr, _connect_port);
711
#endif
712
  } else {
713
    if(_error_cb)
714
      _error_cb(_error_cb_arg, this, -55);
715
    if(_discard_cb)
716
      _discard_cb(_discard_cb_arg, this);
717
  }
718
}
719
 
720
// lwIP Callbacks
721
#if LWIP_VERSION_MAJOR == 1
722
void AsyncClient::_s_dns_found(const char *name, ip_addr_t *ipaddr, void *arg){
723
#else
724
void AsyncClient::_s_dns_found(const char *name, const ip_addr *ipaddr, void *arg){
725
#endif
726
  (void)name;
727
  reinterpret_cast<AsyncClient*>(arg)->_dns_found(ipaddr);
728
}
729
 
730
err_t AsyncClient::_s_poll(void *arg, struct tcp_pcb *tpcb) {
731
  AsyncClient *c = reinterpret_cast<AsyncClient*>(arg);
732
  std::shared_ptr<ACErrorTracker>errorTracker = c->getACErrorTracker();
733
  c->_poll(errorTracker, tpcb);
734
  return errorTracker->getCallbackCloseError();
735
}
736
 
737
err_t AsyncClient::_s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, err_t err) {
738
  AsyncClient *c = reinterpret_cast<AsyncClient*>(arg);
739
  auto errorTracker = c->getACErrorTracker();
740
  c->_recv(errorTracker, tpcb, pb, err);
741
  return errorTracker->getCallbackCloseError();
742
}
743
 
744
void AsyncClient::_s_error(void *arg, err_t err) {
745
  AsyncClient *c = reinterpret_cast<AsyncClient*>(arg);
746
  auto errorTracker = c->getACErrorTracker();
747
  errorTracker->setCloseError(err);
748
  errorTracker->setErrored(EE_ERROR_CB);
749
  c->_error(err);
750
}
751
 
752
err_t AsyncClient::_s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len) {
753
  AsyncClient *c = reinterpret_cast<AsyncClient*>(arg);
754
  auto errorTracker = c->getACErrorTracker();
755
  c->_sent(errorTracker, tpcb, len);
756
  return errorTracker->getCallbackCloseError();
757
}
758
 
759
err_t AsyncClient::_s_connected(void* arg, void* tpcb, err_t err){
760
  AsyncClient *c = reinterpret_cast<AsyncClient*>(arg);
761
  auto errorTracker = c->getACErrorTracker();
762
  c->_connected(errorTracker, tpcb, err);
763
  return errorTracker->getCallbackCloseError();
764
}
765
 
766
#if ASYNC_TCP_SSL_ENABLED
767
void AsyncClient::_s_data(void *arg, struct tcp_pcb *tcp, uint8_t * data, size_t len){
768
  (void)tcp;
769
  AsyncClient *c = reinterpret_cast<AsyncClient*>(arg);
770
  if(c->_recv_cb)
771
    c->_recv_cb(c->_recv_cb_arg, c, data, len);
772
}
773
 
774
void AsyncClient::_s_handshake(void *arg, struct tcp_pcb *tcp, SSL *ssl){
775
  (void)tcp;
776
  (void)ssl;
777
  AsyncClient *c = reinterpret_cast<AsyncClient*>(arg);
778
  c->_handshake_done = true;
779
  if(c->_connect_cb)
780
    c->_connect_cb(c->_connect_cb_arg, c);
781
}
782
 
783
void AsyncClient::_s_ssl_error(void *arg, struct tcp_pcb *tcp, int8_t err){
784
  (void)tcp;
785
#ifdef DEBUG_ESP_ASYNC_TCP
786
  AsyncClient *c = reinterpret_cast<AsyncClient*>(arg);
787
  auto errorTracker = c->getACErrorTracker();
788
  ASYNC_TCP_DEBUG("_ssl_error[%u] err = %d\n", errorTracker->getConnectionId(), err);
789
#endif
790
  reinterpret_cast<AsyncClient*>(arg)->_ssl_error(err);
791
}
792
#endif
793
 
794
// Operators
795
 
796
AsyncClient & AsyncClient::operator+=(const AsyncClient &other) {
797
  if(next == NULL){
798
    next = (AsyncClient*)(&other);
799
    next->prev = this;
800
  } else {
801
    AsyncClient *c = next;
802
    while(c->next != NULL) c = c->next;
803
    c->next =(AsyncClient*)(&other);
804
    c->next->prev = c;
805
  }
806
  return *this;
807
}
808
 
809
void AsyncClient::setRxTimeout(uint32_t timeout){
810
  _rx_since_timeout = timeout;
811
}
812
 
813
uint32_t AsyncClient::getRxTimeout(){
814
  return _rx_since_timeout;
815
}
816
 
817
uint32_t AsyncClient::getAckTimeout(){
818
  return _ack_timeout;
819
}
820
 
821
void AsyncClient::setAckTimeout(uint32_t timeout){
822
  _ack_timeout = timeout;
823
}
824
 
825
void AsyncClient::setNoDelay(bool nodelay){
826
  if(!_pcb)
827
    return;
828
  if(nodelay)
829
    tcp_nagle_disable(_pcb);
830
  else
831
    tcp_nagle_enable(_pcb);
832
}
833
 
834
bool AsyncClient::getNoDelay(){
835
  if(!_pcb)
836
    return false;
837
  return tcp_nagle_disabled(_pcb);
838
}
839
 
840
uint16_t AsyncClient::getMss(){
841
  if(_pcb)
842
    return tcp_mss(_pcb);
843
  return 0;
844
}
845
 
846
uint16_t AsyncClient::getRemotePort() {
847
  if(!_pcb)
848
    return 0;
849
  return _pcb->remote_port;
850
}
851
 
852
 
853
uint16_t AsyncClient::getLocalPort() {
854
  if(!_pcb)
855
    return 0;
856
  return _pcb->local_port;
857
}
858
 
859
IPAddress AsyncClient::remoteIP() {
860
  if(!_pcb)
861
    return IPAddress(0);
862
  return _pcb->remote_ip;
863
}
864
 
865
uint16_t AsyncClient::remotePort() {
866
  return getRemotePort();
867
}
868
 
869
IPAddress AsyncClient::localIP() {
870
  if(!_pcb)
871
    return IPAddress(0);
872
  return _pcb->local_ip;
873
}
874
 
875
uint16_t AsyncClient::localPort() {
876
  return getLocalPort();
877
}
878
 
879
#if ASYNC_TCP_SSL_ENABLED
880
SSL * AsyncClient::getSSL(){
881
  if(_pcb && _pcb_secure){
882
    return tcp_ssl_get_ssl(_pcb);
883
  }
884
  return NULL;
885
}
886
#endif
887
 
888
uint8_t AsyncClient::state() {
889
  if(!_pcb)
890
    return 0;
891
  return _pcb->state;
892
}
893
 
894
bool AsyncClient::connected(){
895
  if (!_pcb)
896
    return false;
897
#if ASYNC_TCP_SSL_ENABLED
898
  return _pcb->state == 4 && _handshake_done;
899
#else
900
  return _pcb->state == 4;
901
#endif
902
}
903
 
904
bool AsyncClient::connecting(){
905
  if (!_pcb)
906
    return false;
907
  return _pcb->state > 0 && _pcb->state < 4;
908
}
909
 
910
bool AsyncClient::disconnecting(){
911
  if (!_pcb)
912
    return false;
913
  return _pcb->state > 4 && _pcb->state < 10;
914
}
915
 
916
bool AsyncClient::disconnected(){
917
  if (!_pcb)
918
    return true;
919
  return _pcb->state == 0 || _pcb->state == 10;
920
}
921
 
922
bool AsyncClient::freeable(){
923
  if (!_pcb)
924
    return true;
925
  return _pcb->state == 0 || _pcb->state > 4;
926
}
927
 
928
bool AsyncClient::canSend(){
929
  return !_pcb_busy && (space() > 0);
930
}
931
 
932
 
933
// Callback Setters
934
 
935
void AsyncClient::onConnect(AcConnectHandler cb, void* arg){
936
  _connect_cb = cb;
937
  _connect_cb_arg = arg;
938
}
939
 
940
void AsyncClient::onDisconnect(AcConnectHandler cb, void* arg){
941
  _discard_cb = cb;
942
  _discard_cb_arg = arg;
943
}
944
 
945
void AsyncClient::onAck(AcAckHandler cb, void* arg){
946
  _sent_cb = cb;
947
  _sent_cb_arg = arg;
948
}
949
 
950
void AsyncClient::onError(AcErrorHandler cb, void* arg){
951
  _error_cb = cb;
952
  _error_cb_arg = arg;
953
}
954
 
955
void AsyncClient::onData(AcDataHandler cb, void* arg){
956
  _recv_cb = cb;
957
  _recv_cb_arg = arg;
958
}
959
 
960
void AsyncClient::onPacket(AcPacketHandler cb, void* arg){
961
  _pb_cb = cb;
962
  _pb_cb_arg = arg;
963
}
964
 
965
void AsyncClient::onTimeout(AcTimeoutHandler cb, void* arg){
966
  _timeout_cb = cb;
967
  _timeout_cb_arg = arg;
968
}
969
 
970
void AsyncClient::onPoll(AcConnectHandler cb, void* arg){
971
  _poll_cb = cb;
972
  _poll_cb_arg = arg;
973
}
974
 
975
 
976
size_t AsyncClient::space(){
977
#if ASYNC_TCP_SSL_ENABLED
978
  if((_pcb != NULL) && (_pcb->state == 4) && _handshake_done){
979
    uint16_t s = tcp_sndbuf(_pcb);
980
    if(_pcb_secure){
981
#ifdef AXTLS_2_0_0_SNDBUF
982
      return tcp_ssl_sndbuf(_pcb);
983
#else
984
      if(s >= 128) //safe approach
985
        return s - 128;
986
      return 0;
987
#endif
988
    }
989
    return s;
990
  }
991
#else // ASYNC_TCP_SSL_ENABLED
992
  if((_pcb != NULL) && (_pcb->state == 4)){
993
    return tcp_sndbuf(_pcb);
994
  }
995
#endif // ASYNC_TCP_SSL_ENABLED
996
  return 0;
997
}
998
 
999
void AsyncClient::ackPacket(struct pbuf * pb){
1000
  if(!pb){
1001
    return;
1002
  }
1003
  tcp_recved(_pcb, pb->len);
1004
  pbuf_free(pb);
1005
}
1006
 
1007
const char * AsyncClient::errorToString(err_t error) {
1008
  switch (error) {
1009
    case ERR_OK:         return "No error, everything OK";
1010
    case ERR_MEM:        return "Out of memory error";
1011
    case ERR_BUF:        return "Buffer error";
1012
    case ERR_TIMEOUT:    return "Timeout";
1013
    case ERR_RTE:        return "Routing problem";
1014
    case ERR_INPROGRESS: return "Operation in progress";
1015
    case ERR_VAL:        return "Illegal value";
1016
    case ERR_WOULDBLOCK: return "Operation would block";
1017
    case ERR_ABRT:       return "Connection aborted";
1018
    case ERR_RST:        return "Connection reset";
1019
    case ERR_CLSD:       return "Connection closed";
1020
    case ERR_CONN:       return "Not connected";
1021
    case ERR_ARG:        return "Illegal argument";
1022
    case ERR_USE:        return "Address in use";
1023
#if defined(LWIP_VERSION_MAJOR) && (LWIP_VERSION_MAJOR > 1)
1024
    case ERR_ALREADY:    return "Already connectioning";
1025
#endif
1026
    case ERR_IF:         return "Low-level netif error";
1027
    case ERR_ISCONN:     return "Connection already established";
1028
    case -55:            return "DNS failed";
1029
    default:             return "Unknown error";
1030
  }
1031
}
1032
 
1033
const char * AsyncClient::stateToString(){
1034
  switch(state()){
1035
    case 0: return "Closed";
1036
    case 1: return "Listen";
1037
    case 2: return "SYN Sent";
1038
    case 3: return "SYN Received";
1039
    case 4: return "Established";
1040
    case 5: return "FIN Wait 1";
1041
    case 6: return "FIN Wait 2";
1042
    case 7: return "Close Wait";
1043
    case 8: return "Closing";
1044
    case 9: return "Last ACK";
1045
    case 10: return "Time Wait";
1046
    default: return "UNKNOWN";
1047
  }
1048
}
1049
 
1050
/*
1051
  Async TCP Server
1052
*/
1053
struct pending_pcb {
1054
    tcp_pcb* pcb;
1055
    pbuf *pb;
1056
    struct pending_pcb * next;
1057
};
1058
 
1059
AsyncServer::AsyncServer(IPAddress addr, uint16_t port)
1060
  : _port(port)
1061
  , _addr(addr)
1062
  , _noDelay(false)
1063
  , _pcb(0)
1064
  , _connect_cb(0)
1065
  , _connect_cb_arg(0)
1066
#if ASYNC_TCP_SSL_ENABLED
1067
  , _pending(NULL)
1068
  , _ssl_ctx(NULL)
1069
  , _file_cb(0)
1070
  , _file_cb_arg(0)
1071
#endif
1072
{
1073
#ifdef DEBUG_MORE
1074
  for (size_t i=0; i<EE_MAX; ++i)
1075
    _event_count[i] = 0;
1076
#endif
1077
}
1078
 
1079
AsyncServer::AsyncServer(uint16_t port)
1080
  : _port(port)
1081
  , _addr(IP_ANY_TYPE)
1082
  , _noDelay(false)
1083
  , _pcb(0)
1084
  , _connect_cb(0)
1085
  , _connect_cb_arg(0)
1086
#if ASYNC_TCP_SSL_ENABLED
1087
  , _pending(NULL)
1088
  , _ssl_ctx(NULL)
1089
  , _file_cb(0)
1090
  , _file_cb_arg(0)
1091
#endif
1092
  {
1093
#ifdef DEBUG_MORE
1094
    for (size_t i=0; i<EE_MAX; ++i)
1095
      _event_count[i] = 0;
1096
#endif
1097
  }
1098
 
1099
AsyncServer::~AsyncServer(){
1100
  end();
1101
}
1102
 
1103
void AsyncServer::onClient(AcConnectHandler cb, void* arg){
1104
  _connect_cb = cb;
1105
  _connect_cb_arg = arg;
1106
}
1107
 
1108
#if ASYNC_TCP_SSL_ENABLED
1109
void AsyncServer::onSslFileRequest(AcSSlFileHandler cb, void* arg){
1110
  _file_cb = cb;
1111
  _file_cb_arg = arg;
1112
}
1113
#endif
1114
 
1115
void AsyncServer::begin(){
1116
  if(_pcb)
1117
    return;
1118
 
1119
  int8_t err;
1120
  tcp_pcb* pcb = tcp_new_ip_type(IPADDR_TYPE_ANY);
1121
  if (!pcb){
1122
    return;
1123
  }
1124
 
1125
  tcp_setprio(pcb, TCP_PRIO_MIN);
1126
  IPAddress local_addr;
1127
  local_addr = _addr;
1128
  err = tcp_bind(pcb, local_addr, _port);
1129
  // Failures are ERR_ISCONN or ERR_USE
1130
  if (err != ERR_OK) {
1131
    tcp_close(pcb);
1132
    return;
1133
  }
1134
 
1135
  tcp_pcb* listen_pcb = tcp_listen(pcb);
1136
  if (!listen_pcb) {
1137
    tcp_close(pcb);
1138
    return;
1139
  }
1140
  _pcb = listen_pcb;
1141
  tcp_arg(_pcb, (void*) this);
1142
  tcp_accept(_pcb, &_s_accept);
1143
}
1144
 
1145
#if ASYNC_TCP_SSL_ENABLED
1146
void AsyncServer::beginSecure(const char *cert, const char *key, const char *password){
1147
  if(_ssl_ctx){
1148
    return;
1149
  }
1150
  tcp_ssl_file(_s_cert, this);
1151
  _ssl_ctx = tcp_ssl_new_server_ctx(cert, key, password);
1152
  if(_ssl_ctx){
1153
    begin();
1154
  }
1155
}
1156
#endif
1157
 
1158
void AsyncServer::end(){
1159
  if(_pcb){
1160
    //cleanup all connections?
1161
    tcp_arg(_pcb, NULL);
1162
    tcp_accept(_pcb, NULL);
1163
    if(tcp_close(_pcb) != ERR_OK){
1164
      tcp_abort(_pcb);
1165
    }
1166
    _pcb = NULL;
1167
  }
1168
#if ASYNC_TCP_SSL_ENABLED
1169
  if(_ssl_ctx){
1170
    ssl_ctx_free(_ssl_ctx);
1171
    _ssl_ctx = NULL;
1172
    if(_pending){
1173
      struct pending_pcb * p;
1174
      while(_pending){
1175
        p = _pending;
1176
        _pending = _pending->next;
1177
        if(p->pb){
1178
          pbuf_free(p->pb);
1179
        }
1180
        free(p);
1181
      }
1182
    }
1183
  }
1184
#endif
1185
}
1186
 
1187
void AsyncServer::setNoDelay(bool nodelay){
1188
  _noDelay = nodelay;
1189
}
1190
 
1191
bool AsyncServer::getNoDelay(){
1192
  return _noDelay;
1193
}
1194
 
1195
uint8_t AsyncServer::status(){
1196
  if (!_pcb)
1197
    return 0;
1198
  return _pcb->state;
1199
}
1200
 
1201
err_t AsyncServer::_accept(tcp_pcb* pcb, err_t err){
1202
  //http://savannah.nongnu.org/bugs/?43739
1203
  if(NULL == pcb || ERR_OK != err){
1204
    // https://www.nongnu.org/lwip/2_1_x/tcp_8h.html#a00517abce6856d6c82f0efebdafb734d
1205
    // An error code if there has been an error accepting. Only return ERR_ABRT
1206
    // if you have called tcp_abort from within the callback function!
1207
    // eg. 2.1.0 could call with error on failure to allocate pcb.
1208
    ASYNC_TCP_DEBUG("_accept:%s err: %ld\n", ((NULL == pcb) ? " NULL == pcb!," : ""), err);
1209
    ASYNC_TCP_ASSERT(ERR_ABRT != err);
1210
#ifdef DEBUG_MORE
1211
    incEventCount(EE_ACCEPT_CB);
1212
#endif
1213
    return ERR_OK;
1214
  }
1215
 
1216
  if(_connect_cb){
1217
#if ASYNC_TCP_SSL_ENABLED
1218
    if (_noDelay || _ssl_ctx)
1219
#else
1220
    if (_noDelay)
1221
#endif
1222
      tcp_nagle_disable(pcb);
1223
    else
1224
      tcp_nagle_enable(pcb);
1225
 
1226
#if ASYNC_TCP_SSL_ENABLED
1227
    if(_ssl_ctx){
1228
      if(tcp_ssl_has_client() || _pending){
1229
        struct pending_pcb * new_item = (struct pending_pcb*)malloc(sizeof(struct pending_pcb));
1230
        if(!new_item){
1231
          ASYNC_TCP_DEBUG("### malloc new pending failed!\n");
1232
          if(tcp_close(pcb) != ERR_OK){
1233
            tcp_abort(pcb);
1234
            return ERR_ABRT;
1235
          }
1236
          return ERR_OK;
1237
        }
1238
        //1 ASYNC_TCP_DEBUG("### put to wait: %d\n", _clients_waiting);
1239
        new_item->pcb = pcb;
1240
        new_item->pb = NULL;
1241
        new_item->next = NULL;
1242
        tcp_setprio(_pcb, TCP_PRIO_MIN);
1243
        tcp_arg(pcb, this);
1244
        tcp_poll(pcb, &_s_poll, 1);
1245
        tcp_recv(pcb, &_s_recv);
1246
 
1247
        if(_pending == NULL){
1248
          _pending = new_item;
1249
        } else {
1250
          struct pending_pcb * p = _pending;
1251
          while(p->next != NULL)
1252
            p = p->next;
1253
          p->next = new_item;
1254
        }
1255
      } else {
1256
        AsyncClient *c = new (std::nothrow) AsyncClient(pcb, _ssl_ctx);
1257
        if(c){
1258
          ASYNC_TCP_DEBUG("_accept[%u]: SSL connected\n", c->getConnectionId());
1259
          c->onConnect([this](void * arg, AsyncClient *c){
1260
            (void)arg;
1261
            _connect_cb(_connect_cb_arg, c);
1262
          }, this);
1263
        } else {
1264
          ASYNC_TCP_DEBUG("_accept[_ssl_ctx]: new AsyncClient() failed, connection aborted!\n");
1265
          if(tcp_close(pcb) != ERR_OK){
1266
            tcp_abort(pcb);
1267
            return ERR_ABRT;
1268
          }
1269
        }
1270
      }
1271
      return ERR_OK;
1272
    } else {
1273
      AsyncClient *c = new (std::nothrow) AsyncClient(pcb, NULL);
1274
#else
1275
      AsyncClient *c = new (std::nothrow) AsyncClient(pcb);
1276
#endif
1277
 
1278
      if(c){
1279
        auto errorTracker = c->getACErrorTracker();
1280
#ifdef DEBUG_MORE
1281
        errorTracker->onErrorEvent(
1282
          [](void *obj, size_t ee){ ((AsyncServer*)(obj))->incEventCount(ee); },
1283
          this);
1284
#endif
1285
        ASYNC_TCP_DEBUG("_accept[%u]: connected\n", errorTracker->getConnectionId());
1286
        _connect_cb(_connect_cb_arg, c);
1287
        return errorTracker->getCallbackCloseError();
1288
      } else {
1289
        ASYNC_TCP_DEBUG("_accept: new AsyncClient() failed, connection aborted!\n");
1290
        if(tcp_close(pcb) != ERR_OK){
1291
          tcp_abort(pcb);
1292
          return ERR_ABRT;
1293
        }
1294
      }
1295
#if ASYNC_TCP_SSL_ENABLED
1296
    }
1297
#endif
1298
  }
1299
  if(tcp_close(pcb) != ERR_OK){
1300
    tcp_abort(pcb);
1301
    return ERR_ABRT;
1302
  }
1303
  return ERR_OK;
1304
}
1305
 
1306
err_t AsyncServer::_s_accept(void *arg, tcp_pcb* pcb, err_t err){
1307
  return reinterpret_cast<AsyncServer*>(arg)->_accept(pcb, err);
1308
}
1309
 
1310
#if ASYNC_TCP_SSL_ENABLED
1311
err_t AsyncServer::_poll(tcp_pcb* pcb){
1312
  err_t err = ERR_OK;
1313
  if(!tcp_ssl_has_client() && _pending){
1314
    struct pending_pcb * p = _pending;
1315
    if(p->pcb == pcb){
1316
      _pending = _pending->next;
1317
    } else {
1318
      while(p->next && p->next->pcb != pcb) p = p->next;
1319
      if(!p->next) return 0;
1320
      struct pending_pcb * b = p->next;
1321
      p->next = b->next;
1322
      p = b;
1323
    }
1324
    //1 ASYNC_TCP_DEBUG("### remove from wait: %d\n", _clients_waiting);
1325
    AsyncClient *c = new (std::nothrow) AsyncClient(pcb, _ssl_ctx);
1326
    if(c){
1327
      c->onConnect([this](void * arg, AsyncClient *c){
1328
        (void)arg;
1329
        _connect_cb(_connect_cb_arg, c);
1330
      }, this);
1331
      if(p->pb) {
1332
        auto errorTracker = c->getACErrorTracker();
1333
        c->_recv(errorTracker, pcb, p->pb, 0);
1334
        err = errorTracker->getCallbackCloseError();
1335
      }
1336
    }
1337
    // Should there be error handling for when "new AsynClient" fails??
1338
    free(p);
1339
  }
1340
  return err;
1341
}
1342
 
1343
err_t AsyncServer::_recv(struct tcp_pcb *pcb, struct pbuf *pb, err_t err){
1344
  (void)err;
1345
  if(!_pending)
1346
    return ERR_OK;
1347
 
1348
  struct pending_pcb * p;
1349
 
1350
  if(!pb){
1351
    //1 ASYNC_TCP_DEBUG("### close from wait: %d\n", _clients_waiting);
1352
    p = _pending;
1353
    if(p->pcb == pcb){
1354
      _pending = _pending->next;
1355
    } else {
1356
      while(p->next && p->next->pcb != pcb) p = p->next;
1357
      if(!p->next) return 0;
1358
      struct pending_pcb * b = p->next;
1359
      p->next = b->next;
1360
      p = b;
1361
    }
1362
    if(p->pb){
1363
      pbuf_free(p->pb);
1364
    }
1365
    free(p);
1366
    size_t err = tcp_close(pcb);
1367
    if (err != ERR_OK) {
1368
      tcp_abort(pcb);
1369
      return ERR_ABRT;
1370
    }
1371
  } else {
1372
    //1 ASYNC_TCP_DEBUG("### wait _recv: %u %d\n", pb->tot_len, _clients_waiting);
1373
    p = _pending;
1374
    while(p && p->pcb != pcb)
1375
      p = p->next;
1376
    if(p){
1377
      if(p->pb){
1378
        pbuf_chain(p->pb, pb);
1379
      } else {
1380
        p->pb = pb;
1381
      }
1382
    }
1383
  }
1384
  return ERR_OK;
1385
}
1386
 
1387
int AsyncServer::_cert(const char *filename, uint8_t **buf){
1388
  if(_file_cb){
1389
    return _file_cb(_file_cb_arg, filename, buf);
1390
  }
1391
  *buf = 0;
1392
  return 0;
1393
}
1394
 
1395
int AsyncServer::_s_cert(void *arg, const char *filename, uint8_t **buf){
1396
  return reinterpret_cast<AsyncServer*>(arg)->_cert(filename, buf);
1397
}
1398
 
1399
err_t AsyncServer::_s_poll(void *arg, struct tcp_pcb *pcb){
1400
  return reinterpret_cast<AsyncServer*>(arg)->_poll(pcb);
1401
}
1402
 
1403
err_t AsyncServer::_s_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, err_t err){
1404
  return reinterpret_cast<AsyncServer*>(arg)->_recv(pcb, pb, err);
1405
}
1406
#endif