@@ -65,7 +65,7 @@ extern "C" {
6565
6666// https://github.com/espressif/arduino-esp32/issues/10526
6767namespace {
68- #ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING
68+ #if defined CONFIG_LWIP_TCPIP_CORE_LOCKING && CONFIG_LWIP_TCPIP_CORE_LOCKING
6969struct 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+ */
395394static 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
544542typedef 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
631650static 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+
744819static 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