Skip to content

Commit

Permalink
Fix #27: Required to lock TCPIP core functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
mathieucarbou committed Oct 26, 2024
1 parent f005448 commit cffe067
Showing 1 changed file with 39 additions and 0 deletions.
39 changes: 39 additions & 0 deletions src/AsyncTCP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,26 @@ extern "C"{
#include <NetworkInterface.h>
#endif

#define TAG "AsyncTCP"

// https://github.com/espressif/arduino-esp32/issues/10526
#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING
#define TCP_MUTEX_LOCK() \
if (!sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { \
ESP_LOGE(TAG, "LOCK_TCPIP_CORE @ %s:%d", __FILE__, __LINE__); \
LOCK_TCPIP_CORE(); \
}

#define TCP_MUTEX_UNLOCK() \
if (sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { \
ESP_LOGE(TAG, "UNLOCK_TCPIP_CORE @ %s:%d", __FILE__, __LINE__); \
UNLOCK_TCPIP_CORE(); \
}
#else // CONFIG_LWIP_TCPIP_CORE_LOCKING
#define TCP_MUTEX_LOCK()
#define TCP_MUTEX_UNLOCK()
#endif // CONFIG_LWIP_TCPIP_CORE_LOCKING

#define INVALID_CLOSED_SLOT -1

/*
Expand Down Expand Up @@ -600,11 +620,13 @@ AsyncClient::AsyncClient(tcp_pcb* pcb)
_closed_slot = INVALID_CLOSED_SLOT;
if(_pcb){
_rx_last_packet = millis();
TCP_MUTEX_LOCK();
tcp_arg(_pcb, this);
tcp_recv(_pcb, &_tcp_recv);
tcp_sent(_pcb, &_tcp_sent);
tcp_err(_pcb, &_tcp_error);
tcp_poll(_pcb, &_tcp_poll, 1);
TCP_MUTEX_UNLOCK();
if(!_allocate_closed_slot()) {
_close();
}
Expand All @@ -631,11 +653,13 @@ AsyncClient& AsyncClient::operator=(const AsyncClient& other){
_closed_slot = other._closed_slot;
if (_pcb) {
_rx_last_packet = millis();
TCP_MUTEX_LOCK();
tcp_arg(_pcb, this);
tcp_recv(_pcb, &_tcp_recv);
tcp_sent(_pcb, &_tcp_sent);
tcp_err(_pcb, &_tcp_error);
tcp_poll(_pcb, &_tcp_poll, 1);
TCP_MUTEX_UNLOCK();
}
return *this;
}
Expand Down Expand Up @@ -722,8 +746,10 @@ bool AsyncClient::_connect(ip_addr_t addr, uint16_t port){
return false;
}

TCP_MUTEX_LOCK();
tcp_pcb* pcb = tcp_new_ip_type(addr.type);
if (!pcb){
TCP_MUTEX_UNLOCK();
log_e("pcb == NULL");
return false;
}
Expand All @@ -733,6 +759,7 @@ bool AsyncClient::_connect(ip_addr_t addr, uint16_t port){
tcp_recv(pcb, &_tcp_recv);
tcp_sent(pcb, &_tcp_sent);
tcp_poll(pcb, &_tcp_poll, 1);
TCP_MUTEX_UNLOCK();
esp_err_t err =_tcp_connect(pcb, _closed_slot, &addr, port,(tcp_connected_fn)&_tcp_connected);
return err == ESP_OK;
}
Expand Down Expand Up @@ -863,11 +890,13 @@ int8_t AsyncClient::_close(){
//ets_printf("X: 0x%08x\n", (uint32_t)this);
int8_t err = ERR_OK;
if(_pcb) {
TCP_MUTEX_LOCK();
tcp_arg(_pcb, NULL);
tcp_sent(_pcb, NULL);
tcp_recv(_pcb, NULL);
tcp_err(_pcb, NULL);
tcp_poll(_pcb, NULL, 0);
TCP_MUTEX_UNLOCK();
_tcp_clear_events(this);
err = _tcp_close(_pcb, _closed_slot);
if(err != ERR_OK) {
Expand Down Expand Up @@ -928,13 +957,15 @@ int8_t AsyncClient::_connected(tcp_pcb* pcb, int8_t err){

void AsyncClient::_error(int8_t err) {
if(_pcb){
TCP_MUTEX_LOCK();
tcp_arg(_pcb, NULL);
if(_pcb->state == LISTEN) {
tcp_sent(_pcb, NULL);
tcp_recv(_pcb, NULL);
tcp_err(_pcb, NULL);
tcp_poll(_pcb, NULL, 0);
}
TCP_MUTEX_UNLOCK();
_free_closed_slot();
_pcb = NULL;
}
Expand All @@ -952,13 +983,15 @@ int8_t AsyncClient::_lwip_fin(tcp_pcb* pcb, int8_t err) {
log_d("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb);
return ERR_OK;
}
TCP_MUTEX_LOCK();
tcp_arg(_pcb, NULL);
if(_pcb->state == LISTEN) {
tcp_sent(_pcb, NULL);
tcp_recv(_pcb, NULL);
tcp_err(_pcb, NULL);
tcp_poll(_pcb, NULL, 0);
}
TCP_MUTEX_UNLOCK();
if(tcp_close(_pcb) != ERR_OK) {
tcp_abort(_pcb);
}
Expand Down Expand Up @@ -1461,7 +1494,9 @@ void AsyncServer::begin(){
return;
}
int8_t err;
TCP_MUTEX_LOCK();
_pcb = tcp_new_ip_type(_bind4 && _bind6 ? IPADDR_TYPE_ANY : (_bind6 ? IPADDR_TYPE_V6 : IPADDR_TYPE_V4));
TCP_MUTEX_UNLOCK();
if (!_pcb){
log_e("_pcb == NULL");
return;
Expand Down Expand Up @@ -1493,14 +1528,18 @@ void AsyncServer::begin(){
log_e("listen_pcb == NULL");
return;
}
TCP_MUTEX_LOCK();
tcp_arg(_pcb, (void*) this);
tcp_accept(_pcb, &_s_accept);
TCP_MUTEX_UNLOCK();
}

void AsyncServer::end(){
if(_pcb){
TCP_MUTEX_LOCK();
tcp_arg(_pcb, NULL);
tcp_accept(_pcb, NULL);
TCP_MUTEX_UNLOCK();
if(tcp_close(_pcb) != ERR_OK){
_tcp_abort(_pcb, -1);
}
Expand Down

0 comments on commit cffe067

Please sign in to comment.