diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index a51bd1e09..2a1a406bf 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -8,6 +8,7 @@ For more details go to [docs.emsesp.org](https://docs.emsesp.org/). - change enum_heatingtype for remote control [#2268](https://github.com/emsesp/EMS-ESP32/issues/2268) - system service commands [#2182](https://github.com/emsesp/EMS-ESP32/issues/2282) +- read 0x02A5 for thermostat CT200 [#2277](https://github.com/emsesp/EMS-ESP32/issues/2277) ## Fixed @@ -19,3 +20,4 @@ For more details go to [docs.emsesp.org](https://docs.emsesp.org/). - show operation in pretty telegram between src and dst [#2263](https://github.com/emsesp/EMS-ESP32/discussions/2263) - update eModbus to 1.7.2 [#2254](https://github.com/emsesp/EMS-ESP32/issues/2254) - modbus timeout default to 300 sec, change setting from ms to sec [#2254](https://github.com/emsesp/EMS-ESP32/issues/2254) +- update AsyncTCP to v3.2.14 diff --git a/lib/AsyncTCP/src/AsyncTCP.cpp b/lib/AsyncTCP/src/AsyncTCP.cpp index 06673f818..c3b0e5e32 100644 --- a/lib/AsyncTCP/src/AsyncTCP.cpp +++ b/lib/AsyncTCP/src/AsyncTCP.cpp @@ -33,6 +33,32 @@ extern "C" { #include "esp_task_wdt.h" #endif +// Required for: +// https://github.com/espressif/arduino-esp32/blob/3.0.3/libraries/Network/src/NetworkInterface.cpp#L37-L47 +#if ESP_IDF_VERSION_MAJOR >= 5 +// #include +#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)) { \ + LOCK_TCPIP_CORE(); \ + } + +#define TCP_MUTEX_UNLOCK() \ + if (sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { \ + 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 + /* * TCP/IP Event Task * */ @@ -54,8 +80,8 @@ typedef struct { void * arg; union { struct { - void * pcb; - int8_t err; + tcp_pcb * pcb; + int8_t err; } connected; struct { int8_t err; @@ -105,8 +131,7 @@ static uint32_t _closed_index = []() { static inline bool _init_async_event_queue() { if (!_async_queue) { - _async_queue = - xQueueCreate(CONFIG_ASYNC_TCP_QUEUE, sizeof(lwip_event_packet_t *)); // double queue to 128 see https://github.com/emsesp/EMS-ESP32/issues/177 + _async_queue = xQueueCreate(CONFIG_ASYNC_TCP_QUEUE_SIZE, sizeof(lwip_event_packet_t *)); if (!_async_queue) { return false; } @@ -252,7 +277,7 @@ static bool _start_async_task() { "async_tcp", CONFIG_ASYNC_TCP_STACK_SIZE, NULL, - CONFIG_ASYNC_TCP_TASK_PRIORITY, + CONFIG_ASYNC_TCP_PRIORITY, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE); if (!_async_service_task_handle) { @@ -410,7 +435,7 @@ typedef struct { static err_t _tcp_output_api(struct tcpip_api_call_data * api_call_msg) { tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = ERR_CONN; - if (msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { + if (msg->closed_slot == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { msg->err = tcp_output(msg->pcb); } return msg->err; @@ -430,7 +455,7 @@ static esp_err_t _tcp_output(tcp_pcb * pcb, int8_t closed_slot) { static err_t _tcp_write_api(struct tcpip_api_call_data * api_call_msg) { tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = ERR_CONN; - if (msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { + if (msg->closed_slot == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { msg->err = tcp_write(msg->pcb, msg->write.data, msg->write.size, msg->write.apiflags); } return msg->err; @@ -453,7 +478,9 @@ static esp_err_t _tcp_write(tcp_pcb * pcb, int8_t closed_slot, const char * data static err_t _tcp_recved_api(struct tcpip_api_call_data * api_call_msg) { tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = ERR_CONN; - if (msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { + if (msg->closed_slot == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { + // if(msg->closed_slot != INVALID_CLOSED_SLOT && !_closed_slots[msg->closed_slot]) { + // if(msg->closed_slot != INVALID_CLOSED_SLOT) { msg->err = 0; tcp_recved(msg->pcb, msg->received); } @@ -475,7 +502,7 @@ static esp_err_t _tcp_recved(tcp_pcb * pcb, int8_t closed_slot, size_t len) { static err_t _tcp_close_api(struct tcpip_api_call_data * api_call_msg) { tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = ERR_CONN; - if (msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { + if (msg->closed_slot == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { msg->err = tcp_close(msg->pcb); } return msg->err; @@ -495,7 +522,7 @@ static esp_err_t _tcp_close(tcp_pcb * pcb, int8_t closed_slot) { static err_t _tcp_abort_api(struct tcpip_api_call_data * api_call_msg) { tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = ERR_CONN; - if (msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { + if (msg->closed_slot == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { tcp_abort(msg->pcb); } return msg->err; @@ -595,20 +622,22 @@ AsyncClient::AsyncClient(tcp_pcb * pcb) , _tx_last_packet(0) , _rx_timeout(0) , _rx_last_ack(0) - , _ack_timeout(ASYNC_MAX_ACK_TIME) + , _ack_timeout(CONFIG_ASYNC_TCP_MAX_ACK_TIME) , _connect_port(0) , prev(NULL) , next(NULL) { _pcb = pcb; - _closed_slot = -1; + _closed_slot = INVALID_CLOSED_SLOT; if (_pcb) { - _allocate_closed_slot(); _rx_last_packet = millis(); 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); + if (!_allocate_closed_slot()) { + _close(); + } } } @@ -710,7 +739,7 @@ void AsyncClient::onPoll(AcConnectHandler cb, void * arg) { bool AsyncClient::_connect(ip_addr_t addr, uint16_t port) { if (_pcb) { - log_w("already connected, state %d", _pcb->state); + log_d("already connected, state %d", _pcb->state); return false; } if (!_start_async_task()) { @@ -718,28 +747,34 @@ bool AsyncClient::_connect(ip_addr_t addr, uint16_t port) { return false; } - tcp_pcb * pcb = tcp_new_ip_type(IPADDR_TYPE_ANY); - if (!pcb) { - log_e("pcb == NULL"); + if (!_allocate_closed_slot()) { + log_e("failed to allocate: closed slot full"); 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; + } tcp_arg(pcb, this); tcp_err(pcb, &_tcp_error); tcp_recv(pcb, &_tcp_recv); tcp_sent(pcb, &_tcp_sent); tcp_poll(pcb, &_tcp_poll, 1); - _tcp_connect(pcb, _closed_slot, &addr, port, (tcp_connected_fn)&_tcp_connected); - return true; + TCP_MUTEX_UNLOCK(); + + esp_err_t err = _tcp_connect(pcb, _closed_slot, &addr, port, (tcp_connected_fn)&_tcp_connected); + return err == ESP_OK; } -bool AsyncClient::connect(IPAddress ip, uint16_t port) { +bool AsyncClient::connect(const IPAddress & ip, uint16_t port) { ip_addr_t addr; #if ESP_IDF_VERSION_MAJOR < 5 - // ip_addr_set_ip4_u32(&addr, ip); addr.u_addr.ip4.addr = ip; addr.type = IPADDR_TYPE_V4; - ip_clear_no4(&addr); #else ip.to_ip_addr_t(&addr); #endif @@ -748,10 +783,9 @@ bool AsyncClient::connect(IPAddress ip, uint16_t port) { } #if LWIP_IPV6 && ESP_IDF_VERSION_MAJOR < 5 -bool AsyncClient::connect(IPv6Address ip, uint16_t port) { - ip_addr_t addr; - addr.type = IPADDR_TYPE_V6; - memcpy(addr.u_addr.ip6.addr, static_cast(ip), sizeof(uint32_t) * 4); +bool AsyncClient::connect(const IPv6Address & ip, uint16_t port) { + auto ipaddr = static_cast(ip); + ip_addr_t addr = IPADDR6_INIT(ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); return _connect(addr, port); } @@ -783,7 +817,7 @@ bool AsyncClient::connect(const char * host, uint16_t port) { _connect_port = port; return true; } - log_e("error: %d", err); + log_d("error: %d", err); return false; } @@ -803,7 +837,7 @@ int8_t AsyncClient::abort() { } size_t AsyncClient::space() { - if ((_pcb != NULL) && (_pcb->state == 4)) { + if ((_pcb != NULL) && (_pcb->state == ESTABLISHED)) { return tcp_sndbuf(_pcb); } return 0; @@ -862,17 +896,19 @@ int8_t AsyncClient::_close() { //ets_printf("X: 0x%08x\n", (uint32_t)this); int8_t err = ERR_OK; if (_pcb) { - //log_i(""); + 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) { err = abort(); } + _free_closed_slot(); _pcb = NULL; if (_discard_cb) { _discard_cb(_discard_cb_arg, this); @@ -881,40 +917,43 @@ int8_t AsyncClient::_close() { return err; } -void AsyncClient::_allocate_closed_slot() { +bool AsyncClient::_allocate_closed_slot() { + if (_closed_slot != INVALID_CLOSED_SLOT) { + return true; + } xSemaphoreTake(_slots_lock, portMAX_DELAY); uint32_t closed_slot_min_index = 0; for (int i = 0; i < _number_of_closed_slots; ++i) { - if ((_closed_slot == -1 || _closed_slots[i] <= closed_slot_min_index) && _closed_slots[i] != 0) { + if ((_closed_slot == INVALID_CLOSED_SLOT || _closed_slots[i] <= closed_slot_min_index) && _closed_slots[i] != 0) { closed_slot_min_index = _closed_slots[i]; _closed_slot = i; } } - if (_closed_slot != -1) { + if (_closed_slot != INVALID_CLOSED_SLOT) { _closed_slots[_closed_slot] = 0; } xSemaphoreGive(_slots_lock); + return (_closed_slot != INVALID_CLOSED_SLOT); } void AsyncClient::_free_closed_slot() { - if (_closed_slot != -1) { + xSemaphoreTake(_slots_lock, portMAX_DELAY); + if (_closed_slot != INVALID_CLOSED_SLOT) { _closed_slots[_closed_slot] = _closed_index; - _closed_slot = -1; + _closed_slot = INVALID_CLOSED_SLOT; ++_closed_index; } + xSemaphoreGive(_slots_lock); } /* * Private Callbacks * */ -int8_t AsyncClient::_connected(void * pcb, int8_t err) { +int8_t AsyncClient::_connected(tcp_pcb * pcb, int8_t err) { _pcb = reinterpret_cast(pcb); if (_pcb) { _rx_last_packet = millis(); - // tcp_recv(_pcb, &_tcp_recv); - // tcp_sent(_pcb, &_tcp_sent); - // tcp_poll(_pcb, &_tcp_poll, 1); } if (_connect_cb) { _connect_cb(_connect_cb_arg, this); @@ -924,6 +963,7 @@ int8_t AsyncClient::_connected(void * 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); @@ -931,6 +971,8 @@ void AsyncClient::_error(int8_t err) { tcp_err(_pcb, NULL); tcp_poll(_pcb, NULL, 0); } + TCP_MUTEX_UNLOCK(); + _free_closed_slot(); _pcb = NULL; } if (_error_cb) { @@ -944,7 +986,7 @@ void AsyncClient::_error(int8_t err) { //In LwIP Thread int8_t AsyncClient::_lwip_fin(tcp_pcb * pcb, int8_t err) { if (!_pcb || pcb != _pcb) { - log_e("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); + log_d("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); return ERR_OK; } tcp_arg(_pcb, NULL); @@ -972,11 +1014,9 @@ int8_t AsyncClient::_fin(tcp_pcb * pcb, int8_t err) { } int8_t AsyncClient::_sent(tcp_pcb * pcb, uint16_t len) { - _rx_last_packet = millis(); - _rx_last_ack = millis(); - //log_i("%u", len); + _rx_last_ack = _rx_last_packet = millis(); if (_sent_cb) { - _sent_cb(_sent_cb_arg, this, len, (millis() - _tx_last_packet)); + _sent_cb(_sent_cb_arg, this, len, (_rx_last_packet - _tx_last_packet)); } return ERR_OK; } @@ -1000,19 +1040,19 @@ int8_t AsyncClient::_recv(tcp_pcb * pcb, pbuf * pb, int8_t err) { } else if (_pcb) { _tcp_recved(_pcb, _closed_slot, b->len); } - pbuf_free(b); } + pbuf_free(b); } return ERR_OK; } int8_t AsyncClient::_poll(tcp_pcb * pcb) { if (!_pcb) { - log_w("pcb is NULL"); + // log_d("pcb is NULL"); return ERR_OK; } if (pcb != _pcb) { - log_e("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); + log_d("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); return ERR_OK; } @@ -1023,7 +1063,7 @@ int8_t AsyncClient::_poll(tcp_pcb * pcb) { const uint32_t one_day = 86400000; bool last_tx_is_after_last_ack = (_rx_last_ack - _tx_last_packet + one_day) < one_day; if (last_tx_is_after_last_ack && (now - _tx_last_packet) >= _ack_timeout) { - log_w("ack timeout %d", pcb->state); + log_d("ack timeout %d", pcb->state); if (_timeout_cb) _timeout_cb(_timeout_cb_arg, this, (now - _tx_last_packet)); return ERR_OK; @@ -1031,7 +1071,7 @@ int8_t AsyncClient::_poll(tcp_pcb * pcb) { } // RX Timeout if (_rx_timeout && (now - _rx_last_packet) >= (_rx_timeout * 1000)) { - log_w("rx timeout %d", pcb->state); + log_d("rx timeout %d", pcb->state); _close(); return ERR_OK; } @@ -1052,7 +1092,9 @@ void AsyncClient::_dns_found(struct ip_addr * ipaddr) { #endif #else if (ipaddr) { - connect(IPAddress(ipaddr), _connect_port); + IPAddress ip; + ip.from_ip_addr_t(ipaddr); + connect(ip, _connect_port); #endif } else { if (_error_cb) { @@ -1076,7 +1118,7 @@ bool AsyncClient::free() { if (!_pcb) { return true; } - if (_pcb->state == 0 || _pcb->state > 4) { + if (_pcb->state == CLOSED || _pcb->state > ESTABLISHED) { return true; } return false; @@ -1131,6 +1173,18 @@ bool AsyncClient::getNoDelay() { return tcp_nagle_disabled(_pcb); } +void AsyncClient::setKeepAlive(uint32_t ms, uint8_t cnt) { + if (ms != 0) { + _pcb->so_options |= SOF_KEEPALIVE; //Turn on TCP Keepalive for the given pcb + // Set the time between keepalive messages in milli-seconds + _pcb->keep_idle = ms; + _pcb->keep_intvl = ms; + _pcb->keep_cnt = cnt; //The number of unanswered probes required to force closure of the socket + } else { + _pcb->so_options &= ~SOF_KEEPALIVE; //Turn off TCP Keepalive for the given pcb + } +} + uint16_t AsyncClient::getMss() { if (!_pcb) { return 0; @@ -1177,11 +1231,21 @@ IPv6Address AsyncClient::localIP6() { } #else IPAddress AsyncClient::remoteIP6() { - return _pcb ? IPAddress(dynamic_cast(&_pcb->remote_ip)) : IPAddress(IPType::IPv6); + if (!_pcb) { + return IPAddress(IPType::IPv6); + } + IPAddress ip; + ip.from_ip_addr_t(&(_pcb->remote_ip)); + return ip; } IPAddress AsyncClient::localIP6() { - return _pcb ? IPAddress(dynamic_cast(&_pcb->local_ip)) : IPAddress(IPType::IPv6); + if (!_pcb) { + return IPAddress(IPType::IPv6); + } + IPAddress ip; + ip.from_ip_addr_t(&(_pcb->local_ip)); + return ip; } #endif #endif @@ -1215,7 +1279,12 @@ IPAddress AsyncClient::remoteIP() { #if ESP_IDF_VERSION_MAJOR < 5 return IPAddress(getRemoteAddress()); #else - return _pcb ? IPAddress(dynamic_cast(&_pcb->remote_ip)) : IPAddress(); + if (!_pcb) { + return IPAddress(); + } + IPAddress ip; + ip.from_ip_addr_t(&(_pcb->remote_ip)); + return ip; #endif } @@ -1227,7 +1296,12 @@ IPAddress AsyncClient::localIP() { #if ESP_IDF_VERSION_MAJOR < 5 return IPAddress(getLocalAddress()); #else - return _pcb ? IPAddress(dynamic_cast(&_pcb->local_ip)) : IPAddress(); + if (!_pcb) { + return IPAddress(); + } + IPAddress ip; + ip.from_ip_addr_t(&(_pcb->local_ip)); + return ip; #endif } @@ -1247,35 +1321,35 @@ bool AsyncClient::connected() { if (!_pcb) { return false; } - return _pcb->state == 4; + return _pcb->state == ESTABLISHED; } bool AsyncClient::connecting() { if (!_pcb) { return false; } - return _pcb->state > 0 && _pcb->state < 4; + return _pcb->state > CLOSED && _pcb->state < ESTABLISHED; } bool AsyncClient::disconnecting() { if (!_pcb) { return false; } - return _pcb->state > 4 && _pcb->state < 10; + return _pcb->state > ESTABLISHED && _pcb->state < TIME_WAIT; } bool AsyncClient::disconnected() { if (!_pcb) { return true; } - return _pcb->state == 0 || _pcb->state == 10; + return _pcb->state == CLOSED || _pcb->state == TIME_WAIT; } bool AsyncClient::freeable() { if (!_pcb) { return true; } - return _pcb->state == 0 || _pcb->state > 4; + return _pcb->state == CLOSED || _pcb->state > ESTABLISHED; } bool AsyncClient::canSend() { @@ -1384,7 +1458,7 @@ void AsyncClient::_s_error(void * arg, int8_t err) { reinterpret_cast(arg)->_error(err); } -int8_t AsyncClient::_s_connected(void * arg, void * pcb, int8_t err) { +int8_t AsyncClient::_s_connected(void * arg, struct tcp_pcb * pcb, int8_t err) { return reinterpret_cast(arg)->_connected(pcb, err); } @@ -1396,6 +1470,7 @@ AsyncServer::AsyncServer(IPAddress addr, uint16_t port) : _port(port) #if ESP_IDF_VERSION_MAJOR < 5 , _bind4(true) + , _bind6(false) #else , _bind4(addr.type() != IPType::IPv6) , _bind6(addr.type() == IPType::IPv6) @@ -1410,6 +1485,7 @@ AsyncServer::AsyncServer(IPAddress addr, uint16_t port) #if ESP_IDF_VERSION_MAJOR < 5 AsyncServer::AsyncServer(IPv6Address addr, uint16_t port) : _port(port) + , _bind4(false) , _bind6(true) , _addr6(addr) , _noDelay(false) @@ -1422,7 +1498,7 @@ AsyncServer::AsyncServer(IPv6Address addr, uint16_t port) AsyncServer::AsyncServer(uint16_t port) : _port(port) , _bind4(true) - , _bind6(true) + , _bind6(false) , _addr((uint32_t)IPADDR_ANY) #if ESP_IDF_VERSION_MAJOR < 5 , _addr6() @@ -1451,17 +1527,10 @@ void AsyncServer::begin() { log_e("failed to start task"); return; } - int8_t err, bind_type; - - if (_bind4 && _bind6) { - bind_type = IPADDR_TYPE_ANY; - } else if (_bind6) { - bind_type = IPADDR_TYPE_V6; - } else { - bind_type = IPADDR_TYPE_V4; - } - - _pcb = tcp_new_ip_type(bind_type); + 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; @@ -1469,13 +1538,13 @@ void AsyncServer::begin() { ip_addr_t local_addr; #if ESP_IDF_VERSION_MAJOR < 5 - // ip_addr_set_ip4_u32(&local_addr, _addr); - local_addr.u_addr.ip4.addr = _addr; - local_addr.type = IPADDR_TYPE_V4; - ip_clear_no4(&local_addr); - /* local_addr.type = bind_type; - local_addr.u_addr.ip4.addr = (uint32_t) _addr; - memcpy(local_addr.u_addr.ip6.addr, static_cast(_addr6), sizeof(uint32_t) * 4); */ + if (_bind6) { // _bind6 && _bind4 both at the same time is not supported on Arduino 2 in this lib API + local_addr.type = IPADDR_TYPE_V6; + memcpy(local_addr.u_addr.ip6.addr, static_cast(_addr6), sizeof(uint32_t) * 4); + } else { + local_addr.type = IPADDR_TYPE_V4; + local_addr.u_addr.ip4.addr = _addr; + } #else _addr.to_ip_addr_t(&local_addr); #endif @@ -1493,16 +1562,22 @@ 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); if (tcp_close(_pcb) != ERR_OK) { + TCP_MUTEX_UNLOCK(); _tcp_abort(_pcb, -1); + } else { + TCP_MUTEX_UNLOCK(); } _pcb = NULL; } @@ -1521,7 +1596,7 @@ int8_t AsyncServer::_accept(tcp_pcb * pcb, int8_t err) { if (tcp_close(pcb) != ERR_OK) { tcp_abort(pcb); } - log_e("FAIL"); + log_d("FAIL"); return ERR_OK; } @@ -1553,4 +1628,4 @@ int8_t AsyncServer::_s_accept(void * arg, tcp_pcb * pcb, int8_t err) { int8_t AsyncServer::_s_accepted(void * arg, AsyncClient * client) { return reinterpret_cast(arg)->_accepted(client); -} \ No newline at end of file +} diff --git a/lib/AsyncTCP/src/AsyncTCP.h b/lib/AsyncTCP/src/AsyncTCP.h index b44a6ced7..40a894e1f 100644 --- a/lib/AsyncTCP/src/AsyncTCP.h +++ b/lib/AsyncTCP/src/AsyncTCP.h @@ -22,6 +22,12 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ +#define ASYNCTCP_VERSION "3.2.14" +#define ASYNCTCP_VERSION_MAJOR 3 +#define ASYNCTCP_VERSION_MINOR 2 +#define ASYNCTCP_VERSION_REVISION 14 +#define ASYNCTCP_FORK_mathieucarbou + #include "IPAddress.h" #if ESP_IDF_VERSION_MAJOR < 5 #include "IPv6Address.h" @@ -52,24 +58,26 @@ extern "C" { #define CONFIG_ASYNC_TCP_USE_WDT 1 //if enabled, adds between 33us and 200us per event #endif -#ifndef CONFIG_ASYNC_TCP_TASK_PRIORITY -#define CONFIG_ASYNC_TCP_TASK_PRIORITY 5 -#endif - // EMS-ESP: stack usage measured: ESP32: ~2.3K, ESP32S3: ~3.5k #ifndef CONFIG_ASYNC_TCP_STACK_SIZE -#define CONFIG_ASYNC_TCP_STACK_SIZE 5120 +#define CONFIG_ASYNC_TCP_STACK_SIZE 6144 #endif +#ifndef CONFIG_ASYNC_TCP_PRIORITY +#define CONFIG_ASYNC_TCP_PRIORITY 5 +#endif // EMS-ESP: maybe enlarge queue to 64 or 128 see https://github.com/emsesp/EMS-ESP32/issues/177 -#ifndef CONFIG_ASYNC_TCP_QUEUE -#define CONFIG_ASYNC_TCP_QUEUE 32 +#ifndef CONFIG_ASYNC_TCP_QUEUE_SIZE +#define CONFIG_ASYNC_TCP_QUEUE_SIZE 32 +#endif + +#ifndef CONFIG_ASYNC_TCP_MAX_ACK_TIME +#define CONFIG_ASYNC_TCP_MAX_ACK_TIME 5000 #endif class AsyncClient; -#define ASYNC_MAX_ACK_TIME 5000 #define ASYNC_WRITE_FLAG_COPY 0x01 //will allocate new buffer to hold the data while sending (else will hold reference to the data given) #define ASYNC_WRITE_FLAG_MORE 0x02 //will not send PSH flag, meaning that there should be more data to be sent before the application should react. @@ -96,9 +104,9 @@ class AsyncClient { bool operator!=(const AsyncClient & other) { return !(*this == other); } - bool connect(IPAddress ip, uint16_t port); + bool connect(const IPAddress & ip, uint16_t port); #if ESP_IDF_VERSION_MAJOR < 5 - bool connect(IPv6Address ip, uint16_t port); + bool connect(const IPv6Address & ip, uint16_t port); #endif bool connect(const char * host, uint16_t port); void close(bool now = false); @@ -133,6 +141,8 @@ class AsyncClient { void setNoDelay(bool nodelay); bool getNoDelay(); + void setKeepAlive(uint32_t ms, uint8_t cnt); + uint32_t getRemoteAddress(); uint16_t getRemotePort(); uint32_t getLocalAddress(); @@ -180,7 +190,7 @@ class AsyncClient { static int8_t _s_lwip_fin(void * arg, struct tcp_pcb * tpcb, int8_t err); static void _s_error(void * arg, int8_t err); static int8_t _s_sent(void * arg, struct tcp_pcb * tpcb, uint16_t len); - static int8_t _s_connected(void * arg, void * tpcb, int8_t err); + static int8_t _s_connected(void * arg, struct tcp_pcb * tpcb, int8_t err); static void _s_dns_found(const char * name, struct ip_addr * ipaddr, void * arg); int8_t _recv(tcp_pcb * pcb, pbuf * pb, int8_t err); @@ -222,8 +232,8 @@ class AsyncClient { int8_t _close(); void _free_closed_slot(); - void _allocate_closed_slot(); - int8_t _connected(void * pcb, int8_t err); + bool _allocate_closed_slot(); + int8_t _connected(tcp_pcb * pcb, int8_t err); void _error(int8_t err); int8_t _poll(tcp_pcb * pcb); int8_t _sent(tcp_pcb * pcb, uint16_t len); @@ -273,4 +283,4 @@ class AsyncServer { }; -#endif /* ASYNCTCP_H_ */ \ No newline at end of file +#endif /* ASYNCTCP_H_ */ diff --git a/src/version.h b/src/version.h index 45867d0f5..075b79798 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.7.2-dev.3" \ No newline at end of file +#define EMSESP_APP_VERSION "3.7.2-dev.4" \ No newline at end of file