Skip to content

Commit e35a0d6

Browse files
committed
replace tcpip_api_call() calls with LWIP_TCPIP_CORE_LOCKING
use of lwip core locking is preferable (if enabled globaly) then using context switching callbacks
1 parent 0faa87b commit e35a0d6

File tree

1 file changed

+100
-20
lines changed

1 file changed

+100
-20
lines changed

src/AsyncTCP.cpp

Lines changed: 100 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ extern "C" {
6565

6666
// https://github.com/espressif/arduino-esp32/issues/10526
6767
namespace {
68-
#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING
68+
#if defined CONFIG_LWIP_TCPIP_CORE_LOCKING && CONFIG_LWIP_TCPIP_CORE_LOCKING
6969
struct tcp_core_guard {
7070
bool do_lock;
7171
inline tcp_core_guard() : do_lock(!sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) {
@@ -390,8 +390,7 @@ static bool _start_async_task() {
390390

391391
/*
392392
* LwIP Callbacks
393-
* */
394-
393+
*/
395394
static void _bind_tcp_callbacks(tcp_pcb *pcb, AsyncClient *client) {
396395
tcp_arg(pcb, client);
397396
tcp_recv(pcb, &AsyncTCP_detail::tcp_recv);
@@ -537,8 +536,7 @@ static void _tcp_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) {
537536

538537
/*
539538
* TCP/IP API Calls
540-
* */
541-
539+
*/
542540
#include "lwip/priv/tcpip_priv.h"
543541

544542
typedef struct {
@@ -566,7 +564,8 @@ typedef struct {
566564
};
567565
} tcp_api_call_t;
568566

569-
static err_t _tcp_output_api(struct tcpip_api_call_data *api_call_msg) {
567+
// context switching callback
568+
[[maybe_unused]] static err_t _tcp_output_api(struct tcpip_api_call_data *api_call_msg) {
570569
tcp_api_call_t *msg = (tcp_api_call_t *)api_call_msg;
571570
msg->err = ERR_CONN;
572571
if (*msg->pcb) {
@@ -575,17 +574,23 @@ static err_t _tcp_output_api(struct tcpip_api_call_data *api_call_msg) {
575574
return msg->err;
576575
}
577576

578-
static esp_err_t _tcp_output(tcp_pcb **pcb) {
577+
inline esp_err_t _tcp_output(tcp_pcb **pcb) {
579578
if (!pcb || !*pcb) {
580579
return ERR_CONN;
581580
}
581+
#if defined CONFIG_LWIP_TCPIP_CORE_LOCKING && CONFIG_LWIP_TCPIP_CORE_LOCKING
582+
tcp_core_guard tcg;
583+
return tcp_output(*pcb);
584+
#else // CONFIG_LWIP_TCPIP_CORE_LOCKING
582585
tcp_api_call_t msg;
583586
msg.pcb = pcb;
584587
tcpip_api_call(_tcp_output_api, (struct tcpip_api_call_data *)&msg);
585588
return msg.err;
589+
#endif // CONFIG_LWIP_TCPIP_CORE_LOCKING
586590
}
587591

588-
static err_t _tcp_write_api(struct tcpip_api_call_data *api_call_msg) {
592+
// context switching callback
593+
[[maybe_unused]] static err_t _tcp_write_api(struct tcpip_api_call_data *api_call_msg) {
589594
tcp_api_call_t *msg = (tcp_api_call_t *)api_call_msg;
590595
msg->err = ERR_CONN;
591596
if (*msg->pcb) {
@@ -594,20 +599,27 @@ static err_t _tcp_write_api(struct tcpip_api_call_data *api_call_msg) {
594599
return msg->err;
595600
}
596601

597-
static esp_err_t _tcp_write(tcp_pcb **pcb, const char *data, size_t size, uint8_t apiflags) {
602+
603+
inline esp_err_t _tcp_write(tcp_pcb **pcb, const char *data, size_t size, uint8_t apiflags) {
598604
if (!pcb || !*pcb) {
599605
return ERR_CONN;
600606
}
607+
#if defined CONFIG_LWIP_TCPIP_CORE_LOCKING && CONFIG_LWIP_TCPIP_CORE_LOCKING
608+
tcp_core_guard tcg;
609+
return tcp_write(*pcb, data, size, apiflags);
610+
#else // CONFIG_LWIP_TCPIP_CORE_LOCKING
601611
tcp_api_call_t msg;
602612
msg.pcb = pcb;
603613
msg.write.data = data;
604614
msg.write.size = size;
605615
msg.write.apiflags = apiflags;
606616
tcpip_api_call(_tcp_write_api, (struct tcpip_api_call_data *)&msg);
607617
return msg.err;
618+
#endif // CONFIG_LWIP_TCPIP_CORE_LOCKING
608619
}
609620

610-
static err_t _tcp_recved_api(struct tcpip_api_call_data *api_call_msg) {
621+
// context switching callback
622+
[[maybe_unused]] static err_t _tcp_recved_api(struct tcpip_api_call_data *api_call_msg) {
611623
tcp_api_call_t *msg = (tcp_api_call_t *)api_call_msg;
612624
msg->err = ERR_CONN;
613625
if (*msg->pcb) {
@@ -617,15 +629,22 @@ static err_t _tcp_recved_api(struct tcpip_api_call_data *api_call_msg) {
617629
return msg->err;
618630
}
619631

620-
static esp_err_t _tcp_recved(tcp_pcb **pcb, size_t len) {
632+
633+
inline esp_err_t _tcp_recved(tcp_pcb **pcb, size_t len) {
621634
if (!pcb || !*pcb) {
622635
return ERR_CONN;
623636
}
637+
#if defined CONFIG_LWIP_TCPIP_CORE_LOCKING && CONFIG_LWIP_TCPIP_CORE_LOCKING
638+
tcp_core_guard tcg;
639+
tcp_recved(*pcb, len);
640+
return ERR_OK;
641+
#else // CONFIG_LWIP_TCPIP_CORE_LOCKING
624642
tcp_api_call_t msg;
625643
msg.pcb = pcb;
626644
msg.received = len;
627645
tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call_data *)&msg);
628646
return msg.err;
647+
#endif // CONFIG_LWIP_TCPIP_CORE_LOCKING
629648
}
630649

631650
static err_t _tcp_close_api(struct tcpip_api_call_data *api_call_msg) {
@@ -645,6 +664,7 @@ static err_t _tcp_close_api(struct tcpip_api_call_data *api_call_msg) {
645664
if (tcp_close(pcb) != ERR_OK) {
646665
// We do not permit failure here: abandon the pcb anyways.
647666
tcp_abort(pcb);
667+
msg->err = ERR_ABRT; // if we called tcp_abort here, then we must return ERR_ABRT
648668
}
649669
msg->err = ERR_OK;
650670
*msg->pcb = nullptr; // PCB is now the property of LwIP
@@ -657,18 +677,38 @@ static err_t _tcp_close_api(struct tcpip_api_call_data *api_call_msg) {
657677
return msg->err;
658678
}
659679

660-
static esp_err_t _tcp_close(tcp_pcb **pcb, AsyncClient *client) {
680+
inline esp_err_t _tcp_close(tcp_pcb **pcb, AsyncClient *client) {
681+
#if defined CONFIG_LWIP_TCPIP_CORE_LOCKING && CONFIG_LWIP_TCPIP_CORE_LOCKING
682+
if (pcb && *pcb) {
683+
esp_err_t err{ERR_OK};
684+
tcp_core_guard tcg;
685+
_reset_tcp_callbacks(*pcb, client);
686+
if (tcp_close(*pcb) != ERR_OK) {
687+
// We do not permit failure here: abandon the pcb anyways.
688+
tcp_abort(*pcb);
689+
err = ERR_ABRT; // if we called tcp_abort here, then we must return ERR_ABRT
690+
}
691+
*pcb = nullptr; // PCB is now the property of LwIP
692+
return err;
693+
} else {
694+
// Ensure there is not an error event queued for this client
695+
return _remove_events_for_client(client) ? ERR_OK : ERR_CONN;
696+
}
697+
#else // CONFIG_LWIP_TCPIP_CORE_LOCKING
661698
tcp_api_call_t msg;
662699
msg.pcb = pcb;
663700
msg.close = client;
664701
tcpip_api_call(_tcp_close_api, (struct tcpip_api_call_data *)&msg);
665702
return msg.err;
703+
#endif // CONFIG_LWIP_TCPIP_CORE_LOCKING
666704
}
667705

668-
static err_t _tcp_abort_api(struct tcpip_api_call_data *api_call_msg) {
669-
// Like close(), we must ensure that the queue is cleared
706+
// context switching callback
707+
[[maybe_unused]] static err_t _tcp_abort_api(struct tcpip_api_call_data *api_call_msg) {
670708
tcp_api_call_t *msg = (tcp_api_call_t *)api_call_msg;
671709
if (*msg->pcb) {
710+
// Like close(), we must ensure that the queue is cleared
711+
_reset_tcp_callbacks(*(msg->pcb), msg->close);
672712
tcp_abort(*msg->pcb);
673713
*msg->pcb = nullptr; // PCB is now the property of LwIP
674714
msg->err = ERR_ABRT;
@@ -678,78 +718,118 @@ static err_t _tcp_abort_api(struct tcpip_api_call_data *api_call_msg) {
678718
return msg->err;
679719
}
680720

681-
static esp_err_t _tcp_abort(tcp_pcb **pcb, AsyncClient *client) {
721+
722+
inline esp_err_t _tcp_abort(tcp_pcb **pcb, AsyncClient *client) {
682723
if (!pcb || !*pcb) {
683724
return ERR_CONN;
684725
}
726+
#if defined CONFIG_LWIP_TCPIP_CORE_LOCKING && CONFIG_LWIP_TCPIP_CORE_LOCKING
727+
tcp_core_guard tcg;
728+
// Like close(), we must ensure that the queue is cleared
729+
_reset_tcp_callbacks(*pcb, client);
730+
tcp_abort(*pcb);
731+
*pcb = nullptr; // PCB is now the property of LwIP
732+
return ERR_ABRT;
733+
#else // CONFIG_LWIP_TCPIP_CORE_LOCKING
685734
tcp_api_call_t msg;
686735
msg.pcb = pcb;
687736
msg.close = client;
688737
tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call_data *)&msg);
689738
return msg.err;
739+
#endif // CONFIG_LWIP_TCPIP_CORE_LOCKING
690740
}
691741

692-
static err_t _tcp_connect_api(struct tcpip_api_call_data *api_call_msg) {
742+
// context switching callback
743+
[[maybe_unused]] static err_t _tcp_connect_api(struct tcpip_api_call_data *api_call_msg) {
693744
tcp_api_call_t *msg = (tcp_api_call_t *)api_call_msg;
694745
msg->err = tcp_connect(*msg->pcb, msg->connect.addr, msg->connect.port, msg->connect.cb);
695746
return msg->err;
696747
}
697748

698-
static esp_err_t _tcp_connect(tcp_pcb *pcb, ip_addr_t *addr, uint16_t port, tcp_connected_fn cb) {
749+
750+
inline esp_err_t _tcp_connect(tcp_pcb *pcb, ip_addr_t *addr, uint16_t port, tcp_connected_fn cb) {
699751
if (!pcb) {
700752
return ESP_FAIL;
701753
}
754+
#if defined CONFIG_LWIP_TCPIP_CORE_LOCKING && CONFIG_LWIP_TCPIP_CORE_LOCKING
755+
tcp_core_guard tcg;
756+
return tcp_connect(pcb, addr, port, cb);
757+
#else // CONFIG_LWIP_TCPIP_CORE_LOCKING
702758
tcp_api_call_t msg;
703759
msg.pcb = &pcb; // cannot be invalidated by LwIP at this point
704760
msg.connect.addr = addr;
705761
msg.connect.port = port;
706762
msg.connect.cb = cb;
707763
tcpip_api_call(_tcp_connect_api, (struct tcpip_api_call_data *)&msg);
708764
return msg.err;
765+
#endif // CONFIG_LWIP_TCPIP_CORE_LOCKING
709766
}
710767

711-
static err_t _tcp_bind_api(struct tcpip_api_call_data *api_call_msg) {
768+
// context switching callback
769+
[[maybe_unused]] static err_t _tcp_bind_api(struct tcpip_api_call_data *api_call_msg) {
712770
tcp_api_call_t *msg = (tcp_api_call_t *)api_call_msg;
713771
tcp_pcb *pcb = *msg->pcb;
714772
msg->err = tcp_bind(pcb, msg->bind.addr, msg->bind.port);
715773
if (msg->err != ERR_OK) {
716774
// Close the pcb on behalf of the server without an extra round-trip through the LwIP lock
717775
if (tcp_close(pcb) != ERR_OK) {
718776
tcp_abort(pcb);
777+
msg->err = ERR_ABRT; // if we called tcp_abort here, then we must return ERR_ABRT
719778
}
720779
*msg->pcb = nullptr; // PCB is now owned by LwIP
721780
}
722781
return msg->err;
723782
}
724783

725-
static esp_err_t _tcp_bind(tcp_pcb **pcb, ip_addr_t *addr, uint16_t port) {
784+
inline esp_err_t _tcp_bind(tcp_pcb **pcb, ip_addr_t *addr, uint16_t port) {
726785
if (!pcb || !*pcb) {
727786
return ESP_FAIL;
728787
}
788+
#if defined CONFIG_LWIP_TCPIP_CORE_LOCKING && CONFIG_LWIP_TCPIP_CORE_LOCKING
789+
tcp_core_guard tcg;
790+
auto err = tcp_bind(*pcb, addr, port);
791+
if (err != ERR_OK) {
792+
// Close the pcb on behalf of the server without an extra round-trip through the LwIP lock
793+
if (tcp_close(*pcb) != ERR_OK) {
794+
tcp_abort(*pcb);
795+
err = ERR_ABRT; // if we called tcp_abort here, then we must return ERR_ABRT
796+
}
797+
*pcb = nullptr; // PCB is now owned by LwIP
798+
}
799+
return err;
800+
#else // CONFIG_LWIP_TCPIP_CORE_LOCKING
729801
tcp_api_call_t msg;
730802
msg.pcb = pcb;
731803
msg.bind.addr = addr;
732804
msg.bind.port = port;
733805
tcpip_api_call(_tcp_bind_api, (struct tcpip_api_call_data *)&msg);
734806
return msg.err;
807+
#endif // CONFIG_LWIP_TCPIP_CORE_LOCKING
735808
}
736809

737-
static err_t _tcp_listen_api(struct tcpip_api_call_data *api_call_msg) {
810+
// context switching callback
811+
[[maybe_unused]] static err_t _tcp_listen_api(struct tcpip_api_call_data *api_call_msg) {
738812
tcp_api_call_t *msg = (tcp_api_call_t *)api_call_msg;
739813
msg->err = 0;
740814
*msg->pcb = tcp_listen_with_backlog(*msg->pcb, msg->backlog);
741815
return msg->err;
742816
}
743817

818+
744819
static tcp_pcb *_tcp_listen_with_backlog(tcp_pcb *pcb, uint8_t backlog) {
745820
if (!pcb) {
746821
return NULL;
747822
}
823+
#if defined CONFIG_LWIP_TCPIP_CORE_LOCKING && CONFIG_LWIP_TCPIP_CORE_LOCKING
824+
tcp_core_guard tcg;
825+
return tcp_listen_with_backlog(pcb, backlog ? backlog : 0xFF);
826+
#else // CONFIG_LWIP_TCPIP_CORE_LOCKING
748827
tcp_api_call_t msg;
749828
msg.pcb = &pcb;
750829
msg.backlog = backlog ? backlog : 0xFF;
751830
tcpip_api_call(_tcp_listen_api, (struct tcpip_api_call_data *)&msg);
752831
return pcb;
832+
#endif // CONFIG_LWIP_TCPIP_CORE_LOCKING
753833
}
754834

755835
/*

0 commit comments

Comments
 (0)