Skip to content

Commit f3ed41a

Browse files
authored
Merge pull request me-no-dev#66 from matt123p/fix-crash-on-fin-v2
Fix crash on fin attempt 2
2 parents 7ab3540 + 7d15cb4 commit f3ed41a

File tree

2 files changed

+56
-29
lines changed

2 files changed

+56
-29
lines changed

src/AsyncTCP.cpp

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,9 @@ typedef struct {
7878

7979
static xQueueHandle _async_queue;
8080
static TaskHandle_t _async_service_task_handle = NULL;
81-
static tcp_pcb * pcb_recently_closed = NULL;
81+
const int _number_of_closed_slots = CONFIG_LWIP_MAX_ACTIVE_TCP;
82+
static int _closed_index = 0;
83+
static int _closed_slots[_number_of_closed_slots];
8284

8385
static inline bool _init_async_event_queue(){
8486
if(!_async_queue){
@@ -333,6 +335,7 @@ static int8_t _tcp_accept(void * arg, AsyncClient * client) {
333335
typedef struct {
334336
struct tcpip_api_call_data call;
335337
tcp_pcb * pcb;
338+
int8_t closed_slot;
336339
int8_t err;
337340
union {
338341
struct {
@@ -357,39 +360,39 @@ typedef struct {
357360
static err_t _tcp_output_api(struct tcpip_api_call_data *api_call_msg){
358361
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
359362
msg->err = ERR_CONN;
360-
if(msg->pcb != pcb_recently_closed) {
363+
if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) {
361364
msg->err = tcp_output(msg->pcb);
362365
}
363-
pcb_recently_closed = NULL;
364366
return msg->err;
365367
}
366368

367-
static esp_err_t _tcp_output(tcp_pcb * pcb) {
369+
static esp_err_t _tcp_output(tcp_pcb * pcb, int8_t closed_slot) {
368370
if(!pcb){
369371
return ERR_CONN;
370372
}
371373
tcp_api_call_t msg;
372374
msg.pcb = pcb;
375+
msg.closed_slot = closed_slot;
373376
tcpip_api_call(_tcp_output_api, (struct tcpip_api_call_data*)&msg);
374377
return msg.err;
375378
}
376379

377380
static err_t _tcp_write_api(struct tcpip_api_call_data *api_call_msg){
378381
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
379382
msg->err = ERR_CONN;
380-
if(msg->pcb != pcb_recently_closed) {
383+
if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) {
381384
msg->err = tcp_write(msg->pcb, msg->write.data, msg->write.size, msg->write.apiflags);
382385
}
383-
pcb_recently_closed = NULL;
384386
return msg->err;
385387
}
386388

387-
static esp_err_t _tcp_write(tcp_pcb * pcb, const char* data, size_t size, uint8_t apiflags) {
389+
static esp_err_t _tcp_write(tcp_pcb * pcb, int8_t closed_slot, const char* data, size_t size, uint8_t apiflags) {
388390
if(!pcb){
389391
return ERR_CONN;
390392
}
391393
tcp_api_call_t msg;
392394
msg.pcb = pcb;
395+
msg.closed_slot = closed_slot;
393396
msg.write.data = data;
394397
msg.write.size = size;
395398
msg.write.apiflags = apiflags;
@@ -400,20 +403,20 @@ static esp_err_t _tcp_write(tcp_pcb * pcb, const char* data, size_t size, uint8_
400403
static err_t _tcp_recved_api(struct tcpip_api_call_data *api_call_msg){
401404
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
402405
msg->err = ERR_CONN;
403-
if(msg->pcb != pcb_recently_closed) {
406+
if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) {
404407
msg->err = 0;
405408
tcp_recved(msg->pcb, msg->received);
406409
}
407-
pcb_recently_closed = NULL;
408410
return msg->err;
409411
}
410412

411-
static esp_err_t _tcp_recved(tcp_pcb * pcb, size_t len) {
413+
static esp_err_t _tcp_recved(tcp_pcb * pcb, int8_t closed_slot, size_t len) {
412414
if(!pcb){
413415
return ERR_CONN;
414416
}
415417
tcp_api_call_t msg;
416418
msg.pcb = pcb;
419+
msg.closed_slot = closed_slot;
417420
msg.received = len;
418421
tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call_data*)&msg);
419422
return msg.err;
@@ -422,39 +425,39 @@ static esp_err_t _tcp_recved(tcp_pcb * pcb, size_t len) {
422425
static err_t _tcp_close_api(struct tcpip_api_call_data *api_call_msg){
423426
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
424427
msg->err = ERR_CONN;
425-
if(msg->pcb != pcb_recently_closed) {
428+
if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) {
426429
msg->err = tcp_close(msg->pcb);
427430
}
428-
pcb_recently_closed = NULL;
429431
return msg->err;
430432
}
431433

432-
static esp_err_t _tcp_close(tcp_pcb * pcb) {
434+
static esp_err_t _tcp_close(tcp_pcb * pcb, int8_t closed_slot) {
433435
if(!pcb){
434436
return ERR_CONN;
435437
}
436438
tcp_api_call_t msg;
437439
msg.pcb = pcb;
440+
msg.closed_slot = closed_slot;
438441
tcpip_api_call(_tcp_close_api, (struct tcpip_api_call_data*)&msg);
439442
return msg.err;
440443
}
441444

442445
static err_t _tcp_abort_api(struct tcpip_api_call_data *api_call_msg){
443446
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
444447
msg->err = ERR_CONN;
445-
if(msg->pcb != pcb_recently_closed) {
448+
if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) {
446449
tcp_abort(msg->pcb);
447450
}
448-
pcb_recently_closed = NULL;
449451
return msg->err;
450452
}
451453

452-
static esp_err_t _tcp_abort(tcp_pcb * pcb) {
454+
static esp_err_t _tcp_abort(tcp_pcb * pcb, int8_t closed_slot) {
453455
if(!pcb){
454456
return ERR_CONN;
455457
}
456458
tcp_api_call_t msg;
457459
msg.pcb = pcb;
460+
msg.closed_slot = closed_slot;
458461
tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call_data*)&msg);
459462
return msg.err;
460463
}
@@ -465,12 +468,13 @@ static err_t _tcp_connect_api(struct tcpip_api_call_data *api_call_msg){
465468
return msg->err;
466469
}
467470

468-
static esp_err_t _tcp_connect(tcp_pcb * pcb, ip_addr_t * addr, uint16_t port, tcp_connected_fn cb) {
471+
static esp_err_t _tcp_connect(tcp_pcb * pcb, int8_t closed_slot, ip_addr_t * addr, uint16_t port, tcp_connected_fn cb) {
469472
if(!pcb){
470473
return ESP_FAIL;
471474
}
472475
tcp_api_call_t msg;
473476
msg.pcb = pcb;
477+
msg.closed_slot = closed_slot;
474478
msg.connect.addr = addr;
475479
msg.connect.port = port;
476480
msg.connect.cb = cb;
@@ -490,6 +494,7 @@ static esp_err_t _tcp_bind(tcp_pcb * pcb, ip_addr_t * addr, uint16_t port) {
490494
}
491495
tcp_api_call_t msg;
492496
msg.pcb = pcb;
497+
msg.closed_slot = -1;
493498
msg.bind.addr = addr;
494499
msg.bind.port = port;
495500
tcpip_api_call(_tcp_bind_api, (struct tcpip_api_call_data*)&msg);
@@ -509,6 +514,7 @@ static tcp_pcb * _tcp_listen_with_backlog(tcp_pcb * pcb, uint8_t backlog) {
509514
}
510515
tcp_api_call_t msg;
511516
msg.pcb = pcb;
517+
msg.closed_slot = -1;
512518
msg.backlog = backlog?backlog:0xFF;
513519
tcpip_api_call(_tcp_listen_api, (struct tcpip_api_call_data*)&msg);
514520
return msg.pcb;
@@ -546,7 +552,25 @@ AsyncClient::AsyncClient(tcp_pcb* pcb)
546552
, next(NULL)
547553
{
548554
_pcb = pcb;
555+
_closed_slot = -1;
549556
if(_pcb){
557+
_closed_slot = 0;
558+
if (_closed_index == 0) {
559+
_closed_index = 1;
560+
for (int i = 0; i < _number_of_closed_slots; ++ i) {
561+
_closed_slots[i] = 1;
562+
}
563+
} else {
564+
int closed_slot_min_index = _closed_slots[0];
565+
for (int i = 0; i < _number_of_closed_slots; ++ i) {
566+
if (_closed_slots[i] <= closed_slot_min_index && _closed_slots[i] != 0) {
567+
closed_slot_min_index = _closed_slots[i];
568+
_closed_slot = i;
569+
}
570+
}
571+
}
572+
_closed_slots[_closed_slot] = 0;
573+
550574
_rx_last_packet = millis();
551575
tcp_arg(_pcb, this);
552576
tcp_recv(_pcb, &_tcp_recv);
@@ -572,6 +596,7 @@ AsyncClient& AsyncClient::operator=(const AsyncClient& other){
572596
}
573597

574598
_pcb = other._pcb;
599+
_closed_slot = other._closed_slot;
575600
if (_pcb) {
576601
_rx_last_packet = millis();
577602
tcp_arg(_pcb, this);
@@ -676,7 +701,7 @@ bool AsyncClient::connect(IPAddress ip, uint16_t port){
676701
tcp_sent(pcb, &_tcp_sent);
677702
tcp_poll(pcb, &_tcp_poll, 1);
678703
//_tcp_connect(pcb, &addr, port,(tcp_connected_fn)&_s_connected);
679-
_tcp_connect(pcb, &addr, port,(tcp_connected_fn)&_tcp_connected);
704+
_tcp_connect(pcb, _closed_slot, &addr, port,(tcp_connected_fn)&_tcp_connected);
680705
return true;
681706
}
682707

@@ -702,14 +727,14 @@ bool AsyncClient::connect(const char* host, uint16_t port){
702727

703728
void AsyncClient::close(bool now){
704729
if(_pcb){
705-
_tcp_recved(_pcb, _rx_ack_len);
730+
_tcp_recved(_pcb, _closed_slot, _rx_ack_len);
706731
}
707732
_close();
708733
}
709734

710735
int8_t AsyncClient::abort(){
711736
if(_pcb) {
712-
_tcp_abort(_pcb);
737+
_tcp_abort(_pcb, _closed_slot );
713738
_pcb = NULL;
714739
}
715740
return ERR_ABRT;
@@ -732,7 +757,7 @@ size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) {
732757
}
733758
size_t will_send = (room < size) ? room : size;
734759
int8_t err = ERR_OK;
735-
err = _tcp_write(_pcb, data, will_send, apiflags);
760+
err = _tcp_write(_pcb, _closed_slot, data, will_send, apiflags);
736761
if(err != ERR_OK) {
737762
return 0;
738763
}
@@ -741,7 +766,7 @@ size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) {
741766

742767
bool AsyncClient::send(){
743768
int8_t err = ERR_OK;
744-
err = _tcp_output(_pcb);
769+
err = _tcp_output(_pcb, _closed_slot);
745770
if(err == ERR_OK){
746771
_pcb_busy = true;
747772
_pcb_sent_at = millis();
@@ -754,7 +779,7 @@ size_t AsyncClient::ack(size_t len){
754779
if(len > _rx_ack_len)
755780
len = _rx_ack_len;
756781
if(len){
757-
_tcp_recved(_pcb, len);
782+
_tcp_recved(_pcb, _closed_slot, len);
758783
}
759784
_rx_ack_len -= len;
760785
return len;
@@ -764,7 +789,7 @@ void AsyncClient::ackPacket(struct pbuf * pb){
764789
if(!pb){
765790
return;
766791
}
767-
_tcp_recved(_pcb, pb->len);
792+
_tcp_recved(_pcb, _closed_slot, pb->len);
768793
pbuf_free(pb);
769794
}
770795

@@ -783,7 +808,7 @@ int8_t AsyncClient::_close(){
783808
tcp_err(_pcb, NULL);
784809
tcp_poll(_pcb, NULL, 0);
785810
_tcp_clear_events(this);
786-
err = _tcp_close(_pcb);
811+
err = _tcp_close(_pcb, _closed_slot);
787812
if(err != ERR_OK) {
788813
err = abort();
789814
}
@@ -845,7 +870,8 @@ int8_t AsyncClient::_lwip_fin(tcp_pcb* pcb, int8_t err) {
845870
if(tcp_close(_pcb) != ERR_OK) {
846871
tcp_abort(_pcb);
847872
}
848-
pcb_recently_closed = _pcb;
873+
_closed_slots[_closed_slot] = _closed_index;
874+
++ _closed_index;
849875
_pcb = NULL;
850876
return ERR_OK;
851877
}
@@ -886,7 +912,7 @@ int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) {
886912
if(!_ack_pcb) {
887913
_rx_ack_len += b->len;
888914
} else if(_pcb) {
889-
_tcp_recved(_pcb, b->len);
915+
_tcp_recved(_pcb, _closed_slot, b->len);
890916
}
891917
pbuf_free(b);
892918
}
@@ -1233,7 +1259,7 @@ void AsyncServer::begin(){
12331259
err = _tcp_bind(_pcb, &local_addr, _port);
12341260

12351261
if (err != ERR_OK) {
1236-
_tcp_close(_pcb);
1262+
_tcp_close(_pcb, -1);
12371263
log_e("bind error: %d", err);
12381264
return;
12391265
}
@@ -1253,7 +1279,7 @@ void AsyncServer::end(){
12531279
tcp_arg(_pcb, NULL);
12541280
tcp_accept(_pcb, NULL);
12551281
if(tcp_close(_pcb) != ERR_OK){
1256-
_tcp_abort(_pcb);
1282+
_tcp_abort(_pcb, -1);
12571283
}
12581284
_pcb = NULL;
12591285
}

src/AsyncTCP.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ class AsyncClient {
141141

142142
protected:
143143
tcp_pcb* _pcb;
144+
int8_t _closed_slot;
144145

145146
AcConnectHandler _connect_cb;
146147
void* _connect_cb_arg;

0 commit comments

Comments
 (0)