From 5b1ef41e83a70da3107aa792b73103de39305d5a Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Mon, 14 Oct 2019 12:45:57 +0200 Subject: [PATCH 001/150] Create fork for esphome --- README.md | 4 +++- library.json | 6 +++--- library.properties | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 983aabd..f12573a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ -# AsyncTCP +# AsyncTCP [![Build Status](https://travis-ci.org/me-no-dev/AsyncTCP.svg?branch=master)](https://travis-ci.org/me-no-dev/AsyncTCP) ![](https://github.com/me-no-dev/AsyncTCP/workflows/Async%20TCP%20CI/badge.svg) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/2f7e4d1df8b446d192cbfec6dc174d2d)](https://www.codacy.com/manual/me-no-dev/AsyncTCP?utm_source=github.com&utm_medium=referral&utm_content=me-no-dev/AsyncTCP&utm_campaign=Badge_Grade) +A fork of the [AsyncTCP](https://github.com/me-no-dev/AsyncTCP) library by [@me-no-dev](https://github.com/me-no-dev) for [ESPHome](https://esphome.io). + ### Async TCP Library for ESP32 Arduino [![Join the chat at https://gitter.im/me-no-dev/ESPAsyncWebServer](https://badges.gitter.im/me-no-dev/ESPAsyncWebServer.svg)](https://gitter.im/me-no-dev/ESPAsyncWebServer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) diff --git a/library.json b/library.json index 89f90e4..5041b7c 100644 --- a/library.json +++ b/library.json @@ -1,5 +1,5 @@ { - "name":"AsyncTCP", + "name":"AsyncTCP-esphome", "description":"Asynchronous TCP Library for ESP32", "keywords":"async,tcp", "authors": @@ -10,7 +10,7 @@ "repository": { "type": "git", - "url": "https://github.com/me-no-dev/AsyncTCP.git" + "url": "https://github.com/OttoWinter/AsyncTCP.git" }, "version": "1.1.1", "license": "LGPL-3.0", @@ -18,5 +18,5 @@ "platforms": "espressif32", "build": { "libCompatMode": 2 - } + } } diff --git a/library.properties b/library.properties index eb4e26e..38f03d4 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ -name=AsyncTCP +name=AsyncTCP-esphome version=1.1.1 author=Me-No-Dev maintainer=Me-No-Dev sentence=Async TCP Library for ESP32 paragraph=Async TCP Library for ESP32 category=Other -url=https://github.com/me-no-dev/AsyncTCP +url=https://github.com/OttoWinter/AsyncTCP architectures=* From c18b7cafcc86b03166f7025584e16c62bff9adbe Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Mon, 14 Oct 2019 12:46:51 +0200 Subject: [PATCH 002/150] Create fallback xTaskCreateUniversal function --- src/AsyncTCP.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 9071ead..b1b47cd 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -210,12 +210,32 @@ static void _stop_async_task(){ } } */ + +static bool customTaskCreateUniversal( + TaskFunction_t pxTaskCode, + const char * const pcName, + const uint32_t usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pxCreatedTask, + const BaseType_t xCoreID) { +#ifndef CONFIG_FREERTOS_UNICORE + if(xCoreID >= 0 && xCoreID < 2) { + return xTaskCreatePinnedToCore(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, xCoreID); + } else { +#endif + return xTaskCreate(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask); +#ifndef CONFIG_FREERTOS_UNICORE + } +#endif +} + static bool _start_async_task(){ if(!_init_async_event_queue()){ return false; } if(!_async_service_task_handle){ - xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 * 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE); + customTaskCreateUniversal(_async_service_task, "async_tcp", 8192 * 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE); if(!_async_service_task_handle){ return false; } From cfecaa3a1ce00052e00335da30b21266781849ec Mon Sep 17 00:00:00 2001 From: Otto winter Date: Thu, 8 Apr 2021 15:34:35 +0200 Subject: [PATCH 003/150] Bump version to 1.2.0 --- library.json | 2 +- library.properties | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) delete mode 100644 library.properties diff --git a/library.json b/library.json index 5041b7c..3acca7b 100644 --- a/library.json +++ b/library.json @@ -12,7 +12,7 @@ "type": "git", "url": "https://github.com/OttoWinter/AsyncTCP.git" }, - "version": "1.1.1", + "version": "1.2.0", "license": "LGPL-3.0", "frameworks": "arduino", "platforms": "espressif32", diff --git a/library.properties b/library.properties deleted file mode 100644 index 38f03d4..0000000 --- a/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=AsyncTCP-esphome -version=1.1.1 -author=Me-No-Dev -maintainer=Me-No-Dev -sentence=Async TCP Library for ESP32 -paragraph=Async TCP Library for ESP32 -category=Other -url=https://github.com/OttoWinter/AsyncTCP -architectures=* From 030b7476164e58c355cb3a47d44b8cc3d82e0ec5 Mon Sep 17 00:00:00 2001 From: Maurice Makaay Date: Sun, 11 Apr 2021 19:09:21 +0200 Subject: [PATCH 004/150] Fix race condition causing 'ack timeout 4' disconnects (#4) The AsyncClient::send() methods sets a boolean to true after pushing data over the TCP socket successfully using tcp_output(). It also sets a timestamp to remember at what time the data was sent. The AsyncClient::_sent() callback method reacts to ACKs coming from the connected client. This method sets the boolean to false. In the AsyncClient::_poll() method, a check is done to see if the boolean is true ("I'm waiting for an ACK") and if the time at which the data was sent is too long ago (5000 ms). If this is the case, a connection issue with the connected client is assumed and the connection is forcibly closed by the server. The race condition is when these operations get mixed up, because of multithreading behavior. The _sent() method can be called during the execution of the send() method: 1. send() sends out data using tcp_output() 2. _sent() is called because an ACK is processed, sets boolean to false 3. send() continues and sets boolean to true + timestamp to "now" After this, the data exchange with the client was successful. Data were sent and the ACK was seen. However, the boolean ended up as true, making the _poll() method think that an ACK is still to be expected. As a result, 5000 ms later, the connection is dropped. This commit fixes the code by first registering that an ACK is expected, before calling tcp_output(). This way, there is no race condition when the ACK is processed right after that call. Additionally, I changed the boolean to an integer counter value. The server might send multiple messages to the client, resulting in multiple expected ACKs. A boolean does not cover this situation. Co-authored-by: Maurice Makaay --- src/AsyncTCP.cpp | 21 +++++++++++---------- src/AsyncTCP.h | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index c305a70..471e8fc 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -575,7 +575,7 @@ AsyncClient::AsyncClient(tcp_pcb* pcb) , _pb_cb_arg(0) , _timeout_cb(0) , _timeout_cb_arg(0) -, _pcb_busy(false) +, _pcb_busy(0) , _pcb_sent_at(0) , _ack_pcb(true) , _rx_last_packet(0) @@ -783,13 +783,14 @@ size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) { } bool AsyncClient::send(){ - int8_t err = ERR_OK; - err = _tcp_output(_pcb, _closed_slot); - if(err == ERR_OK){ - _pcb_busy = true; - _pcb_sent_at = millis(); + auto pcb_sent_at_backup = _pcb_sent_at; + _pcb_sent_at = millis(); + _pcb_busy++; + if (_tcp_output(_pcb, _closed_slot) == ERR_OK) { return true; } + _pcb_sent_at = pcb_sent_at_backup; + _pcb_busy--; return false; } @@ -869,7 +870,7 @@ int8_t AsyncClient::_connected(void* pcb, int8_t err){ _pcb = reinterpret_cast(pcb); if(_pcb){ _rx_last_packet = millis(); - _pcb_busy = false; + _pcb_busy = 0; // tcp_recv(_pcb, &_tcp_recv); // tcp_sent(_pcb, &_tcp_sent); // tcp_poll(_pcb, &_tcp_poll, 1); @@ -932,7 +933,7 @@ int8_t AsyncClient::_fin(tcp_pcb* pcb, int8_t err) { int8_t AsyncClient::_sent(tcp_pcb* pcb, uint16_t len) { _rx_last_packet = millis(); //log_i("%u", len); - _pcb_busy = false; + _pcb_busy--; if(_sent_cb) { _sent_cb(_sent_cb_arg, this, len, (millis() - _pcb_sent_at)); } @@ -977,8 +978,8 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){ uint32_t now = millis(); // ACK Timeout - if(_pcb_busy && _ack_timeout && (now - _pcb_sent_at) >= _ack_timeout){ - _pcb_busy = false; + if(_pcb_busy > 0 && _ack_timeout && (now - _pcb_sent_at) >= _ack_timeout){ + _pcb_busy = 0; log_w("ack timeout %d", pcb->state); if(_timeout_cb) _timeout_cb(_timeout_cb_arg, this, (now - _pcb_sent_at)); diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index ac87ded..fcd511b 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -160,7 +160,7 @@ class AsyncClient { AcConnectHandler _poll_cb; void* _poll_cb_arg; - bool _pcb_busy; + uint32_t _pcb_busy; uint32_t _pcb_sent_at; bool _ack_pcb; uint32_t _rx_ack_len; From f278522a5961086e3bb798557cb89d6094f82d5c Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Sun, 11 Apr 2021 19:09:48 +0200 Subject: [PATCH 005/150] Bump version to 1.2.1 --- library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.json b/library.json index 3acca7b..c5e1f44 100644 --- a/library.json +++ b/library.json @@ -12,7 +12,7 @@ "type": "git", "url": "https://github.com/OttoWinter/AsyncTCP.git" }, - "version": "1.2.0", + "version": "1.2.1", "license": "LGPL-3.0", "frameworks": "arduino", "platforms": "espressif32", From 6f379678f014deae1a5103cec2bf4f4536a56c6b Mon Sep 17 00:00:00 2001 From: Maurice Makaay Date: Wed, 5 May 2021 23:56:48 +0200 Subject: [PATCH 006/150] Better fix for "ack timeout 4" client disconnects. After my first attempt at fixing the client disconnects (https://github.com/OttoWinter/AsyncTCP/pull/4) got merged into AsyncTCP, it turned out that there was regression for some devices: the connection stability actually went down instead of up. After a lot of debugging and discussion with @glmnet (some of the results can be found in the above pull request discussion), we came up with an improved fix for the disconnect issues. **Changed:** The code that checks for ACK timeouts has been simplified in such way, that only two timestamps are now used to determine if an ACK timeout has happened: the time of the last sent packet (this was already recorded), and the time of the last received ACK from the client (this has been added). Using these timestamps, there is no more need for a separate field to keep track if we are waiting for an ACK or not (`_pcb_busy`). Therefore, this field was completely removed from the code. While I was at it, I renamed a few variables to make the code easier to read and more consistent. **Results:** I connected Home Assistant plus 8 OTA loggers at the same time, using very verbose logging output. This normally was an easy way to trigger the disconnect errors. It turned out, this solution runs as solid for me, as when disabling the ACK timeout checks completely (using `AsyncClient::setAckTimeout(0)`). --- src/AsyncTCP.cpp | 41 ++++++++++++++++++++--------------------- src/AsyncTCP.h | 6 +++--- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 471e8fc..771c0a8 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -575,11 +575,10 @@ AsyncClient::AsyncClient(tcp_pcb* pcb) , _pb_cb_arg(0) , _timeout_cb(0) , _timeout_cb_arg(0) -, _pcb_busy(0) -, _pcb_sent_at(0) , _ack_pcb(true) -, _rx_last_packet(0) -, _rx_since_timeout(0) +, _tx_last_packet(0) +, _rx_timeout(0) +, _rx_last_ack(0) , _ack_timeout(ASYNC_MAX_ACK_TIME) , _connect_port(0) , prev(NULL) @@ -783,14 +782,12 @@ size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) { } bool AsyncClient::send(){ - auto pcb_sent_at_backup = _pcb_sent_at; - _pcb_sent_at = millis(); - _pcb_busy++; + auto backup = _tx_last_packet; + _tx_last_packet = millis(); if (_tcp_output(_pcb, _closed_slot) == ERR_OK) { return true; } - _pcb_sent_at = pcb_sent_at_backup; - _pcb_busy--; + _tx_last_packet = backup; return false; } @@ -870,7 +867,6 @@ int8_t AsyncClient::_connected(void* pcb, int8_t err){ _pcb = reinterpret_cast(pcb); if(_pcb){ _rx_last_packet = millis(); - _pcb_busy = 0; // tcp_recv(_pcb, &_tcp_recv); // tcp_sent(_pcb, &_tcp_sent); // tcp_poll(_pcb, &_tcp_poll, 1); @@ -932,10 +928,10 @@ 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); - _pcb_busy--; if(_sent_cb) { - _sent_cb(_sent_cb_arg, this, len, (millis() - _pcb_sent_at)); + _sent_cb(_sent_cb_arg, this, len, (millis() - _tx_last_packet)); } return ERR_OK; } @@ -978,15 +974,18 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){ uint32_t now = millis(); // ACK Timeout - if(_pcb_busy > 0 && _ack_timeout && (now - _pcb_sent_at) >= _ack_timeout){ - _pcb_busy = 0; - log_w("ack timeout %d", pcb->state); - if(_timeout_cb) - _timeout_cb(_timeout_cb_arg, this, (now - _pcb_sent_at)); - return ERR_OK; + if(_ack_timeout){ + 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); + if(_timeout_cb) + _timeout_cb(_timeout_cb_arg, this, (now - _tx_last_packet)); + return ERR_OK; + } } // RX Timeout - if(_rx_since_timeout && (now - _rx_last_packet) >= (_rx_since_timeout * 1000)){ + if(_rx_timeout && (now - _rx_last_packet) >= (_rx_timeout * 1000)) { log_w("rx timeout %d", pcb->state); _close(); return ERR_OK; @@ -1045,11 +1044,11 @@ size_t AsyncClient::write(const char* data, size_t size, uint8_t apiflags) { } void AsyncClient::setRxTimeout(uint32_t timeout){ - _rx_since_timeout = timeout; + _rx_timeout = timeout; } uint32_t AsyncClient::getRxTimeout(){ - return _rx_since_timeout; + return _rx_timeout; } uint32_t AsyncClient::getAckTimeout(){ diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index fcd511b..9786490 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -160,12 +160,12 @@ class AsyncClient { AcConnectHandler _poll_cb; void* _poll_cb_arg; - uint32_t _pcb_busy; - uint32_t _pcb_sent_at; bool _ack_pcb; + uint32_t _tx_last_packet; uint32_t _rx_ack_len; uint32_t _rx_last_packet; - uint32_t _rx_since_timeout; + uint32_t _rx_timeout; + uint32_t _rx_last_ack; uint32_t _ack_timeout; uint16_t _connect_port; From 18ac673e82bfd2542c0ba12f10615963c13fb5b9 Mon Sep 17 00:00:00 2001 From: Maurice Makaay Date: Thu, 6 May 2021 00:41:06 +0200 Subject: [PATCH 007/150] Define one_day var as a const. --- src/AsyncTCP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 771c0a8..59ef186 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -975,7 +975,7 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){ // ACK Timeout if(_ack_timeout){ - uint32_t one_day = 86400000; + 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); From 7c767c3f6b36adb0c54bd09f7070b23d46d544d8 Mon Sep 17 00:00:00 2001 From: Guillermo Ruffino Date: Sun, 9 May 2021 19:11:18 -0300 Subject: [PATCH 008/150] Bump version to 1.2.2 --- library.json | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/library.json b/library.json index c5e1f44..bf6a412 100644 --- a/library.json +++ b/library.json @@ -1,18 +1,16 @@ { - "name":"AsyncTCP-esphome", - "description":"Asynchronous TCP Library for ESP32", - "keywords":"async,tcp", - "authors": - { + "name": "AsyncTCP-esphome", + "description": "Asynchronous TCP Library for ESP32", + "keywords": "async,tcp", + "authors": { "name": "Hristo Gochkov", "maintainer": true }, - "repository": - { + "repository": { "type": "git", - "url": "https://github.com/OttoWinter/AsyncTCP.git" + "url": "https://github.com/esphome/AsyncTCP.git" }, - "version": "1.2.1", + "version": "1.2.2", "license": "LGPL-3.0", "frameworks": "arduino", "platforms": "espressif32", From fb0411b699ec9c81f3a7cab72a8574ae380f55dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Tue, 9 Aug 2022 07:34:14 +0200 Subject: [PATCH 009/150] Adapt for LibreTuya compatibility (#3) --- library.json | 2 +- src/AsyncTCP.cpp | 29 ++++++++++++++++++++++++++++- src/AsyncTCP.h | 16 +++++++++++++++- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/library.json b/library.json index bf6a412..0f1142f 100644 --- a/library.json +++ b/library.json @@ -13,7 +13,7 @@ "version": "1.2.2", "license": "LGPL-3.0", "frameworks": "arduino", - "platforms": "espressif32", + "platforms": ["espressif32", "libretuya"], "build": { "libCompatMode": 2 } diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 59ef186..ff82593 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -29,7 +29,9 @@ extern "C"{ #include "lwip/dns.h" #include "lwip/err.h" } +#if CONFIG_ASYNC_TCP_USE_WDT #include "esp_task_wdt.h" +#endif /* * TCP/IP Event Task @@ -238,7 +240,7 @@ static bool _start_async_task(){ return false; } if(!_async_service_task_handle){ - customTaskCreateUniversal(_async_service_task, "async_tcp", 8192 * 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE); + customTaskCreateUniversal(_async_service_task, "async_tcp", CONFIG_ASYNC_TCP_STACK_SIZE, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE); if(!_async_service_task_handle){ return false; } @@ -704,8 +706,12 @@ bool AsyncClient::connect(IPAddress ip, uint16_t port){ } ip_addr_t addr; +#if LWIP_IPV4 && LWIP_IPV6 addr.type = IPADDR_TYPE_V4; addr.u_addr.ip4.addr = ip; +#else + addr.addr = ip; +#endif tcp_pcb* pcb = tcp_new_ip_type(IPADDR_TYPE_V4); if (!pcb){ @@ -733,7 +739,11 @@ bool AsyncClient::connect(const char* host, uint16_t port){ err_t err = dns_gethostbyname(host, &addr, (dns_found_callback)&_tcp_dns_found, this); if(err == ERR_OK) { +#if LWIP_IPV4 && LWIP_IPV6 return connect(IPAddress(addr.u_addr.ip4.addr), port); +#else + return connect(IPAddress(addr.addr), port); +#endif } else if(err == ERR_INPROGRESS) { _connect_port = port; return true; @@ -998,8 +1008,13 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){ } void AsyncClient::_dns_found(struct ip_addr *ipaddr){ +#if LWIP_IPV4 && LWIP_IPV6 if(ipaddr && ipaddr->u_addr.ip4.addr){ connect(IPAddress(ipaddr->u_addr.ip4.addr), _connect_port); +#else + if (ipaddr && ipaddr->addr){ + connect(IPAddress(ipaddr->addr), _connect_port); +#endif } else { if(_error_cb) { _error_cb(_error_cb_arg, this, -55); @@ -1088,7 +1103,11 @@ uint32_t AsyncClient::getRemoteAddress() { if(!_pcb) { return 0; } +#if LWIP_IPV4 && LWIP_IPV6 return _pcb->remote_ip.u_addr.ip4.addr; +#else + return _pcb->remote_ip.addr; +#endif } uint16_t AsyncClient::getRemotePort() { @@ -1102,7 +1121,11 @@ uint32_t AsyncClient::getLocalAddress() { if(!_pcb) { return 0; } +#if LWIP_IPV4 && LWIP_IPV6 return _pcb->local_ip.u_addr.ip4.addr; +#else + return _pcb->local_ip.addr; +#endif } uint16_t AsyncClient::getLocalPort() { @@ -1298,8 +1321,12 @@ void AsyncServer::begin(){ } ip_addr_t local_addr; +#if LWIP_IPV4 && LWIP_IPV6 local_addr.type = IPADDR_TYPE_V4; local_addr.u_addr.ip4.addr = (uint32_t) _addr; +#else + local_addr.addr = (uint32_t) _addr; +#endif err = _tcp_bind(_pcb, &local_addr, _port); if (err != ERR_OK) { diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 9786490..74659db 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -23,12 +23,22 @@ #define ASYNCTCP_H_ #include "IPAddress.h" -#include "sdkconfig.h" #include + +#ifndef LIBRETUYA +#include "sdkconfig.h" extern "C" { #include "freertos/semphr.h" #include "lwip/pbuf.h" } +#else +extern "C" { + #include + #include +} +#define CONFIG_ASYNC_TCP_RUNNING_CORE -1 //any available core +#define CONFIG_ASYNC_TCP_USE_WDT 0 +#endif //If core is not defined, then we are running in Arduino or PIO #ifndef CONFIG_ASYNC_TCP_RUNNING_CORE @@ -36,6 +46,10 @@ extern "C" { #define CONFIG_ASYNC_TCP_USE_WDT 1 //if enabled, adds between 33us and 200us per event #endif +#ifndef CONFIG_ASYNC_TCP_STACK_SIZE +#define CONFIG_ASYNC_TCP_STACK_SIZE 8192 * 2 +#endif + class AsyncClient; #define ASYNC_MAX_ACK_TIME 5000 From c04346412903c0ccd4eaab565b7089e96b55003e Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 9 Aug 2022 17:34:36 +1200 Subject: [PATCH 010/150] Bump version to 2.0.0 --- library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.json b/library.json index 0f1142f..468e29c 100644 --- a/library.json +++ b/library.json @@ -10,7 +10,7 @@ "type": "git", "url": "https://github.com/esphome/AsyncTCP.git" }, - "version": "1.2.2", + "version": "2.0.0", "license": "LGPL-3.0", "frameworks": "arduino", "platforms": ["espressif32", "libretuya"], From c53368456fc79630b39b37a8464455c92c50b6dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Fri, 1 Sep 2023 04:12:55 +0200 Subject: [PATCH 011/150] Rename LibreTuya to LibreTiny (#4) --- library.json | 2 +- src/AsyncTCP.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.json b/library.json index 468e29c..dba64db 100644 --- a/library.json +++ b/library.json @@ -13,7 +13,7 @@ "version": "2.0.0", "license": "LGPL-3.0", "frameworks": "arduino", - "platforms": ["espressif32", "libretuya"], + "platforms": ["espressif32", "libretiny"], "build": { "libCompatMode": 2 } diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 74659db..1e781b3 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -25,7 +25,7 @@ #include "IPAddress.h" #include -#ifndef LIBRETUYA +#ifndef LIBRETINY #include "sdkconfig.h" extern "C" { #include "freertos/semphr.h" From dc64fedec0c953ba4f52b6bb8bc5ef1a3abdc22d Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 1 Sep 2023 14:18:18 +1200 Subject: [PATCH 012/150] Bump version to 2.0.1 --- library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.json b/library.json index dba64db..957bd19 100644 --- a/library.json +++ b/library.json @@ -10,7 +10,7 @@ "type": "git", "url": "https://github.com/esphome/AsyncTCP.git" }, - "version": "2.0.0", + "version": "2.0.1", "license": "LGPL-3.0", "frameworks": "arduino", "platforms": ["espressif32", "libretiny"], From 42a8644bb2fe2e0526a35eeaa6021dd55c1b362c Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Thu, 21 Dec 2023 04:59:30 +0100 Subject: [PATCH 013/150] IPv6 support added (#5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Paweł pidpawel Kozubal --- src/AsyncTCP.cpp | 103 +++++++++++++++++++++++++++++++++++------------ src/AsyncTCP.h | 21 ++++++++-- 2 files changed, 96 insertions(+), 28 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index ff82593..3ab2a7b 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -695,7 +695,7 @@ void AsyncClient::onPoll(AcConnectHandler cb, void* arg){ * Main Public Methods * */ -bool AsyncClient::connect(IPAddress ip, uint16_t port){ +bool AsyncClient::_connect(ip_addr_t addr, uint16_t port){ if (_pcb){ log_w("already connected, state %d", _pcb->state); return false; @@ -705,15 +705,7 @@ bool AsyncClient::connect(IPAddress ip, uint16_t port){ return false; } - ip_addr_t addr; -#if LWIP_IPV4 && LWIP_IPV6 - addr.type = IPADDR_TYPE_V4; - addr.u_addr.ip4.addr = ip; -#else - addr.addr = ip; -#endif - - tcp_pcb* pcb = tcp_new_ip_type(IPADDR_TYPE_V4); + tcp_pcb* pcb = tcp_new_ip_type(addr.type); if (!pcb){ log_e("pcb == NULL"); return false; @@ -724,22 +716,39 @@ bool AsyncClient::connect(IPAddress ip, uint16_t port){ tcp_recv(pcb, &_tcp_recv); tcp_sent(pcb, &_tcp_sent); tcp_poll(pcb, &_tcp_poll, 1); - //_tcp_connect(pcb, &addr, port,(tcp_connected_fn)&_s_connected); _tcp_connect(pcb, _closed_slot, &addr, port,(tcp_connected_fn)&_tcp_connected); return true; } +bool AsyncClient::connect(IPAddress ip, uint16_t port){ + ip_addr_t addr; + addr.type = IPADDR_TYPE_V4; + addr.u_addr.ip4.addr = ip; + + return _connect(addr, port); +} + +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); + + return _connect(addr, port); +} + bool AsyncClient::connect(const char* host, uint16_t port){ ip_addr_t addr; - + if(!_start_async_task()){ log_e("failed to start task"); return false; } - + err_t err = dns_gethostbyname(host, &addr, (dns_found_callback)&_tcp_dns_found, this); if(err == ERR_OK) { -#if LWIP_IPV4 && LWIP_IPV6 + if(addr.type == IPADDR_TYPE_V6) { + return connect(IPv6Address(addr.u_addr.ip6.addr), port); + } return connect(IPAddress(addr.u_addr.ip4.addr), port); #else return connect(IPAddress(addr.addr), port); @@ -1011,10 +1020,8 @@ void AsyncClient::_dns_found(struct ip_addr *ipaddr){ #if LWIP_IPV4 && LWIP_IPV6 if(ipaddr && ipaddr->u_addr.ip4.addr){ connect(IPAddress(ipaddr->u_addr.ip4.addr), _connect_port); -#else - if (ipaddr && ipaddr->addr){ - connect(IPAddress(ipaddr->addr), _connect_port); -#endif + } else if(ipaddr && ipaddr->u_addr.ip6.addr){ + connect(IPv6Address(ipaddr->u_addr.ip6.addr), _connect_port); } else { if(_error_cb) { _error_cb(_error_cb_arg, this, -55); @@ -1110,6 +1117,15 @@ uint32_t AsyncClient::getRemoteAddress() { #endif } +ip6_addr_t AsyncClient::getRemoteAddress6() { + if(!_pcb) { + ip6_addr_t nulladdr; + ip6_addr_set_zero(&nulladdr); + return nulladdr; + } + return _pcb->remote_ip.u_addr.ip6; +} + uint16_t AsyncClient::getRemotePort() { if(!_pcb) { return 0; @@ -1128,6 +1144,15 @@ uint32_t AsyncClient::getLocalAddress() { #endif } +ip6_addr_t AsyncClient::getLocalAddress6() { + if(!_pcb) { + ip6_addr_t nulladdr; + ip6_addr_set_zero(&nulladdr); + return nulladdr; + } + return _pcb->local_ip.u_addr.ip6; +} + uint16_t AsyncClient::getLocalPort() { if(!_pcb) { return 0; @@ -1139,6 +1164,10 @@ IPAddress AsyncClient::remoteIP() { return IPAddress(getRemoteAddress()); } +IPv6Address AsyncClient::remoteIP6() { + return IPv6Address(getRemoteAddress6().addr); +} + uint16_t AsyncClient::remotePort() { return getRemotePort(); } @@ -1147,6 +1176,10 @@ IPAddress AsyncClient::localIP() { return IPAddress(getLocalAddress()); } +IPv6Address AsyncClient::localIP6() { + return IPv6Address(getLocalAddress6().addr); +} + uint16_t AsyncClient::localPort() { return getLocalPort(); } @@ -1279,6 +1312,7 @@ int8_t AsyncClient::_s_connected(void * arg, void * pcb, int8_t err){ AsyncServer::AsyncServer(IPAddress addr, uint16_t port) : _port(port) +, _bind4(true) , _addr(addr) , _noDelay(false) , _pcb(0) @@ -1286,9 +1320,22 @@ AsyncServer::AsyncServer(IPAddress addr, uint16_t port) , _connect_cb_arg(0) {} +AsyncServer::AsyncServer(IPv6Address addr, uint16_t port) +: _port(port) +, _bind6(true) +, _addr6(addr) +, _noDelay(false) +, _pcb(0) +, _connect_cb(0) +, _connect_cb_arg(0) +{} + AsyncServer::AsyncServer(uint16_t port) : _port(port) +, _bind4(true) +, _bind6(true) , _addr((uint32_t) IPADDR_ANY) +, _addr6() , _noDelay(false) , _pcb(0) , _connect_cb(0) @@ -1313,20 +1360,26 @@ void AsyncServer::begin(){ log_e("failed to start task"); return; } - int8_t err; - _pcb = tcp_new_ip_type(IPADDR_TYPE_V4); + 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); if (!_pcb){ log_e("_pcb == NULL"); return; } ip_addr_t local_addr; -#if LWIP_IPV4 && LWIP_IPV6 - local_addr.type = IPADDR_TYPE_V4; + local_addr.type = bind_type; local_addr.u_addr.ip4.addr = (uint32_t) _addr; -#else - local_addr.addr = (uint32_t) _addr; -#endif + memcpy(local_addr.u_addr.ip6.addr, static_cast(_addr6), sizeof(uint32_t) * 4); err = _tcp_bind(_pcb, &local_addr, _port); if (err != ERR_OK) { diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 1e781b3..39931c0 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -23,6 +23,8 @@ #define ASYNCTCP_H_ #include "IPAddress.h" +#include "IPv6Address.h" +#include "sdkconfig.h" #include #ifndef LIBRETINY @@ -30,6 +32,8 @@ extern "C" { #include "freertos/semphr.h" #include "lwip/pbuf.h" + #include "lwip/ip_addr.h" + #include "lwip/ip6_addr.h" } #else extern "C" { @@ -80,7 +84,8 @@ class AsyncClient { return !(*this == other); } bool connect(IPAddress ip, uint16_t port); - bool connect(const char* host, uint16_t port); + bool connect(IPv6Address ip, uint16_t port); + bool connect(const char *host, uint16_t port); void close(bool now = false); void stop(); int8_t abort(); @@ -114,15 +119,19 @@ class AsyncClient { bool getNoDelay(); uint32_t getRemoteAddress(); + ip6_addr_t getRemoteAddress6(); uint16_t getRemotePort(); uint32_t getLocalAddress(); + ip6_addr_t getLocalAddress6(); uint16_t getLocalPort(); //compatibility IPAddress remoteIP(); - uint16_t remotePort(); + IPv6Address remoteIP6(); + uint16_t remotePort(); IPAddress localIP(); - uint16_t localPort(); + IPv6Address localIP6(); + uint16_t localPort(); void onConnect(AcConnectHandler cb, void* arg = 0); //on successful connect void onDisconnect(AcConnectHandler cb, void* arg = 0); //disconnected @@ -154,6 +163,8 @@ class AsyncClient { tcp_pcb * pcb(){ return _pcb; } protected: + bool _connect(ip_addr_t addr, uint16_t port); + tcp_pcb* _pcb; int8_t _closed_slot; @@ -202,6 +213,7 @@ class AsyncClient { class AsyncServer { public: AsyncServer(IPAddress addr, uint16_t port); + AsyncServer(IPv6Address addr, uint16_t port); AsyncServer(uint16_t port); ~AsyncServer(); void onClient(AcConnectHandler cb, void* arg); @@ -217,7 +229,10 @@ class AsyncServer { protected: uint16_t _port; + bool _bind4 = false; + bool _bind6 = false; IPAddress _addr; + IPv6Address _addr6; bool _noDelay; tcp_pcb* _pcb; AcConnectHandler _connect_cb; From ab9b7d4a22d2bbc15ed81ef4e7a0130440ad7ab3 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 21 Dec 2023 13:01:47 +0900 Subject: [PATCH 014/150] Bump version to 2.1.0 --- library.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/library.json b/library.json index 957bd19..e38ef1c 100644 --- a/library.json +++ b/library.json @@ -10,10 +10,13 @@ "type": "git", "url": "https://github.com/esphome/AsyncTCP.git" }, - "version": "2.0.1", + "version": "2.1.0", "license": "LGPL-3.0", "frameworks": "arduino", - "platforms": ["espressif32", "libretiny"], + "platforms": [ + "espressif32", + "libretiny" + ], "build": { "libCompatMode": 2 } From bf3e4d23f32bd4bf8af9d681fe76d69861eee5dd Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Thu, 18 Jan 2024 00:13:53 +0100 Subject: [PATCH 015/150] Rework CI and fix an error (#6) --- .github/dependabot.yml | 10 + .github/scripts/install-arduino-core-esp32.sh | 36 --- .github/scripts/install-arduino-ide.sh | 220 ------------------ .github/scripts/install-platformio.sh | 133 ----------- .github/scripts/on-push.sh | 64 ----- .github/workflows/push.yml | 31 ++- README.md | 5 +- arduino-cli.yaml | 25 ++ examples/ClientServer/Client/Client.ino | 42 ++++ examples/ClientServer/Client/config.h | 23 ++ src/AsyncTCP.cpp | 2 +- 11 files changed, 116 insertions(+), 475 deletions(-) create mode 100644 .github/dependabot.yml delete mode 100755 .github/scripts/install-arduino-core-esp32.sh delete mode 100755 .github/scripts/install-arduino-ide.sh delete mode 100644 .github/scripts/install-platformio.sh delete mode 100755 .github/scripts/on-push.sh create mode 100644 arduino-cli.yaml create mode 100644 examples/ClientServer/Client/Client.ino create mode 100644 examples/ClientServer/Client/config.h diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..dfd0e30 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +# Set update schedule for GitHub Actions + +version: 2 +updates: + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + # Check for updates to GitHub Actions every week + interval: "weekly" diff --git a/.github/scripts/install-arduino-core-esp32.sh b/.github/scripts/install-arduino-core-esp32.sh deleted file mode 100755 index cf1026d..0000000 --- a/.github/scripts/install-arduino-core-esp32.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -export ARDUINO_ESP32_PATH="$ARDUINO_USR_PATH/hardware/espressif/esp32" -if [ ! -d "$ARDUINO_ESP32_PATH" ]; then - echo "Installing ESP32 Arduino Core ..." - script_init_path="$PWD" - mkdir -p "$ARDUINO_USR_PATH/hardware/espressif" - cd "$ARDUINO_USR_PATH/hardware/espressif" - - echo "Installing Python Serial ..." - pip install pyserial > /dev/null - - if [ "$OS_IS_WINDOWS" == "1" ]; then - echo "Installing Python Requests ..." - pip install requests > /dev/null - fi - - if [ "$GITHUB_REPOSITORY" == "espressif/arduino-esp32" ]; then - echo "Linking Core..." - ln -s $GITHUB_WORKSPACE esp32 - else - echo "Cloning Core Repository..." - git clone https://github.com/espressif/arduino-esp32.git esp32 > /dev/null 2>&1 - fi - - echo "Updating Submodules ..." - cd esp32 - git submodule update --init --recursive > /dev/null 2>&1 - - echo "Installing Platform Tools ..." - cd tools && python get.py - cd $script_init_path - - echo "ESP32 Arduino has been installed in '$ARDUINO_ESP32_PATH'" - echo "" -fi diff --git a/.github/scripts/install-arduino-ide.sh b/.github/scripts/install-arduino-ide.sh deleted file mode 100755 index 7e268b1..0000000 --- a/.github/scripts/install-arduino-ide.sh +++ /dev/null @@ -1,220 +0,0 @@ -#!/bin/bash - -#OSTYPE: 'linux-gnu', ARCH: 'x86_64' => linux64 -#OSTYPE: 'msys', ARCH: 'x86_64' => win32 -#OSTYPE: 'darwin18', ARCH: 'i386' => macos - -OSBITS=`arch` -if [[ "$OSTYPE" == "linux"* ]]; then - export OS_IS_LINUX="1" - ARCHIVE_FORMAT="tar.xz" - if [[ "$OSBITS" == "i686" ]]; then - OS_NAME="linux32" - elif [[ "$OSBITS" == "x86_64" ]]; then - OS_NAME="linux64" - elif [[ "$OSBITS" == "armv7l" || "$OSBITS" == "aarch64" ]]; then - OS_NAME="linuxarm" - else - OS_NAME="$OSTYPE-$OSBITS" - echo "Unknown OS '$OS_NAME'" - exit 1 - fi -elif [[ "$OSTYPE" == "darwin"* ]]; then - export OS_IS_MACOS="1" - ARCHIVE_FORMAT="zip" - OS_NAME="macosx" -elif [[ "$OSTYPE" == "cygwin" ]] || [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then - export OS_IS_WINDOWS="1" - ARCHIVE_FORMAT="zip" - OS_NAME="windows" -else - OS_NAME="$OSTYPE-$OSBITS" - echo "Unknown OS '$OS_NAME'" - exit 1 -fi -export OS_NAME - -ARDUINO_BUILD_DIR="$HOME/.arduino/build.tmp" -ARDUINO_CACHE_DIR="$HOME/.arduino/cache.tmp" - -if [ "$OS_IS_MACOS" == "1" ]; then - export ARDUINO_IDE_PATH="/Applications/Arduino.app/Contents/Java" - export ARDUINO_USR_PATH="$HOME/Documents/Arduino" -elif [ "$OS_IS_WINDOWS" == "1" ]; then - export ARDUINO_IDE_PATH="$HOME/arduino_ide" - export ARDUINO_USR_PATH="$HOME/Documents/Arduino" -else - export ARDUINO_IDE_PATH="$HOME/arduino_ide" - export ARDUINO_USR_PATH="$HOME/Arduino" -fi - -if [ ! -d "$ARDUINO_IDE_PATH" ]; then - echo "Installing Arduino IDE on $OS_NAME ..." - echo "Downloading 'arduino-nightly-$OS_NAME.$ARCHIVE_FORMAT' to 'arduino.$ARCHIVE_FORMAT' ..." - if [ "$OS_IS_LINUX" == "1" ]; then - wget -O "arduino.$ARCHIVE_FORMAT" "https://www.arduino.cc/download.php?f=/arduino-nightly-$OS_NAME.$ARCHIVE_FORMAT" > /dev/null 2>&1 - echo "Extracting 'arduino.$ARCHIVE_FORMAT' ..." - tar xf "arduino.$ARCHIVE_FORMAT" > /dev/null - mv arduino-nightly "$ARDUINO_IDE_PATH" - else - curl -o "arduino.$ARCHIVE_FORMAT" -L "https://www.arduino.cc/download.php?f=/arduino-nightly-$OS_NAME.$ARCHIVE_FORMAT" > /dev/null 2>&1 - echo "Extracting 'arduino.$ARCHIVE_FORMAT' ..." - unzip "arduino.$ARCHIVE_FORMAT" > /dev/null - if [ "$OS_IS_MACOS" == "1" ]; then - mv "Arduino.app" "/Applications/Arduino.app" - else - mv arduino-nightly "$ARDUINO_IDE_PATH" - fi - fi - rm -rf "arduino.$ARCHIVE_FORMAT" - - mkdir -p "$ARDUINO_USR_PATH/libraries" - mkdir -p "$ARDUINO_USR_PATH/hardware" - - echo "Arduino IDE Installed in '$ARDUINO_IDE_PATH'" - echo "" -fi - -function build_sketch(){ # build_sketch [extra-options] - if [ "$#" -lt 2 ]; then - echo "ERROR: Illegal number of parameters" - echo "USAGE: build_sketch [extra-options]" - return 1 - fi - - local fqbn="$1" - local sketch="$2" - local xtra_opts="$3" - local win_opts="" - if [ "$OS_IS_WINDOWS" == "1" ]; then - local ctags_version=`ls "$ARDUINO_IDE_PATH/tools-builder/ctags/"` - local preprocessor_version=`ls "$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/"` - win_opts="-prefs=runtime.tools.ctags.path=$ARDUINO_IDE_PATH/tools-builder/ctags/$ctags_version -prefs=runtime.tools.arduino-preprocessor.path=$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/$preprocessor_version" - fi - - echo "" - echo "Compiling '"$(basename "$sketch")"' ..." - mkdir -p "$ARDUINO_BUILD_DIR" - mkdir -p "$ARDUINO_CACHE_DIR" - $ARDUINO_IDE_PATH/arduino-builder -compile -logger=human -core-api-version=10810 \ - -fqbn=$fqbn \ - -warnings="all" \ - -tools "$ARDUINO_IDE_PATH/tools-builder" \ - -tools "$ARDUINO_IDE_PATH/tools" \ - -built-in-libraries "$ARDUINO_IDE_PATH/libraries" \ - -hardware "$ARDUINO_IDE_PATH/hardware" \ - -hardware "$ARDUINO_USR_PATH/hardware" \ - -libraries "$ARDUINO_USR_PATH/libraries" \ - -build-cache "$ARDUINO_CACHE_DIR" \ - -build-path "$ARDUINO_BUILD_DIR" \ - $win_opts $xtra_opts "$sketch" -} - -function count_sketches() # count_sketches -{ - local examples="$1" - rm -rf sketches.txt - if [ ! -d "$examples" ]; then - touch sketches.txt - return 0 - fi - local sketches=$(find $examples -name *.ino) - local sketchnum=0 - for sketch in $sketches; do - local sketchdir=$(dirname $sketch) - local sketchdirname=$(basename $sketchdir) - local sketchname=$(basename $sketch) - if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then - continue - fi; - if [[ -f "$sketchdir/.test.skip" ]]; then - continue - fi - echo $sketch >> sketches.txt - sketchnum=$(($sketchnum + 1)) - done - return $sketchnum -} - -function build_sketches() # build_sketches [extra-options] -{ - local fqbn=$1 - local examples=$2 - local chunk_idex=$3 - local chunks_num=$4 - local xtra_opts=$5 - - if [ "$#" -lt 2 ]; then - echo "ERROR: Illegal number of parameters" - echo "USAGE: build_sketches [ ] [extra-options]" - return 1 - fi - - if [ "$#" -lt 4 ]; then - chunk_idex="0" - chunks_num="1" - xtra_opts=$3 - fi - - if [ "$chunks_num" -le 0 ]; then - echo "ERROR: Chunks count must be positive number" - return 1 - fi - if [ "$chunk_idex" -ge "$chunks_num" ]; then - echo "ERROR: Chunk index must be less than chunks count" - return 1 - fi - - set +e - count_sketches "$examples" - local sketchcount=$? - set -e - local sketches=$(cat sketches.txt) - rm -rf sketches.txt - - local chunk_size=$(( $sketchcount / $chunks_num )) - local all_chunks=$(( $chunks_num * $chunk_size )) - if [ "$all_chunks" -lt "$sketchcount" ]; then - chunk_size=$(( $chunk_size + 1 )) - fi - - local start_index=$(( $chunk_idex * $chunk_size )) - if [ "$sketchcount" -le "$start_index" ]; then - echo "Skipping job" - return 0 - fi - - local end_index=$(( $(( $chunk_idex + 1 )) * $chunk_size )) - if [ "$end_index" -gt "$sketchcount" ]; then - end_index=$sketchcount - fi - - local start_num=$(( $start_index + 1 )) - echo "Found $sketchcount Sketches"; - echo "Chunk Count : $chunks_num" - echo "Chunk Size : $chunk_size" - echo "Start Sketch: $start_num" - echo "End Sketch : $end_index" - - local sketchnum=0 - for sketch in $sketches; do - local sketchdir=$(dirname $sketch) - local sketchdirname=$(basename $sketchdir) - local sketchname=$(basename $sketch) - if [ "${sketchdirname}.ino" != "$sketchname" ] \ - || [ -f "$sketchdir/.test.skip" ]; then - continue - fi - sketchnum=$(($sketchnum + 1)) - if [ "$sketchnum" -le "$start_index" ] \ - || [ "$sketchnum" -gt "$end_index" ]; then - continue - fi - build_sketch "$fqbn" "$sketch" "$xtra_opts" - local result=$? - if [ $result -ne 0 ]; then - return $result - fi - done - return 0 -} diff --git a/.github/scripts/install-platformio.sh b/.github/scripts/install-platformio.sh deleted file mode 100644 index 61c94fe..0000000 --- a/.github/scripts/install-platformio.sh +++ /dev/null @@ -1,133 +0,0 @@ -#!/bin/bash - -echo "Installing Python Wheel ..." -pip install wheel > /dev/null 2>&1 - -echo "Installing PlatformIO ..." -pip install -U platformio > /dev/null 2>&1 - -echo "PlatformIO has been installed" -echo "" - - -function build_pio_sketch(){ # build_pio_sketch - if [ "$#" -lt 2 ]; then - echo "ERROR: Illegal number of parameters" - echo "USAGE: build_pio_sketch " - return 1 - fi - - local board="$1" - local sketch="$2" - local sketch_dir=$(dirname "$sketch") - echo "" - echo "Compiling '"$(basename "$sketch")"' ..." - python -m platformio ci -l '.' --board "$board" "$sketch_dir" --project-option="board_build.partitions = huge_app.csv" -} - -function count_sketches() # count_sketches -{ - local examples="$1" - rm -rf sketches.txt - if [ ! -d "$examples" ]; then - touch sketches.txt - return 0 - fi - local sketches=$(find $examples -name *.ino) - local sketchnum=0 - for sketch in $sketches; do - local sketchdir=$(dirname $sketch) - local sketchdirname=$(basename $sketchdir) - local sketchname=$(basename $sketch) - if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then - continue - fi; - if [[ -f "$sketchdir/.test.skip" ]]; then - continue - fi - echo $sketch >> sketches.txt - sketchnum=$(($sketchnum + 1)) - done - return $sketchnum -} - -function build_pio_sketches() # build_pio_sketches -{ - if [ "$#" -lt 2 ]; then - echo "ERROR: Illegal number of parameters" - echo "USAGE: build_pio_sketches [ ]" - return 1 - fi - - local board=$1 - local examples=$2 - local chunk_idex=$3 - local chunks_num=$4 - - if [ "$#" -lt 4 ]; then - chunk_idex="0" - chunks_num="1" - fi - - if [ "$chunks_num" -le 0 ]; then - echo "ERROR: Chunks count must be positive number" - return 1 - fi - if [ "$chunk_idex" -ge "$chunks_num" ]; then - echo "ERROR: Chunk index must be less than chunks count" - return 1 - fi - - set +e - count_sketches "$examples" - local sketchcount=$? - set -e - local sketches=$(cat sketches.txt) - rm -rf sketches.txt - - local chunk_size=$(( $sketchcount / $chunks_num )) - local all_chunks=$(( $chunks_num * $chunk_size )) - if [ "$all_chunks" -lt "$sketchcount" ]; then - chunk_size=$(( $chunk_size + 1 )) - fi - - local start_index=$(( $chunk_idex * $chunk_size )) - if [ "$sketchcount" -le "$start_index" ]; then - echo "Skipping job" - return 0 - fi - - local end_index=$(( $(( $chunk_idex + 1 )) * $chunk_size )) - if [ "$end_index" -gt "$sketchcount" ]; then - end_index=$sketchcount - fi - - local start_num=$(( $start_index + 1 )) - echo "Found $sketchcount Sketches"; - echo "Chunk Count : $chunks_num" - echo "Chunk Size : $chunk_size" - echo "Start Sketch: $start_num" - echo "End Sketch : $end_index" - - local sketchnum=0 - for sketch in $sketches; do - local sketchdir=$(dirname $sketch) - local sketchdirname=$(basename $sketchdir) - local sketchname=$(basename $sketch) - if [ "${sketchdirname}.ino" != "$sketchname" ] \ - || [ -f "$sketchdir/.test.skip" ]; then - continue - fi - sketchnum=$(($sketchnum + 1)) - if [ "$sketchnum" -le "$start_index" ] \ - || [ "$sketchnum" -gt "$end_index" ]; then - continue - fi - build_pio_sketch "$board" "$sketch" - local result=$? - if [ $result -ne 0 ]; then - return $result - fi - done - return 0 -} diff --git a/.github/scripts/on-push.sh b/.github/scripts/on-push.sh deleted file mode 100755 index ece5d7a..0000000 --- a/.github/scripts/on-push.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/bash - -set -e - -if [ ! -z "$TRAVIS_BUILD_DIR" ]; then - export GITHUB_WORKSPACE="$TRAVIS_BUILD_DIR" - export GITHUB_REPOSITORY="$TRAVIS_REPO_SLUG" -elif [ -z "$GITHUB_WORKSPACE" ]; then - export GITHUB_WORKSPACE="$PWD" - export GITHUB_REPOSITORY="me-no-dev/AsyncTCP" -fi - -CHUNK_INDEX=$1 -CHUNKS_CNT=$2 -BUILD_PIO=0 -if [ "$#" -lt 2 ] || [ "$CHUNKS_CNT" -le 0 ]; then - CHUNK_INDEX=0 - CHUNKS_CNT=1 -elif [ "$CHUNK_INDEX" -gt "$CHUNKS_CNT" ]; then - CHUNK_INDEX=$CHUNKS_CNT -elif [ "$CHUNK_INDEX" -eq "$CHUNKS_CNT" ]; then - BUILD_PIO=1 -fi - -if [ "$BUILD_PIO" -eq 0 ]; then - # ArduinoIDE Test - source ./.github/scripts/install-arduino-ide.sh - source ./.github/scripts/install-arduino-core-esp32.sh - - echo "Installing AsyncTCP ..." - cp -rf "$GITHUB_WORKSPACE" "$ARDUINO_USR_PATH/libraries/AsyncTCP" - - FQBN="espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=huge_app" - build_sketches "$FQBN" "$GITHUB_WORKSPACE/examples" - if [ ! "$OS_IS_WINDOWS" == "1" ]; then - echo "Installing ESPAsyncWebServer ..." - git clone https://github.com/me-no-dev/ESPAsyncWebServer "$ARDUINO_USR_PATH/libraries/ESPAsyncWebServer" > /dev/null 2>&1 - - echo "Installing ArduinoJson ..." - git clone https://github.com/bblanchon/ArduinoJson "$ARDUINO_USR_PATH/libraries/ArduinoJson" > /dev/null 2>&1 - - build_sketches "$FQBN" "$ARDUINO_USR_PATH/libraries/ESPAsyncWebServer/examples" - fi -else - # PlatformIO Test - source ./.github/scripts/install-platformio.sh - - echo "Installing AsyncTCP ..." - python -m platformio lib --storage-dir "$GITHUB_WORKSPACE" install - - BOARD="esp32dev" - build_pio_sketches "$BOARD" "$GITHUB_WORKSPACE/examples" - - if [[ "$OSTYPE" != "cygwin" ]] && [[ "$OSTYPE" != "msys" ]] && [[ "$OSTYPE" != "win32" ]]; then - echo "Installing ESPAsyncWebServer ..." - python -m platformio lib -g install https://github.com/me-no-dev/ESPAsyncWebServer.git > /dev/null 2>&1 - git clone https://github.com/me-no-dev/ESPAsyncWebServer "$HOME/ESPAsyncWebServer" > /dev/null 2>&1 - - echo "Installing ArduinoJson ..." - python -m platformio lib -g install https://github.com/bblanchon/ArduinoJson.git > /dev/null 2>&1 - - build_pio_sketches "$BOARD" "$HOME/ESPAsyncWebServer/examples" - fi -fi diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 15cd441..b7b62c6 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -3,8 +3,6 @@ name: Async TCP CI on: push: branches: - - master - - release/* pull_request: jobs: @@ -14,19 +12,18 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest, macOS-latest] + os: [ubuntu-latest] steps: - - uses: actions/checkout@v1 - - name: Build Tests - run: bash ./.github/scripts/on-push.sh 0 1 - - build-pio: - name: PlatformIO on ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, macOS-latest] - steps: - - uses: actions/checkout@v1 - - name: Build Tests - run: bash ./.github/scripts/on-push.sh 1 1 + - uses: actions/checkout@v3 + - uses: arduino/setup-arduino-cli@v1 + - name: Download board + run: | + arduino-cli --config-file arduino-cli.yaml core update-index + arduino-cli --config-file arduino-cli.yaml board listall + arduino-cli --config-file arduino-cli.yaml core install esp32:esp32@2.0.2 + - name: Compile Sketch + run: arduino-cli --config-file arduino-cli.yaml --library ./src/ compile --fqbn esp32:esp32:esp32 ./examples/ClientServer/Client/Client.ino + - name: Compile Sketch with IPv6 + env: + LWIP_IPV6: true + run: arduino-cli --config-file arduino-cli.yaml --library ./src/ compile --fqbn esp32:esp32:esp32 ./examples/ClientServer/Client/Client.ino diff --git a/README.md b/README.md index f12573a..17b145b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ # AsyncTCP -[![Build Status](https://travis-ci.org/me-no-dev/AsyncTCP.svg?branch=master)](https://travis-ci.org/me-no-dev/AsyncTCP) ![](https://github.com/me-no-dev/AsyncTCP/workflows/Async%20TCP%20CI/badge.svg) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/2f7e4d1df8b446d192cbfec6dc174d2d)](https://www.codacy.com/manual/me-no-dev/AsyncTCP?utm_source=github.com&utm_medium=referral&utm_content=me-no-dev/AsyncTCP&utm_campaign=Badge_Grade) - +![Build Status](https://github.com/esphome/AsyncTCP/actions/workflows/push.yml/badge.svg) A fork of the [AsyncTCP](https://github.com/me-no-dev/AsyncTCP) library by [@me-no-dev](https://github.com/me-no-dev) for [ESPHome](https://esphome.io). ### Async TCP Library for ESP32 Arduino -[![Join the chat at https://gitter.im/me-no-dev/ESPAsyncWebServer](https://badges.gitter.im/me-no-dev/ESPAsyncWebServer.svg)](https://gitter.im/me-no-dev/ESPAsyncWebServer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - This is a fully asynchronous TCP library, aimed at enabling trouble-free, multi-connection network environment for Espressif's ESP32 MCUs. This library is the base for [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) diff --git a/arduino-cli.yaml b/arduino-cli.yaml new file mode 100644 index 0000000..42365f4 --- /dev/null +++ b/arduino-cli.yaml @@ -0,0 +1,25 @@ +board_manager: + additional_urls: + - https://espressif.github.io/arduino-esp32/package_esp32_index.json +directories: + builtin.libraries: ./src/ +build_cache: + compilations_before_purge: 10 + ttl: 720h0m0s +daemon: + port: "50051" +library: + enable_unsafe_install: false +logging: + file: "" + format: text + level: info +metrics: + addr: :9090 + enabled: true +output: + no_color: false +sketch: + always_export_binaries: false +updater: + enable_notification: true diff --git a/examples/ClientServer/Client/Client.ino b/examples/ClientServer/Client/Client.ino new file mode 100644 index 0000000..47d8bc7 --- /dev/null +++ b/examples/ClientServer/Client/Client.ino @@ -0,0 +1,42 @@ +#include + +#include "config.h" + +static void replyToServer(void* arg) { + AsyncClient* client = reinterpret_cast(arg); + + // send reply + if (client->space() > 32 && client->canSend()) { + char message[32]; + client->add(message, strlen(message)); + client->send(); + } +} + +/* event callbacks */ +static void handleData(void* arg, AsyncClient* client, void *data, size_t len) { + Serial.printf("\n data received from %s \n", client->remoteIP().toString().c_str()); + Serial.write((uint8_t*)data, len); + +} + +void onConnect(void* arg, AsyncClient* client) { + Serial.printf("\n client has been connected to %s on port %d \n", SERVER_HOST_NAME, TCP_PORT); + replyToServer(client); +} + + +void setup() { + Serial.begin(115200); + delay(20); + + AsyncClient* client = new AsyncClient; + client->onData(&handleData, client); + client->onConnect(&onConnect, client); + client->connect(SERVER_HOST_NAME, TCP_PORT); + +} + +void loop() { + +} diff --git a/examples/ClientServer/Client/config.h b/examples/ClientServer/Client/config.h new file mode 100644 index 0000000..cf51e91 --- /dev/null +++ b/examples/ClientServer/Client/config.h @@ -0,0 +1,23 @@ +#ifndef CONFIG_H +#define CONFIG_H + +/* + * This example demonstrate how to use asynchronous client & server APIs + * in order to establish tcp socket connections in client server manner. + * server is running (on port 7050) on one ESP, acts as AP, and other clients running on + * remaining ESPs acts as STAs. after connection establishment between server and clients + * there is a simple message transfer in every 2s. clients connect to server via it's host name + * (in this case 'esp_server') with help of DNS service running on server side. + * + * Note: default MSS for ESPAsyncTCP is 536 byte and defualt ACK timeout is 5s. +*/ + +#define SSID "ESP-TEST" +#define PASSWORD "123456789" + +#define SERVER_HOST_NAME "esp_server" + +#define TCP_PORT 7050 +#define DNS_PORT 53 + +#endif // CONFIG_H diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 3ab2a7b..3892240 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -749,6 +749,7 @@ bool AsyncClient::connect(const char* host, uint16_t port){ if(addr.type == IPADDR_TYPE_V6) { return connect(IPv6Address(addr.u_addr.ip6.addr), port); } +#if LWIP_IPV6 return connect(IPAddress(addr.u_addr.ip4.addr), port); #else return connect(IPAddress(addr.addr), port); @@ -1017,7 +1018,6 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){ } void AsyncClient::_dns_found(struct ip_addr *ipaddr){ -#if LWIP_IPV4 && LWIP_IPV6 if(ipaddr && ipaddr->u_addr.ip4.addr){ connect(IPAddress(ipaddr->u_addr.ip4.addr), _connect_port); } else if(ipaddr && ipaddr->u_addr.ip6.addr){ From 117fee9149e2132da5355f5121b243e5d015a2c9 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 18 Jan 2024 08:16:33 +0900 Subject: [PATCH 016/150] Bump version to 2.1.1 --- library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.json b/library.json index e38ef1c..e6befd4 100644 --- a/library.json +++ b/library.json @@ -10,7 +10,7 @@ "type": "git", "url": "https://github.com/esphome/AsyncTCP.git" }, - "version": "2.1.0", + "version": "2.1.1", "license": "LGPL-3.0", "frameworks": "arduino", "platforms": [ From 87d4daa4abdfa940720cc4832dc193df99b14508 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Mon, 22 Jan 2024 10:31:54 +0100 Subject: [PATCH 017/150] Make LIBRETINY compile (#9) --- src/AsyncTCP.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 39931c0..9074dfe 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -24,7 +24,6 @@ #include "IPAddress.h" #include "IPv6Address.h" -#include "sdkconfig.h" #include #ifndef LIBRETINY From d852ef9c212faceff18375711c3a5cfcc46e33e3 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 8 Feb 2024 08:28:20 +1300 Subject: [PATCH 018/150] Bump version to 2.1.2 --- library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.json b/library.json index e6befd4..15456e7 100644 --- a/library.json +++ b/library.json @@ -10,7 +10,7 @@ "type": "git", "url": "https://github.com/esphome/AsyncTCP.git" }, - "version": "2.1.1", + "version": "2.1.2", "license": "LGPL-3.0", "frameworks": "arduino", "platforms": [ From 2ae3787c7148c491d11c09a5d536f4fe2a190262 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Sun, 18 Feb 2024 20:08:25 +0100 Subject: [PATCH 019/150] Fixes libretiny (#10) --- src/AsyncTCP.cpp | 55 +++++++++++++++++++++++++++--------------------- src/AsyncTCP.h | 14 ++++++------ 2 files changed, 39 insertions(+), 30 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 3892240..df0739b 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -705,7 +705,7 @@ bool AsyncClient::_connect(ip_addr_t addr, uint16_t port){ return false; } - tcp_pcb* pcb = tcp_new_ip_type(addr.type); + tcp_pcb* pcb = tcp_new_ip_type(IPADDR_TYPE_ANY); if (!pcb){ log_e("pcb == NULL"); return false; @@ -722,12 +722,12 @@ bool AsyncClient::_connect(ip_addr_t addr, uint16_t port){ bool AsyncClient::connect(IPAddress ip, uint16_t port){ ip_addr_t addr; - addr.type = IPADDR_TYPE_V4; - addr.u_addr.ip4.addr = ip; + ip_addr_set_ip4_u32(&addr, ip); return _connect(addr, port); } +#if LWIP_IPV6 bool AsyncClient::connect(IPv6Address ip, uint16_t port){ ip_addr_t addr; addr.type = IPADDR_TYPE_V6; @@ -735,6 +735,7 @@ bool AsyncClient::connect(IPv6Address ip, uint16_t port){ return _connect(addr, port); } +#endif bool AsyncClient::connect(const char* host, uint16_t port){ ip_addr_t addr; @@ -746,10 +747,10 @@ bool AsyncClient::connect(const char* host, uint16_t port){ err_t err = dns_gethostbyname(host, &addr, (dns_found_callback)&_tcp_dns_found, this); if(err == ERR_OK) { +#if LWIP_IPV6 if(addr.type == IPADDR_TYPE_V6) { return connect(IPv6Address(addr.u_addr.ip6.addr), port); } -#if LWIP_IPV6 return connect(IPAddress(addr.u_addr.ip4.addr), port); #else return connect(IPAddress(addr.addr), port); @@ -1018,10 +1019,12 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){ } void AsyncClient::_dns_found(struct ip_addr *ipaddr){ - if(ipaddr && ipaddr->u_addr.ip4.addr){ - connect(IPAddress(ipaddr->u_addr.ip4.addr), _connect_port); + if(ipaddr && IP_IS_V4(ipaddr)){ + connect(IPAddress(ip_addr_get_ip4_u32(ipaddr)), _connect_port); +#if LWIP_IPV6 } else if(ipaddr && ipaddr->u_addr.ip6.addr){ connect(IPv6Address(ipaddr->u_addr.ip6.addr), _connect_port); +#endif } else { if(_error_cb) { _error_cb(_error_cb_arg, this, -55); @@ -1117,6 +1120,7 @@ uint32_t AsyncClient::getRemoteAddress() { #endif } +#if LWIP_IPV6 ip6_addr_t AsyncClient::getRemoteAddress6() { if(!_pcb) { ip6_addr_t nulladdr; @@ -1126,6 +1130,24 @@ ip6_addr_t AsyncClient::getRemoteAddress6() { return _pcb->remote_ip.u_addr.ip6; } +ip6_addr_t AsyncClient::getLocalAddress6() { + if(!_pcb) { + ip6_addr_t nulladdr; + ip6_addr_set_zero(&nulladdr); + return nulladdr; + } + return _pcb->local_ip.u_addr.ip6; +} + +IPv6Address AsyncClient::remoteIP6() { + return IPv6Address(getRemoteAddress6().addr); +} + +IPv6Address AsyncClient::localIP6() { + return IPv6Address(getLocalAddress6().addr); +} +#endif + uint16_t AsyncClient::getRemotePort() { if(!_pcb) { return 0; @@ -1144,15 +1166,6 @@ uint32_t AsyncClient::getLocalAddress() { #endif } -ip6_addr_t AsyncClient::getLocalAddress6() { - if(!_pcb) { - ip6_addr_t nulladdr; - ip6_addr_set_zero(&nulladdr); - return nulladdr; - } - return _pcb->local_ip.u_addr.ip6; -} - uint16_t AsyncClient::getLocalPort() { if(!_pcb) { return 0; @@ -1164,10 +1177,6 @@ IPAddress AsyncClient::remoteIP() { return IPAddress(getRemoteAddress()); } -IPv6Address AsyncClient::remoteIP6() { - return IPv6Address(getRemoteAddress6().addr); -} - uint16_t AsyncClient::remotePort() { return getRemotePort(); } @@ -1176,9 +1185,6 @@ IPAddress AsyncClient::localIP() { return IPAddress(getLocalAddress()); } -IPv6Address AsyncClient::localIP6() { - return IPv6Address(getLocalAddress6().addr); -} uint16_t AsyncClient::localPort() { return getLocalPort(); @@ -1377,9 +1383,10 @@ void AsyncServer::begin(){ } ip_addr_t local_addr; - local_addr.type = bind_type; + ip_addr_set_ip4_u32(&local_addr, _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); + memcpy(local_addr.u_addr.ip6.addr, static_cast(_addr6), sizeof(uint32_t) * 4); */ err = _tcp_bind(_pcb, &local_addr, _port); if (err != ERR_OK) { diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 9074dfe..32edaa9 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -25,14 +25,14 @@ #include "IPAddress.h" #include "IPv6Address.h" #include +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" #ifndef LIBRETINY #include "sdkconfig.h" extern "C" { #include "freertos/semphr.h" #include "lwip/pbuf.h" - #include "lwip/ip_addr.h" - #include "lwip/ip6_addr.h" } #else extern "C" { @@ -118,18 +118,20 @@ class AsyncClient { bool getNoDelay(); uint32_t getRemoteAddress(); - ip6_addr_t getRemoteAddress6(); uint16_t getRemotePort(); uint32_t getLocalAddress(); - ip6_addr_t getLocalAddress6(); uint16_t getLocalPort(); +#if LWIP_IPV6 + ip6_addr_t getRemoteAddress6(); + ip6_addr_t getLocalAddress6(); + IPv6Address remoteIP6(); + IPv6Address localIP6(); +#endif //compatibility IPAddress remoteIP(); - IPv6Address remoteIP6(); uint16_t remotePort(); IPAddress localIP(); - IPv6Address localIP6(); uint16_t localPort(); void onConnect(AcConnectHandler cb, void* arg = 0); //on successful connect From 54fcd1085d647d07cf09d95e2ad9776ab1668a33 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 22 Feb 2024 09:27:52 +1300 Subject: [PATCH 020/150] Bump version to 2.1.3 --- library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.json b/library.json index 15456e7..52819dc 100644 --- a/library.json +++ b/library.json @@ -10,7 +10,7 @@ "type": "git", "url": "https://github.com/esphome/AsyncTCP.git" }, - "version": "2.1.2", + "version": "2.1.3", "license": "LGPL-3.0", "frameworks": "arduino", "platforms": [ From 1518f62a240d2c0762e8ae49541b7360c1ee8f32 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 19 Apr 2024 19:15:41 +0200 Subject: [PATCH 021/150] Add back library.properties required for Arduino projects --- library.properties | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 library.properties diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..ea7eeb1 --- /dev/null +++ b/library.properties @@ -0,0 +1,9 @@ +me=AsyncTCP-esphome +version=2.1.3 +author=Me-No-Dev +maintainer=ESPHome +sentence=Async TCP Library for ESP32 +paragraph=Async TCP Library for ESP32 +category=Other +url=https://github.com/esphome/AsyncTCP.git +architectures=* From ab88e234348decb5cadc0ea0317c32e970c4102c Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 19 Apr 2024 19:20:11 +0200 Subject: [PATCH 022/150] fix CI to support building both with Arduino release version and future version (currently v3 rc1) --- .github/workflows/push.yml | 19 +++++++++---------- arduino-cli-dev.yaml | 25 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 arduino-cli-dev.yaml diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index b7b62c6..bc5cfab 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -2,28 +2,27 @@ name: Async TCP CI on: push: - branches: pull_request: + workflow_dispatch: jobs: - build-arduino: - name: Arduino on ${{ matrix.os }} - runs-on: ${{ matrix.os }} + name: ${{ matrix.config }} + runs-on: ubuntu-latest strategy: matrix: - os: [ubuntu-latest] + config: [arduino-cli.yaml, arduino-cli-dev.yaml] steps: - uses: actions/checkout@v3 - uses: arduino/setup-arduino-cli@v1 - name: Download board run: | - arduino-cli --config-file arduino-cli.yaml core update-index - arduino-cli --config-file arduino-cli.yaml board listall - arduino-cli --config-file arduino-cli.yaml core install esp32:esp32@2.0.2 + arduino-cli --config-file ${{ matrix.config }} core update-index + arduino-cli --config-file ${{ matrix.config }} board listall + arduino-cli --config-file ${{ matrix.config }} core install esp32:esp32 - name: Compile Sketch - run: arduino-cli --config-file arduino-cli.yaml --library ./src/ compile --fqbn esp32:esp32:esp32 ./examples/ClientServer/Client/Client.ino + run: arduino-cli --config-file ${{ matrix.config }} --library ./src/ compile --fqbn esp32:esp32:esp32 ./examples/ClientServer/Client/Client.ino - name: Compile Sketch with IPv6 env: LWIP_IPV6: true - run: arduino-cli --config-file arduino-cli.yaml --library ./src/ compile --fqbn esp32:esp32:esp32 ./examples/ClientServer/Client/Client.ino + run: arduino-cli --config-file ${{ matrix.config }} --library ./src/ compile --fqbn esp32:esp32:esp32 ./examples/ClientServer/Client/Client.ino diff --git a/arduino-cli-dev.yaml b/arduino-cli-dev.yaml new file mode 100644 index 0000000..174df7a --- /dev/null +++ b/arduino-cli-dev.yaml @@ -0,0 +1,25 @@ +board_manager: + additional_urls: + - https://espressif.github.io/arduino-esp32/package_esp32_dev_index.json +directories: + builtin.libraries: ./src/ +build_cache: + compilations_before_purge: 10 + ttl: 720h0m0s +daemon: + port: "50051" +library: + enable_unsafe_install: false +logging: + file: "" + format: text + level: info +metrics: + addr: :9090 + enabled: true +output: + no_color: false +sketch: + always_export_binaries: false +updater: + enable_notification: true From c4cb7653fe042b7294c9a8bedb48e07dbc9b573e Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 19 Apr 2024 22:43:05 +0200 Subject: [PATCH 023/150] Arduino 3 / ESP IDF 5 compatibility --- src/AsyncTCP.cpp | 43 +++++++++++++++++++++++++++++++++++++++++-- src/AsyncTCP.h | 13 +++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index df0739b..eac129f 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -722,12 +722,16 @@ bool AsyncClient::_connect(ip_addr_t addr, uint16_t port){ bool AsyncClient::connect(IPAddress ip, uint16_t port){ ip_addr_t addr; +#if ESP_IDF_VERSION_MAJOR < 5 ip_addr_set_ip4_u32(&addr, ip); +#else + ip.to_ip_addr_t(&addr); +#endif return _connect(addr, port); } -#if LWIP_IPV6 +#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; @@ -747,6 +751,7 @@ bool AsyncClient::connect(const char* host, uint16_t port){ err_t err = dns_gethostbyname(host, &addr, (dns_found_callback)&_tcp_dns_found, this); if(err == ERR_OK) { +#if ESP_IDF_VERSION_MAJOR < 5 #if LWIP_IPV6 if(addr.type == IPADDR_TYPE_V6) { return connect(IPv6Address(addr.u_addr.ip6.addr), port); @@ -754,6 +759,9 @@ bool AsyncClient::connect(const char* host, uint16_t port){ return connect(IPAddress(addr.u_addr.ip4.addr), port); #else return connect(IPAddress(addr.addr), port); +#endif +#else + return _connect(addr, port); #endif } else if(err == ERR_INPROGRESS) { _connect_port = port; @@ -1019,11 +1027,16 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){ } void AsyncClient::_dns_found(struct ip_addr *ipaddr){ +#if ESP_IDF_VERSION_MAJOR < 5 if(ipaddr && IP_IS_V4(ipaddr)){ connect(IPAddress(ip_addr_get_ip4_u32(ipaddr)), _connect_port); #if LWIP_IPV6 } else if(ipaddr && ipaddr->u_addr.ip6.addr){ connect(IPv6Address(ipaddr->u_addr.ip6.addr), _connect_port); +#endif +#else + if(ipaddr) { + connect(IPAddress(ipaddr), _connect_port); #endif } else { if(_error_cb) { @@ -1138,7 +1151,7 @@ ip6_addr_t AsyncClient::getLocalAddress6() { } return _pcb->local_ip.u_addr.ip6; } - +#if ESP_IDF_VERSION_MAJOR < 5 IPv6Address AsyncClient::remoteIP6() { return IPv6Address(getRemoteAddress6().addr); } @@ -1146,6 +1159,15 @@ IPv6Address AsyncClient::remoteIP6() { IPv6Address AsyncClient::localIP6() { return IPv6Address(getLocalAddress6().addr); } +#else +IPAddress AsyncClient::remoteIP6() { + return _pcb ? IPAddress(dynamic_cast(&_pcb->remote_ip)) : IPAddress(IPType::IPv6); +} + +IPAddress AsyncClient::localIP6() { + return _pcb ? IPAddress(dynamic_cast(&_pcb->local_ip)) : IPAddress(IPType::IPv6); +} +#endif #endif uint16_t AsyncClient::getRemotePort() { @@ -1174,7 +1196,11 @@ uint16_t AsyncClient::getLocalPort() { } IPAddress AsyncClient::remoteIP() { +#if ESP_IDF_VERSION_MAJOR < 5 return IPAddress(getRemoteAddress()); +#else + return _pcb ? IPAddress(dynamic_cast(&_pcb->remote_ip)) : IPAddress(); +#endif } uint16_t AsyncClient::remotePort() { @@ -1182,7 +1208,11 @@ uint16_t AsyncClient::remotePort() { } IPAddress AsyncClient::localIP() { +#if ESP_IDF_VERSION_MAJOR < 5 return IPAddress(getLocalAddress()); +#else + return _pcb ? IPAddress(dynamic_cast(&_pcb->local_ip)) : IPAddress(); +#endif } @@ -1318,7 +1348,12 @@ int8_t AsyncClient::_s_connected(void * arg, void * pcb, int8_t err){ AsyncServer::AsyncServer(IPAddress addr, uint16_t port) : _port(port) +#if ESP_IDF_VERSION_MAJOR < 5 , _bind4(true) +#else +, _bind4(addr.type() != IPType::IPv6) +, _bind6(addr.type() == IPType::IPv6) +#endif , _addr(addr) , _noDelay(false) , _pcb(0) @@ -1326,6 +1361,7 @@ AsyncServer::AsyncServer(IPAddress addr, uint16_t port) , _connect_cb_arg(0) {} +#if ESP_IDF_VERSION_MAJOR < 5 AsyncServer::AsyncServer(IPv6Address addr, uint16_t port) : _port(port) , _bind6(true) @@ -1335,13 +1371,16 @@ AsyncServer::AsyncServer(IPv6Address addr, uint16_t port) , _connect_cb(0) , _connect_cb_arg(0) {} +#endif AsyncServer::AsyncServer(uint16_t port) : _port(port) , _bind4(true) , _bind6(true) , _addr((uint32_t) IPADDR_ANY) +#if ESP_IDF_VERSION_MAJOR < 5 , _addr6() +#endif , _noDelay(false) , _pcb(0) , _connect_cb(0) diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 32edaa9..268fb78 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -23,7 +23,9 @@ #define ASYNCTCP_H_ #include "IPAddress.h" +#if ESP_IDF_VERSION_MAJOR < 5 #include "IPv6Address.h" +#endif #include #include "lwip/ip_addr.h" #include "lwip/ip6_addr.h" @@ -83,7 +85,9 @@ class AsyncClient { return !(*this == other); } bool connect(IPAddress ip, uint16_t port); +#if ESP_IDF_VERSION_MAJOR < 5 bool connect(IPv6Address ip, uint16_t port); +#endif bool connect(const char *host, uint16_t port); void close(bool now = false); void stop(); @@ -124,8 +128,13 @@ class AsyncClient { #if LWIP_IPV6 ip6_addr_t getRemoteAddress6(); ip6_addr_t getLocalAddress6(); +#if ESP_IDF_VERSION_MAJOR < 5 IPv6Address remoteIP6(); IPv6Address localIP6(); +#else + IPAddress remoteIP6(); + IPAddress localIP6(); +#endif #endif //compatibility @@ -214,7 +223,9 @@ class AsyncClient { class AsyncServer { public: AsyncServer(IPAddress addr, uint16_t port); +#if ESP_IDF_VERSION_MAJOR < 5 AsyncServer(IPv6Address addr, uint16_t port); +#endif AsyncServer(uint16_t port); ~AsyncServer(); void onClient(AcConnectHandler cb, void* arg); @@ -233,7 +244,9 @@ class AsyncServer { bool _bind4 = false; bool _bind6 = false; IPAddress _addr; +#if ESP_IDF_VERSION_MAJOR < 5 IPv6Address _addr6; +#endif bool _noDelay; tcp_pcb* _pcb; AcConnectHandler _connect_cb; From 70943fffbfcadb4db3fdd0c4a516a023cc7ba0c4 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 19 Apr 2024 23:33:28 +0200 Subject: [PATCH 024/150] v3.0.0 --- README.md | 8 +++++++- library.json | 31 +++++++++++++++++++++++-------- library.properties | 8 ++++---- src/AsyncTCP.h | 6 ++++++ 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 17b145b..9c7228b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # AsyncTCP -![Build Status](https://github.com/esphome/AsyncTCP/actions/workflows/push.yml/badge.svg) +![Build Status](https://github.com/mathieucarbou/AsyncTCP/actions/workflows/push.yml/badge.svg) A fork of the [AsyncTCP](https://github.com/me-no-dev/AsyncTCP) library by [@me-no-dev](https://github.com/me-no-dev) for [ESPHome](https://esphome.io). ### Async TCP Library for ESP32 Arduino @@ -10,3 +10,9 @@ This library is the base for [ESPAsyncWebServer](https://github.com/me-no-dev/ES ## AsyncClient and AsyncServer The base classes on which everything else is built. They expose all possible scenarios, but are really raw and require more skills to use. + +## Changes in this fork + +- All improvements from [ESPHome fork](https://github.com/esphome/AsyncTCP) +- Reverted back `library.properties` for Arduino IDE users +- Arduino 3 / ESP-IDF 5 compatibility diff --git a/library.json b/library.json index 52819dc..ae21731 100644 --- a/library.json +++ b/library.json @@ -1,16 +1,21 @@ { - "name": "AsyncTCP-esphome", + "name": "AsyncTCP", + "version": "3.0.0", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", - "authors": { - "name": "Hristo Gochkov", - "maintainer": true - }, "repository": { "type": "git", - "url": "https://github.com/esphome/AsyncTCP.git" + "url": "https://github.com/mathieucarbou/AsyncTCP.git" }, - "version": "2.1.3", + "authors": [ + { + "name": "Hristo Gochkov" + }, + { + "name": "Mathieu Carbou", + "maintainer": true + } + ], "license": "LGPL-3.0", "frameworks": "arduino", "platforms": [ @@ -19,5 +24,15 @@ ], "build": { "libCompatMode": 2 + }, + "export": { + "include": [ + "examples", + "src", + "library.json", + "library.properties", + "LICENSE", + "README.md" + ] } -} +} \ No newline at end of file diff --git a/library.properties b/library.properties index ea7eeb1..140f60e 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ -me=AsyncTCP-esphome -version=2.1.3 +me=AsyncTCP +version=3.0.0 author=Me-No-Dev -maintainer=ESPHome +maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 paragraph=Async TCP Library for ESP32 category=Other -url=https://github.com/esphome/AsyncTCP.git +url=https://github.com/mathieucarbou/AsyncTCP.git architectures=* diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 268fb78..289db44 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,6 +22,12 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ +#define ASYNCTCP_VERSION "3.0.0" +#define ASYNCTCP_VERSION_MAJOR 0 +#define ASYNCTCP_VERSION_MINOR 0 +#define ASYNCTCP_VERSION_REVISION 0 +#define ASYNCTCP_FORK_mathieucarbou + #include "IPAddress.h" #if ESP_IDF_VERSION_MAJOR < 5 #include "IPv6Address.h" From 1824a6d52ed03634b4f71a55bc6a2c40a795963a Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 19 Apr 2024 23:40:44 +0200 Subject: [PATCH 025/150] Fix name field --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 140f60e..7060a30 100644 --- a/library.properties +++ b/library.properties @@ -1,4 +1,4 @@ -me=AsyncTCP +name=AsyncTCP version=3.0.0 author=Me-No-Dev maintainer=Mathieu Carbou From 1a183074fe7ee96577f57adda87ba280ee389688 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 19 Apr 2024 23:47:14 +0200 Subject: [PATCH 026/150] Update lib name --- library.json | 2 +- library.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.json b/library.json index ae21731..8bcf5d7 100644 --- a/library.json +++ b/library.json @@ -1,5 +1,5 @@ { - "name": "AsyncTCP", + "name": "Async TCP", "version": "3.0.0", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", diff --git a/library.properties b/library.properties index 7060a30..90a89b1 100644 --- a/library.properties +++ b/library.properties @@ -1,4 +1,4 @@ -name=AsyncTCP +name=Async TCP version=3.0.0 author=Me-No-Dev maintainer=Mathieu Carbou From f9a1c81464ce53d227f76ba439ea8dc2a9c9c9b9 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 19 Apr 2024 23:54:56 +0200 Subject: [PATCH 027/150] doc update --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9c7228b..f7700a8 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,16 @@ # AsyncTCP -![Build Status](https://github.com/mathieucarbou/AsyncTCP/actions/workflows/push.yml/badge.svg) + +[![License: LGPL 3.0](https://img.shields.io/badge/License-LGPL%203.0-yellow.svg)](https://opensource.org/license/lgpl-3-0/) +[![Continuous Integration](https://github.com/mathieucarbou/AsyncTCP/actions/workflows/push.yml/badge.svg)](https://github.com/mathieucarbou/AsyncTCP/actions/workflows/push.yml) +[![PlatformIO Registry](https://badges.registry.platformio.org/packages/mathieucarbou/library/Async%20TCP.svg)](https://registry.platformio.org/libraries/mathieucarbou/Async%20TCP) + A fork of the [AsyncTCP](https://github.com/me-no-dev/AsyncTCP) library by [@me-no-dev](https://github.com/me-no-dev) for [ESPHome](https://esphome.io). ### Async TCP Library for ESP32 Arduino This is a fully asynchronous TCP library, aimed at enabling trouble-free, multi-connection network environment for Espressif's ESP32 MCUs. -This library is the base for [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) +This library is the base for [ESPAsyncWebServer](https://github.com/mathieucarbou/ESPAsyncWebServer) ## AsyncClient and AsyncServer The base classes on which everything else is built. They expose all possible scenarios, but are really raw and require more skills to use. @@ -16,3 +20,5 @@ The base classes on which everything else is built. They expose all possible sce - All improvements from [ESPHome fork](https://github.com/esphome/AsyncTCP) - Reverted back `library.properties` for Arduino IDE users - Arduino 3 / ESP-IDF 5 compatibility +- Changed lib name: `AsyncTCP` -> `Async TCP` +- Point to `mathieucarbou/Async TCP @ ^3.0.0` From 81f30aaa722ddc85eb27377321ea003399003421 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 20 Apr 2024 11:06:36 +0200 Subject: [PATCH 028/150] Add some project files --- .gitignore | 6 +++++- platformio.ini | 26 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 platformio.ini diff --git a/.gitignore b/.gitignore index 9bea433..4ac15a4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ - .DS_Store +.lh +/.pio +/.vscode/* +!/.vscode/settings.json +/logs diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..5890000 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,26 @@ +[env] +framework = arduino + +build_flags = + -Wall -Wextra + -D CONFIG_ARDUHAL_LOG_COLORS + -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG + +upload_protocol = esptool +monitor_speed = 115200 +monitor_filters = esp32_exception_decoder, log2file + +[platformio] +default_envs = esp32 +lib_dir = . +src_dir = examples/ClientServer/Client + +[env:esp32] +; platform = espressif32@6.6.0 +; platform = espressif32 +; platform = https://github.com/platformio/platform-espressif32.git +platform = https://github.com/Jason2866/platform-espressif32.git#Arduino/IDF5 +; platform_packages= +; platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.0-rc1 +; platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1 +board = esp32dev From ea3ebd7289ebe20c5360472e8032fb2b22ad5bf8 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 20 Apr 2024 11:07:12 +0200 Subject: [PATCH 029/150] Do not rely on configENABLE_BACKWARD_COMPATIBILITY --- src/AsyncTCP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index eac129f..b6c7d5e 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -78,7 +78,7 @@ typedef struct { }; } lwip_event_packet_t; -static xQueueHandle _async_queue; +static QueueHandle_t _async_queue; static TaskHandle_t _async_service_task_handle = NULL; From 3a2435e6175b4fa879cd35d747ac44d4f0d09082 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 20 Apr 2024 11:20:28 +0200 Subject: [PATCH 030/150] Update project files and CI --- .github/workflows/push.yml | 22 ++++++++++++++++++++++ .vscode/settings.json | 3 +++ platformio.ini | 31 ++++++++++++++++++++----------- 3 files changed, 45 insertions(+), 11 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index bc5cfab..8ce6d3f 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -10,6 +10,7 @@ jobs: name: ${{ matrix.config }} runs-on: ubuntu-latest strategy: + fail-fast: true matrix: config: [arduino-cli.yaml, arduino-cli-dev.yaml] steps: @@ -26,3 +27,24 @@ jobs: env: LWIP_IPV6: true run: arduino-cli --config-file ${{ matrix.config }} --library ./src/ compile --fqbn esp32:esp32:esp32 ./examples/ClientServer/Client/Client.ino + + build-pio: + name: pio ${{ matrix.env }} + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + env: [latest, v660, master, v300-rc1, Jason2866] + steps: + - uses: actions/checkout@v4 + - uses: actions/cache@v4 + with: + path: | + ~/.platformio + ~/.cache/pip + key: ${{ runner.os }}-platformio + - uses: actions/setup-python@v5 + with: + python-version: "3.x" + - run: pip install platformio + - run: pio run -e ${{ matrix.env }} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..eb7750c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cmake.configureOnOpen": false +} \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 5890000..063ce62 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,26 +1,35 @@ [env] framework = arduino - +board = esp32dev build_flags = -Wall -Wextra -D CONFIG_ARDUHAL_LOG_COLORS -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG - upload_protocol = esptool monitor_speed = 115200 monitor_filters = esp32_exception_decoder, log2file [platformio] -default_envs = esp32 lib_dir = . src_dir = examples/ClientServer/Client -[env:esp32] -; platform = espressif32@6.6.0 -; platform = espressif32 -; platform = https://github.com/platformio/platform-espressif32.git +[env:latest] +platform = espressif32 + +[env:v660] +platform = espressif32@6.6.0 + +[env:master] +platform = espressif32 +platform_packages= + platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#master + platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1 + +[env:v300-rc1] +platform = espressif32 +platform_packages= + platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.0-rc1 + platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1 + +[env:Jason2866] platform = https://github.com/Jason2866/platform-espressif32.git#Arduino/IDF5 -; platform_packages= -; platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.0-rc1 -; platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1 -board = esp32dev From 755c8cb8e0b52abea3c430e50742f716959bd3f8 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 20 Apr 2024 11:48:50 +0200 Subject: [PATCH 031/150] v3.0.1 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f7700a8..756ebc0 100644 --- a/README.md +++ b/README.md @@ -21,4 +21,4 @@ The base classes on which everything else is built. They expose all possible sce - Reverted back `library.properties` for Arduino IDE users - Arduino 3 / ESP-IDF 5 compatibility - Changed lib name: `AsyncTCP` -> `Async TCP` -- Point to `mathieucarbou/Async TCP @ ^3.0.0` +- Point to `mathieucarbou/Async TCP @ ^3.0.1` diff --git a/library.json b/library.json index 8bcf5d7..bae3736 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Async TCP", - "version": "3.0.0", + "version": "3.0.1", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index 90a89b1..0b3e95c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Async TCP -version=3.0.0 +version=3.0.1 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 289db44..22daa63 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.0.0" +#define ASYNCTCP_VERSION "3.0.1" #define ASYNCTCP_VERSION_MAJOR 0 #define ASYNCTCP_VERSION_MINOR 0 -#define ASYNCTCP_VERSION_REVISION 0 +#define ASYNCTCP_VERSION_REVISION 1 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From 482cddd835aaf0744f26b87dfe65656c10c52064 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 20 Apr 2024 12:20:45 +0200 Subject: [PATCH 032/150] Remove warning --- src/AsyncTCP.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index b6c7d5e..3df01f5 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -723,7 +723,10 @@ bool AsyncClient::_connect(ip_addr_t addr, uint16_t port){ bool AsyncClient::connect(IPAddress ip, uint16_t port){ ip_addr_t addr; #if ESP_IDF_VERSION_MAJOR < 5 - ip_addr_set_ip4_u32(&addr, ip); + // 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 @@ -1422,10 +1425,17 @@ void AsyncServer::begin(){ } ip_addr_t local_addr; - ip_addr_set_ip4_u32(&local_addr, _addr); -/* local_addr.type = bind_type; +#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); */ +#else + _addr.to_ip_addr_t(&local_addr); +#endif err = _tcp_bind(_pcb, &local_addr, _port); if (err != ERR_OK) { From aac8c67dae1db24613770c07c3f26cea910a20c1 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 20 Apr 2024 12:31:17 +0200 Subject: [PATCH 033/150] v3.0.2 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 756ebc0..09c7c5a 100644 --- a/README.md +++ b/README.md @@ -21,4 +21,4 @@ The base classes on which everything else is built. They expose all possible sce - Reverted back `library.properties` for Arduino IDE users - Arduino 3 / ESP-IDF 5 compatibility - Changed lib name: `AsyncTCP` -> `Async TCP` -- Point to `mathieucarbou/Async TCP @ ^3.0.1` +- Point to `mathieucarbou/Async TCP @ ^3.0.2` diff --git a/library.json b/library.json index bae3736..b4ac7ab 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Async TCP", - "version": "3.0.1", + "version": "3.0.2", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index 0b3e95c..af7728a 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Async TCP -version=3.0.1 +version=3.0.2 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 22daa63..476f781 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.0.1" +#define ASYNCTCP_VERSION "3.0.2" #define ASYNCTCP_VERSION_MAJOR 0 #define ASYNCTCP_VERSION_MINOR 0 -#define ASYNCTCP_VERSION_REVISION 1 +#define ASYNCTCP_VERSION_REVISION 2 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From 1f1d7a4d7cf45273a761b8ff9e3194f64563ba07 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 20 Apr 2024 15:04:56 +0200 Subject: [PATCH 034/150] Try CI with S3 board --- .github/workflows/push.yml | 10 ++++++---- platformio.ini | 19 ++++++++++++++----- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 8ce6d3f..536a8ac 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -29,12 +29,13 @@ jobs: run: arduino-cli --config-file ${{ matrix.config }} --library ./src/ compile --fqbn esp32:esp32:esp32 ./examples/ClientServer/Client/Client.ino build-pio: - name: pio ${{ matrix.env }} + name: ${{ matrix.board }} ${{ matrix.env }} runs-on: ubuntu-latest strategy: - fail-fast: true + fail-fast: false matrix: - env: [latest, v660, master, v300-rc1, Jason2866] + board: [esp32dev, esp32-s3-devkitc-1] + env: [v660, latest-espressif32, latest-arduino, v300-rc1, Jason2866] steps: - uses: actions/checkout@v4 - uses: actions/cache@v4 @@ -42,9 +43,10 @@ jobs: path: | ~/.platformio ~/.cache/pip - key: ${{ runner.os }}-platformio + key: ${{ matrix.env }} - uses: actions/setup-python@v5 with: python-version: "3.x" - run: pip install platformio + - run: sed -i -e 's/esp32dev/${{ matrix.board }}/g' platformio.ini - run: pio run -e ${{ matrix.env }} diff --git a/platformio.ini b/platformio.ini index 063ce62..4feee67 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,6 +1,5 @@ [env] framework = arduino -board = esp32dev build_flags = -Wall -Wextra -D CONFIG_ARDUHAL_LOG_COLORS @@ -13,23 +12,33 @@ monitor_filters = esp32_exception_decoder, log2file lib_dir = . src_dir = examples/ClientServer/Client -[env:latest] -platform = espressif32 - [env:v660] platform = espressif32@6.6.0 +board = esp32dev +; board = esp32dev -[env:master] +[env:latest-espressif32] +platform = https://github.com/platformio/platform-espressif32.git +board = esp32dev +; board = esp32dev + +[env:latest-arduino] platform = espressif32 platform_packages= platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#master platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1 +board = esp32dev +; board = esp32dev [env:v300-rc1] platform = espressif32 platform_packages= platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.0-rc1 platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1 +board = esp32dev +; board = esp32dev [env:Jason2866] platform = https://github.com/Jason2866/platform-espressif32.git#Arduino/IDF5 +board = esp32dev +; board = esp32dev From e49705cdb9e19510c8b697931f0824f13e0f363c Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 20 Apr 2024 16:27:46 +0200 Subject: [PATCH 035/150] cleanup --- platformio.ini | 5 ----- 1 file changed, 5 deletions(-) diff --git a/platformio.ini b/platformio.ini index 4feee67..c1b4c91 100644 --- a/platformio.ini +++ b/platformio.ini @@ -15,12 +15,10 @@ src_dir = examples/ClientServer/Client [env:v660] platform = espressif32@6.6.0 board = esp32dev -; board = esp32dev [env:latest-espressif32] platform = https://github.com/platformio/platform-espressif32.git board = esp32dev -; board = esp32dev [env:latest-arduino] platform = espressif32 @@ -28,7 +26,6 @@ platform_packages= platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#master platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1 board = esp32dev -; board = esp32dev [env:v300-rc1] platform = espressif32 @@ -36,9 +33,7 @@ platform_packages= platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.0-rc1 platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1 board = esp32dev -; board = esp32dev [env:Jason2866] platform = https://github.com/Jason2866/platform-espressif32.git#Arduino/IDF5 board = esp32dev -; board = esp32dev From af2991a133d17e45b6d962904a5201e89f1a6b60 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 20 Apr 2024 23:01:09 +0200 Subject: [PATCH 036/150] Remove Jason2866 from CI --- .github/workflows/push.yml | 2 +- platformio.ini | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 536a8ac..d3869df 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -35,7 +35,7 @@ jobs: fail-fast: false matrix: board: [esp32dev, esp32-s3-devkitc-1] - env: [v660, latest-espressif32, latest-arduino, v300-rc1, Jason2866] + env: [v660, latest-espressif32, latest-arduino, v300-rc1] steps: - uses: actions/checkout@v4 - uses: actions/cache@v4 diff --git a/platformio.ini b/platformio.ini index c1b4c91..2a6a2ea 100644 --- a/platformio.ini +++ b/platformio.ini @@ -33,7 +33,3 @@ platform_packages= platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.0-rc1 platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1 board = esp32dev - -[env:Jason2866] -platform = https://github.com/Jason2866/platform-espressif32.git#Arduino/IDF5 -board = esp32dev From 29b1807a5a4e63bf5c234edc3cb2475158c44a7e Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 27 Apr 2024 00:40:31 +0200 Subject: [PATCH 037/150] IDE file --- .vscode/settings.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index eb7750c..950debb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,9 @@ { - "cmake.configureOnOpen": false + "cmake.configureOnOpen": false, + "githubPullRequests.remotes": [ + "origin", + "upstream", + "OttoWinter", + "me-no-dev" + ] } \ No newline at end of file From 0227108fc404a544f63514b589967fc16c8ef2e6 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 27 Apr 2024 00:41:21 +0200 Subject: [PATCH 038/150] Add CONFIG_ASYNC_TCP_PRIORITY --- src/AsyncTCP.cpp | 2 +- src/AsyncTCP.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 3df01f5..5afccbc 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -240,7 +240,7 @@ static bool _start_async_task(){ return false; } if(!_async_service_task_handle){ - customTaskCreateUniversal(_async_service_task, "async_tcp", CONFIG_ASYNC_TCP_STACK_SIZE, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE); + customTaskCreateUniversal(_async_service_task, "async_tcp", CONFIG_ASYNC_TCP_STACK_SIZE, NULL, CONFIG_ASYNC_TCP_PRIORITY, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE); if(!_async_service_task_handle){ return false; } diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 476f781..9c525cd 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -61,6 +61,10 @@ extern "C" { #define CONFIG_ASYNC_TCP_STACK_SIZE 8192 * 2 #endif +#ifndef CONFIG_ASYNC_TCP_PRIORITY +#define CONFIG_ASYNC_TCP_PRIORITY 3 +#endif + class AsyncClient; #define ASYNC_MAX_ACK_TIME 5000 From de284cc5cc8a56839dfb3a49958e0ba33ab87408 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 27 Apr 2024 00:46:02 +0200 Subject: [PATCH 039/150] Add CONFIG_ASYNC_TCP_QUEUE_SIZE --- src/AsyncTCP.cpp | 2 +- src/AsyncTCP.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 5afccbc..9a4cdf0 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -97,7 +97,7 @@ static uint32_t _closed_index = []() { static inline bool _init_async_event_queue(){ if(!_async_queue){ - _async_queue = xQueueCreate(32, sizeof(lwip_event_packet_t *)); + _async_queue = xQueueCreate(CONFIG_ASYNC_TCP_QUEUE_SIZE, sizeof(lwip_event_packet_t *)); if(!_async_queue){ return false; } diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 9c525cd..005ec51 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -65,6 +65,10 @@ extern "C" { #define CONFIG_ASYNC_TCP_PRIORITY 3 #endif +#ifndef CONFIG_ASYNC_TCP_QUEUE_SIZE +#define CONFIG_ASYNC_TCP_QUEUE_SIZE 32 +#endif + class AsyncClient; #define ASYNC_MAX_ACK_TIME 5000 From 92628f1f4dc32b1f61b82be9efccdd18340844e7 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 27 Apr 2024 00:48:02 +0200 Subject: [PATCH 040/150] Set CONFIG_ASYNC_TCP_PRIORITY to 10 --- src/AsyncTCP.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 005ec51..ebf57a7 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -62,7 +62,7 @@ extern "C" { #endif #ifndef CONFIG_ASYNC_TCP_PRIORITY -#define CONFIG_ASYNC_TCP_PRIORITY 3 +#define CONFIG_ASYNC_TCP_PRIORITY 10 #endif #ifndef CONFIG_ASYNC_TCP_QUEUE_SIZE From 46a1dce19f5b3869d50d0da661a8801706776171 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 27 Apr 2024 00:48:24 +0200 Subject: [PATCH 041/150] Set CONFIG_ASYNC_TCP_QUEUE_SIZE to 64 --- src/AsyncTCP.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index ebf57a7..7dbcf1c 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -66,7 +66,7 @@ extern "C" { #endif #ifndef CONFIG_ASYNC_TCP_QUEUE_SIZE -#define CONFIG_ASYNC_TCP_QUEUE_SIZE 32 +#define CONFIG_ASYNC_TCP_QUEUE_SIZE 64 #endif class AsyncClient; From db8cfa1ee77a551323eddad5a6c5a5b3416e11e4 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 27 Apr 2024 00:53:20 +0200 Subject: [PATCH 042/150] Add setKeepAlive() --- src/AsyncTCP.cpp | 12 ++++++++++++ src/AsyncTCP.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 9a4cdf0..0f4a707 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -1118,6 +1118,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; diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 7dbcf1c..2110edc 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -135,6 +135,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(); From ec5d01ed5977c26c44a57f117c0b97e7c4f96236 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 27 Apr 2024 01:13:25 +0200 Subject: [PATCH 043/150] code cleanup --- src/AsyncTCP.cpp | 9 +++------ src/AsyncTCP.h | 4 ++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 0f4a707..1a4e8bd 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -46,7 +46,7 @@ typedef struct { void *arg; union { struct { - void * pcb; + tcp_pcb * pcb; int8_t err; } connected; struct { @@ -895,13 +895,10 @@ void AsyncClient::_free_closed_slot(){ * 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); @@ -1353,7 +1350,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); } diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 2110edc..abb1f48 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -182,7 +182,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); @@ -223,7 +223,7 @@ class AsyncClient { int8_t _close(); void _free_closed_slot(); void _allocate_closed_slot(); - int8_t _connected(void* pcb, int8_t err); + 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); From 9b5f04627feab52815d5d08e88f595e985c86ec0 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 27 Apr 2024 01:19:50 +0200 Subject: [PATCH 044/150] v3.1.0 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 09c7c5a..a6c02ca 100644 --- a/README.md +++ b/README.md @@ -21,4 +21,4 @@ The base classes on which everything else is built. They expose all possible sce - Reverted back `library.properties` for Arduino IDE users - Arduino 3 / ESP-IDF 5 compatibility - Changed lib name: `AsyncTCP` -> `Async TCP` -- Point to `mathieucarbou/Async TCP @ ^3.0.2` +- Point to `mathieucarbou/Async TCP @ ^3.1.0` diff --git a/library.json b/library.json index b4ac7ab..299ff2b 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Async TCP", - "version": "3.0.2", + "version": "3.1.0", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index af7728a..bd85cae 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Async TCP -version=3.0.2 +version=3.1.0 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index abb1f48..b79afc0 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.0.2" -#define ASYNCTCP_VERSION_MAJOR 0 -#define ASYNCTCP_VERSION_MINOR 0 -#define ASYNCTCP_VERSION_REVISION 2 +#define ASYNCTCP_VERSION "3.1.0" +#define ASYNCTCP_VERSION_MAJOR 3 +#define ASYNCTCP_VERSION_MINOR 1 +#define ASYNCTCP_VERSION_REVISION 0 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From 85988d5a449e47cc6c709efdb58f3192c3399ab5 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 27 Apr 2024 12:20:28 +0200 Subject: [PATCH 045/150] CONFIG_ASYNC_TCP_MAX_ACK_TIME --- src/AsyncTCP.cpp | 2 +- src/AsyncTCP.h | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 1a4e8bd..e048d58 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -581,7 +581,7 @@ 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) diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index b79afc0..7486f5e 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -69,9 +69,12 @@ extern "C" { #define CONFIG_ASYNC_TCP_QUEUE_SIZE 64 #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. From 65b4e998c7512b269dfff160d079eb39481e4826 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 27 Apr 2024 01:10:31 +0200 Subject: [PATCH 046/150] Grab fixes from https://github.com/me-no-dev/AsyncTCP/pull/173 --- src/AsyncTCP.cpp | 38 ++++++++++++++++++++++++++++++-------- src/AsyncTCP.h | 2 +- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index e048d58..6a44951 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -589,13 +589,15 @@ AsyncClient::AsyncClient(tcp_pcb* pcb) _pcb = pcb; _closed_slot = -1; 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(); + } } } @@ -705,6 +707,11 @@ bool AsyncClient::_connect(ip_addr_t addr, uint16_t port){ return false; } + if(!_allocate_closed_slot()) { + log_e("failed to allocate: closed slot full"); + return false; + } + tcp_pcb* pcb = tcp_new_ip_type(IPADDR_TYPE_ANY); if (!pcb){ log_e("pcb == NULL"); @@ -860,6 +867,7 @@ int8_t AsyncClient::_close(){ if(err != ERR_OK) { err = abort(); } + _free_closed_slot(); _pcb = NULL; if(_discard_cb) { _discard_cb(_discard_cb_arg, this); @@ -868,7 +876,10 @@ int8_t AsyncClient::_close(){ return err; } -void AsyncClient::_allocate_closed_slot(){ +bool AsyncClient::_allocate_closed_slot(){ + if (_closed_slot != -1) { + return true; + } xSemaphoreTake(_slots_lock, portMAX_DELAY); uint32_t closed_slot_min_index = 0; for (int i = 0; i < _number_of_closed_slots; ++ i) { @@ -881,14 +892,17 @@ void AsyncClient::_allocate_closed_slot(){ _closed_slots[_closed_slot] = 0; } xSemaphoreGive(_slots_lock); + return (_closed_slot != -1); } void AsyncClient::_free_closed_slot(){ + xSemaphoreTake(_slots_lock, portMAX_DELAY); if (_closed_slot != -1) { _closed_slots[_closed_slot] = _closed_index; _closed_slot = -1; ++ _closed_index; } + xSemaphoreGive(_slots_lock); } /* @@ -915,6 +929,7 @@ void AsyncClient::_error(int8_t err) { tcp_err(_pcb, NULL); tcp_poll(_pcb, NULL, 0); } + _free_closed_slot(); _pcb = NULL; } if(_error_cb) { @@ -966,13 +981,19 @@ int8_t AsyncClient::_sent(tcp_pcb* pcb, uint16_t len) { } int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { - while(pb != NULL) { + if(!_pcb || pcb != _pcb){ + log_e("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); + return ERR_OK; + } + size_t total = 0; + while((pb != NULL) && (ERR_OK == err)) { _rx_last_packet = millis(); //we should not ack before we assimilate the data _ack_pcb = true; pbuf *b = pb; pb = b->next; b->next = NULL; + total += b->len; if(_pb_cb){ _pb_cb(_pb_cb_arg, this, b); } else { @@ -981,13 +1002,11 @@ int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { } if(!_ack_pcb) { _rx_ack_len += b->len; - } else if(_pcb) { - _tcp_recved(_pcb, _closed_slot, b->len); } - pbuf_free(b); } + pbuf_free(b); } - return ERR_OK; + return _tcp_recved(pcb, _closed_slot, total); } int8_t AsyncClient::_poll(tcp_pcb* pcb){ @@ -1075,9 +1094,12 @@ size_t AsyncClient::write(const char* data) { size_t AsyncClient::write(const char* data, size_t size, uint8_t apiflags) { size_t will_send = add(data, size, apiflags); - if(!will_send || !send()) { + if(!will_send) { return 0; } + while (connected() && !send()) { + taskYIELD(); + } return will_send; } diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 7486f5e..bb08e68 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -225,7 +225,7 @@ class AsyncClient { int8_t _close(); void _free_closed_slot(); - void _allocate_closed_slot(); + bool _allocate_closed_slot(); int8_t _connected(tcp_pcb* pcb, int8_t err); void _error(int8_t err); int8_t _poll(tcp_pcb* pcb); From 1b443f97ab47bf88e2eff182e9114da56b657481 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 27 Apr 2024 11:48:34 +0200 Subject: [PATCH 047/150] v3.1.1 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a6c02ca..04b1261 100644 --- a/README.md +++ b/README.md @@ -21,4 +21,4 @@ The base classes on which everything else is built. They expose all possible sce - Reverted back `library.properties` for Arduino IDE users - Arduino 3 / ESP-IDF 5 compatibility - Changed lib name: `AsyncTCP` -> `Async TCP` -- Point to `mathieucarbou/Async TCP @ ^3.1.0` +- Point to `mathieucarbou/Async TCP @ ^3.1.1` diff --git a/library.json b/library.json index 299ff2b..f2fef0b 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Async TCP", - "version": "3.1.0", + "version": "3.1.1", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index bd85cae..2abc9b1 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Async TCP -version=3.1.0 +version=3.1.1 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index bb08e68..2eed823 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.1.0" +#define ASYNCTCP_VERSION "3.1.1" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 1 -#define ASYNCTCP_VERSION_REVISION 0 +#define ASYNCTCP_VERSION_REVISION 1 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From 212780ced13b57fe1328eba54e1d09eca2d09fcc Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 27 Apr 2024 14:17:23 +0200 Subject: [PATCH 048/150] Reduce logging of non critical messages --- src/AsyncTCP.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 6a44951..3247cbc 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -699,7 +699,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()){ @@ -777,7 +777,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; } @@ -856,7 +856,6 @@ int8_t AsyncClient::_close(){ //ets_printf("X: 0x%08x\n", (uint32_t)this); int8_t err = ERR_OK; if(_pcb) { - //log_i(""); tcp_arg(_pcb, NULL); tcp_sent(_pcb, NULL); tcp_recv(_pcb, NULL); @@ -943,7 +942,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); @@ -973,7 +972,6 @@ 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); if(_sent_cb) { _sent_cb(_sent_cb_arg, this, len, (millis() - _tx_last_packet)); } @@ -982,7 +980,7 @@ int8_t AsyncClient::_sent(tcp_pcb* pcb, uint16_t len) { int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, 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; } size_t total = 0; @@ -1011,11 +1009,11 @@ int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { 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; } @@ -1026,7 +1024,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; @@ -1034,7 +1032,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; } @@ -1509,7 +1507,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; } From 1594d56060ba4273099fa010069da06e846a29c7 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 27 Apr 2024 14:18:08 +0200 Subject: [PATCH 049/150] v3.1.2 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 04b1261..9186e58 100644 --- a/README.md +++ b/README.md @@ -21,4 +21,4 @@ The base classes on which everything else is built. They expose all possible sce - Reverted back `library.properties` for Arduino IDE users - Arduino 3 / ESP-IDF 5 compatibility - Changed lib name: `AsyncTCP` -> `Async TCP` -- Point to `mathieucarbou/Async TCP @ ^3.1.1` +- Point to `mathieucarbou/Async TCP @ ^3.1.2` diff --git a/library.json b/library.json index f2fef0b..77c4946 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Async TCP", - "version": "3.1.1", + "version": "3.1.2", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index 2abc9b1..b2114e2 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Async TCP -version=3.1.1 +version=3.1.2 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 2eed823..db2c17f 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.1.1" +#define ASYNCTCP_VERSION "3.1.2" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 1 -#define ASYNCTCP_VERSION_REVISION 1 +#define ASYNCTCP_VERSION_REVISION 2 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From 5d00a45410368592842388135ed59272ffdda64f Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 15 May 2024 07:41:50 +0200 Subject: [PATCH 050/150] upgrade --- .github/workflows/push.yml | 2 +- platformio.ini | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index d3869df..2eeb88b 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -35,7 +35,7 @@ jobs: fail-fast: false matrix: board: [esp32dev, esp32-s3-devkitc-1] - env: [v660, latest-espressif32, latest-arduino, v300-rc1] + env: [v660, latest-espressif32, latest-arduino, arduino-v3] steps: - uses: actions/checkout@v4 - uses: actions/cache@v4 diff --git a/platformio.ini b/platformio.ini index 2a6a2ea..4125dd8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -13,7 +13,7 @@ lib_dir = . src_dir = examples/ClientServer/Client [env:v660] -platform = espressif32@6.6.0 +platform = espressif32@6.7.0 board = esp32dev [env:latest-espressif32] @@ -27,9 +27,9 @@ platform_packages= platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1 board = esp32dev -[env:v300-rc1] +[env:arduino-v3] platform = espressif32 platform_packages= - platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.0-rc1 + platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.0-rc2 platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1 board = esp32dev From 8ee3d60c86fefd0226a0eb09784f6beefda29e50 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 27 May 2024 13:16:59 +0200 Subject: [PATCH 051/150] Fix CI --- .github/workflows/push.yml | 2 +- platformio.ini | 23 ++++++++--------------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 2eeb88b..529b5d2 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -35,7 +35,7 @@ jobs: fail-fast: false matrix: board: [esp32dev, esp32-s3-devkitc-1] - env: [v660, latest-espressif32, latest-arduino, arduino-v3] + env: [arduino-2, arduino-3] steps: - uses: actions/checkout@v4 - uses: actions/cache@v4 diff --git a/platformio.ini b/platformio.ini index 4125dd8..37e1df9 100644 --- a/platformio.ini +++ b/platformio.ini @@ -12,24 +12,17 @@ monitor_filters = esp32_exception_decoder, log2file lib_dir = . src_dir = examples/ClientServer/Client -[env:v660] +[env:arduino] +platform = espressif32 +board = esp32dev + +[env:arduino-2] platform = espressif32@6.7.0 board = esp32dev -[env:latest-espressif32] -platform = https://github.com/platformio/platform-espressif32.git -board = esp32dev - -[env:latest-arduino] +[env:arduino-3] platform = espressif32 platform_packages= - platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#master - platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1 -board = esp32dev - -[env:arduino-v3] -platform = espressif32 -platform_packages= - platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.0-rc2 - platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1 + platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.0-rc3 + platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#951ade74d7886e1ce931ea46614c4ac47ae3a6c0 board = esp32dev From b59f0395144aa259a4924994f6b9c9ece4e14af9 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 27 May 2024 21:03:47 +0200 Subject: [PATCH 052/150] Update CI to Arduino 3 --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 37e1df9..2eab45f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -23,6 +23,6 @@ board = esp32dev [env:arduino-3] platform = espressif32 platform_packages= - platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.0-rc3 - platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#951ade74d7886e1ce931ea46614c4ac47ae3a6c0 + platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.0 + platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.0/esp32-arduino-libs-3.0.0.zip board = esp32dev From 2f349ff0a29479c50882a2b99019a6f7f2026825 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 May 2024 05:42:48 +0000 Subject: [PATCH 053/150] Bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 529b5d2..d758cac 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -14,7 +14,7 @@ jobs: matrix: config: [arduino-cli.yaml, arduino-cli-dev.yaml] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: arduino/setup-arduino-cli@v1 - name: Download board run: | From b1df6526c11a66459061434a8e164d4204450c7d Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 29 May 2024 23:09:26 +0200 Subject: [PATCH 054/150] IPv6 cleanups --- .travis.yml | 34 ---------------------------------- src/AsyncTCP.cpp | 40 +++++++++++++++------------------------- 2 files changed, 15 insertions(+), 59 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index dbfc064..0000000 --- a/.travis.yml +++ /dev/null @@ -1,34 +0,0 @@ -sudo: false -language: python -os: - - linux - -git: - depth: false - -stages: - - build - -jobs: - include: - - - name: "Arduino Build" - if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) - stage: build - script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh - - - name: "PlatformIO Build" - if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) - stage: build - script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 1 1 - -notifications: - email: - on_success: change - on_failure: change - webhooks: - urls: - - https://webhooks.gitter.im/e/60e65d0c78ea0a920347 - on_success: change # options: [always|never|change] default: always - on_failure: always # options: [always|never|change] default: always - on_start: false # default: false diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 3247cbc..bb4da8e 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -712,7 +712,7 @@ bool AsyncClient::_connect(ip_addr_t addr, uint16_t port){ return false; } - tcp_pcb* pcb = tcp_new_ip_type(IPADDR_TYPE_ANY); + tcp_pcb* pcb = tcp_new_ip_type(addr.type); if (!pcb){ log_e("pcb == NULL"); return false; @@ -730,10 +730,8 @@ bool AsyncClient::_connect(ip_addr_t addr, uint16_t port){ bool AsyncClient::connect(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 @@ -970,10 +968,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(); + _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; } @@ -1382,6 +1379,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) @@ -1396,6 +1394,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) @@ -1408,7 +1407,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() @@ -1437,17 +1436,8 @@ 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; + _pcb = tcp_new_ip_type(_bind4 && _bind6 ? IPADDR_TYPE_ANY : (_bind6 ? IPADDR_TYPE_V6 : IPADDR_TYPE_V4)); if (!_pcb){ log_e("_pcb == NULL"); return; @@ -1455,13 +1445,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 From c6c124d382c46cf81e931637fa8b73c2981bb66c Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 30 May 2024 00:34:45 +0200 Subject: [PATCH 055/150] v3.1.3 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9186e58..dda4397 100644 --- a/README.md +++ b/README.md @@ -21,4 +21,4 @@ The base classes on which everything else is built. They expose all possible sce - Reverted back `library.properties` for Arduino IDE users - Arduino 3 / ESP-IDF 5 compatibility - Changed lib name: `AsyncTCP` -> `Async TCP` -- Point to `mathieucarbou/Async TCP @ ^3.1.2` +- Point to `mathieucarbou/Async TCP @ ^3.1.3` diff --git a/library.json b/library.json index 77c4946..9904c21 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Async TCP", - "version": "3.1.2", + "version": "3.1.3", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index b2114e2..198d65d 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Async TCP -version=3.1.2 +version=3.1.3 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index db2c17f..a503c04 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.1.2" +#define ASYNCTCP_VERSION "3.1.3" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 1 -#define ASYNCTCP_VERSION_REVISION 2 +#define ASYNCTCP_VERSION_REVISION 3 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From f1a50539e62dd587537635122fe9ec4115c906f4 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 30 May 2024 00:48:47 +0200 Subject: [PATCH 056/150] CI: fail-fast: false --- .github/workflows/push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index d758cac..7e275f5 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -10,7 +10,7 @@ jobs: name: ${{ matrix.config }} runs-on: ubuntu-latest strategy: - fail-fast: true + fail-fast: false matrix: config: [arduino-cli.yaml, arduino-cli-dev.yaml] steps: From c81405543ac4033c18a27ca033358349f4026641 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 30 May 2024 00:54:02 +0200 Subject: [PATCH 057/150] doc --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index dda4397..9d63bae 100644 --- a/README.md +++ b/README.md @@ -22,3 +22,4 @@ The base classes on which everything else is built. They expose all possible sce - Arduino 3 / ESP-IDF 5 compatibility - Changed lib name: `AsyncTCP` -> `Async TCP` - Point to `mathieucarbou/Async TCP @ ^3.1.3` +- IPv6 support From b572c1e969631ff8584799e9c2c7e377f76619ec Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 30 May 2024 01:30:32 +0200 Subject: [PATCH 058/150] Fix for https://github.com/mathieucarbou/ESPAsyncWebServer/issues/26 --- src/AsyncTCP.cpp | 36 +++++++++++++++++++++++++++++------- src/AsyncTCP.h | 4 ++-- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index bb4da8e..135ba8c 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -727,7 +727,7 @@ bool AsyncClient::_connect(ip_addr_t addr, uint16_t port){ return true; } -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 addr.u_addr.ip4.addr = ip; @@ -740,7 +740,7 @@ bool AsyncClient::connect(IPAddress ip, uint16_t port){ } #if LWIP_IPV6 && ESP_IDF_VERSION_MAJOR < 5 -bool AsyncClient::connect(IPv6Address ip, uint16_t port){ +bool AsyncClient::connect(const 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); @@ -1050,7 +1050,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) { @@ -1190,11 +1192,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 @@ -1228,7 +1240,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 } @@ -1240,7 +1257,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 } diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index a503c04..7da0532 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -101,9 +101,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); From b20e92e2af779400f5361a83bba03903379554b0 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 30 May 2024 01:33:45 +0200 Subject: [PATCH 059/150] v3.1.4 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9d63bae..006110c 100644 --- a/README.md +++ b/README.md @@ -21,5 +21,5 @@ The base classes on which everything else is built. They expose all possible sce - Reverted back `library.properties` for Arduino IDE users - Arduino 3 / ESP-IDF 5 compatibility - Changed lib name: `AsyncTCP` -> `Async TCP` -- Point to `mathieucarbou/Async TCP @ ^3.1.3` +- Point to `mathieucarbou/Async TCP @ ^3.1.4` - IPv6 support diff --git a/library.json b/library.json index 9904c21..8a8c569 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Async TCP", - "version": "3.1.3", + "version": "3.1.4", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index 198d65d..9818aba 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Async TCP -version=3.1.3 +version=3.1.4 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 7da0532..9079d44 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.1.3" +#define ASYNCTCP_VERSION "3.1.4" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 1 -#define ASYNCTCP_VERSION_REVISION 3 +#define ASYNCTCP_VERSION_REVISION 4 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From 1e283235d80af113db504f218b53763454f6f193 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 5 Jun 2024 10:49:38 +0200 Subject: [PATCH 060/150] Arduino 3.0.1 --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 2eab45f..c447b67 100644 --- a/platformio.ini +++ b/platformio.ini @@ -23,6 +23,6 @@ board = esp32dev [env:arduino-3] platform = espressif32 platform_packages= - platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.0 - platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.0/esp32-arduino-libs-3.0.0.zip + platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.1 + platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.1/esp32-arduino-libs-3.0.1.zip board = esp32dev From edb9d62b6de347ce3c049e544b702d6548cf3b6a Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 23 Jun 2024 12:13:09 +0200 Subject: [PATCH 061/150] update doc --- README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/README.md b/README.md index 006110c..fc76b63 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ This is a fully asynchronous TCP library, aimed at enabling trouble-free, multi- This library is the base for [ESPAsyncWebServer](https://github.com/mathieucarbou/ESPAsyncWebServer) ## AsyncClient and AsyncServer + The base classes on which everything else is built. They expose all possible scenarios, but are really raw and require more skills to use. ## Changes in this fork @@ -23,3 +24,29 @@ The base classes on which everything else is built. They expose all possible sce - Changed lib name: `AsyncTCP` -> `Async TCP` - Point to `mathieucarbou/Async TCP @ ^3.1.4` - IPv6 support + +## Important recommendations + +Most of the crashes are caused by improper configuration of the library for the project. +Here are some recommendations to avoid them. + +1. Set the running core to be on the same core of your application (usually core 1) `-D CONFIG_ASYNC_TCP_RUNNING_CORE=1` +2. Set the stack size appropriately with `-D CONFIG_ASYNC_TCP_STACK_SIZE=16384`. + The default value of `16384` might be too much for your project. + You can look at the [MycilaTaskMonitor](https://oss.carbou.me/MycilaTaskMonitor) project to monitor the stack usage. +3. You can change **if you know what you are doing** the task priority with `-D CONFIG_ASYNC_TCP_PRIORITY=10`. + Default is `10`. +4. You can increase the queue size with `-D CONFIG_ASYNC_TCP_QUEUE_SIZE=128`. + Default is `64`. +5. You can decrease the maximum ack time `-D CONFIG_ASYNC_TCP_MAX_ACK_TIME=3000`. + Default is `5000`. + +I personally use the following configuration in my projects: + +```c++ + -D CONFIG_ASYNC_TCP_MAX_ACK_TIME=3000 + -D CONFIG_ASYNC_TCP_PRIORITY=10 + -D CONFIG_ASYNC_TCP_QUEUE_SIZE=128 + -D CONFIG_ASYNC_TCP_RUNNING_CORE=1 + -D CONFIG_ASYNC_TCP_STACK_SIZE=4096 +``` From bd77f62141e740aa76305b673333aa8c96beda77 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 23 Jun 2024 12:23:12 +0200 Subject: [PATCH 062/150] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 33 ++++++++++++++++++++++++++++ .github/ISSUE_TEMPLATE/question.md | 10 +++++++++ 2 files changed, 43 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/question.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..fa9052c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,33 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[BUG]" +labels: bug +assignees: '' + +--- + +**Please make sure to go through the recommendations before opening a bug report:** + +[https://github.com/mathieucarbou/AsyncTCP?tab=readme-ov-file#important-recommendations](https://github.com/mathieucarbou/AsyncTCP?tab=readme-ov-file#important-recommendations) + +**Description** + +A clear and concise description of what the bug is. + +**Board** + +esp32dev, esp32s3, etc + +**Ethernet adpater used ?** + +If yes, please specify which one + +**Stack trace** + +Please provide the stack trace here taken with `monitor_filters = esp32_exception_decoder`. +**Any issue opened with a non readable stack trace will be ignored because not helpful at all.** + +**Additional notes** + +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md new file mode 100644 index 0000000..634179c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.md @@ -0,0 +1,10 @@ +--- +name: Question +about: Describe your question +title: "[Q]" +labels: question +assignees: '' + +--- + + From 27bf9218d95a9a4f829512fc3f9572e930269baa Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 23 Jun 2024 23:11:00 +0200 Subject: [PATCH 063/150] typo --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index fa9052c..7b3ee89 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -19,7 +19,7 @@ A clear and concise description of what the bug is. esp32dev, esp32s3, etc -**Ethernet adpater used ?** +**Ethernet adapter used ?** If yes, please specify which one From 75db319967e76ac82dc2cf97e92685e44001e953 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 24 Jun 2024 22:30:00 +0200 Subject: [PATCH 064/150] Arduino Release v3.0.2 based on ESP-IDF v5.1.4+ --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index c447b67..f96351b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -23,6 +23,6 @@ board = esp32dev [env:arduino-3] platform = espressif32 platform_packages= - platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.1 - platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.1/esp32-arduino-libs-3.0.1.zip + platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.2 + platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.2/esp32-arduino-libs-3.0.2.zip board = esp32dev From 34989cc45596b621264a859694335bb206382fb4 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 30 Jun 2024 10:37:56 +0200 Subject: [PATCH 065/150] Issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 7b3ee89..8e2c31c 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -28,6 +28,8 @@ If yes, please specify which one Please provide the stack trace here taken with `monitor_filters = esp32_exception_decoder`. **Any issue opened with a non readable stack trace will be ignored because not helpful at all.** +As an alternative, you can use [https://maximeborges.github.io/esp-stacktrace-decoder/](https://maximeborges.github.io/esp-stacktrace-decoder/). + **Additional notes** Add any other context about the problem here. From f0319ac64e2199d823f9c8f116f4765b121502f7 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 4 Jul 2024 12:14:45 +0200 Subject: [PATCH 066/150] Add fix from https://github.com/me-no-dev/AsyncTCP/pull/184 --- src/AsyncTCP.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 135ba8c..4b61573 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -723,8 +723,8 @@ 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_connect(pcb, _closed_slot, &addr, port,(tcp_connected_fn)&_tcp_connected); - return true; + esp_err_t err =_tcp_connect(pcb, _closed_slot, &addr, port,(tcp_connected_fn)&_tcp_connected); + return err == ESP_OK; } bool AsyncClient::connect(const IPAddress& ip, uint16_t port){ From a1cfe8df35023fbc9472c19e78df63c9991921a8 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 16 Jul 2024 22:16:00 +0200 Subject: [PATCH 067/150] Async TCP => AsyncTCP --- README.md | 5 ++--- library.json | 2 +- library.properties | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fc76b63..0a3b0d7 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![License: LGPL 3.0](https://img.shields.io/badge/License-LGPL%203.0-yellow.svg)](https://opensource.org/license/lgpl-3-0/) [![Continuous Integration](https://github.com/mathieucarbou/AsyncTCP/actions/workflows/push.yml/badge.svg)](https://github.com/mathieucarbou/AsyncTCP/actions/workflows/push.yml) -[![PlatformIO Registry](https://badges.registry.platformio.org/packages/mathieucarbou/library/Async%20TCP.svg)](https://registry.platformio.org/libraries/mathieucarbou/Async%20TCP) +[![PlatformIO Registry](https://badges.registry.platformio.org/packages/mathieucarbou/library/AsyncTCP.svg)](https://registry.platformio.org/libraries/mathieucarbou/AsyncTCP) A fork of the [AsyncTCP](https://github.com/me-no-dev/AsyncTCP) library by [@me-no-dev](https://github.com/me-no-dev) for [ESPHome](https://esphome.io). @@ -21,8 +21,7 @@ The base classes on which everything else is built. They expose all possible sce - All improvements from [ESPHome fork](https://github.com/esphome/AsyncTCP) - Reverted back `library.properties` for Arduino IDE users - Arduino 3 / ESP-IDF 5 compatibility -- Changed lib name: `AsyncTCP` -> `Async TCP` -- Point to `mathieucarbou/Async TCP @ ^3.1.4` +- Point to `mathieucarbou/AsyncTCP @ ^3.1.4` - IPv6 support ## Important recommendations diff --git a/library.json b/library.json index 8a8c569..b821b20 100644 --- a/library.json +++ b/library.json @@ -1,5 +1,5 @@ { - "name": "Async TCP", + "name": "AsyncTCP", "version": "3.1.4", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", diff --git a/library.properties b/library.properties index 9818aba..c21784d 100644 --- a/library.properties +++ b/library.properties @@ -1,4 +1,4 @@ -name=Async TCP +name=AsyncTCP version=3.1.4 author=Me-No-Dev maintainer=Mathieu Carbou From c174f6c4674cb3f3892915a65a21c4e4f7f98d30 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 4 Jul 2024 12:27:36 +0200 Subject: [PATCH 068/150] Try fix from https://github.com/me-no-dev/AsyncTCP/pull/173/files#r1581612715 --- src/AsyncTCP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 4b61573..bd768a0 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -439,7 +439,7 @@ 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 != -1 || !_closed_slots[msg->closed_slot]) { msg->err = 0; tcp_recved(msg->pcb, msg->received); } From 20b139c07c3ef017023d3035d48b52d0cedbac81 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 16 Jul 2024 22:17:49 +0200 Subject: [PATCH 069/150] v3.2.0 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0a3b0d7..a0861e5 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ The base classes on which everything else is built. They expose all possible sce - All improvements from [ESPHome fork](https://github.com/esphome/AsyncTCP) - Reverted back `library.properties` for Arduino IDE users - Arduino 3 / ESP-IDF 5 compatibility -- Point to `mathieucarbou/AsyncTCP @ ^3.1.4` +- Point to `mathieucarbou/AsyncTCP @ ^3.2.0` - IPv6 support ## Important recommendations diff --git a/library.json b/library.json index b821b20..f5b7ff2 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "AsyncTCP", - "version": "3.1.4", + "version": "3.2.0", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index c21784d..9582f4d 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=AsyncTCP -version=3.1.4 +version=3.2.0 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 9079d44..813ccb1 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.1.4" +#define ASYNCTCP_VERSION "3.2.0" #define ASYNCTCP_VERSION_MAJOR 3 -#define ASYNCTCP_VERSION_MINOR 1 -#define ASYNCTCP_VERSION_REVISION 4 +#define ASYNCTCP_VERSION_MINOR 2 +#define ASYNCTCP_VERSION_REVISION 0 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From acdf1f5e71a7e8afa85addfb2b9c32b93414cecc Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 16 Jul 2024 22:54:24 +0200 Subject: [PATCH 070/150] Revert "Try fix from https://github.com/me-no-dev/AsyncTCP/pull/173/files#r1581612715" This reverts commit c174f6c4674cb3f3892915a65a21c4e4f7f98d30. --- src/AsyncTCP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index bd768a0..4b61573 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -439,7 +439,7 @@ 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 == -1 || !_closed_slots[msg->closed_slot]) { msg->err = 0; tcp_recved(msg->pcb, msg->received); } From 76e49649e641ca372561ebe4c4ff344e96fd4792 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 16 Jul 2024 23:00:11 +0200 Subject: [PATCH 071/150] v3.2.1 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a0861e5..2ef59f5 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ The base classes on which everything else is built. They expose all possible sce - All improvements from [ESPHome fork](https://github.com/esphome/AsyncTCP) - Reverted back `library.properties` for Arduino IDE users - Arduino 3 / ESP-IDF 5 compatibility -- Point to `mathieucarbou/AsyncTCP @ ^3.2.0` +- Point to `mathieucarbou/AsyncTCP @ ^3.2.1` - IPv6 support ## Important recommendations diff --git a/library.json b/library.json index f5b7ff2..d73c49c 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "AsyncTCP", - "version": "3.2.0", + "version": "3.2.1", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index 9582f4d..b7e5881 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=AsyncTCP -version=3.2.0 +version=3.2.1 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 813ccb1..c6cf761 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.2.0" +#define ASYNCTCP_VERSION "3.2.1" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 2 -#define ASYNCTCP_VERSION_REVISION 0 +#define ASYNCTCP_VERSION_REVISION 1 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From af12f8fac6f9f7a8454cd868643ce331cef63838 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 17 Jul 2024 15:39:06 +0200 Subject: [PATCH 072/150] Arduino 3.0.3 --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index f96351b..864b1c1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -23,6 +23,6 @@ board = esp32dev [env:arduino-3] platform = espressif32 platform_packages= - platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.2 - platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.2/esp32-arduino-libs-3.0.2.zip + platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.3 + platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.3/esp32-arduino-libs-3.0.3.zip board = esp32dev From 15581b57ecbc1e7545a083f6e6be93cf49da0c36 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 17 Jul 2024 15:54:03 +0200 Subject: [PATCH 073/150] Arduino 3.0.3 compatibility --- src/AsyncTCP.cpp | 6 ++++++ src/AsyncTCP.h | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 4b61573..a20151a 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -33,6 +33,12 @@ 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 + /* * TCP/IP Event Task * */ diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index c6cf761..eb9c769 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.2.1" +#define ASYNCTCP_VERSION "3.2.2" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 2 -#define ASYNCTCP_VERSION_REVISION 1 +#define ASYNCTCP_VERSION_REVISION 2 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From 61ec506a1b833d120888923a3d9ca6fb5b464be0 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 17 Jul 2024 16:00:19 +0200 Subject: [PATCH 074/150] v3.2.2 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2ef59f5..fa6cf9f 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ The base classes on which everything else is built. They expose all possible sce - All improvements from [ESPHome fork](https://github.com/esphome/AsyncTCP) - Reverted back `library.properties` for Arduino IDE users - Arduino 3 / ESP-IDF 5 compatibility -- Point to `mathieucarbou/AsyncTCP @ ^3.2.1` +- Point to `mathieucarbou/AsyncTCP @ ^3.2.2` - IPv6 support ## Important recommendations diff --git a/library.json b/library.json index d73c49c..5d4c4b4 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "AsyncTCP", - "version": "3.2.1", + "version": "3.2.2", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index b7e5881..d9d5cb0 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=AsyncTCP -version=3.2.1 +version=3.2.2 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 From 018e8ae8b6d4a00ed21eaa1f8b69900efb4800fb Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 17 Jul 2024 16:02:20 +0200 Subject: [PATCH 075/150] Try remove busy loop to fix https://github.com/mathieucarbou/ESPAsyncWebServer/issues/57 --- src/AsyncTCP.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index a20151a..6266fd3 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -1097,12 +1097,9 @@ size_t AsyncClient::write(const char* data) { size_t AsyncClient::write(const char* data, size_t size, uint8_t apiflags) { size_t will_send = add(data, size, apiflags); - if(!will_send) { + if(!will_send || !send()) { return 0; } - while (connected() && !send()) { - taskYIELD(); - } return will_send; } From 700ad8850d1b6d834c9ff9d2038d6f845158cd44 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 17 Jul 2024 21:50:06 +0200 Subject: [PATCH 076/150] v3.2.3 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fa6cf9f..5459951 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ The base classes on which everything else is built. They expose all possible sce - All improvements from [ESPHome fork](https://github.com/esphome/AsyncTCP) - Reverted back `library.properties` for Arduino IDE users - Arduino 3 / ESP-IDF 5 compatibility -- Point to `mathieucarbou/AsyncTCP @ ^3.2.2` +- Point to `mathieucarbou/AsyncTCP @ ^3.2.3` - IPv6 support ## Important recommendations diff --git a/library.json b/library.json index 5d4c4b4..e965d44 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "AsyncTCP", - "version": "3.2.2", + "version": "3.2.3", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index d9d5cb0..a50f4ca 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=AsyncTCP -version=3.2.2 +version=3.2.3 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index eb9c769..3d2f56c 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.2.2" +#define ASYNCTCP_VERSION "3.2.3" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 2 -#define ASYNCTCP_VERSION_REVISION 2 +#define ASYNCTCP_VERSION_REVISION 3 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From e5ffb8c378f300eebde0d19680d6b3c62716f551 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 18 Jul 2024 12:41:17 +0200 Subject: [PATCH 077/150] Add CI support for esp32-c6-devkitc-1 --- .github/workflows/push.yml | 24 ++++++++++++++++++++++++ platformio.ini | 4 ++++ 2 files changed, 28 insertions(+) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 7e275f5..475bb91 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -50,3 +50,27 @@ jobs: - run: pip install platformio - run: sed -i -e 's/esp32dev/${{ matrix.board }}/g' platformio.ini - run: pio run -e ${{ matrix.env }} + + build-pioarduino: + name: ${{ matrix.board }} ${{ matrix.env }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + board: [esp32-c6-devkitc-1] + env: [pioarduino] + steps: + - uses: actions/checkout@v4 + - uses: actions/cache@v4 + with: + path: | + ~/.platformio + ~/.cache/pip + key: ${{ matrix.env }} + - uses: actions/setup-python@v5 + with: + python-version: "3.x" + - run: pip install platformio + - run: sed -i -e 's/esp32-c6-devkitc-1/${{ matrix.board }}/g' platformio.ini + - run: pio run -e ${{ matrix.env }} + \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 864b1c1..6e7e7c0 100644 --- a/platformio.ini +++ b/platformio.ini @@ -26,3 +26,7 @@ platform_packages= platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.3 platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.3/esp32-arduino-libs-3.0.3.zip board = esp32dev + +[env:pioarduino] +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.03/platform-espressif32.zip +board = esp32-c6-devkitc-1 From 247083787b80d385177748d3c5e8e56daef8399d Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 19 Jul 2024 09:25:26 +0200 Subject: [PATCH 078/150] doc update --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5459951..a112bf0 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,14 @@ The base classes on which everything else is built. They expose all possible sce - All improvements from [ESPHome fork](https://github.com/esphome/AsyncTCP) - Reverted back `library.properties` for Arduino IDE users - Arduino 3 / ESP-IDF 5 compatibility -- Point to `mathieucarbou/AsyncTCP @ ^3.2.3` - IPv6 support +## Coordinates + +``` +mathieucarbou/AsyncTCP @ ^3.2.3 +``` + ## Important recommendations Most of the crashes are caused by improper configuration of the library for the project. From 9eeef4cc1f6b801139891aaaedc1511aafb602bb Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 19 Jul 2024 13:03:07 +0200 Subject: [PATCH 079/150] CI update --- .github/workflows/{push.yml => ci.yml} | 50 ++++++++++++++------------ platformio.ini | 18 +++++++++- 2 files changed, 45 insertions(+), 23 deletions(-) rename .github/workflows/{push.yml => ci.yml} (62%) diff --git a/.github/workflows/push.yml b/.github/workflows/ci.yml similarity index 62% rename from .github/workflows/push.yml rename to .github/workflows/ci.yml index 475bb91..7d3b583 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/ci.yml @@ -28,37 +28,39 @@ jobs: LWIP_IPV6: true run: arduino-cli --config-file ${{ matrix.config }} --library ./src/ compile --fqbn esp32:esp32:esp32 ./examples/ClientServer/Client/Client.ino - build-pio: - name: ${{ matrix.board }} ${{ matrix.env }} + pio_envs: + name: Get PlatformIO Envs runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - board: [esp32dev, esp32-s3-devkitc-1] - env: [arduino-2, arduino-3] steps: - uses: actions/checkout@v4 - uses: actions/cache@v4 with: - path: | - ~/.platformio - ~/.cache/pip - key: ${{ matrix.env }} + key: pip + path: ~/.cache/pip - uses: actions/setup-python@v5 with: python-version: "3.x" - - run: pip install platformio - - run: sed -i -e 's/esp32dev/${{ matrix.board }}/g' platformio.ini - - run: pio run -e ${{ matrix.env }} + - name: Install PlatformIO + run: | + python -m pip install --upgrade pip + pip install --upgrade platformio + - name: Get Envs + id: envs + run: | + echo "pio_default_envs=$(pio project config --json-output | jq -cr '[ .[][0] | select(startswith("env:") and (endswith("-debug")|not)) | .[4:] ]')" >> $GITHUB_OUTPUT - build-pioarduino: - name: ${{ matrix.board }} ${{ matrix.env }} + outputs: + pio_default_envs: ${{ steps.envs.outputs.pio_default_envs }} + + build-pio: + name: "pio:${{ matrix.environment }}" + needs: [pio_envs] runs-on: ubuntu-latest strategy: fail-fast: false matrix: - board: [esp32-c6-devkitc-1] - env: [pioarduino] + environment: ${{ fromJSON(needs.pio_envs.outputs.pio_default_envs) }} + steps: - uses: actions/checkout@v4 - uses: actions/cache@v4 @@ -66,11 +68,15 @@ jobs: path: | ~/.platformio ~/.cache/pip - key: ${{ matrix.env }} + key: pio - uses: actions/setup-python@v5 with: python-version: "3.x" - run: pip install platformio - - run: sed -i -e 's/esp32-c6-devkitc-1/${{ matrix.board }}/g' platformio.ini - - run: pio run -e ${{ matrix.env }} - \ No newline at end of file + + - name: Install platformio + run: | + python -m pip install --upgrade pip + pip install --upgrade platformio + + - run: PLATFORMIO_SRC_DIR=examples/ClientServer/Client pio run -e ${{ matrix.environment }} diff --git a/platformio.ini b/platformio.ini index 6e7e7c0..4cfad22 100644 --- a/platformio.ini +++ b/platformio.ini @@ -27,6 +27,22 @@ platform_packages= platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.3/esp32-arduino-libs-3.0.3.zip board = esp32dev -[env:pioarduino] +[env:pioarduino-esp32dev] +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.03/platform-espressif32.zip +board = esp32dev + +[env:pioarduino-esp32-s2] +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.03/platform-espressif32.zip +board = esp32-s2-saola-1 + +[env:pioarduino-esp32-s3] +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.03/platform-espressif32.zip +board = esp32-s3-devkitc-1 + +[env:pioarduino-esp32-c3] +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.03/platform-espressif32.zip +board = esp32-c3-devkitc-02 + +[env:pioarduino-esp32-c6] platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.03/platform-espressif32.zip board = esp32-c6-devkitc-1 From b20e646658f2bfa482c9be9a098cc0ffe405774b Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 26 Jul 2024 13:28:06 +0200 Subject: [PATCH 080/150] Try fix #14 --- src/AsyncTCP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 6266fd3..2da1703 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -445,7 +445,7 @@ 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 != -1 && !_closed_slots[msg->closed_slot]) { msg->err = 0; tcp_recved(msg->pcb, msg->received); } From f374fabaa25cfa46788d7fd50bee648bf766ce41 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 29 Jul 2024 17:20:04 +0200 Subject: [PATCH 081/150] Fix link --- README.md | 2 +- src/AsyncTCP.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a112bf0..c65f018 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # AsyncTCP [![License: LGPL 3.0](https://img.shields.io/badge/License-LGPL%203.0-yellow.svg)](https://opensource.org/license/lgpl-3-0/) -[![Continuous Integration](https://github.com/mathieucarbou/AsyncTCP/actions/workflows/push.yml/badge.svg)](https://github.com/mathieucarbou/AsyncTCP/actions/workflows/push.yml) +[![Continuous Integration](https://github.com/mathieucarbou/AsyncTCP/actions/workflows/ci.yml/badge.svg)](https://github.com/mathieucarbou/AsyncTCP/actions/workflows/ci.yml) [![PlatformIO Registry](https://badges.registry.platformio.org/packages/mathieucarbou/library/AsyncTCP.svg)](https://registry.platformio.org/libraries/mathieucarbou/AsyncTCP) A fork of the [AsyncTCP](https://github.com/me-no-dev/AsyncTCP) library by [@me-no-dev](https://github.com/me-no-dev) for [ESPHome](https://esphome.io). diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 2da1703..2dae2cb 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -1012,7 +1012,7 @@ int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { int8_t AsyncClient::_poll(tcp_pcb* pcb){ if(!_pcb){ - log_d("pcb is NULL"); + // log_d("pcb is NULL"); return ERR_OK; } if(pcb != _pcb){ From 11f6a803fcc4d0abc8872ca03fcbac7df25d3d51 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 29 Jul 2024 18:55:48 +0200 Subject: [PATCH 082/150] v3.2.4 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c65f018..61ccd09 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ The base classes on which everything else is built. They expose all possible sce ## Coordinates ``` -mathieucarbou/AsyncTCP @ ^3.2.3 +mathieucarbou/AsyncTCP @ ^3.2.4 ``` ## Important recommendations diff --git a/library.json b/library.json index e965d44..c449f2a 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "AsyncTCP", - "version": "3.2.3", + "version": "3.2.4", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index a50f4ca..12a504c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=AsyncTCP -version=3.2.3 +version=3.2.4 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 3d2f56c..feac4d2 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.2.3" +#define ASYNCTCP_VERSION "3.2.4" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 2 -#define ASYNCTCP_VERSION_REVISION 3 +#define ASYNCTCP_VERSION_REVISION 4 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From d0a44bc74cfa41b9ca5e51c441e74e34932f3336 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 31 Jul 2024 09:55:26 +0200 Subject: [PATCH 083/150] espressif32@6.8.1 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 4cfad22..0a95c78 100644 --- a/platformio.ini +++ b/platformio.ini @@ -17,7 +17,7 @@ platform = espressif32 board = esp32dev [env:arduino-2] -platform = espressif32@6.7.0 +platform = espressif32@6.8.1 board = esp32dev [env:arduino-3] From 1c15d8d0d0f08a09a5ac5ab4499dd428a50d008c Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 2 Aug 2024 12:16:23 +0200 Subject: [PATCH 084/150] Arduino 3.0.4 --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 0a95c78..db7c7b2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -23,8 +23,8 @@ board = esp32dev [env:arduino-3] platform = espressif32 platform_packages= - platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.3 - platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.3/esp32-arduino-libs-3.0.3.zip + platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.4 + platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.4/esp32-arduino-libs-3.0.4.zip board = esp32dev [env:pioarduino-esp32dev] From 3a59a49c0bce5a8a00738e5e3fb79ededec84d8e Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 10 Aug 2024 22:38:52 +0200 Subject: [PATCH 085/150] pioarduino 51.03.04 --- platformio.ini | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platformio.ini b/platformio.ini index db7c7b2..cb46458 100644 --- a/platformio.ini +++ b/platformio.ini @@ -28,21 +28,21 @@ platform_packages= board = esp32dev [env:pioarduino-esp32dev] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.03/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip board = esp32dev [env:pioarduino-esp32-s2] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.03/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip board = esp32-s2-saola-1 [env:pioarduino-esp32-s3] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.03/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip board = esp32-s3-devkitc-1 [env:pioarduino-esp32-c3] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.03/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip board = esp32-c3-devkitc-02 [env:pioarduino-esp32-c6] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.03/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip board = esp32-c6-devkitc-1 From 49c7cc15d9e8bda1c5be882a4ff0a51da64ef8d6 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 16 Aug 2024 01:02:11 +0200 Subject: [PATCH 086/150] Added CI for H2 --- platformio.ini | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platformio.ini b/platformio.ini index cb46458..8625e23 100644 --- a/platformio.ini +++ b/platformio.ini @@ -46,3 +46,7 @@ board = esp32-c3-devkitc-02 [env:pioarduino-esp32-c6] platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip board = esp32-c6-devkitc-1 + +[env:pioarduino-h2] +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip +board = esp32-h2-devkitm-1 From 95de78acbb854d85983d0db2a71932643ced048c Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 2 Sep 2024 13:12:04 +0100 Subject: [PATCH 087/150] Use IPADDR6_INIT() macro to set connecting IPv6 address If LwIP is built with LWIP_IPV6_SCOPES, there is a 'zone' member in struct ip6_addr which was not being initialized correctly, leading to routing failures. The tcp_connect() call would return ERR_RTE and we would completely fail to report that error. All the user would see is 'Connecting to MQTT...' over and over again. --- src/AsyncTCP.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 2dae2cb..ea695ef 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -747,9 +747,8 @@ bool AsyncClient::connect(const IPAddress& ip, uint16_t port){ #if LWIP_IPV6 && ESP_IDF_VERSION_MAJOR < 5 bool AsyncClient::connect(const 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); + auto ipaddr = static_cast(ip); + ip_addr_t addr = IPADDR6_INIT(ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); return _connect(addr, port); } From 8fc4aa43b7fdf06ed4dd8d63c852eff512eb5556 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 3 Sep 2024 12:20:41 +0200 Subject: [PATCH 088/150] v3.2.5 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 61ccd09..0536ac3 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ The base classes on which everything else is built. They expose all possible sce ## Coordinates ``` -mathieucarbou/AsyncTCP @ ^3.2.4 +mathieucarbou/AsyncTCP @ ^3.2.5 ``` ## Important recommendations diff --git a/library.json b/library.json index c449f2a..b84e397 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "AsyncTCP", - "version": "3.2.4", + "version": "3.2.5", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index 12a504c..0f59514 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=AsyncTCP -version=3.2.4 +version=3.2.5 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index feac4d2..0c374ed 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.2.4" +#define ASYNCTCP_VERSION "3.2.5" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 2 -#define ASYNCTCP_VERSION_REVISION 4 +#define ASYNCTCP_VERSION_REVISION 5 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From 6a8203b671c9794729f191d11964d77f5e9062db Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 5 Sep 2024 23:10:41 +0200 Subject: [PATCH 089/150] Update gitignore --- .vscode/settings.json | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 950debb..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "cmake.configureOnOpen": false, - "githubPullRequests.remotes": [ - "origin", - "upstream", - "OttoWinter", - "me-no-dev" - ] -} \ No newline at end of file From 6cd96265dfb8a9b9d054b5c51f7a316a021fc02a Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 5 Sep 2024 23:16:11 +0200 Subject: [PATCH 090/150] Update gitignore --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 4ac15a4..18584e8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ .DS_Store .lh /.pio -/.vscode/* -!/.vscode/settings.json +/.vscode + /logs From f35d15b57c843e5d305a7568be020a17368637be Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 5 Sep 2024 23:22:24 +0200 Subject: [PATCH 091/150] Add gitpod files and CoC --- .gitpod.Dockerfile | 2 + .gitpod.yml | 9 ++++ CODE_OF_CONDUCT.md | 129 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 .gitpod.Dockerfile create mode 100644 .gitpod.yml create mode 100644 CODE_OF_CONDUCT.md diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile new file mode 100644 index 0000000..29eeb43 --- /dev/null +++ b/.gitpod.Dockerfile @@ -0,0 +1,2 @@ +FROM gitpod/workspace-python-3.11 +USER gitpod diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 0000000..75c35e2 --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,9 @@ +tasks: + - command: pip install --upgrade pip && pip install -U platformio && platformio run -e dev + +image: + file: .gitpod.Dockerfile + +vscode: + extensions: + - shardulm94.trailing-spaces diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..0a5f914 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,129 @@ + +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +https://sidweb.nl/cms3/en/contact. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. From 4468959bf0698822461a8ee993cc60aa4f5a8ec6 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 6 Sep 2024 11:31:02 +0200 Subject: [PATCH 092/150] update CI --- .github/workflows/ci.yml | 92 +++++++++++++++++++++++----------------- .gitpod.yml | 2 +- platformio.ini | 40 ++++++----------- 3 files changed, 68 insertions(+), 66 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7d3b583..44cd617 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,10 @@ on: pull_request: workflow_dispatch: +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: build-arduino: name: ${{ matrix.config }} @@ -28,55 +32,67 @@ jobs: LWIP_IPV6: true run: arduino-cli --config-file ${{ matrix.config }} --library ./src/ compile --fqbn esp32:esp32:esp32 ./examples/ClientServer/Client/Client.ino - pio_envs: - name: Get PlatformIO Envs - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/cache@v4 - with: - key: pip - path: ~/.cache/pip - - uses: actions/setup-python@v5 - with: - python-version: "3.x" - - name: Install PlatformIO - run: | - python -m pip install --upgrade pip - pip install --upgrade platformio - - name: Get Envs - id: envs - run: | - echo "pio_default_envs=$(pio project config --json-output | jq -cr '[ .[][0] | select(startswith("env:") and (endswith("-debug")|not)) | .[4:] ]')" >> $GITHUB_OUTPUT - - outputs: - pio_default_envs: ${{ steps.envs.outputs.pio_default_envs }} - - build-pio: - name: "pio:${{ matrix.environment }}" - needs: [pio_envs] + platformio: + name: "pio:${{ matrix.env }}:${{ matrix.board }}" runs-on: ubuntu-latest strategy: - fail-fast: false matrix: - environment: ${{ fromJSON(needs.pio_envs.outputs.pio_default_envs) }} + include: + - env: ci-arduino-2 + board: esp32dev + - env: ci-arduino-2 + board: esp32-s2-saola-1 + - env: ci-arduino-2 + board: esp32-s3-devkitc-1 + - env: ci-arduino-2 + board: esp32-c3-devkitc-02 + + - env: ci-arduino-3 + board: esp32dev + - env: ci-arduino-3 + board: esp32-s2-saola-1 + - env: ci-arduino-3 + board: esp32-s3-devkitc-1 + - env: ci-arduino-3 + board: esp32-c3-devkitc-02 + - env: ci-arduino-3 + board: esp32-c6-devkitc-1 + - env: ci-arduino-3 + board: esp32-h2-devkitm-1 + + - env: ci-arduino-310rc1 + board: esp32dev + - env: ci-arduino-310rc1 + board: esp32-s2-saola-1 + - env: ci-arduino-310rc1 + board: esp32-s3-devkitc-1 + - env: ci-arduino-310rc1 + board: esp32-c3-devkitc-02 + - env: ci-arduino-310rc1 + board: esp32-c6-devkitc-1 + - env: ci-arduino-310rc1 + board: esp32-h2-devkitm-1 steps: - - uses: actions/checkout@v4 - - uses: actions/cache@v4 + - name: Checkout + uses: actions/checkout@v4 + + - name: Cache PlatformIO + uses: actions/cache@v4 with: + key: ${{ runner.os }}-pio path: | - ~/.platformio ~/.cache/pip - key: pio - - uses: actions/setup-python@v5 + ~/.platformio + + - name: Python + uses: actions/setup-python@v5 with: python-version: "3.x" - - run: pip install platformio - - name: Install platformio + - name: Build run: | python -m pip install --upgrade pip pip install --upgrade platformio - - - run: PLATFORMIO_SRC_DIR=examples/ClientServer/Client pio run -e ${{ matrix.environment }} + + - run: PLATFORMIO_SRC_DIR=examples/ClientServer/Client PIO_BOARD=${{ matrix.board }} pio run -e ${{ matrix.env }} diff --git a/.gitpod.yml b/.gitpod.yml index 75c35e2..2f8a443 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -1,5 +1,5 @@ tasks: - - command: pip install --upgrade pip && pip install -U platformio && platformio run -e dev + - command: pip install --upgrade pip && pip install -U platformio && platformio run image: file: .gitpod.Dockerfile diff --git a/platformio.ini b/platformio.ini index 8625e23..a17ca1b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -7,46 +7,32 @@ build_flags = upload_protocol = esptool monitor_speed = 115200 monitor_filters = esp32_exception_decoder, log2file +board = esp32dev [platformio] +default_envs = arduino-2, arduino-3, arduino-310rc1 lib_dir = . src_dir = examples/ClientServer/Client -[env:arduino] -platform = espressif32 -board = esp32dev - [env:arduino-2] platform = espressif32@6.8.1 -board = esp32dev [env:arduino-3] -platform = espressif32 -platform_packages= - platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.4 - platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.4/esp32-arduino-libs-3.0.4.zip -board = esp32dev - -[env:pioarduino-esp32dev] platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip -board = esp32dev -[env:pioarduino-esp32-s2] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip -board = esp32-s2-saola-1 +[env:arduino-310rc1] +platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10%%2Brc1/platform-espressif32.zip -[env:pioarduino-esp32-s3] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip -board = esp32-s3-devkitc-1 +; CI -[env:pioarduino-esp32-c3] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip -board = esp32-c3-devkitc-02 +[env:ci-arduino-2] +platform = espressif32@6.8.1 +board = ${sysenv.PIO_BOARD} -[env:pioarduino-esp32-c6] +[env:ci-arduino-3] platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip -board = esp32-c6-devkitc-1 +board = ${sysenv.PIO_BOARD} -[env:pioarduino-h2] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip -board = esp32-h2-devkitm-1 +[env:ci-arduino-310rc1] +platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10%%2Brc1/platform-espressif32.zip +board = ${sysenv.PIO_BOARD} From ea65eed4404f9b359a8d6ede3ef78f0efbaf0468 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 6 Sep 2024 11:56:09 +0200 Subject: [PATCH 093/150] fail-fast: false --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 44cd617..18e8924 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,6 +36,7 @@ jobs: name: "pio:${{ matrix.env }}:${{ matrix.board }}" runs-on: ubuntu-latest strategy: + fail-fast: false matrix: include: - env: ci-arduino-2 From 5093f8dbcdb3fcda0f2922f4d145d0d3f52ee36c Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 9 Sep 2024 22:25:40 +0200 Subject: [PATCH 094/150] Changed numbers to enum for _pcb->state --- src/AsyncTCP.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index ea695ef..8ad7d29 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -800,7 +800,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; @@ -1081,7 +1081,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; @@ -1284,35 +1284,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(){ From 62eb9682b1d84ae24c30edf73d9763e2733f31c0 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 12 Sep 2024 20:03:38 +0200 Subject: [PATCH 095/150] pioarduino 53.03.10-rc1 --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index a17ca1b..f7bdbe2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -21,7 +21,7 @@ platform = espressif32@6.8.1 platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip [env:arduino-310rc1] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10%%2Brc1/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc1/platform-espressif32.zip ; CI @@ -34,5 +34,5 @@ platform = https://github.com/pioarduino/platform-espressif32/releases/download/ board = ${sysenv.PIO_BOARD} [env:ci-arduino-310rc1] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10%%2Brc1/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc1/platform-espressif32.zip board = ${sysenv.PIO_BOARD} From fec30f93b64610f0aafc4cc71a85164763a161dd Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 18 Sep 2024 15:45:24 +0200 Subject: [PATCH 096/150] Arduino Release v3.0.5 based on ESP-IDF v5.1.4+ --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index f7bdbe2..19b5f37 100644 --- a/platformio.ini +++ b/platformio.ini @@ -18,7 +18,7 @@ src_dir = examples/ClientServer/Client platform = espressif32@6.8.1 [env:arduino-3] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip [env:arduino-310rc1] platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc1/platform-espressif32.zip @@ -30,7 +30,7 @@ platform = espressif32@6.8.1 board = ${sysenv.PIO_BOARD} [env:ci-arduino-3] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip board = ${sysenv.PIO_BOARD} [env:ci-arduino-310rc1] From 56ed8c9e28fcbf4099fe1dba2163e6e8d404fd79 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 26 Sep 2024 14:53:51 +0200 Subject: [PATCH 097/150] espressif32@6.9.0 --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 19b5f37..91bcf13 100644 --- a/platformio.ini +++ b/platformio.ini @@ -15,7 +15,7 @@ lib_dir = . src_dir = examples/ClientServer/Client [env:arduino-2] -platform = espressif32@6.8.1 +platform = espressif32@6.9.0 [env:arduino-3] platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip @@ -26,7 +26,7 @@ platform = https://github.com/pioarduino/platform-espressif32/releases/download/ ; CI [env:ci-arduino-2] -platform = espressif32@6.8.1 +platform = espressif32@6.9.0 board = ${sysenv.PIO_BOARD} [env:ci-arduino-3] From 4837967b6497ed24f9cfb57d8693188dc936842f Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 2 Oct 2024 22:53:10 +0200 Subject: [PATCH 098/150] Introduced macro INVALID_CLOSED_SLOT --- src/AsyncTCP.cpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 8ad7d29..d112672 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -39,6 +39,8 @@ extern "C"{ #include #endif +#define INVALID_CLOSED_SLOT -1 + /* * TCP/IP Event Task * */ @@ -402,7 +404,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; @@ -422,7 +424,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; @@ -445,7 +447,7 @@ 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]) { msg->err = 0; tcp_recved(msg->pcb, msg->received); } @@ -467,7 +469,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; @@ -487,7 +489,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; @@ -593,7 +595,7 @@ AsyncClient::AsyncClient(tcp_pcb* pcb) , next(NULL) { _pcb = pcb; - _closed_slot = -1; + _closed_slot = INVALID_CLOSED_SLOT; if(_pcb){ _rx_last_packet = millis(); tcp_arg(_pcb, this); @@ -879,29 +881,29 @@ int8_t AsyncClient::_close(){ } bool AsyncClient::_allocate_closed_slot(){ - if (_closed_slot != -1) { + 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 != -1); + return (_closed_slot != INVALID_CLOSED_SLOT); } void AsyncClient::_free_closed_slot(){ xSemaphoreTake(_slots_lock, portMAX_DELAY); - if (_closed_slot != -1) { + 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); From c3f21889014f0ff69f55258fc4dd3c131dca2ec4 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 2 Oct 2024 22:57:58 +0200 Subject: [PATCH 099/150] Rollback #18 --- src/AsyncTCP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index d112672..76282d6 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -447,7 +447,7 @@ 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 != INVALID_CLOSED_SLOT && !_closed_slots[msg->closed_slot]) { + if(msg->closed_slot == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { msg->err = 0; tcp_recved(msg->pcb, msg->received); } From 6631d51e7262cbaef88fba15be92de4a762a4b03 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 3 Oct 2024 00:33:26 +0200 Subject: [PATCH 100/150] v3.2.6 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0536ac3..ba65e1e 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ The base classes on which everything else is built. They expose all possible sce ## Coordinates ``` -mathieucarbou/AsyncTCP @ ^3.2.5 +mathieucarbou/AsyncTCP @ ^3.2.6 ``` ## Important recommendations diff --git a/library.json b/library.json index b84e397..fb86713 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "AsyncTCP", - "version": "3.2.5", + "version": "3.2.6", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index 0f59514..d4759af 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=AsyncTCP -version=3.2.5 +version=3.2.6 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 0c374ed..5b04c34 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.2.5" +#define ASYNCTCP_VERSION "3.2.6" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 2 -#define ASYNCTCP_VERSION_REVISION 5 +#define ASYNCTCP_VERSION_REVISION 6 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From 63ff671ac551e9f06fa839f0057e11dabf9b5ae8 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 7 Oct 2024 14:19:04 +0200 Subject: [PATCH 101/150] v3.2.7 --- README.md | 2 +- library.json | 2 +- library.properties | 5 +++-- src/AsyncTCP.h | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ba65e1e..623f673 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ The base classes on which everything else is built. They expose all possible sce ## Coordinates ``` -mathieucarbou/AsyncTCP @ ^3.2.6 +mathieucarbou/AsyncTCP @ ^3.2.7 ``` ## Important recommendations diff --git a/library.json b/library.json index fb86713..326934d 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "AsyncTCP", - "version": "3.2.6", + "version": "3.2.7", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index d4759af..b7d1885 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,6 @@ -name=AsyncTCP -version=3.2.6 +name=Async TCP +cludes=AsyncTCP.h +version=3.2.7 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 5b04c34..5b08df1 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.2.6" +#define ASYNCTCP_VERSION "3.2.7" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 2 -#define ASYNCTCP_VERSION_REVISION 6 +#define ASYNCTCP_VERSION_REVISION 7 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From 52a00344fa8146217655c6f930385f22b693656d Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 7 Oct 2024 14:31:12 +0200 Subject: [PATCH 102/150] Fix: includes=AsyncTCP.h --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index b7d1885..c5d9217 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Async TCP -cludes=AsyncTCP.h +includes=AsyncTCP.h version=3.2.7 author=Me-No-Dev maintainer=Mathieu Carbou From 91f0086735042ac56ca8747794d1794fddd78e21 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 7 Oct 2024 14:31:40 +0200 Subject: [PATCH 103/150] v3.2.8 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 623f673..14de0dd 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ The base classes on which everything else is built. They expose all possible sce ## Coordinates ``` -mathieucarbou/AsyncTCP @ ^3.2.7 +mathieucarbou/AsyncTCP @ ^3.2.8 ``` ## Important recommendations diff --git a/library.json b/library.json index 326934d..2e6d5de 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "AsyncTCP", - "version": "3.2.7", + "version": "3.2.8", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index c5d9217..c3cc1a7 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=Async TCP includes=AsyncTCP.h -version=3.2.7 +version=3.2.8 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 5b08df1..95fa866 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.2.7" +#define ASYNCTCP_VERSION "3.2.8" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 2 -#define ASYNCTCP_VERSION_REVISION 7 +#define ASYNCTCP_VERSION_REVISION 8 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From 665d34ca0b4683477e22878738f072d6c2ba047d Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 8 Oct 2024 11:52:54 +0200 Subject: [PATCH 104/150] Domain move --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 14de0dd..70b46f9 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Here are some recommendations to avoid them. 1. Set the running core to be on the same core of your application (usually core 1) `-D CONFIG_ASYNC_TCP_RUNNING_CORE=1` 2. Set the stack size appropriately with `-D CONFIG_ASYNC_TCP_STACK_SIZE=16384`. The default value of `16384` might be too much for your project. - You can look at the [MycilaTaskMonitor](https://oss.carbou.me/MycilaTaskMonitor) project to monitor the stack usage. + You can look at the [MycilaTaskMonitor](https://mathieu.carbou.me/MycilaTaskMonitor) project to monitor the stack usage. 3. You can change **if you know what you are doing** the task priority with `-D CONFIG_ASYNC_TCP_PRIORITY=10`. Default is `10`. 4. You can increase the queue size with `-D CONFIG_ASYNC_TCP_QUEUE_SIZE=128`. From b4a974dc31dc632721adc72a588f7bf839716935 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 12 Oct 2024 20:55:11 +0200 Subject: [PATCH 105/150] Fix #26 --- src/AsyncTCP.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 76282d6..cedf006 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -447,7 +447,17 @@ 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 == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { + // original code: + // if(msg->closed_slot == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { + + // attempted fix which was rolled back since non reproductible after middleware support in ESPAsyncWebServer: + // - https://github.com/mathieucarbou/AsyncTCP/pull/24 + // if(msg->closed_slot != INVALID_CLOSED_SLOT && !_closed_slots[msg->closed_slot]) { + + // final fix based on: + // - OpenDTU testing: https://github.com/tbnobody/OpenDTU/discussions/2326 + // - Original fix https://github.com/me-no-dev/AsyncTCP/pull/173/files#diff-5312944d5b5f39741f3827dd678a8e828e2624ceab236264c025ef2bdf400d6aR422-R428 + if(msg->closed_slot != INVALID_CLOSED_SLOT) { msg->err = 0; tcp_recved(msg->pcb, msg->received); } From c9044bf85974faff310a0ee18ea6a5c5580ac127 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 12 Oct 2024 20:58:59 +0200 Subject: [PATCH 106/150] v3.2.9 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 70b46f9..710a9d8 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ The base classes on which everything else is built. They expose all possible sce ## Coordinates ``` -mathieucarbou/AsyncTCP @ ^3.2.8 +mathieucarbou/AsyncTCP @ ^3.2.9 ``` ## Important recommendations diff --git a/library.json b/library.json index 2e6d5de..ad9d3d0 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "AsyncTCP", - "version": "3.2.8", + "version": "3.2.9", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index c3cc1a7..ae96c6a 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=Async TCP includes=AsyncTCP.h -version=3.2.8 +version=3.2.9 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 95fa866..7313c4a 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.2.8" +#define ASYNCTCP_VERSION "3.2.9" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 2 -#define ASYNCTCP_VERSION_REVISION 8 +#define ASYNCTCP_VERSION_REVISION 9 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From 784df13d4b3118f9790230fe6f6cd5567dc4c4b3 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 13 Oct 2024 09:21:27 +0200 Subject: [PATCH 107/150] Try fix #26 again --- .github/workflows/ci.yml | 10 +--- examples/Client/Client.ino | 79 +++++++++++++++++++++++++ examples/ClientServer/Client/Client.ino | 42 ------------- examples/ClientServer/Client/config.h | 23 ------- platformio.ini | 17 ++++-- src/AsyncTCP.cpp | 11 ++-- 6 files changed, 100 insertions(+), 82 deletions(-) create mode 100644 examples/Client/Client.ino delete mode 100644 examples/ClientServer/Client/Client.ino delete mode 100644 examples/ClientServer/Client/config.h diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 18e8924..f9c39f8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,11 +26,11 @@ jobs: arduino-cli --config-file ${{ matrix.config }} board listall arduino-cli --config-file ${{ matrix.config }} core install esp32:esp32 - name: Compile Sketch - run: arduino-cli --config-file ${{ matrix.config }} --library ./src/ compile --fqbn esp32:esp32:esp32 ./examples/ClientServer/Client/Client.ino + run: arduino-cli --config-file ${{ matrix.config }} --library ./src/ compile --fqbn esp32:esp32:esp32 ./examples/Client/Client.ino - name: Compile Sketch with IPv6 env: LWIP_IPV6: true - run: arduino-cli --config-file ${{ matrix.config }} --library ./src/ compile --fqbn esp32:esp32:esp32 ./examples/ClientServer/Client/Client.ino + run: arduino-cli --config-file ${{ matrix.config }} --library ./src/ compile --fqbn esp32:esp32:esp32 ./examples/Client/Client.ino platformio: name: "pio:${{ matrix.env }}:${{ matrix.board }}" @@ -58,8 +58,6 @@ jobs: board: esp32-c3-devkitc-02 - env: ci-arduino-3 board: esp32-c6-devkitc-1 - - env: ci-arduino-3 - board: esp32-h2-devkitm-1 - env: ci-arduino-310rc1 board: esp32dev @@ -71,8 +69,6 @@ jobs: board: esp32-c3-devkitc-02 - env: ci-arduino-310rc1 board: esp32-c6-devkitc-1 - - env: ci-arduino-310rc1 - board: esp32-h2-devkitm-1 steps: - name: Checkout @@ -96,4 +92,4 @@ jobs: python -m pip install --upgrade pip pip install --upgrade platformio - - run: PLATFORMIO_SRC_DIR=examples/ClientServer/Client PIO_BOARD=${{ matrix.board }} pio run -e ${{ matrix.env }} + - run: PLATFORMIO_SRC_DIR=examples/Client PIO_BOARD=${{ matrix.board }} pio run -e ${{ matrix.env }} diff --git a/examples/Client/Client.ino b/examples/Client/Client.ino new file mode 100644 index 0000000..3f190bf --- /dev/null +++ b/examples/Client/Client.ino @@ -0,0 +1,79 @@ +/* + -D CONFIG_ASYNC_TCP_MAX_ACK_TIME=3000 + -D CONFIG_ASYNC_TCP_PRIORITY=10 + -D CONFIG_ASYNC_TCP_QUEUE_SIZE=128 + -D CONFIG_ASYNC_TCP_RUNNING_CORE=1 + -D CONFIG_ASYNC_TCP_STACK_SIZE=4096 +*/ +#include +#include +#include + +#define HOST "homeassistant.local" +#define PORT 8123 + +size_t permits = CONFIG_LWIP_MAX_ACTIVE_TCP; + +void makeRequest() { + if (!permits) + return; + + Serial.printf("** permits: %d\n", permits); + + AsyncClient* client = new AsyncClient; + + client->onError([](void* arg, AsyncClient* client, int8_t error) { + Serial.printf("** error occurred %s \n", client->errorToString(error)); + client->close(true); + delete client; + }); + + client->onConnect([](void* arg, AsyncClient* client) { + permits--; + Serial.printf("** client has been connected: %" PRIu16 "\n", client->localPort()); + + client->onDisconnect([](void* arg, AsyncClient* client) { + Serial.printf("** client has been disconnected: %" PRIu16 "\n", client->localPort()); + client->close(true); + delete client; + + permits++; + makeRequest(); + }); + + client->onData([](void* arg, AsyncClient* client, void* data, size_t len) { + Serial.printf("** data received by client: %" PRIu16 "\n", client->localPort()); + // Serial.write((uint8_t*)data, len); + }); + + client->write("GET / HTTP/1.1\r\nHost: " HOST "\r\nUser-Agent: ESP\r\nConnection: close\r\n\r\n"); + }); + + if (client->connect(HOST, PORT)) { + } else { + Serial.println("** connection failed"); + } +} + +void setup() { + Serial.begin(115200); + while (!Serial) + continue; + + WiFi.mode(WIFI_STA); + WiFi.begin("IoT"); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println("** connected to WiFi"); + Serial.println(WiFi.localIP()); + + // 16 slots on esp32 (CONFIG_LWIP_MAX_ACTIVE_TCP) + for (size_t i = 0; i < CONFIG_LWIP_MAX_ACTIVE_TCP; i++) + makeRequest(); +} + +void loop() { + delay(500); +} diff --git a/examples/ClientServer/Client/Client.ino b/examples/ClientServer/Client/Client.ino deleted file mode 100644 index 47d8bc7..0000000 --- a/examples/ClientServer/Client/Client.ino +++ /dev/null @@ -1,42 +0,0 @@ -#include - -#include "config.h" - -static void replyToServer(void* arg) { - AsyncClient* client = reinterpret_cast(arg); - - // send reply - if (client->space() > 32 && client->canSend()) { - char message[32]; - client->add(message, strlen(message)); - client->send(); - } -} - -/* event callbacks */ -static void handleData(void* arg, AsyncClient* client, void *data, size_t len) { - Serial.printf("\n data received from %s \n", client->remoteIP().toString().c_str()); - Serial.write((uint8_t*)data, len); - -} - -void onConnect(void* arg, AsyncClient* client) { - Serial.printf("\n client has been connected to %s on port %d \n", SERVER_HOST_NAME, TCP_PORT); - replyToServer(client); -} - - -void setup() { - Serial.begin(115200); - delay(20); - - AsyncClient* client = new AsyncClient; - client->onData(&handleData, client); - client->onConnect(&onConnect, client); - client->connect(SERVER_HOST_NAME, TCP_PORT); - -} - -void loop() { - -} diff --git a/examples/ClientServer/Client/config.h b/examples/ClientServer/Client/config.h deleted file mode 100644 index cf51e91..0000000 --- a/examples/ClientServer/Client/config.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef CONFIG_H -#define CONFIG_H - -/* - * This example demonstrate how to use asynchronous client & server APIs - * in order to establish tcp socket connections in client server manner. - * server is running (on port 7050) on one ESP, acts as AP, and other clients running on - * remaining ESPs acts as STAs. after connection establishment between server and clients - * there is a simple message transfer in every 2s. clients connect to server via it's host name - * (in this case 'esp_server') with help of DNS service running on server side. - * - * Note: default MSS for ESPAsyncTCP is 536 byte and defualt ACK timeout is 5s. -*/ - -#define SSID "ESP-TEST" -#define PASSWORD "123456789" - -#define SERVER_HOST_NAME "esp_server" - -#define TCP_PORT 7050 -#define DNS_PORT 53 - -#endif // CONFIG_H diff --git a/platformio.ini b/platformio.ini index 91bcf13..0de5c49 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,19 +1,24 @@ +[platformio] +default_envs = arduino-2, arduino-3, arduino-310rc1 +lib_dir = . +src_dir = examples/Client + [env] framework = arduino build_flags = -Wall -Wextra + -D CONFIG_ASYNC_TCP_MAX_ACK_TIME=3000 + -D CONFIG_ASYNC_TCP_PRIORITY=10 + -D CONFIG_ASYNC_TCP_QUEUE_SIZE=128 + -D CONFIG_ASYNC_TCP_RUNNING_CORE=1 + -D CONFIG_ASYNC_TCP_STACK_SIZE=4096 -D CONFIG_ARDUHAL_LOG_COLORS - -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG + -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO upload_protocol = esptool monitor_speed = 115200 monitor_filters = esp32_exception_decoder, log2file board = esp32dev -[platformio] -default_envs = arduino-2, arduino-3, arduino-310rc1 -lib_dir = . -src_dir = examples/ClientServer/Client - [env:arduino-2] platform = espressif32@6.9.0 diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index cedf006..75a631d 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -448,16 +448,19 @@ 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; // original code: + // causes the issue: assert failed: tcp_update_rcv_ann_wnd IDF/components/lwip/lwip/src/core/tcp.c:951 (new_rcv_ann_wnd <= 0xffff) // if(msg->closed_slot == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { - // attempted fix which was rolled back since non reproductible after middleware support in ESPAsyncWebServer: + // attempted fix 1, which was rolled back since non reproductible after middleware support in ESPAsyncWebServer but works in some cases: + // - https://github.com/tbnobody/OpenDTU/discussions/2326 // - https://github.com/mathieucarbou/AsyncTCP/pull/24 - // if(msg->closed_slot != INVALID_CLOSED_SLOT && !_closed_slots[msg->closed_slot]) { + if(msg->closed_slot != INVALID_CLOSED_SLOT && !_closed_slots[msg->closed_slot]) { - // final fix based on: + // attempted fix 2, // - OpenDTU testing: https://github.com/tbnobody/OpenDTU/discussions/2326 // - Original fix https://github.com/me-no-dev/AsyncTCP/pull/173/files#diff-5312944d5b5f39741f3827dd678a8e828e2624ceab236264c025ef2bdf400d6aR422-R428 - if(msg->closed_slot != INVALID_CLOSED_SLOT) { + // Seems to have side effects: https://github.com/me-no-dev/ESPAsyncWebServer/issues/1437 + // if(msg->closed_slot != INVALID_CLOSED_SLOT) { msg->err = 0; tcp_recved(msg->pcb, msg->received); } From b5d869b70bdff2176f7aac3edb3b2c4c56b29860 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 13 Oct 2024 10:10:21 +0200 Subject: [PATCH 108/150] Point to google --- examples/Client/Client.ino | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/Client/Client.ino b/examples/Client/Client.ino index 3f190bf..22248b8 100644 --- a/examples/Client/Client.ino +++ b/examples/Client/Client.ino @@ -9,8 +9,11 @@ #include #include -#define HOST "homeassistant.local" -#define PORT 8123 +// #define HOST "homeassistant.local" +// #define PORT 8123 + +#define HOST "www.google.com" +#define PORT 80 size_t permits = CONFIG_LWIP_MAX_ACTIVE_TCP; From e8133fbd46bdd398d883020e5e6c90de0ec345ef Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 13 Oct 2024 10:12:38 +0200 Subject: [PATCH 109/150] testing against a local jekyll server --- examples/Client/Client.ino | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/Client/Client.ino b/examples/Client/Client.ino index 22248b8..d41b196 100644 --- a/examples/Client/Client.ino +++ b/examples/Client/Client.ino @@ -12,8 +12,11 @@ // #define HOST "homeassistant.local" // #define PORT 8123 -#define HOST "www.google.com" -#define PORT 80 +// #define HOST "www.google.com" +// #define PORT 80 + +#define HOST "192.168.125.118" +#define PORT 4000 size_t permits = CONFIG_LWIP_MAX_ACTIVE_TCP; From b11bfff4fd98eb405609278984fbaf83d5e4007e Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 13 Oct 2024 10:21:00 +0200 Subject: [PATCH 110/150] added MAX_CLIENTS --- examples/Client/Client.ino | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/Client/Client.ino b/examples/Client/Client.ino index d41b196..cf3de05 100644 --- a/examples/Client/Client.ino +++ b/examples/Client/Client.ino @@ -18,7 +18,11 @@ #define HOST "192.168.125.118" #define PORT 4000 -size_t permits = CONFIG_LWIP_MAX_ACTIVE_TCP; +// 16 slots on esp32 (CONFIG_LWIP_MAX_ACTIVE_TCP) +#define MAX_CLIENTS CONFIG_LWIP_MAX_ACTIVE_TCP +// #define MAX_CLIENTS 3 + +size_t permits = MAX_CLIENTS; void makeRequest() { if (!permits) @@ -75,8 +79,7 @@ void setup() { Serial.println("** connected to WiFi"); Serial.println(WiFi.localIP()); - // 16 slots on esp32 (CONFIG_LWIP_MAX_ACTIVE_TCP) - for (size_t i = 0; i < CONFIG_LWIP_MAX_ACTIVE_TCP; i++) + for (size_t i = 0; i < MAX_CLIENTS; i++) makeRequest(); } From d1982482408d2ff61a6da6a87bec4a6a95d8086d Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 13 Oct 2024 11:28:15 +0200 Subject: [PATCH 111/150] Fix _recv method --- examples/Client/Client.ino | 8 ++++---- platformio.ini | 2 +- src/AsyncTCP.cpp | 27 ++++++--------------------- 3 files changed, 11 insertions(+), 26 deletions(-) diff --git a/examples/Client/Client.ino b/examples/Client/Client.ino index cf3de05..f2f7c28 100644 --- a/examples/Client/Client.ino +++ b/examples/Client/Client.ino @@ -20,7 +20,7 @@ // 16 slots on esp32 (CONFIG_LWIP_MAX_ACTIVE_TCP) #define MAX_CLIENTS CONFIG_LWIP_MAX_ACTIVE_TCP -// #define MAX_CLIENTS 3 +// #define MAX_CLIENTS 1 size_t permits = MAX_CLIENTS; @@ -52,8 +52,7 @@ void makeRequest() { }); client->onData([](void* arg, AsyncClient* client, void* data, size_t len) { - Serial.printf("** data received by client: %" PRIu16 "\n", client->localPort()); - // Serial.write((uint8_t*)data, len); + Serial.printf("** data received by client: %" PRIu16 ": len=%u\n", client->localPort(), len); }); client->write("GET / HTTP/1.1\r\nHost: " HOST "\r\nUser-Agent: ESP\r\nConnection: close\r\n\r\n"); @@ -84,5 +83,6 @@ void setup() { } void loop() { - delay(500); + delay(1000); + Serial.printf("** free heap: %" PRIu32 "\n", ESP.getFreeHeap()); } diff --git a/platformio.ini b/platformio.ini index 0de5c49..387a5b8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -13,7 +13,7 @@ build_flags = -D CONFIG_ASYNC_TCP_RUNNING_CORE=1 -D CONFIG_ASYNC_TCP_STACK_SIZE=4096 -D CONFIG_ARDUHAL_LOG_COLORS - -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO + -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG upload_protocol = esptool monitor_speed = 115200 monitor_filters = esp32_exception_decoder, log2file diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 75a631d..8b4bc16 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -447,19 +447,8 @@ 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; - // original code: - // causes the issue: assert failed: tcp_update_rcv_ann_wnd IDF/components/lwip/lwip/src/core/tcp.c:951 (new_rcv_ann_wnd <= 0xffff) - // if(msg->closed_slot == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { - - // attempted fix 1, which was rolled back since non reproductible after middleware support in ESPAsyncWebServer but works in some cases: - // - https://github.com/tbnobody/OpenDTU/discussions/2326 - // - https://github.com/mathieucarbou/AsyncTCP/pull/24 - if(msg->closed_slot != INVALID_CLOSED_SLOT && !_closed_slots[msg->closed_slot]) { - - // attempted fix 2, - // - OpenDTU testing: https://github.com/tbnobody/OpenDTU/discussions/2326 - // - Original fix https://github.com/me-no-dev/AsyncTCP/pull/173/files#diff-5312944d5b5f39741f3827dd678a8e828e2624ceab236264c025ef2bdf400d6aR422-R428 - // Seems to have side effects: https://github.com/me-no-dev/ESPAsyncWebServer/issues/1437 + 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); @@ -996,19 +985,13 @@ int8_t AsyncClient::_sent(tcp_pcb* pcb, uint16_t len) { } int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { - if(!_pcb || pcb != _pcb){ - log_d("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); - return ERR_OK; - } - size_t total = 0; - while((pb != NULL) && (ERR_OK == err)) { + while(pb != NULL) { _rx_last_packet = millis(); //we should not ack before we assimilate the data _ack_pcb = true; pbuf *b = pb; pb = b->next; b->next = NULL; - total += b->len; if(_pb_cb){ _pb_cb(_pb_cb_arg, this, b); } else { @@ -1017,11 +1000,13 @@ int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { } if(!_ack_pcb) { _rx_ack_len += b->len; + } else if(_pcb) { + _tcp_recved(_pcb, _closed_slot, b->len); } } pbuf_free(b); } - return _tcp_recved(pcb, _closed_slot, total); + return ERR_OK; } int8_t AsyncClient::_poll(tcp_pcb* pcb){ From e0af59060ba7bf3109f584d783d1acae16942580 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 13 Oct 2024 11:38:27 +0200 Subject: [PATCH 112/150] v3.2.10 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 710a9d8..196be45 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ The base classes on which everything else is built. They expose all possible sce ## Coordinates ``` -mathieucarbou/AsyncTCP @ ^3.2.9 +mathieucarbou/AsyncTCP @ ^3.2.10 ``` ## Important recommendations diff --git a/library.json b/library.json index ad9d3d0..747ecc1 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "AsyncTCP", - "version": "3.2.9", + "version": "3.2.10", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index ae96c6a..8dfdc52 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=Async TCP includes=AsyncTCP.h -version=3.2.9 +version=3.2.10 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 7313c4a..caee72d 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.2.9" +#define ASYNCTCP_VERSION "3.2.10" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 2 -#define ASYNCTCP_VERSION_REVISION 9 +#define ASYNCTCP_VERSION_REVISION 10 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From f005448495d12eb3081f168087999f180b947ec0 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 25 Oct 2024 22:51:29 +0200 Subject: [PATCH 113/150] pioardiono 53.03.10-rc2 --- .github/workflows/ci.yml | 10 +++++----- platformio.ini | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f9c39f8..fd79c93 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,15 +59,15 @@ jobs: - env: ci-arduino-3 board: esp32-c6-devkitc-1 - - env: ci-arduino-310rc1 + - env: ci-arduino-310 board: esp32dev - - env: ci-arduino-310rc1 + - env: ci-arduino-310 board: esp32-s2-saola-1 - - env: ci-arduino-310rc1 + - env: ci-arduino-310 board: esp32-s3-devkitc-1 - - env: ci-arduino-310rc1 + - env: ci-arduino-310 board: esp32-c3-devkitc-02 - - env: ci-arduino-310rc1 + - env: ci-arduino-310 board: esp32-c6-devkitc-1 steps: diff --git a/platformio.ini b/platformio.ini index 387a5b8..15bdd9f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,5 +1,5 @@ [platformio] -default_envs = arduino-2, arduino-3, arduino-310rc1 +default_envs = arduino-2, arduino-3, arduino-310 lib_dir = . src_dir = examples/Client @@ -25,8 +25,8 @@ platform = espressif32@6.9.0 [env:arduino-3] platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip -[env:arduino-310rc1] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc1/platform-espressif32.zip +[env:arduino-310] +platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc2/platform-espressif32.zip ; CI @@ -38,6 +38,6 @@ board = ${sysenv.PIO_BOARD} platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip board = ${sysenv.PIO_BOARD} -[env:ci-arduino-310rc1] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc1/platform-espressif32.zip +[env:ci-arduino-310] +platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc2/platform-espressif32.zip board = ${sysenv.PIO_BOARD} From bad497273488adef3bcfe1ffd930e38c6a74e824 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 26 Oct 2024 11:51:20 +0200 Subject: [PATCH 114/150] Fix #27: Required to lock TCPIP core functionality Ref: - https://github.com/mathieucarbou/AsyncTCP/issues/27 - https://github.com/espressif/arduino-esp32/issues/10526 --- src/AsyncTCP.cpp | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 8b4bc16..c07c813 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -39,6 +39,24 @@ extern "C"{ #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 /* @@ -722,17 +740,20 @@ 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; } - 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_MUTEX_UNLOCK(); + esp_err_t err =_tcp_connect(pcb, _closed_slot, &addr, port,(tcp_connected_fn)&_tcp_connected); return err == ESP_OK; } @@ -863,11 +884,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) { @@ -1461,7 +1484,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; @@ -1493,14 +1518,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); } From 9e5fd7940d15d605068fec3a42ba66a37faecadb Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sat, 26 Oct 2024 12:32:02 +0200 Subject: [PATCH 115/150] v3.2.11 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 196be45..798f432 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ The base classes on which everything else is built. They expose all possible sce ## Coordinates ``` -mathieucarbou/AsyncTCP @ ^3.2.10 +mathieucarbou/AsyncTCP @ ^3.2.11 ``` ## Important recommendations diff --git a/library.json b/library.json index 747ecc1..bc2ed12 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "AsyncTCP", - "version": "3.2.10", + "version": "3.2.11", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index 8dfdc52..e822445 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=Async TCP includes=AsyncTCP.h -version=3.2.10 +version=3.2.11 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index caee72d..c93ffb7 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.2.10" +#define ASYNCTCP_VERSION "3.2.11" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 2 -#define ASYNCTCP_VERSION_REVISION 10 +#define ASYNCTCP_VERSION_REVISION 11 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From 828e8d027ebc4d1c144f70ca87ae3c13ebf4c2dd Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 27 Oct 2024 01:09:05 +0200 Subject: [PATCH 116/150] update readme --- README.md | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 798f432..ae2b666 100644 --- a/README.md +++ b/README.md @@ -18,10 +18,27 @@ The base classes on which everything else is built. They expose all possible sce ## Changes in this fork -- All improvements from [ESPHome fork](https://github.com/esphome/AsyncTCP) -- Reverted back `library.properties` for Arduino IDE users +- Based on [ESPHome fork](https://github.com/esphome/AsyncTCP) + +- `library.properties` for Arduino IDE users +- Add `CONFIG_ASYNC_TCP_MAX_ACK_TIME` +- Add `CONFIG_ASYNC_TCP_PRIORITY` +- Add `CONFIG_ASYNC_TCP_QUEUE_SIZE` +- Add `setKeepAlive()` - Arduino 3 / ESP-IDF 5 compatibility -- IPv6 support +- Better CI +- Better example +- Customizable macros +- Fix for "Required to lock TCPIP core functionality". Ref: https://github.com/mathieucarbou/AsyncTCP/issues/27 and https://github.com/espressif/arduino-esp32/issues/10526 +- Fix for "ack timeout 4" client disconnects. +- Fix from https://github.com/me-no-dev/AsyncTCP/pull/173 (partially applied) +- Fix from https://github.com/me-no-dev/AsyncTCP/pull/184 +- IPv6 +- LIBRETINY support +- LibreTuya +- Reduce logging of non critical messages +- Use IPADDR6_INIT() macro to set connecting IPv6 address +- xTaskCreateUniversal function ## Coordinates From c4eac0999df3019580866b952cd51963d36e5a6a Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 27 Oct 2024 08:31:56 +0100 Subject: [PATCH 117/150] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ae2b666..a9e6b16 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Continuous Integration](https://github.com/mathieucarbou/AsyncTCP/actions/workflows/ci.yml/badge.svg)](https://github.com/mathieucarbou/AsyncTCP/actions/workflows/ci.yml) [![PlatformIO Registry](https://badges.registry.platformio.org/packages/mathieucarbou/library/AsyncTCP.svg)](https://registry.platformio.org/libraries/mathieucarbou/AsyncTCP) -A fork of the [AsyncTCP](https://github.com/me-no-dev/AsyncTCP) library by [@me-no-dev](https://github.com/me-no-dev) for [ESPHome](https://esphome.io). +A fork of the [AsyncTCP](https://github.com/me-no-dev/AsyncTCP) library by [@me-no-dev](https://github.com/me-no-dev). ### Async TCP Library for ESP32 Arduino From 45b7ee826bb530eaae296c6c2dae0cc0081caa3d Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 27 Oct 2024 08:37:58 +0100 Subject: [PATCH 118/150] Fix #27: Required to lock TCPIP core functionality --- src/AsyncTCP.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index c07c813..595ae2f 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -951,6 +951,7 @@ 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); @@ -958,6 +959,7 @@ void AsyncClient::_error(int8_t err) { tcp_err(_pcb, NULL); tcp_poll(_pcb, NULL, 0); } + TCP_MUTEX_UNLOCK(); _free_closed_slot(); _pcb = NULL; } From 48a37dedf64be25ea569b89eebbf5a0e7f86fa82 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 27 Oct 2024 08:39:34 +0100 Subject: [PATCH 119/150] v3.2.12 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a9e6b16..efe0519 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ The base classes on which everything else is built. They expose all possible sce ## Coordinates ``` -mathieucarbou/AsyncTCP @ ^3.2.11 +mathieucarbou/AsyncTCP @ ^3.2.12 ``` ## Important recommendations diff --git a/library.json b/library.json index bc2ed12..005ed3f 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "AsyncTCP", - "version": "3.2.11", + "version": "3.2.12", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index e822445..3c70f5b 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=Async TCP includes=AsyncTCP.h -version=3.2.11 +version=3.2.12 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index c93ffb7..b40239c 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.2.11" +#define ASYNCTCP_VERSION "3.2.12" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 2 -#define ASYNCTCP_VERSION_REVISION 11 +#define ASYNCTCP_VERSION_REVISION 12 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From d2509602595422f80a1e3eaa835201671a4b6b3a Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 12 Nov 2024 18:24:53 +0100 Subject: [PATCH 120/150] Fix: Required to lock TCPIP core functionality See: https://github.com/espressif/arduino-esp32/issues/10526#issuecomment-2471122550 --- src/AsyncTCP.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 595ae2f..21755f4 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -1531,9 +1531,11 @@ void AsyncServer::end(){ TCP_MUTEX_LOCK(); tcp_arg(_pcb, NULL); tcp_accept(_pcb, NULL); - TCP_MUTEX_UNLOCK(); if(tcp_close(_pcb) != ERR_OK){ + TCP_MUTEX_UNLOCK(); _tcp_abort(_pcb, -1); + } else { + TCP_MUTEX_UNLOCK(); } _pcb = NULL; } From f4b81e56fffbadeeda74ece36a1f833f9c53f13b Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 12 Nov 2024 18:25:42 +0100 Subject: [PATCH 121/150] v3.2.14 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index efe0519..8e9b0a0 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ The base classes on which everything else is built. They expose all possible sce ## Coordinates ``` -mathieucarbou/AsyncTCP @ ^3.2.12 +mathieucarbou/AsyncTCP @ ^3.2.14 ``` ## Important recommendations diff --git a/library.json b/library.json index 005ed3f..6082db7 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "AsyncTCP", - "version": "3.2.12", + "version": "3.2.14", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index 3c70f5b..032c0c5 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=Async TCP includes=AsyncTCP.h -version=3.2.12 +version=3.2.14 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index b40239c..25fb462 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.2.12" +#define ASYNCTCP_VERSION "3.2.14" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 2 -#define ASYNCTCP_VERSION_REVISION 12 +#define ASYNCTCP_VERSION_REVISION 14 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From edb81edf5e35d6befb927d58b5ca928b940cd3fb Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Fri, 15 Nov 2024 20:38:35 +0100 Subject: [PATCH 122/150] Arduino Core 3.1.0 RC3 / ESP-IDF 5.3 --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 15bdd9f..4f84693 100644 --- a/platformio.ini +++ b/platformio.ini @@ -26,7 +26,7 @@ platform = espressif32@6.9.0 platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip [env:arduino-310] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc2/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc3/platform-espressif32.zip ; CI @@ -39,5 +39,5 @@ platform = https://github.com/pioarduino/platform-espressif32/releases/download/ board = ${sysenv.PIO_BOARD} [env:ci-arduino-310] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc2/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc3/platform-espressif32.zip board = ${sysenv.PIO_BOARD} From ebf989fc44c6a046d889813bb829f1d2ec7c73bd Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 10 Dec 2024 22:22:29 +0100 Subject: [PATCH 123/150] Added clang file --- .clang-format | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..63f29c0 --- /dev/null +++ b/.clang-format @@ -0,0 +1,22 @@ +Language: Cpp +BasedOnStyle: LLVM + +AccessModifierOffset: -2 +AlignConsecutiveMacros: true +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortIfStatementsOnASingleLine: false +AllowShortLambdasOnASingleLine: Inline +BinPackArguments: false +ColumnLimit: 0 +ContinuationIndentWidth: 2 +FixNamespaceComments: false +IndentAccessModifiers: true +IndentCaseLabels: true +IndentPPDirectives: BeforeHash +IndentWidth: 2 +NamespaceIndentation: All +PointerAlignment: Left +ReferenceAlignment: Left +TabWidth: 2 +UseTab: Never From e48f2a5db865245a38fc90be8239e355af057482 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 10 Dec 2024 22:44:18 +0100 Subject: [PATCH 124/150] Fix missing lock/unlock around dns_gethostbyname --- src/AsyncTCP.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 21755f4..84a87ac 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -787,7 +787,9 @@ bool AsyncClient::connect(const char* host, uint16_t port){ return false; } + TCP_MUTEX_LOCK(); err_t err = dns_gethostbyname(host, &addr, (dns_found_callback)&_tcp_dns_found, this); + TCP_MUTEX_UNLOCK(); if(err == ERR_OK) { #if ESP_IDF_VERSION_MAJOR < 5 #if LWIP_IPV6 From 7a407a6d5c334efb1c55f9b6c79e3a6a9d0dec85 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 10 Dec 2024 22:45:36 +0100 Subject: [PATCH 125/150] Added clang file --- .clang-format copy | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .clang-format copy diff --git a/.clang-format copy b/.clang-format copy new file mode 100644 index 0000000..63f29c0 --- /dev/null +++ b/.clang-format copy @@ -0,0 +1,22 @@ +Language: Cpp +BasedOnStyle: LLVM + +AccessModifierOffset: -2 +AlignConsecutiveMacros: true +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortIfStatementsOnASingleLine: false +AllowShortLambdasOnASingleLine: Inline +BinPackArguments: false +ColumnLimit: 0 +ContinuationIndentWidth: 2 +FixNamespaceComments: false +IndentAccessModifiers: true +IndentCaseLabels: true +IndentPPDirectives: BeforeHash +IndentWidth: 2 +NamespaceIndentation: All +PointerAlignment: Left +ReferenceAlignment: Left +TabWidth: 2 +UseTab: Never From 4d3ea14bfe166152ad1d6d069c1ac437d959db5b Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 11 Dec 2024 10:38:02 +0100 Subject: [PATCH 126/150] update client --- examples/Client/Client.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/Client/Client.ino b/examples/Client/Client.ino index f2f7c28..b0a2e8a 100644 --- a/examples/Client/Client.ino +++ b/examples/Client/Client.ino @@ -15,7 +15,7 @@ // #define HOST "www.google.com" // #define PORT 80 -#define HOST "192.168.125.118" +#define HOST "192.168.125.122" #define PORT 4000 // 16 slots on esp32 (CONFIG_LWIP_MAX_ACTIVE_TCP) @@ -52,7 +52,7 @@ void makeRequest() { }); client->onData([](void* arg, AsyncClient* client, void* data, size_t len) { - Serial.printf("** data received by client: %" PRIu16 ": len=%u\n", client->localPort(), len); + // Serial.printf("** data received by client: %" PRIu16 ": len=%u\n", client->localPort(), len); }); client->write("GET / HTTP/1.1\r\nHost: " HOST "\r\nUser-Agent: ESP\r\nConnection: close\r\n\r\n"); From a1f27e66ce8c7c9e8fc4a0bf8e4c9ad4a577d4a1 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 11 Dec 2024 11:05:16 +0100 Subject: [PATCH 127/150] update recommendations --- README.md | 21 +++++---------------- platformio.ini | 4 ++-- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 8e9b0a0..aa768a5 100644 --- a/README.md +++ b/README.md @@ -51,23 +51,12 @@ mathieucarbou/AsyncTCP @ ^3.2.14 Most of the crashes are caused by improper configuration of the library for the project. Here are some recommendations to avoid them. -1. Set the running core to be on the same core of your application (usually core 1) `-D CONFIG_ASYNC_TCP_RUNNING_CORE=1` -2. Set the stack size appropriately with `-D CONFIG_ASYNC_TCP_STACK_SIZE=16384`. - The default value of `16384` might be too much for your project. - You can look at the [MycilaTaskMonitor](https://mathieu.carbou.me/MycilaTaskMonitor) project to monitor the stack usage. -3. You can change **if you know what you are doing** the task priority with `-D CONFIG_ASYNC_TCP_PRIORITY=10`. - Default is `10`. -4. You can increase the queue size with `-D CONFIG_ASYNC_TCP_QUEUE_SIZE=128`. - Default is `64`. -5. You can decrease the maximum ack time `-D CONFIG_ASYNC_TCP_MAX_ACK_TIME=3000`. - Default is `5000`. - I personally use the following configuration in my projects: ```c++ - -D CONFIG_ASYNC_TCP_MAX_ACK_TIME=3000 - -D CONFIG_ASYNC_TCP_PRIORITY=10 - -D CONFIG_ASYNC_TCP_QUEUE_SIZE=128 - -D CONFIG_ASYNC_TCP_RUNNING_CORE=1 - -D CONFIG_ASYNC_TCP_STACK_SIZE=4096 + -D CONFIG_ASYNC_TCP_MAX_ACK_TIME=5000 // (keep default) + -D CONFIG_ASYNC_TCP_PRIORITY=10 // (keep default) + -D CONFIG_ASYNC_TCP_QUEUE_SIZE=64 // (keep default) + -D CONFIG_ASYNC_TCP_RUNNING_CORE=1 // force async_tcp task to be on same core as the app (default is core 0) + -D CONFIG_ASYNC_TCP_STACK_SIZE=4096 // reduce the stack size (default is 16K) ``` diff --git a/platformio.ini b/platformio.ini index 4f84693..ec65a36 100644 --- a/platformio.ini +++ b/platformio.ini @@ -7,9 +7,9 @@ src_dir = examples/Client framework = arduino build_flags = -Wall -Wextra - -D CONFIG_ASYNC_TCP_MAX_ACK_TIME=3000 + -D CONFIG_ASYNC_TCP_MAX_ACK_TIME=5000 -D CONFIG_ASYNC_TCP_PRIORITY=10 - -D CONFIG_ASYNC_TCP_QUEUE_SIZE=128 + -D CONFIG_ASYNC_TCP_QUEUE_SIZE=64 -D CONFIG_ASYNC_TCP_RUNNING_CORE=1 -D CONFIG_ASYNC_TCP_STACK_SIZE=4096 -D CONFIG_ARDUHAL_LOG_COLORS From 67f0fa607cbef4cebef06c47692bea98c4c49407 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 11 Dec 2024 11:34:41 +0100 Subject: [PATCH 128/150] update example doc --- examples/Client/Client.ino | 7 ------- 1 file changed, 7 deletions(-) diff --git a/examples/Client/Client.ino b/examples/Client/Client.ino index b0a2e8a..20d1bcf 100644 --- a/examples/Client/Client.ino +++ b/examples/Client/Client.ino @@ -1,10 +1,3 @@ -/* - -D CONFIG_ASYNC_TCP_MAX_ACK_TIME=3000 - -D CONFIG_ASYNC_TCP_PRIORITY=10 - -D CONFIG_ASYNC_TCP_QUEUE_SIZE=128 - -D CONFIG_ASYNC_TCP_RUNNING_CORE=1 - -D CONFIG_ASYNC_TCP_STACK_SIZE=4096 -*/ #include #include #include From ba3fa2a2ca32dfa0e59f35e7af9bf64d86d9c671 Mon Sep 17 00:00:00 2001 From: Emil Muratov Date: Tue, 10 Dec 2024 22:59:08 +0900 Subject: [PATCH 129/150] throttle polling events when message queue gets filled up a proof of concept, might help on long/large responces with user callbacks (cherry picked from commit 18bbb3318547bde7a34a84229227ea1f5b80cc72) --- src/AsyncTCP.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 84a87ac..c8eb60b 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -302,6 +302,10 @@ static int8_t _tcp_connected(void * arg, tcp_pcb * pcb, int8_t err) { } static int8_t _tcp_poll(void * arg, struct tcp_pcb * pcb) { + // throttle polling events queing when event queue is getting filled up, let it handle _onack's + if (uxQueueMessagesWaiting(_async_queue) > (rand() % CONFIG_ASYNC_TCP_QUEUE_SIZE / 2 + CONFIG_ASYNC_TCP_QUEUE_SIZE / 4) ) + return ERR_OK; + //ets_printf("+P: 0x%08x\n", pcb); lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); e->event = LWIP_TCP_POLL; From 8302dba2b8cf409fbd8882cf7df1c661bec77f1f Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 11 Dec 2024 10:37:39 +0100 Subject: [PATCH 130/150] Issue 169 --- src/AsyncTCP.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index c8eb60b..15338e8 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -303,8 +303,10 @@ static int8_t _tcp_connected(void * arg, tcp_pcb * pcb, int8_t err) { static int8_t _tcp_poll(void * arg, struct tcp_pcb * pcb) { // throttle polling events queing when event queue is getting filled up, let it handle _onack's - if (uxQueueMessagesWaiting(_async_queue) > (rand() % CONFIG_ASYNC_TCP_QUEUE_SIZE / 2 + CONFIG_ASYNC_TCP_QUEUE_SIZE / 4) ) + if (uxQueueMessagesWaiting(_async_queue) > (rand() % CONFIG_ASYNC_TCP_QUEUE_SIZE / 2 + CONFIG_ASYNC_TCP_QUEUE_SIZE / 4) ) { + log_d("throttling"); return ERR_OK; + } //ets_printf("+P: 0x%08x\n", pcb); lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); From 31b3452efbec1ce08b1de9c058ea8b5d083ca7b0 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 11 Dec 2024 19:55:13 +0100 Subject: [PATCH 131/150] Code reformat according to clang file --- src/AsyncTCP.cpp | 2298 +++++++++++++++++++++++----------------------- src/AsyncTCP.h | 141 ++- 2 files changed, 1218 insertions(+), 1221 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 15338e8..18cd24a 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -22,40 +22,42 @@ #include "Arduino.h" #include "AsyncTCP.h" -extern "C"{ -#include "lwip/opt.h" -#include "lwip/tcp.h" -#include "lwip/inet.h" + +extern "C" { #include "lwip/dns.h" #include "lwip/err.h" +#include "lwip/inet.h" +#include "lwip/opt.h" +#include "lwip/tcp.h" } + #if CONFIG_ASYNC_TCP_USE_WDT -#include "esp_task_wdt.h" + #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 + #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_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 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 @@ -64,174 +66,180 @@ extern "C"{ * */ typedef enum { - LWIP_TCP_SENT, LWIP_TCP_RECV, LWIP_TCP_FIN, LWIP_TCP_ERROR, LWIP_TCP_POLL, LWIP_TCP_CLEAR, LWIP_TCP_ACCEPT, LWIP_TCP_CONNECTED, LWIP_TCP_DNS + LWIP_TCP_SENT, + LWIP_TCP_RECV, + LWIP_TCP_FIN, + LWIP_TCP_ERROR, + LWIP_TCP_POLL, + LWIP_TCP_CLEAR, + LWIP_TCP_ACCEPT, + LWIP_TCP_CONNECTED, + LWIP_TCP_DNS } lwip_event_t; typedef struct { - lwip_event_t event; - void *arg; - union { - struct { - tcp_pcb * pcb; - int8_t err; - } connected; - struct { - int8_t err; - } error; - struct { - tcp_pcb * pcb; - uint16_t len; - } sent; - struct { - tcp_pcb * pcb; - pbuf * pb; - int8_t err; - } recv; - struct { - tcp_pcb * pcb; - int8_t err; - } fin; - struct { - tcp_pcb * pcb; - } poll; - struct { - AsyncClient * client; - } accept; - struct { - const char * name; - ip_addr_t addr; - } dns; - }; + lwip_event_t event; + void* arg; + union { + struct { + tcp_pcb* pcb; + int8_t err; + } connected; + struct { + int8_t err; + } error; + struct { + tcp_pcb* pcb; + uint16_t len; + } sent; + struct { + tcp_pcb* pcb; + pbuf* pb; + int8_t err; + } recv; + struct { + tcp_pcb* pcb; + int8_t err; + } fin; + struct { + tcp_pcb* pcb; + } poll; + struct { + AsyncClient* client; + } accept; + struct { + const char* name; + ip_addr_t addr; + } dns; + }; } lwip_event_packet_t; static QueueHandle_t _async_queue; static TaskHandle_t _async_service_task_handle = NULL; - SemaphoreHandle_t _slots_lock; const int _number_of_closed_slots = CONFIG_LWIP_MAX_ACTIVE_TCP; static uint32_t _closed_slots[_number_of_closed_slots]; static uint32_t _closed_index = []() { - _slots_lock = xSemaphoreCreateBinary(); - xSemaphoreGive(_slots_lock); - for (int i = 0; i < _number_of_closed_slots; ++ i) { - _closed_slots[i] = 1; - } - return 1; + _slots_lock = xSemaphoreCreateBinary(); + xSemaphoreGive(_slots_lock); + for (int i = 0; i < _number_of_closed_slots; ++i) { + _closed_slots[i] = 1; + } + return 1; }(); - -static inline bool _init_async_event_queue(){ - if(!_async_queue){ - _async_queue = xQueueCreate(CONFIG_ASYNC_TCP_QUEUE_SIZE, sizeof(lwip_event_packet_t *)); - if(!_async_queue){ - return false; - } +static inline bool _init_async_event_queue() { + if (!_async_queue) { + _async_queue = xQueueCreate(CONFIG_ASYNC_TCP_QUEUE_SIZE, sizeof(lwip_event_packet_t*)); + if (!_async_queue) { + return false; } - return true; + } + return true; } -static inline bool _send_async_event(lwip_event_packet_t ** e){ - return _async_queue && xQueueSend(_async_queue, e, portMAX_DELAY) == pdPASS; +static inline bool _send_async_event(lwip_event_packet_t** e) { + return _async_queue && xQueueSend(_async_queue, e, portMAX_DELAY) == pdPASS; } -static inline bool _prepend_async_event(lwip_event_packet_t ** e){ - return _async_queue && xQueueSendToFront(_async_queue, e, portMAX_DELAY) == pdPASS; +static inline bool _prepend_async_event(lwip_event_packet_t** e) { + return _async_queue && xQueueSendToFront(_async_queue, e, portMAX_DELAY) == pdPASS; } -static inline bool _get_async_event(lwip_event_packet_t ** e){ - return _async_queue && xQueueReceive(_async_queue, e, portMAX_DELAY) == pdPASS; +static inline bool _get_async_event(lwip_event_packet_t** e) { + return _async_queue && xQueueReceive(_async_queue, e, portMAX_DELAY) == pdPASS; } -static bool _remove_events_with_arg(void * arg){ - lwip_event_packet_t * first_packet = NULL; - lwip_event_packet_t * packet = NULL; +static bool _remove_events_with_arg(void* arg) { + lwip_event_packet_t* first_packet = NULL; + lwip_event_packet_t* packet = NULL; - if(!_async_queue){ - return false; + if (!_async_queue) { + return false; + } + // figure out which is the first packet so we can keep the order + while (!first_packet) { + if (xQueueReceive(_async_queue, &first_packet, 0) != pdPASS) { + return false; } - //figure out which is the first packet so we can keep the order - while(!first_packet){ - if(xQueueReceive(_async_queue, &first_packet, 0) != pdPASS){ - return false; - } - //discard packet if matching - if((int)first_packet->arg == (int)arg){ - free(first_packet); - first_packet = NULL; - //return first packet to the back of the queue - } else if(xQueueSend(_async_queue, &first_packet, portMAX_DELAY) != pdPASS){ - return false; - } + // discard packet if matching + if ((int)first_packet->arg == (int)arg) { + free(first_packet); + first_packet = NULL; + // return first packet to the back of the queue + } else if (xQueueSend(_async_queue, &first_packet, portMAX_DELAY) != pdPASS) { + return false; } + } - while(xQueuePeek(_async_queue, &packet, 0) == pdPASS && packet != first_packet){ - if(xQueueReceive(_async_queue, &packet, 0) != pdPASS){ - return false; - } - if((int)packet->arg == (int)arg){ - free(packet); - packet = NULL; - } else if(xQueueSend(_async_queue, &packet, portMAX_DELAY) != pdPASS){ - return false; - } + while (xQueuePeek(_async_queue, &packet, 0) == pdPASS && packet != first_packet) { + if (xQueueReceive(_async_queue, &packet, 0) != pdPASS) { + return false; } - return true; + if ((int)packet->arg == (int)arg) { + free(packet); + packet = NULL; + } else if (xQueueSend(_async_queue, &packet, portMAX_DELAY) != pdPASS) { + return false; + } + } + return true; } -static void _handle_async_event(lwip_event_packet_t * e){ - if(e->arg == NULL){ - // do nothing when arg is NULL - //ets_printf("event arg == NULL: 0x%08x\n", e->recv.pcb); - } else if(e->event == LWIP_TCP_CLEAR){ - _remove_events_with_arg(e->arg); - } else if(e->event == LWIP_TCP_RECV){ - //ets_printf("-R: 0x%08x\n", e->recv.pcb); - AsyncClient::_s_recv(e->arg, e->recv.pcb, e->recv.pb, e->recv.err); - } else if(e->event == LWIP_TCP_FIN){ - //ets_printf("-F: 0x%08x\n", e->fin.pcb); - AsyncClient::_s_fin(e->arg, e->fin.pcb, e->fin.err); - } else if(e->event == LWIP_TCP_SENT){ - //ets_printf("-S: 0x%08x\n", e->sent.pcb); - AsyncClient::_s_sent(e->arg, e->sent.pcb, e->sent.len); - } else if(e->event == LWIP_TCP_POLL){ - //ets_printf("-P: 0x%08x\n", e->poll.pcb); - AsyncClient::_s_poll(e->arg, e->poll.pcb); - } else if(e->event == LWIP_TCP_ERROR){ - //ets_printf("-E: 0x%08x %d\n", e->arg, e->error.err); - AsyncClient::_s_error(e->arg, e->error.err); - } else if(e->event == LWIP_TCP_CONNECTED){ - //ets_printf("C: 0x%08x 0x%08x %d\n", e->arg, e->connected.pcb, e->connected.err); - AsyncClient::_s_connected(e->arg, e->connected.pcb, e->connected.err); - } else if(e->event == LWIP_TCP_ACCEPT){ - //ets_printf("A: 0x%08x 0x%08x\n", e->arg, e->accept.client); - AsyncServer::_s_accepted(e->arg, e->accept.client); - } else if(e->event == LWIP_TCP_DNS){ - //ets_printf("D: 0x%08x %s = %s\n", e->arg, e->dns.name, ipaddr_ntoa(&e->dns.addr)); - AsyncClient::_s_dns_found(e->dns.name, &e->dns.addr, e->arg); - } - free((void*)(e)); +static void _handle_async_event(lwip_event_packet_t* e) { + if (e->arg == NULL) { + // do nothing when arg is NULL + // ets_printf("event arg == NULL: 0x%08x\n", e->recv.pcb); + } else if (e->event == LWIP_TCP_CLEAR) { + _remove_events_with_arg(e->arg); + } else if (e->event == LWIP_TCP_RECV) { + // ets_printf("-R: 0x%08x\n", e->recv.pcb); + AsyncClient::_s_recv(e->arg, e->recv.pcb, e->recv.pb, e->recv.err); + } else if (e->event == LWIP_TCP_FIN) { + // ets_printf("-F: 0x%08x\n", e->fin.pcb); + AsyncClient::_s_fin(e->arg, e->fin.pcb, e->fin.err); + } else if (e->event == LWIP_TCP_SENT) { + // ets_printf("-S: 0x%08x\n", e->sent.pcb); + AsyncClient::_s_sent(e->arg, e->sent.pcb, e->sent.len); + } else if (e->event == LWIP_TCP_POLL) { + // ets_printf("-P: 0x%08x\n", e->poll.pcb); + AsyncClient::_s_poll(e->arg, e->poll.pcb); + } else if (e->event == LWIP_TCP_ERROR) { + // ets_printf("-E: 0x%08x %d\n", e->arg, e->error.err); + AsyncClient::_s_error(e->arg, e->error.err); + } else if (e->event == LWIP_TCP_CONNECTED) { + // ets_printf("C: 0x%08x 0x%08x %d\n", e->arg, e->connected.pcb, e->connected.err); + AsyncClient::_s_connected(e->arg, e->connected.pcb, e->connected.err); + } else if (e->event == LWIP_TCP_ACCEPT) { + // ets_printf("A: 0x%08x 0x%08x\n", e->arg, e->accept.client); + AsyncServer::_s_accepted(e->arg, e->accept.client); + } else if (e->event == LWIP_TCP_DNS) { + // ets_printf("D: 0x%08x %s = %s\n", e->arg, e->dns.name, ipaddr_ntoa(&e->dns.addr)); + AsyncClient::_s_dns_found(e->dns.name, &e->dns.addr, e->arg); + } + free((void*)(e)); } -static void _async_service_task(void *pvParameters){ - lwip_event_packet_t * packet = NULL; - for (;;) { - if(_get_async_event(&packet)){ +static void _async_service_task(void* pvParameters) { + lwip_event_packet_t* packet = NULL; + for (;;) { + if (_get_async_event(&packet)) { #if CONFIG_ASYNC_TCP_USE_WDT - if(esp_task_wdt_add(NULL) != ESP_OK){ - log_e("Failed to add async task to WDT"); - } + if (esp_task_wdt_add(NULL) != ESP_OK) { + log_e("Failed to add async task to WDT"); + } #endif - _handle_async_event(packet); + _handle_async_event(packet); #if CONFIG_ASYNC_TCP_USE_WDT - if(esp_task_wdt_delete(NULL) != ESP_OK){ - log_e("Failed to remove loop task from WDT"); - } + if (esp_task_wdt_delete(NULL) != ESP_OK) { + log_e("Failed to remove loop task from WDT"); + } #endif - } } - vTaskDelete(NULL); - _async_service_task_handle = NULL; + } + vTaskDelete(NULL); + _async_service_task_handle = NULL; } /* static void _stop_async_task(){ @@ -243,155 +251,155 @@ static void _stop_async_task(){ */ static bool customTaskCreateUniversal( - TaskFunction_t pxTaskCode, - const char * const pcName, - const uint32_t usStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - TaskHandle_t * const pxCreatedTask, - const BaseType_t xCoreID) { + TaskFunction_t pxTaskCode, + const char* const pcName, + const uint32_t usStackDepth, + void* const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t* const pxCreatedTask, + const BaseType_t xCoreID) { #ifndef CONFIG_FREERTOS_UNICORE - if(xCoreID >= 0 && xCoreID < 2) { - return xTaskCreatePinnedToCore(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, xCoreID); - } else { + if (xCoreID >= 0 && xCoreID < 2) { + return xTaskCreatePinnedToCore(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, xCoreID); + } else { #endif return xTaskCreate(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask); #ifndef CONFIG_FREERTOS_UNICORE - } + } #endif } -static bool _start_async_task(){ - if(!_init_async_event_queue()){ - return false; +static bool _start_async_task() { + if (!_init_async_event_queue()) { + return false; + } + if (!_async_service_task_handle) { + customTaskCreateUniversal(_async_service_task, "async_tcp", CONFIG_ASYNC_TCP_STACK_SIZE, NULL, CONFIG_ASYNC_TCP_PRIORITY, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE); + if (!_async_service_task_handle) { + return false; } - if(!_async_service_task_handle){ - customTaskCreateUniversal(_async_service_task, "async_tcp", CONFIG_ASYNC_TCP_STACK_SIZE, NULL, CONFIG_ASYNC_TCP_PRIORITY, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE); - if(!_async_service_task_handle){ - return false; - } - } - return true; + } + return true; } /* * LwIP Callbacks * */ -static int8_t _tcp_clear_events(void * arg) { - lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); - e->event = LWIP_TCP_CLEAR; - e->arg = arg; - if (!_prepend_async_event(&e)) { - free((void*)(e)); - } +static int8_t _tcp_clear_events(void* arg) { + lwip_event_packet_t* e = (lwip_event_packet_t*)malloc(sizeof(lwip_event_packet_t)); + e->event = LWIP_TCP_CLEAR; + e->arg = arg; + if (!_prepend_async_event(&e)) { + free((void*)(e)); + } + return ERR_OK; +} + +static int8_t _tcp_connected(void* arg, tcp_pcb* pcb, int8_t err) { + // ets_printf("+C: 0x%08x\n", pcb); + lwip_event_packet_t* e = (lwip_event_packet_t*)malloc(sizeof(lwip_event_packet_t)); + e->event = LWIP_TCP_CONNECTED; + e->arg = arg; + e->connected.pcb = pcb; + e->connected.err = err; + if (!_prepend_async_event(&e)) { + free((void*)(e)); + } + return ERR_OK; +} + +static int8_t _tcp_poll(void* arg, struct tcp_pcb* pcb) { + // throttle polling events queing when event queue is getting filled up, let it handle _onack's + if (uxQueueMessagesWaiting(_async_queue) > (rand() % CONFIG_ASYNC_TCP_QUEUE_SIZE / 2 + CONFIG_ASYNC_TCP_QUEUE_SIZE / 4)) { + log_d("throttling"); return ERR_OK; + } + + // ets_printf("+P: 0x%08x\n", pcb); + lwip_event_packet_t* e = (lwip_event_packet_t*)malloc(sizeof(lwip_event_packet_t)); + e->event = LWIP_TCP_POLL; + e->arg = arg; + e->poll.pcb = pcb; + if (!_send_async_event(&e)) { + free((void*)(e)); + } + return ERR_OK; } -static int8_t _tcp_connected(void * arg, tcp_pcb * pcb, int8_t err) { - //ets_printf("+C: 0x%08x\n", pcb); - lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); - e->event = LWIP_TCP_CONNECTED; - e->arg = arg; - e->connected.pcb = pcb; - e->connected.err = err; - if (!_prepend_async_event(&e)) { - free((void*)(e)); - } - return ERR_OK; +static int8_t _tcp_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* pb, int8_t err) { + lwip_event_packet_t* e = (lwip_event_packet_t*)malloc(sizeof(lwip_event_packet_t)); + e->arg = arg; + if (pb) { + // ets_printf("+R: 0x%08x\n", pcb); + e->event = LWIP_TCP_RECV; + e->recv.pcb = pcb; + e->recv.pb = pb; + e->recv.err = err; + } else { + // ets_printf("+F: 0x%08x\n", pcb); + e->event = LWIP_TCP_FIN; + e->fin.pcb = pcb; + e->fin.err = err; + // close the PCB in LwIP thread + AsyncClient::_s_lwip_fin(e->arg, e->fin.pcb, e->fin.err); + } + if (!_send_async_event(&e)) { + free((void*)(e)); + } + return ERR_OK; } -static int8_t _tcp_poll(void * arg, struct tcp_pcb * pcb) { - // throttle polling events queing when event queue is getting filled up, let it handle _onack's - if (uxQueueMessagesWaiting(_async_queue) > (rand() % CONFIG_ASYNC_TCP_QUEUE_SIZE / 2 + CONFIG_ASYNC_TCP_QUEUE_SIZE / 4) ) { - log_d("throttling"); - return ERR_OK; - } - - //ets_printf("+P: 0x%08x\n", pcb); - lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); - e->event = LWIP_TCP_POLL; - e->arg = arg; - e->poll.pcb = pcb; - if (!_send_async_event(&e)) { - free((void*)(e)); - } - return ERR_OK; +static int8_t _tcp_sent(void* arg, struct tcp_pcb* pcb, uint16_t len) { + // ets_printf("+S: 0x%08x\n", pcb); + lwip_event_packet_t* e = (lwip_event_packet_t*)malloc(sizeof(lwip_event_packet_t)); + e->event = LWIP_TCP_SENT; + e->arg = arg; + e->sent.pcb = pcb; + e->sent.len = len; + if (!_send_async_event(&e)) { + free((void*)(e)); + } + return ERR_OK; } -static int8_t _tcp_recv(void * arg, struct tcp_pcb * pcb, struct pbuf *pb, int8_t err) { - lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); - e->arg = arg; - if(pb){ - //ets_printf("+R: 0x%08x\n", pcb); - e->event = LWIP_TCP_RECV; - e->recv.pcb = pcb; - e->recv.pb = pb; - e->recv.err = err; - } else { - //ets_printf("+F: 0x%08x\n", pcb); - e->event = LWIP_TCP_FIN; - e->fin.pcb = pcb; - e->fin.err = err; - //close the PCB in LwIP thread - AsyncClient::_s_lwip_fin(e->arg, e->fin.pcb, e->fin.err); - } - if (!_send_async_event(&e)) { - free((void*)(e)); - } - return ERR_OK; +static void _tcp_error(void* arg, int8_t err) { + // ets_printf("+E: 0x%08x\n", arg); + lwip_event_packet_t* e = (lwip_event_packet_t*)malloc(sizeof(lwip_event_packet_t)); + e->event = LWIP_TCP_ERROR; + e->arg = arg; + e->error.err = err; + if (!_send_async_event(&e)) { + free((void*)(e)); + } } -static int8_t _tcp_sent(void * arg, struct tcp_pcb * pcb, uint16_t len) { - //ets_printf("+S: 0x%08x\n", pcb); - lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); - e->event = LWIP_TCP_SENT; - e->arg = arg; - e->sent.pcb = pcb; - e->sent.len = len; - if (!_send_async_event(&e)) { - free((void*)(e)); - } - return ERR_OK; +static void _tcp_dns_found(const char* name, struct ip_addr* ipaddr, void* arg) { + lwip_event_packet_t* e = (lwip_event_packet_t*)malloc(sizeof(lwip_event_packet_t)); + // ets_printf("+DNS: name=%s ipaddr=0x%08x arg=%x\n", name, ipaddr, arg); + e->event = LWIP_TCP_DNS; + e->arg = arg; + e->dns.name = name; + if (ipaddr) { + memcpy(&e->dns.addr, ipaddr, sizeof(struct ip_addr)); + } else { + memset(&e->dns.addr, 0, sizeof(e->dns.addr)); + } + if (!_send_async_event(&e)) { + free((void*)(e)); + } } -static void _tcp_error(void * arg, int8_t err) { - //ets_printf("+E: 0x%08x\n", arg); - lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); - e->event = LWIP_TCP_ERROR; - e->arg = arg; - e->error.err = err; - if (!_send_async_event(&e)) { - free((void*)(e)); - } -} - -static void _tcp_dns_found(const char * name, struct ip_addr * ipaddr, void * arg) { - lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); - //ets_printf("+DNS: name=%s ipaddr=0x%08x arg=%x\n", name, ipaddr, arg); - e->event = LWIP_TCP_DNS; - e->arg = arg; - e->dns.name = name; - if (ipaddr) { - memcpy(&e->dns.addr, ipaddr, sizeof(struct ip_addr)); - } else { - memset(&e->dns.addr, 0, sizeof(e->dns.addr)); - } - if (!_send_async_event(&e)) { - free((void*)(e)); - } -} - -//Used to switch out from LwIP thread -static int8_t _tcp_accept(void * arg, AsyncClient * client) { - lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); - e->event = LWIP_TCP_ACCEPT; - e->arg = arg; - e->accept.client = client; - if (!_prepend_async_event(&e)) { - free((void*)(e)); - } - return ERR_OK; +// Used to switch out from LwIP thread +static int8_t _tcp_accept(void* arg, AsyncClient* client) { + lwip_event_packet_t* e = (lwip_event_packet_t*)malloc(sizeof(lwip_event_packet_t)); + e->event = LWIP_TCP_ACCEPT; + e->arg = arg; + e->accept.client = client; + if (!_prepend_async_event(&e)) { + free((void*)(e)); + } + return ERR_OK; } /* @@ -402,482 +410,458 @@ static int8_t _tcp_accept(void * arg, AsyncClient * client) { typedef struct { struct tcpip_api_call_data call; - tcp_pcb * pcb; + tcp_pcb* pcb; int8_t closed_slot; int8_t err; union { - struct { - const char* data; - size_t size; - uint8_t apiflags; - } write; - size_t received; - struct { - ip_addr_t * addr; - uint16_t port; - tcp_connected_fn cb; - } connect; - struct { - ip_addr_t * addr; - uint16_t port; - } bind; - uint8_t backlog; + struct { + const char* data; + size_t size; + uint8_t apiflags; + } write; + size_t received; + struct { + ip_addr_t* addr; + uint16_t port; + tcp_connected_fn cb; + } connect; + struct { + ip_addr_t* addr; + uint16_t port; + } bind; + uint8_t backlog; }; } tcp_api_call_t; -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 == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { - msg->err = tcp_output(msg->pcb); - } - return msg->err; +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 == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { + msg->err = tcp_output(msg->pcb); + } + return msg->err; } -static esp_err_t _tcp_output(tcp_pcb * pcb, int8_t closed_slot) { - if(!pcb){ - return ERR_CONN; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = closed_slot; - tcpip_api_call(_tcp_output_api, (struct tcpip_api_call_data*)&msg); - return msg.err; +static esp_err_t _tcp_output(tcp_pcb* pcb, int8_t closed_slot) { + if (!pcb) { + return ERR_CONN; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = closed_slot; + tcpip_api_call(_tcp_output_api, (struct tcpip_api_call_data*)&msg); + return msg.err; } -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 == 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; +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 == 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; } -static esp_err_t _tcp_write(tcp_pcb * pcb, int8_t closed_slot, const char* data, size_t size, uint8_t apiflags) { - if(!pcb){ - return ERR_CONN; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = closed_slot; - msg.write.data = data; - msg.write.size = size; - msg.write.apiflags = apiflags; - tcpip_api_call(_tcp_write_api, (struct tcpip_api_call_data*)&msg); - return msg.err; +static esp_err_t _tcp_write(tcp_pcb* pcb, int8_t closed_slot, const char* data, size_t size, uint8_t apiflags) { + if (!pcb) { + return ERR_CONN; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = closed_slot; + msg.write.data = data; + msg.write.size = size; + msg.write.apiflags = apiflags; + tcpip_api_call(_tcp_write_api, (struct tcpip_api_call_data*)&msg); + return msg.err; } -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 == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { +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 == 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); - } - return msg->err; -} - -static esp_err_t _tcp_recved(tcp_pcb * pcb, int8_t closed_slot, size_t len) { - if(!pcb){ - return ERR_CONN; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = closed_slot; - msg.received = len; - tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call_data*)&msg); - return msg.err; -} - -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 == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { - msg->err = tcp_close(msg->pcb); - } - return msg->err; -} - -static esp_err_t _tcp_close(tcp_pcb * pcb, int8_t closed_slot) { - if(!pcb){ - return ERR_CONN; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = closed_slot; - tcpip_api_call(_tcp_close_api, (struct tcpip_api_call_data*)&msg); - return msg.err; -} - -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 == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { - tcp_abort(msg->pcb); - } - return msg->err; -} - -static esp_err_t _tcp_abort(tcp_pcb * pcb, int8_t closed_slot) { - if(!pcb){ - return ERR_CONN; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = closed_slot; - tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call_data*)&msg); - return msg.err; -} - -static err_t _tcp_connect_api(struct tcpip_api_call_data *api_call_msg){ - tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; - msg->err = tcp_connect(msg->pcb, msg->connect.addr, msg->connect.port, msg->connect.cb); - return msg->err; -} - -static esp_err_t _tcp_connect(tcp_pcb * pcb, int8_t closed_slot, ip_addr_t * addr, uint16_t port, tcp_connected_fn cb) { - if(!pcb){ - return ESP_FAIL; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = closed_slot; - msg.connect.addr = addr; - msg.connect.port = port; - msg.connect.cb = cb; - tcpip_api_call(_tcp_connect_api, (struct tcpip_api_call_data*)&msg); - return msg.err; -} - -static err_t _tcp_bind_api(struct tcpip_api_call_data *api_call_msg){ - tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; - msg->err = tcp_bind(msg->pcb, msg->bind.addr, msg->bind.port); - return msg->err; -} - -static esp_err_t _tcp_bind(tcp_pcb * pcb, ip_addr_t * addr, uint16_t port) { - if(!pcb){ - return ESP_FAIL; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = -1; - msg.bind.addr = addr; - msg.bind.port = port; - tcpip_api_call(_tcp_bind_api, (struct tcpip_api_call_data*)&msg); - return msg.err; -} - -static err_t _tcp_listen_api(struct tcpip_api_call_data *api_call_msg){ - tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; msg->err = 0; - msg->pcb = tcp_listen_with_backlog(msg->pcb, msg->backlog); - return msg->err; + tcp_recved(msg->pcb, msg->received); + } + return msg->err; } -static tcp_pcb * _tcp_listen_with_backlog(tcp_pcb * pcb, uint8_t backlog) { - if(!pcb){ - return NULL; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = -1; - msg.backlog = backlog?backlog:0xFF; - tcpip_api_call(_tcp_listen_api, (struct tcpip_api_call_data*)&msg); - return msg.pcb; +static esp_err_t _tcp_recved(tcp_pcb* pcb, int8_t closed_slot, size_t len) { + if (!pcb) { + return ERR_CONN; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = closed_slot; + msg.received = len; + tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call_data*)&msg); + return msg.err; } +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 == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { + msg->err = tcp_close(msg->pcb); + } + return msg->err; +} +static esp_err_t _tcp_close(tcp_pcb* pcb, int8_t closed_slot) { + if (!pcb) { + return ERR_CONN; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = closed_slot; + tcpip_api_call(_tcp_close_api, (struct tcpip_api_call_data*)&msg); + return msg.err; +} + +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 == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { + tcp_abort(msg->pcb); + } + return msg->err; +} + +static esp_err_t _tcp_abort(tcp_pcb* pcb, int8_t closed_slot) { + if (!pcb) { + return ERR_CONN; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = closed_slot; + tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call_data*)&msg); + return msg.err; +} + +static err_t _tcp_connect_api(struct tcpip_api_call_data* api_call_msg) { + tcp_api_call_t* msg = (tcp_api_call_t*)api_call_msg; + msg->err = tcp_connect(msg->pcb, msg->connect.addr, msg->connect.port, msg->connect.cb); + return msg->err; +} + +static esp_err_t _tcp_connect(tcp_pcb* pcb, int8_t closed_slot, ip_addr_t* addr, uint16_t port, tcp_connected_fn cb) { + if (!pcb) { + return ESP_FAIL; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = closed_slot; + msg.connect.addr = addr; + msg.connect.port = port; + msg.connect.cb = cb; + tcpip_api_call(_tcp_connect_api, (struct tcpip_api_call_data*)&msg); + return msg.err; +} + +static err_t _tcp_bind_api(struct tcpip_api_call_data* api_call_msg) { + tcp_api_call_t* msg = (tcp_api_call_t*)api_call_msg; + msg->err = tcp_bind(msg->pcb, msg->bind.addr, msg->bind.port); + return msg->err; +} + +static esp_err_t _tcp_bind(tcp_pcb* pcb, ip_addr_t* addr, uint16_t port) { + if (!pcb) { + return ESP_FAIL; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = -1; + msg.bind.addr = addr; + msg.bind.port = port; + tcpip_api_call(_tcp_bind_api, (struct tcpip_api_call_data*)&msg); + return msg.err; +} + +static err_t _tcp_listen_api(struct tcpip_api_call_data* api_call_msg) { + tcp_api_call_t* msg = (tcp_api_call_t*)api_call_msg; + msg->err = 0; + msg->pcb = tcp_listen_with_backlog(msg->pcb, msg->backlog); + return msg->err; +} + +static tcp_pcb* _tcp_listen_with_backlog(tcp_pcb* pcb, uint8_t backlog) { + if (!pcb) { + return NULL; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = -1; + msg.backlog = backlog ? backlog : 0xFF; + tcpip_api_call(_tcp_listen_api, (struct tcpip_api_call_data*)&msg); + return msg.pcb; +} /* Async TCP Client */ AsyncClient::AsyncClient(tcp_pcb* pcb) -: _connect_cb(0) -, _connect_cb_arg(0) -, _discard_cb(0) -, _discard_cb_arg(0) -, _sent_cb(0) -, _sent_cb_arg(0) -, _error_cb(0) -, _error_cb_arg(0) -, _recv_cb(0) -, _recv_cb_arg(0) -, _pb_cb(0) -, _pb_cb_arg(0) -, _timeout_cb(0) -, _timeout_cb_arg(0) -, _ack_pcb(true) -, _tx_last_packet(0) -, _rx_timeout(0) -, _rx_last_ack(0) -, _ack_timeout(CONFIG_ASYNC_TCP_MAX_ACK_TIME) -, _connect_port(0) -, prev(NULL) -, next(NULL) -{ - _pcb = pcb; - _closed_slot = INVALID_CLOSED_SLOT; - if(_pcb){ - _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(); - } + : _connect_cb(0), _connect_cb_arg(0), _discard_cb(0), _discard_cb_arg(0), _sent_cb(0), _sent_cb_arg(0), _error_cb(0), _error_cb_arg(0), _recv_cb(0), _recv_cb_arg(0), _pb_cb(0), _pb_cb_arg(0), _timeout_cb(0), _timeout_cb_arg(0), _ack_pcb(true), _tx_last_packet(0), _rx_timeout(0), _rx_last_ack(0), _ack_timeout(CONFIG_ASYNC_TCP_MAX_ACK_TIME), _connect_port(0), prev(NULL), next(NULL) { + _pcb = pcb; + _closed_slot = INVALID_CLOSED_SLOT; + if (_pcb) { + _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(); } + } } -AsyncClient::~AsyncClient(){ - if(_pcb) { - _close(); - } - _free_closed_slot(); +AsyncClient::~AsyncClient() { + if (_pcb) { + _close(); + } + _free_closed_slot(); } /* * Operators * */ -AsyncClient& AsyncClient::operator=(const AsyncClient& other){ - if (_pcb) { - _close(); - } +AsyncClient& AsyncClient::operator=(const AsyncClient& other) { + if (_pcb) { + _close(); + } - _pcb = other._pcb; - _closed_slot = other._closed_slot; - if (_pcb) { - _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); - } - return *this; + _pcb = other._pcb; + _closed_slot = other._closed_slot; + if (_pcb) { + _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); + } + return *this; } -bool AsyncClient::operator==(const AsyncClient &other) { - return _pcb == other._pcb; +bool AsyncClient::operator==(const AsyncClient& other) { + return _pcb == other._pcb; } -AsyncClient & AsyncClient::operator+=(const AsyncClient &other) { - if(next == NULL){ - next = (AsyncClient*)(&other); - next->prev = this; - } else { - AsyncClient *c = next; - while(c->next != NULL) { - c = c->next; - } - c->next =(AsyncClient*)(&other); - c->next->prev = c; +AsyncClient& AsyncClient::operator+=(const AsyncClient& other) { + if (next == NULL) { + next = (AsyncClient*)(&other); + next->prev = this; + } else { + AsyncClient* c = next; + while (c->next != NULL) { + c = c->next; } - return *this; + c->next = (AsyncClient*)(&other); + c->next->prev = c; + } + return *this; } /* * Callback Setters * */ -void AsyncClient::onConnect(AcConnectHandler cb, void* arg){ - _connect_cb = cb; - _connect_cb_arg = arg; +void AsyncClient::onConnect(AcConnectHandler cb, void* arg) { + _connect_cb = cb; + _connect_cb_arg = arg; } -void AsyncClient::onDisconnect(AcConnectHandler cb, void* arg){ - _discard_cb = cb; - _discard_cb_arg = arg; +void AsyncClient::onDisconnect(AcConnectHandler cb, void* arg) { + _discard_cb = cb; + _discard_cb_arg = arg; } -void AsyncClient::onAck(AcAckHandler cb, void* arg){ - _sent_cb = cb; - _sent_cb_arg = arg; +void AsyncClient::onAck(AcAckHandler cb, void* arg) { + _sent_cb = cb; + _sent_cb_arg = arg; } -void AsyncClient::onError(AcErrorHandler cb, void* arg){ - _error_cb = cb; - _error_cb_arg = arg; +void AsyncClient::onError(AcErrorHandler cb, void* arg) { + _error_cb = cb; + _error_cb_arg = arg; } -void AsyncClient::onData(AcDataHandler cb, void* arg){ - _recv_cb = cb; - _recv_cb_arg = arg; +void AsyncClient::onData(AcDataHandler cb, void* arg) { + _recv_cb = cb; + _recv_cb_arg = arg; } -void AsyncClient::onPacket(AcPacketHandler cb, void* arg){ +void AsyncClient::onPacket(AcPacketHandler cb, void* arg) { _pb_cb = cb; _pb_cb_arg = arg; } -void AsyncClient::onTimeout(AcTimeoutHandler cb, void* arg){ - _timeout_cb = cb; - _timeout_cb_arg = arg; +void AsyncClient::onTimeout(AcTimeoutHandler cb, void* arg) { + _timeout_cb = cb; + _timeout_cb_arg = arg; } -void AsyncClient::onPoll(AcConnectHandler cb, void* arg){ - _poll_cb = cb; - _poll_cb_arg = arg; +void AsyncClient::onPoll(AcConnectHandler cb, void* arg) { + _poll_cb = cb; + _poll_cb_arg = arg; } /* * Main Public Methods * */ -bool AsyncClient::_connect(ip_addr_t addr, uint16_t port){ - if (_pcb){ - log_d("already connected, state %d", _pcb->state); - return false; - } - if(!_start_async_task()){ - log_e("failed to start task"); - return false; - } +bool AsyncClient::_connect(ip_addr_t addr, uint16_t port) { + if (_pcb) { + log_d("already connected, state %d", _pcb->state); + return false; + } + if (!_start_async_task()) { + log_e("failed to start task"); + return false; + } - if(!_allocate_closed_slot()) { - log_e("failed to allocate: closed slot full"); - return false; - } + 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_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_MUTEX_UNLOCK(); - esp_err_t err =_tcp_connect(pcb, _closed_slot, &addr, port,(tcp_connected_fn)&_tcp_connected); - return err == ESP_OK; + esp_err_t err = _tcp_connect(pcb, _closed_slot, &addr, port, (tcp_connected_fn)&_tcp_connected); + return err == ESP_OK; } -bool AsyncClient::connect(const IPAddress& ip, uint16_t port){ - ip_addr_t addr; +bool AsyncClient::connect(const IPAddress& ip, uint16_t port) { + ip_addr_t addr; #if ESP_IDF_VERSION_MAJOR < 5 - addr.u_addr.ip4.addr = ip; - addr.type = IPADDR_TYPE_V4; + addr.u_addr.ip4.addr = ip; + addr.type = IPADDR_TYPE_V4; #else - ip.to_ip_addr_t(&addr); + ip.to_ip_addr_t(&addr); #endif - return _connect(addr, port); + return _connect(addr, port); } #if LWIP_IPV6 && ESP_IDF_VERSION_MAJOR < 5 -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]); +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); + return _connect(addr, port); } #endif -bool AsyncClient::connect(const char* host, uint16_t port){ - ip_addr_t addr; +bool AsyncClient::connect(const char* host, uint16_t port) { + ip_addr_t addr; - if(!_start_async_task()){ - log_e("failed to start task"); - return false; - } - - TCP_MUTEX_LOCK(); - err_t err = dns_gethostbyname(host, &addr, (dns_found_callback)&_tcp_dns_found, this); - TCP_MUTEX_UNLOCK(); - if(err == ERR_OK) { -#if ESP_IDF_VERSION_MAJOR < 5 -#if LWIP_IPV6 - if(addr.type == IPADDR_TYPE_V6) { - return connect(IPv6Address(addr.u_addr.ip6.addr), port); - } - return connect(IPAddress(addr.u_addr.ip4.addr), port); -#else - return connect(IPAddress(addr.addr), port); -#endif -#else - return _connect(addr, port); -#endif - } else if(err == ERR_INPROGRESS) { - _connect_port = port; - return true; - } - log_d("error: %d", err); + if (!_start_async_task()) { + log_e("failed to start task"); return false; + } + + TCP_MUTEX_LOCK(); + err_t err = dns_gethostbyname(host, &addr, (dns_found_callback)&_tcp_dns_found, this); + TCP_MUTEX_UNLOCK(); + if (err == ERR_OK) { +#if ESP_IDF_VERSION_MAJOR < 5 + #if LWIP_IPV6 + if (addr.type == IPADDR_TYPE_V6) { + return connect(IPv6Address(addr.u_addr.ip6.addr), port); + } + return connect(IPAddress(addr.u_addr.ip4.addr), port); + #else + return connect(IPAddress(addr.addr), port); + #endif +#else + return _connect(addr, port); +#endif + } else if (err == ERR_INPROGRESS) { + _connect_port = port; + return true; + } + log_d("error: %d", err); + return false; } -void AsyncClient::close(bool now){ - if(_pcb){ - _tcp_recved(_pcb, _closed_slot, _rx_ack_len); - } - _close(); +void AsyncClient::close(bool now) { + if (_pcb) { + _tcp_recved(_pcb, _closed_slot, _rx_ack_len); + } + _close(); } -int8_t AsyncClient::abort(){ - if(_pcb) { - _tcp_abort(_pcb, _closed_slot ); - _pcb = NULL; - } - return ERR_ABRT; +int8_t AsyncClient::abort() { + if (_pcb) { + _tcp_abort(_pcb, _closed_slot); + _pcb = NULL; + } + return ERR_ABRT; } -size_t AsyncClient::space(){ - if((_pcb != NULL) && (_pcb->state == ESTABLISHED)){ - return tcp_sndbuf(_pcb); - } - return 0; +size_t AsyncClient::space() { + if ((_pcb != NULL) && (_pcb->state == ESTABLISHED)) { + return tcp_sndbuf(_pcb); + } + return 0; } size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) { - if(!_pcb || size == 0 || data == NULL) { - return 0; - } - size_t room = space(); - if(!room) { - return 0; - } - size_t will_send = (room < size) ? room : size; - int8_t err = ERR_OK; - err = _tcp_write(_pcb, _closed_slot, data, will_send, apiflags); - if(err != ERR_OK) { - return 0; - } - return will_send; + if (!_pcb || size == 0 || data == NULL) { + return 0; + } + size_t room = space(); + if (!room) { + return 0; + } + size_t will_send = (room < size) ? room : size; + int8_t err = ERR_OK; + err = _tcp_write(_pcb, _closed_slot, data, will_send, apiflags); + if (err != ERR_OK) { + return 0; + } + return will_send; } -bool AsyncClient::send(){ - auto backup = _tx_last_packet; - _tx_last_packet = millis(); - if (_tcp_output(_pcb, _closed_slot) == ERR_OK) { - return true; - } - _tx_last_packet = backup; - return false; +bool AsyncClient::send() { + auto backup = _tx_last_packet; + _tx_last_packet = millis(); + if (_tcp_output(_pcb, _closed_slot) == ERR_OK) { + return true; + } + _tx_last_packet = backup; + return false; } -size_t AsyncClient::ack(size_t len){ - if(len > _rx_ack_len) - len = _rx_ack_len; - if(len){ - _tcp_recved(_pcb, _closed_slot, len); - } - _rx_ack_len -= len; - return len; +size_t AsyncClient::ack(size_t len) { + if (len > _rx_ack_len) + len = _rx_ack_len; + if (len) { + _tcp_recved(_pcb, _closed_slot, len); + } + _rx_ack_len -= len; + return len; } -void AsyncClient::ackPacket(struct pbuf * pb){ - if(!pb){ +void AsyncClient::ackPacket(struct pbuf* pb) { + if (!pb) { return; } _tcp_recved(_pcb, _closed_slot, pb->len); @@ -888,218 +872,218 @@ void AsyncClient::ackPacket(struct pbuf * pb){ * Main Private Methods * */ -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) { - err = abort(); - } - _free_closed_slot(); - _pcb = NULL; - if(_discard_cb) { - _discard_cb(_discard_cb_arg, this); - } +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) { + err = abort(); } - return err; + _free_closed_slot(); + _pcb = NULL; + if (_discard_cb) { + _discard_cb(_discard_cb_arg, this); + } + } + return err; } -bool AsyncClient::_allocate_closed_slot(){ - if (_closed_slot != INVALID_CLOSED_SLOT) { - return true; +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 == INVALID_CLOSED_SLOT || _closed_slots[i] <= closed_slot_min_index) && _closed_slots[i] != 0) { + closed_slot_min_index = _closed_slots[i]; + _closed_slot = i; } - 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 == 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 != INVALID_CLOSED_SLOT) { - _closed_slots[_closed_slot] = 0; - } - xSemaphoreGive(_slots_lock); - return (_closed_slot != INVALID_CLOSED_SLOT); + } + 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(){ - xSemaphoreTake(_slots_lock, portMAX_DELAY); - if (_closed_slot != INVALID_CLOSED_SLOT) { - _closed_slots[_closed_slot] = _closed_index; - _closed_slot = INVALID_CLOSED_SLOT; - ++ _closed_index; - } - xSemaphoreGive(_slots_lock); +void AsyncClient::_free_closed_slot() { + xSemaphoreTake(_slots_lock, portMAX_DELAY); + if (_closed_slot != INVALID_CLOSED_SLOT) { + _closed_slots[_closed_slot] = _closed_index; + _closed_slot = INVALID_CLOSED_SLOT; + ++_closed_index; + } + xSemaphoreGive(_slots_lock); } /* * Private Callbacks * */ -int8_t AsyncClient::_connected(tcp_pcb* pcb, int8_t err){ - _pcb = reinterpret_cast(pcb); - if(_pcb){ - _rx_last_packet = millis(); - } - if(_connect_cb) { - _connect_cb(_connect_cb_arg, this); - } - return ERR_OK; +int8_t AsyncClient::_connected(tcp_pcb* pcb, int8_t err) { + _pcb = reinterpret_cast(pcb); + if (_pcb) { + _rx_last_packet = millis(); + } + if (_connect_cb) { + _connect_cb(_connect_cb_arg, this); + } + return ERR_OK; } 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; - } - if(_error_cb) { - _error_cb(_error_cb_arg, this, err); - } - if(_discard_cb) { - _discard_cb(_discard_cb_arg, this); - } -} - -//In LwIP Thread -int8_t AsyncClient::_lwip_fin(tcp_pcb* pcb, int8_t err) { - if(!_pcb || pcb != _pcb){ - log_d("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); - return ERR_OK; - } + 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); - } - if(tcp_close(_pcb) != ERR_OK) { - tcp_abort(_pcb); + 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; - return ERR_OK; + } + if (_error_cb) { + _error_cb(_error_cb_arg, this, err); + } + if (_discard_cb) { + _discard_cb(_discard_cb_arg, this); + } } -//In Async Thread -int8_t AsyncClient::_fin(tcp_pcb* pcb, int8_t err) { - _tcp_clear_events(this); - if(_discard_cb) { - _discard_cb(_discard_cb_arg, this); - } +// In LwIP Thread +int8_t AsyncClient::_lwip_fin(tcp_pcb* pcb, int8_t err) { + if (!_pcb || pcb != _pcb) { + log_d("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); return ERR_OK; + } + 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); + } + if (tcp_close(_pcb) != ERR_OK) { + tcp_abort(_pcb); + } + _free_closed_slot(); + _pcb = NULL; + return ERR_OK; +} + +// In Async Thread +int8_t AsyncClient::_fin(tcp_pcb* pcb, int8_t err) { + _tcp_clear_events(this); + if (_discard_cb) { + _discard_cb(_discard_cb_arg, this); + } + return ERR_OK; } int8_t AsyncClient::_sent(tcp_pcb* pcb, uint16_t len) { - _rx_last_ack = _rx_last_packet = millis(); - if(_sent_cb) { - _sent_cb(_sent_cb_arg, this, len, (_rx_last_packet - _tx_last_packet)); - } - return ERR_OK; + _rx_last_ack = _rx_last_packet = millis(); + if (_sent_cb) { + _sent_cb(_sent_cb_arg, this, len, (_rx_last_packet - _tx_last_packet)); + } + return ERR_OK; } int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { - while(pb != NULL) { - _rx_last_packet = millis(); - //we should not ack before we assimilate the data - _ack_pcb = true; - pbuf *b = pb; - pb = b->next; - b->next = NULL; - if(_pb_cb){ - _pb_cb(_pb_cb_arg, this, b); - } else { - if(_recv_cb) { - _recv_cb(_recv_cb_arg, this, b->payload, b->len); - } - if(!_ack_pcb) { - _rx_ack_len += b->len; - } else if(_pcb) { - _tcp_recved(_pcb, _closed_slot, b->len); - } - } - pbuf_free(b); - } - return ERR_OK; -} - -int8_t AsyncClient::_poll(tcp_pcb* pcb){ - if(!_pcb){ - // log_d("pcb is NULL"); - return ERR_OK; - } - if(pcb != _pcb){ - log_d("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); - return ERR_OK; - } - - uint32_t now = millis(); - - // ACK Timeout - if(_ack_timeout){ - 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_d("ack timeout %d", pcb->state); - if(_timeout_cb) - _timeout_cb(_timeout_cb_arg, this, (now - _tx_last_packet)); - return ERR_OK; - } - } - // RX Timeout - if(_rx_timeout && (now - _rx_last_packet) >= (_rx_timeout * 1000)) { - log_d("rx timeout %d", pcb->state); - _close(); - return ERR_OK; - } - // Everything is fine - if(_poll_cb) { - _poll_cb(_poll_cb_arg, this); - } - return ERR_OK; -} - -void AsyncClient::_dns_found(struct ip_addr *ipaddr){ -#if ESP_IDF_VERSION_MAJOR < 5 - if(ipaddr && IP_IS_V4(ipaddr)){ - connect(IPAddress(ip_addr_get_ip4_u32(ipaddr)), _connect_port); -#if LWIP_IPV6 - } else if(ipaddr && ipaddr->u_addr.ip6.addr){ - connect(IPv6Address(ipaddr->u_addr.ip6.addr), _connect_port); -#endif -#else - if(ipaddr) { - IPAddress ip; - ip.from_ip_addr_t(ipaddr); - connect(ip, _connect_port); -#endif + while (pb != NULL) { + _rx_last_packet = millis(); + // we should not ack before we assimilate the data + _ack_pcb = true; + pbuf* b = pb; + pb = b->next; + b->next = NULL; + if (_pb_cb) { + _pb_cb(_pb_cb_arg, this, b); } else { - if(_error_cb) { - _error_cb(_error_cb_arg, this, -55); - } - if(_discard_cb) { - _discard_cb(_discard_cb_arg, this); - } + if (_recv_cb) { + _recv_cb(_recv_cb_arg, this, b->payload, b->len); + } + if (!_ack_pcb) { + _rx_ack_len += b->len; + } else if (_pcb) { + _tcp_recved(_pcb, _closed_slot, b->len); + } } + pbuf_free(b); + } + return ERR_OK; +} + +int8_t AsyncClient::_poll(tcp_pcb* pcb) { + if (!_pcb) { + // log_d("pcb is NULL"); + return ERR_OK; + } + if (pcb != _pcb) { + log_d("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); + return ERR_OK; + } + + uint32_t now = millis(); + + // ACK Timeout + if (_ack_timeout) { + 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_d("ack timeout %d", pcb->state); + if (_timeout_cb) + _timeout_cb(_timeout_cb_arg, this, (now - _tx_last_packet)); + return ERR_OK; + } + } + // RX Timeout + if (_rx_timeout && (now - _rx_last_packet) >= (_rx_timeout * 1000)) { + log_d("rx timeout %d", pcb->state); + _close(); + return ERR_OK; + } + // Everything is fine + if (_poll_cb) { + _poll_cb(_poll_cb_arg, this); + } + return ERR_OK; +} + +void AsyncClient::_dns_found(struct ip_addr* ipaddr) { +#if ESP_IDF_VERSION_MAJOR < 5 + if (ipaddr && IP_IS_V4(ipaddr)) { + connect(IPAddress(ip_addr_get_ip4_u32(ipaddr)), _connect_port); + #if LWIP_IPV6 + } else if (ipaddr && ipaddr->u_addr.ip6.addr) { + connect(IPv6Address(ipaddr->u_addr.ip6.addr), _connect_port); + #endif +#else + if (ipaddr) { + IPAddress ip; + ip.from_ip_addr_t(ipaddr); + connect(ip, _connect_port); +#endif + } else { + if (_error_cb) { + _error_cb(_error_cb_arg, this, -55); + } + if (_discard_cb) { + _discard_cb(_discard_cb_arg, this); + } + } } /* @@ -1107,325 +1091,354 @@ void AsyncClient::_dns_found(struct ip_addr *ipaddr){ * */ void AsyncClient::stop() { - close(false); + close(false); } -bool AsyncClient::free(){ - if(!_pcb) { - return true; - } - if(_pcb->state == CLOSED || _pcb->state > ESTABLISHED) { - return true; - } - return false; +bool AsyncClient::free() { + if (!_pcb) { + return true; + } + if (_pcb->state == CLOSED || _pcb->state > ESTABLISHED) { + return true; + } + return false; } size_t AsyncClient::write(const char* data) { - if(data == NULL) { - return 0; - } - return write(data, strlen(data)); + if (data == NULL) { + return 0; + } + return write(data, strlen(data)); } size_t AsyncClient::write(const char* data, size_t size, uint8_t apiflags) { - size_t will_send = add(data, size, apiflags); - if(!will_send || !send()) { - return 0; - } - return will_send; + size_t will_send = add(data, size, apiflags); + if (!will_send || !send()) { + return 0; + } + return will_send; } -void AsyncClient::setRxTimeout(uint32_t timeout){ - _rx_timeout = timeout; +void AsyncClient::setRxTimeout(uint32_t timeout) { + _rx_timeout = timeout; } -uint32_t AsyncClient::getRxTimeout(){ - return _rx_timeout; +uint32_t AsyncClient::getRxTimeout() { + return _rx_timeout; } -uint32_t AsyncClient::getAckTimeout(){ - return _ack_timeout; +uint32_t AsyncClient::getAckTimeout() { + return _ack_timeout; } -void AsyncClient::setAckTimeout(uint32_t timeout){ - _ack_timeout = timeout; +void AsyncClient::setAckTimeout(uint32_t timeout) { + _ack_timeout = timeout; } -void AsyncClient::setNoDelay(bool nodelay){ - if(!_pcb) { - return; - } - if(nodelay) { - tcp_nagle_disable(_pcb); - } else { - tcp_nagle_enable(_pcb); - } +void AsyncClient::setNoDelay(bool nodelay) { + if (!_pcb) { + return; + } + if (nodelay) { + tcp_nagle_disable(_pcb); + } else { + tcp_nagle_enable(_pcb); + } } -bool AsyncClient::getNoDelay(){ - if(!_pcb) { - return false; - } - return tcp_nagle_disabled(_pcb); +bool AsyncClient::getNoDelay() { + if (!_pcb) { + return false; + } + 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 - } +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; - } - return tcp_mss(_pcb); +uint16_t AsyncClient::getMss() { + if (!_pcb) { + return 0; + } + return tcp_mss(_pcb); } uint32_t AsyncClient::getRemoteAddress() { - if(!_pcb) { - return 0; - } + if (!_pcb) { + return 0; + } #if LWIP_IPV4 && LWIP_IPV6 - return _pcb->remote_ip.u_addr.ip4.addr; + return _pcb->remote_ip.u_addr.ip4.addr; #else - return _pcb->remote_ip.addr; + return _pcb->remote_ip.addr; #endif } #if LWIP_IPV6 ip6_addr_t AsyncClient::getRemoteAddress6() { - if(!_pcb) { - ip6_addr_t nulladdr; - ip6_addr_set_zero(&nulladdr); - return nulladdr; - } - return _pcb->remote_ip.u_addr.ip6; + if (!_pcb) { + ip6_addr_t nulladdr; + ip6_addr_set_zero(&nulladdr); + return nulladdr; + } + return _pcb->remote_ip.u_addr.ip6; } ip6_addr_t AsyncClient::getLocalAddress6() { - if(!_pcb) { - ip6_addr_t nulladdr; - ip6_addr_set_zero(&nulladdr); - return nulladdr; - } - return _pcb->local_ip.u_addr.ip6; + if (!_pcb) { + ip6_addr_t nulladdr; + ip6_addr_set_zero(&nulladdr); + return nulladdr; + } + return _pcb->local_ip.u_addr.ip6; } -#if ESP_IDF_VERSION_MAJOR < 5 + #if ESP_IDF_VERSION_MAJOR < 5 IPv6Address AsyncClient::remoteIP6() { - return IPv6Address(getRemoteAddress6().addr); + return IPv6Address(getRemoteAddress6().addr); } IPv6Address AsyncClient::localIP6() { - return IPv6Address(getLocalAddress6().addr); + return IPv6Address(getLocalAddress6().addr); } -#else + #else IPAddress AsyncClient::remoteIP6() { - if (!_pcb) { - return IPAddress(IPType::IPv6); - } - IPAddress ip; - ip.from_ip_addr_t(&(_pcb->remote_ip)); - return ip; + if (!_pcb) { + return IPAddress(IPType::IPv6); + } + IPAddress ip; + ip.from_ip_addr_t(&(_pcb->remote_ip)); + return ip; } IPAddress AsyncClient::localIP6() { - if (!_pcb) { - return IPAddress(IPType::IPv6); - } - IPAddress ip; - ip.from_ip_addr_t(&(_pcb->local_ip)); - return ip; + if (!_pcb) { + return IPAddress(IPType::IPv6); + } + IPAddress ip; + ip.from_ip_addr_t(&(_pcb->local_ip)); + return ip; } -#endif + #endif #endif uint16_t AsyncClient::getRemotePort() { - if(!_pcb) { - return 0; - } - return _pcb->remote_port; + if (!_pcb) { + return 0; + } + return _pcb->remote_port; } uint32_t AsyncClient::getLocalAddress() { - if(!_pcb) { - return 0; - } + if (!_pcb) { + return 0; + } #if LWIP_IPV4 && LWIP_IPV6 - return _pcb->local_ip.u_addr.ip4.addr; + return _pcb->local_ip.u_addr.ip4.addr; #else - return _pcb->local_ip.addr; + return _pcb->local_ip.addr; #endif } uint16_t AsyncClient::getLocalPort() { - if(!_pcb) { - return 0; - } - return _pcb->local_port; + if (!_pcb) { + return 0; + } + return _pcb->local_port; } IPAddress AsyncClient::remoteIP() { #if ESP_IDF_VERSION_MAJOR < 5 - return IPAddress(getRemoteAddress()); + return IPAddress(getRemoteAddress()); #else - if (!_pcb) { - return IPAddress(); - } - IPAddress ip; - ip.from_ip_addr_t(&(_pcb->remote_ip)); - return ip; + if (!_pcb) { + return IPAddress(); + } + IPAddress ip; + ip.from_ip_addr_t(&(_pcb->remote_ip)); + return ip; #endif } uint16_t AsyncClient::remotePort() { - return getRemotePort(); + return getRemotePort(); } IPAddress AsyncClient::localIP() { #if ESP_IDF_VERSION_MAJOR < 5 - return IPAddress(getLocalAddress()); + return IPAddress(getLocalAddress()); #else - if (!_pcb) { - return IPAddress(); - } - IPAddress ip; - ip.from_ip_addr_t(&(_pcb->local_ip)); - return ip; + if (!_pcb) { + return IPAddress(); + } + IPAddress ip; + ip.from_ip_addr_t(&(_pcb->local_ip)); + return ip; #endif } - uint16_t AsyncClient::localPort() { - return getLocalPort(); + return getLocalPort(); } uint8_t AsyncClient::state() { - if(!_pcb) { - return 0; - } - return _pcb->state; + if (!_pcb) { + return 0; + } + return _pcb->state; } -bool AsyncClient::connected(){ - if (!_pcb) { - return false; - } - return _pcb->state == ESTABLISHED; +bool AsyncClient::connected() { + if (!_pcb) { + return false; + } + return _pcb->state == ESTABLISHED; } -bool AsyncClient::connecting(){ - if (!_pcb) { - return false; - } - return _pcb->state > CLOSED && _pcb->state < ESTABLISHED; +bool AsyncClient::connecting() { + if (!_pcb) { + return false; + } + return _pcb->state > CLOSED && _pcb->state < ESTABLISHED; } -bool AsyncClient::disconnecting(){ - if (!_pcb) { - return false; - } - return _pcb->state > ESTABLISHED && _pcb->state < TIME_WAIT; +bool AsyncClient::disconnecting() { + if (!_pcb) { + return false; + } + return _pcb->state > ESTABLISHED && _pcb->state < TIME_WAIT; } -bool AsyncClient::disconnected(){ - if (!_pcb) { - return true; - } - return _pcb->state == CLOSED || _pcb->state == TIME_WAIT; +bool AsyncClient::disconnected() { + if (!_pcb) { + return true; + } + return _pcb->state == CLOSED || _pcb->state == TIME_WAIT; } -bool AsyncClient::freeable(){ - if (!_pcb) { - return true; - } - return _pcb->state == CLOSED || _pcb->state > ESTABLISHED; +bool AsyncClient::freeable() { + if (!_pcb) { + return true; + } + return _pcb->state == CLOSED || _pcb->state > ESTABLISHED; } -bool AsyncClient::canSend(){ - return space() > 0; +bool AsyncClient::canSend() { + return space() > 0; } -const char * AsyncClient::errorToString(int8_t error){ - switch(error){ - case ERR_OK: return "OK"; - case ERR_MEM: return "Out of memory error"; - case ERR_BUF: return "Buffer error"; - case ERR_TIMEOUT: return "Timeout"; - case ERR_RTE: return "Routing problem"; - case ERR_INPROGRESS: return "Operation in progress"; - case ERR_VAL: return "Illegal value"; - case ERR_WOULDBLOCK: return "Operation would block"; - case ERR_USE: return "Address in use"; - case ERR_ALREADY: return "Already connected"; - case ERR_CONN: return "Not connected"; - case ERR_IF: return "Low-level netif error"; - case ERR_ABRT: return "Connection aborted"; - case ERR_RST: return "Connection reset"; - case ERR_CLSD: return "Connection closed"; - case ERR_ARG: return "Illegal argument"; - case -55: return "DNS failed"; - default: return "UNKNOWN"; - } +const char* AsyncClient::errorToString(int8_t error) { + switch (error) { + case ERR_OK: + return "OK"; + case ERR_MEM: + return "Out of memory error"; + case ERR_BUF: + return "Buffer error"; + case ERR_TIMEOUT: + return "Timeout"; + case ERR_RTE: + return "Routing problem"; + case ERR_INPROGRESS: + return "Operation in progress"; + case ERR_VAL: + return "Illegal value"; + case ERR_WOULDBLOCK: + return "Operation would block"; + case ERR_USE: + return "Address in use"; + case ERR_ALREADY: + return "Already connected"; + case ERR_CONN: + return "Not connected"; + case ERR_IF: + return "Low-level netif error"; + case ERR_ABRT: + return "Connection aborted"; + case ERR_RST: + return "Connection reset"; + case ERR_CLSD: + return "Connection closed"; + case ERR_ARG: + return "Illegal argument"; + case -55: + return "DNS failed"; + default: + return "UNKNOWN"; + } } -const char * AsyncClient::stateToString(){ - switch(state()){ - case 0: return "Closed"; - case 1: return "Listen"; - case 2: return "SYN Sent"; - case 3: return "SYN Received"; - case 4: return "Established"; - case 5: return "FIN Wait 1"; - case 6: return "FIN Wait 2"; - case 7: return "Close Wait"; - case 8: return "Closing"; - case 9: return "Last ACK"; - case 10: return "Time Wait"; - default: return "UNKNOWN"; - } +const char* AsyncClient::stateToString() { + switch (state()) { + case 0: + return "Closed"; + case 1: + return "Listen"; + case 2: + return "SYN Sent"; + case 3: + return "SYN Received"; + case 4: + return "Established"; + case 5: + return "FIN Wait 1"; + case 6: + return "FIN Wait 2"; + case 7: + return "Close Wait"; + case 8: + return "Closing"; + case 9: + return "Last ACK"; + case 10: + return "Time Wait"; + default: + return "UNKNOWN"; + } } /* * Static Callbacks (LwIP C2C++ interconnect) * */ -void AsyncClient::_s_dns_found(const char * name, struct ip_addr * ipaddr, void * arg){ - reinterpret_cast(arg)->_dns_found(ipaddr); +void AsyncClient::_s_dns_found(const char* name, struct ip_addr* ipaddr, void* arg) { + reinterpret_cast(arg)->_dns_found(ipaddr); } -int8_t AsyncClient::_s_poll(void * arg, struct tcp_pcb * pcb) { - return reinterpret_cast(arg)->_poll(pcb); +int8_t AsyncClient::_s_poll(void* arg, struct tcp_pcb* pcb) { + return reinterpret_cast(arg)->_poll(pcb); } -int8_t AsyncClient::_s_recv(void * arg, struct tcp_pcb * pcb, struct pbuf *pb, int8_t err) { - return reinterpret_cast(arg)->_recv(pcb, pb, err); +int8_t AsyncClient::_s_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* pb, int8_t err) { + return reinterpret_cast(arg)->_recv(pcb, pb, err); } -int8_t AsyncClient::_s_fin(void * arg, struct tcp_pcb * pcb, int8_t err) { - return reinterpret_cast(arg)->_fin(pcb, err); +int8_t AsyncClient::_s_fin(void* arg, struct tcp_pcb* pcb, int8_t err) { + return reinterpret_cast(arg)->_fin(pcb, err); } -int8_t AsyncClient::_s_lwip_fin(void * arg, struct tcp_pcb * pcb, int8_t err) { - return reinterpret_cast(arg)->_lwip_fin(pcb, err); +int8_t AsyncClient::_s_lwip_fin(void* arg, struct tcp_pcb* pcb, int8_t err) { + return reinterpret_cast(arg)->_lwip_fin(pcb, err); } -int8_t AsyncClient::_s_sent(void * arg, struct tcp_pcb * pcb, uint16_t len) { - return reinterpret_cast(arg)->_sent(pcb, len); +int8_t AsyncClient::_s_sent(void* arg, struct tcp_pcb* pcb, uint16_t len) { + return reinterpret_cast(arg)->_sent(pcb, len); } -void AsyncClient::_s_error(void * arg, int8_t err) { - reinterpret_cast(arg)->_error(err); +void AsyncClient::_s_error(void* arg, int8_t err) { + reinterpret_cast(arg)->_error(err); } -int8_t AsyncClient::_s_connected(void * arg, struct tcp_pcb * pcb, int8_t err){ - return reinterpret_cast(arg)->_connected(pcb, err); +int8_t AsyncClient::_s_connected(void* arg, struct tcp_pcb* pcb, int8_t err) { + return reinterpret_cast(arg)->_connected(pcb, err); } /* @@ -1433,165 +1446,150 @@ int8_t AsyncClient::_s_connected(void * arg, struct tcp_pcb * pcb, int8_t err){ */ AsyncServer::AsyncServer(IPAddress addr, uint16_t port) -: _port(port) + : _port(port) #if ESP_IDF_VERSION_MAJOR < 5 -, _bind4(true) -, _bind6(false) + , + _bind4(true), _bind6(false) #else -, _bind4(addr.type() != IPType::IPv6) -, _bind6(addr.type() == IPType::IPv6) + , + _bind4(addr.type() != IPType::IPv6), _bind6(addr.type() == IPType::IPv6) #endif -, _addr(addr) -, _noDelay(false) -, _pcb(0) -, _connect_cb(0) -, _connect_cb_arg(0) -{} + , + _addr(addr), _noDelay(false), _pcb(0), _connect_cb(0), _connect_cb_arg(0) { +} #if ESP_IDF_VERSION_MAJOR < 5 AsyncServer::AsyncServer(IPv6Address addr, uint16_t port) -: _port(port) -, _bind4(false) -, _bind6(true) -, _addr6(addr) -, _noDelay(false) -, _pcb(0) -, _connect_cb(0) -, _connect_cb_arg(0) -{} + : _port(port), _bind4(false), _bind6(true), _addr6(addr), _noDelay(false), _pcb(0), _connect_cb(0), _connect_cb_arg(0) {} #endif AsyncServer::AsyncServer(uint16_t port) -: _port(port) -, _bind4(true) -, _bind6(false) -, _addr((uint32_t) IPADDR_ANY) + : _port(port), _bind4(true), _bind6(false), _addr((uint32_t)IPADDR_ANY) #if ESP_IDF_VERSION_MAJOR < 5 -, _addr6() + , + _addr6() #endif -, _noDelay(false) -, _pcb(0) -, _connect_cb(0) -, _connect_cb_arg(0) -{} - -AsyncServer::~AsyncServer(){ - end(); + , + _noDelay(false), _pcb(0), _connect_cb(0), _connect_cb_arg(0) { } -void AsyncServer::onClient(AcConnectHandler cb, void* arg){ - _connect_cb = cb; - _connect_cb_arg = arg; +AsyncServer::~AsyncServer() { + end(); } -void AsyncServer::begin(){ - if(_pcb) { - return; - } +void AsyncServer::onClient(AcConnectHandler cb, void* arg) { + _connect_cb = cb; + _connect_cb_arg = arg; +} - if(!_start_async_task()){ - log_e("failed to start task"); - 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; - } +void AsyncServer::begin() { + if (_pcb) { + return; + } - ip_addr_t local_addr; + if (!_start_async_task()) { + log_e("failed to start task"); + 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; + } + + ip_addr_t local_addr; #if ESP_IDF_VERSION_MAJOR < 5 - 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; - } + 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); + _addr.to_ip_addr_t(&local_addr); #endif - err = _tcp_bind(_pcb, &local_addr, _port); + err = _tcp_bind(_pcb, &local_addr, _port); - if (err != ERR_OK) { - _tcp_close(_pcb, -1); - log_e("bind error: %d", err); - return; - } + if (err != ERR_OK) { + _tcp_close(_pcb, -1); + log_e("bind error: %d", err); + return; + } - static uint8_t backlog = 5; - _pcb = _tcp_listen_with_backlog(_pcb, backlog); - if (!_pcb) { - log_e("listen_pcb == NULL"); - return; - } + static uint8_t backlog = 5; + _pcb = _tcp_listen_with_backlog(_pcb, backlog); + if (!_pcb) { + 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, (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; + 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; + } } -//runs on LwIP thread -int8_t AsyncServer::_accept(tcp_pcb* pcb, int8_t err){ - //ets_printf("+A: 0x%08x\n", pcb); - if(_connect_cb){ - AsyncClient *c = new AsyncClient(pcb); - if(c){ - c->setNoDelay(_noDelay); - return _tcp_accept(this, c); - } +// runs on LwIP thread +int8_t AsyncServer::_accept(tcp_pcb* pcb, int8_t err) { + // ets_printf("+A: 0x%08x\n", pcb); + if (_connect_cb) { + AsyncClient* c = new AsyncClient(pcb); + if (c) { + c->setNoDelay(_noDelay); + return _tcp_accept(this, c); } - if(tcp_close(pcb) != ERR_OK){ - tcp_abort(pcb); - } - log_d("FAIL"); - return ERR_OK; + } + if (tcp_close(pcb) != ERR_OK) { + tcp_abort(pcb); + } + log_d("FAIL"); + return ERR_OK; } -int8_t AsyncServer::_accepted(AsyncClient* client){ - if(_connect_cb){ - _connect_cb(_connect_cb_arg, client); - } - return ERR_OK; +int8_t AsyncServer::_accepted(AsyncClient* client) { + if (_connect_cb) { + _connect_cb(_connect_cb_arg, client); + } + return ERR_OK; } -void AsyncServer::setNoDelay(bool nodelay){ - _noDelay = nodelay; +void AsyncServer::setNoDelay(bool nodelay) { + _noDelay = nodelay; } -bool AsyncServer::getNoDelay(){ - return _noDelay; +bool AsyncServer::getNoDelay() { + return _noDelay; } -uint8_t AsyncServer::status(){ - if (!_pcb) { - return 0; - } - return _pcb->state; +uint8_t AsyncServer::status() { + if (!_pcb) { + return 0; + } + return _pcb->state; } -int8_t AsyncServer::_s_accept(void * arg, tcp_pcb * pcb, int8_t err){ - return reinterpret_cast(arg)->_accept(pcb, err); +int8_t AsyncServer::_s_accept(void* arg, tcp_pcb* pcb, int8_t err) { + return reinterpret_cast(arg)->_accept(pcb, err); } -int8_t AsyncServer::_s_accepted(void *arg, AsyncClient* client){ - return reinterpret_cast(arg)->_accepted(client); +int8_t AsyncServer::_s_accepted(void* arg, AsyncClient* client) { + return reinterpret_cast(arg)->_accepted(client); } diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 25fb462..4d21cbe 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,67 +22,67 @@ #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 "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" + #include "IPv6Address.h" #endif -#include -#include "lwip/ip_addr.h" #include "lwip/ip6_addr.h" +#include "lwip/ip_addr.h" +#include #ifndef LIBRETINY -#include "sdkconfig.h" + #include "sdkconfig.h" extern "C" { - #include "freertos/semphr.h" - #include "lwip/pbuf.h" + #include "freertos/semphr.h" + #include "lwip/pbuf.h" } #else extern "C" { - #include - #include + #include + #include } -#define CONFIG_ASYNC_TCP_RUNNING_CORE -1 //any available core -#define CONFIG_ASYNC_TCP_USE_WDT 0 + #define CONFIG_ASYNC_TCP_RUNNING_CORE -1 // any available core + #define CONFIG_ASYNC_TCP_USE_WDT 0 #endif -//If core is not defined, then we are running in Arduino or PIO +// If core is not defined, then we are running in Arduino or PIO #ifndef CONFIG_ASYNC_TCP_RUNNING_CORE -#define CONFIG_ASYNC_TCP_RUNNING_CORE -1 //any available core -#define CONFIG_ASYNC_TCP_USE_WDT 1 //if enabled, adds between 33us and 200us per event + #define CONFIG_ASYNC_TCP_RUNNING_CORE -1 // any available core + #define CONFIG_ASYNC_TCP_USE_WDT 1 // if enabled, adds between 33us and 200us per event #endif #ifndef CONFIG_ASYNC_TCP_STACK_SIZE -#define CONFIG_ASYNC_TCP_STACK_SIZE 8192 * 2 + #define CONFIG_ASYNC_TCP_STACK_SIZE 8192 * 2 #endif #ifndef CONFIG_ASYNC_TCP_PRIORITY -#define CONFIG_ASYNC_TCP_PRIORITY 10 + #define CONFIG_ASYNC_TCP_PRIORITY 10 #endif #ifndef CONFIG_ASYNC_TCP_QUEUE_SIZE -#define CONFIG_ASYNC_TCP_QUEUE_SIZE 64 + #define CONFIG_ASYNC_TCP_QUEUE_SIZE 64 #endif #ifndef CONFIG_ASYNC_TCP_MAX_ACK_TIME -#define CONFIG_ASYNC_TCP_MAX_ACK_TIME 5000 + #define CONFIG_ASYNC_TCP_MAX_ACK_TIME 5000 #endif class AsyncClient; -#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. +#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. typedef std::function AcConnectHandler; typedef std::function AcAckHandler; typedef std::function AcErrorHandler; -typedef std::function AcDataHandler; -typedef std::function AcPacketHandler; +typedef std::function AcDataHandler; +typedef std::function AcPacketHandler; typedef std::function AcTimeoutHandler; struct tcp_pcb; @@ -93,47 +93,47 @@ class AsyncClient { AsyncClient(tcp_pcb* pcb = 0); ~AsyncClient(); - AsyncClient & operator=(const AsyncClient &other); - AsyncClient & operator+=(const AsyncClient &other); + AsyncClient& operator=(const AsyncClient& other); + AsyncClient& operator+=(const AsyncClient& other); - bool operator==(const AsyncClient &other); + bool operator==(const AsyncClient& other); - bool operator!=(const AsyncClient &other) { + bool operator!=(const AsyncClient& other) { return !(*this == other); } bool connect(const IPAddress& ip, uint16_t port); #if ESP_IDF_VERSION_MAJOR < 5 bool connect(const IPv6Address& ip, uint16_t port); #endif - bool connect(const char *host, uint16_t port); + bool connect(const char* host, uint16_t port); void close(bool now = false); void stop(); int8_t abort(); bool free(); - bool canSend();//ack is not pending - size_t space();//space available in the TCP window - size_t add(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY);//add for sending - bool send();//send all data added with the method above + bool canSend(); // ack is not pending + size_t space(); // space available in the TCP window + size_t add(const char* data, size_t size, uint8_t apiflags = ASYNC_WRITE_FLAG_COPY); // add for sending + bool send(); // send all data added with the method above - //write equals add()+send() + // write equals add()+send() size_t write(const char* data); - size_t write(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY); //only when canSend() == true + size_t write(const char* data, size_t size, uint8_t apiflags = ASYNC_WRITE_FLAG_COPY); // only when canSend() == true uint8_t state(); bool connecting(); bool connected(); bool disconnecting(); bool disconnected(); - bool freeable();//disconnected or disconnecting + bool freeable(); // disconnected or disconnecting uint16_t getMss(); uint32_t getRxTimeout(); - void setRxTimeout(uint32_t timeout);//no RX data timeout for the connection in seconds + void setRxTimeout(uint32_t timeout); // no RX data timeout for the connection in seconds uint32_t getAckTimeout(); - void setAckTimeout(uint32_t timeout);//no ACK timeout for the last sent packet in milliseconds + void setAckTimeout(uint32_t timeout); // no ACK timeout for the last sent packet in milliseconds void setNoDelay(bool nodelay); bool getNoDelay(); @@ -147,55 +147,55 @@ class AsyncClient { #if LWIP_IPV6 ip6_addr_t getRemoteAddress6(); ip6_addr_t getLocalAddress6(); -#if ESP_IDF_VERSION_MAJOR < 5 + #if ESP_IDF_VERSION_MAJOR < 5 IPv6Address remoteIP6(); IPv6Address localIP6(); -#else + #else IPAddress remoteIP6(); IPAddress localIP6(); -#endif + #endif #endif - //compatibility + // compatibility IPAddress remoteIP(); uint16_t remotePort(); IPAddress localIP(); uint16_t localPort(); - void onConnect(AcConnectHandler cb, void* arg = 0); //on successful connect - void onDisconnect(AcConnectHandler cb, void* arg = 0); //disconnected - void onAck(AcAckHandler cb, void* arg = 0); //ack received - void onError(AcErrorHandler cb, void* arg = 0); //unsuccessful connect or error - void onData(AcDataHandler cb, void* arg = 0); //data received (called if onPacket is not used) - void onPacket(AcPacketHandler cb, void* arg = 0); //data received - void onTimeout(AcTimeoutHandler cb, void* arg = 0); //ack timeout - void onPoll(AcConnectHandler cb, void* arg = 0); //every 125ms when connected + void onConnect(AcConnectHandler cb, void* arg = 0); // on successful connect + void onDisconnect(AcConnectHandler cb, void* arg = 0); // disconnected + void onAck(AcAckHandler cb, void* arg = 0); // ack received + void onError(AcErrorHandler cb, void* arg = 0); // unsuccessful connect or error + void onData(AcDataHandler cb, void* arg = 0); // data received (called if onPacket is not used) + void onPacket(AcPacketHandler cb, void* arg = 0); // data received + void onTimeout(AcTimeoutHandler cb, void* arg = 0); // ack timeout + void onPoll(AcConnectHandler cb, void* arg = 0); // every 125ms when connected - void ackPacket(struct pbuf * pb);//ack pbuf from onPacket - size_t ack(size_t len); //ack data that you have not acked using the method below - void ackLater(){ _ack_pcb = false; } //will not ack the current packet. Call from onData + void ackPacket(struct pbuf* pb); // ack pbuf from onPacket + size_t ack(size_t len); // ack data that you have not acked using the method below + void ackLater() { _ack_pcb = false; } // will not ack the current packet. Call from onData - const char * errorToString(int8_t error); - const char * stateToString(); + const char* errorToString(int8_t error); + const char* stateToString(); - //Do not use any of the functions below! - static int8_t _s_poll(void *arg, struct tcp_pcb *tpcb); - static int8_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, int8_t err); - static int8_t _s_fin(void *arg, struct tcp_pcb *tpcb, int8_t err); - 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, struct tcp_pcb *tpcb, int8_t err); - static void _s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg); + // Do not use any of the functions below! + static int8_t _s_poll(void* arg, struct tcp_pcb* tpcb); + static int8_t _s_recv(void* arg, struct tcp_pcb* tpcb, struct pbuf* pb, int8_t err); + static int8_t _s_fin(void* arg, struct tcp_pcb* tpcb, int8_t err); + 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, 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); - tcp_pcb * pcb(){ return _pcb; } + tcp_pcb* pcb() { return _pcb; } protected: bool _connect(ip_addr_t addr, uint16_t port); tcp_pcb* _pcb; - int8_t _closed_slot; + int8_t _closed_slot; AcConnectHandler _connect_cb; void* _connect_cb_arg; @@ -232,7 +232,7 @@ class AsyncClient { int8_t _sent(tcp_pcb* pcb, uint16_t len); int8_t _fin(tcp_pcb* pcb, int8_t err); int8_t _lwip_fin(tcp_pcb* pcb, int8_t err); - void _dns_found(struct ip_addr *ipaddr); + void _dns_found(struct ip_addr* ipaddr); public: AsyncClient* prev; @@ -254,9 +254,9 @@ class AsyncServer { bool getNoDelay(); uint8_t status(); - //Do not use any of the functions below! - static int8_t _s_accept(void *arg, tcp_pcb* newpcb, int8_t err); - static int8_t _s_accepted(void *arg, AsyncClient* client); + // Do not use any of the functions below! + static int8_t _s_accept(void* arg, tcp_pcb* newpcb, int8_t err); + static int8_t _s_accepted(void* arg, AsyncClient* client); protected: uint16_t _port; @@ -275,5 +275,4 @@ class AsyncServer { int8_t _accepted(AsyncClient* client); }; - #endif /* ASYNCTCP_H_ */ From 9355538a8f9a6b7aa3eac25a70c37b2dbc523e19 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Wed, 11 Dec 2024 19:59:42 +0100 Subject: [PATCH 132/150] v3.2.15 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index aa768a5..f64b62b 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ The base classes on which everything else is built. They expose all possible sce ## Coordinates ``` -mathieucarbou/AsyncTCP @ ^3.2.14 +mathieucarbou/AsyncTCP @ ^3.2.15 ``` ## Important recommendations diff --git a/library.json b/library.json index 6082db7..1ff0814 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "AsyncTCP", - "version": "3.2.14", + "version": "3.2.15", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index 032c0c5..a436126 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=Async TCP includes=AsyncTCP.h -version=3.2.14 +version=3.2.15 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 4d21cbe..ab2609f 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.2.14" +#define ASYNCTCP_VERSION "3.2.15" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 2 -#define ASYNCTCP_VERSION_REVISION 14 +#define ASYNCTCP_VERSION_REVISION 15 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From afa162b73ad9a53b8186d3a32ac589cb83edaa5d Mon Sep 17 00:00:00 2001 From: Emil Muratov Date: Fri, 13 Dec 2024 16:32:15 +0900 Subject: [PATCH 133/150] Coalesce poll events on queue eviction Refer: https://github.com/mathieucarbou/ESPAsyncWebServer/discussions/165 Let's try to coalesce two (or more) consecutive poll events into one this usually happens with poor implemented user-callbacks that are runs too long and makes poll events to stack in the queue if consecutive user callback for a same connection runs longer that poll time then it will fill the queue with events until it deadlocks. This is a workaround to mitigate such poor designs and won't let other events/connections to starve the task time. It won't be effective if user would run multiple simultaneous long running callbacks due to message interleaving. todo: implement some kind of fair dequeing or (better) simply punish user for a bad designed callbacks by resetting hog connections --- src/AsyncTCP.cpp | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 18cd24a..ae79d4c 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -61,6 +61,12 @@ extern "C" { #define INVALID_CLOSED_SLOT -1 +/* + TCP poll interval is specified in terms of the TCP coarse timer interval, which is called twice a second + https://github.com/espressif/esp-lwip/blob/2acf959a2bb559313cd2bf9306c24612ba3d0e19/src/core/tcp.c#L1895 +*/ +#define CONFIG_ASYNC_TCP_POLL_TIMER 1 + /* * TCP/IP Event Task * */ @@ -148,7 +154,34 @@ static inline bool _prepend_async_event(lwip_event_packet_t** e) { } static inline bool _get_async_event(lwip_event_packet_t** e) { - return _async_queue && xQueueReceive(_async_queue, e, portMAX_DELAY) == pdPASS; + if (!_async_queue) { + return false; + } + + if (xQueueReceive(_async_queue, e, portMAX_DELAY) != pdPASS) + return false; + + /* + Let's try to coalesce two (or more) consecutive poll events into one + this usually happens with poor implemented user-callbacks that are runs too long and makes poll events to stack in the queue + if consecutive user callback for a same connection runs longer that poll time then it will fill the queue with events until it deadlocks. + This is a workaround to mitigate such poor designs and won't let other events/connections to starve the task time. + It won't be effective if user would run multiple simultaneous long running callbacks due to message interleaving. + todo: implement some kind of fair dequeing or (better) simply punish user for a bad designed callbacks by resetting hog connections + */ + lwip_event_packet_t* next_pkt = NULL; + while (xQueuePeek(_async_queue, &next_pkt, 0) == pdPASS){ + if (next_pkt->arg == (*e)->arg && next_pkt->event == LWIP_TCP_POLL && (*e)->event == LWIP_TCP_POLL){ + if (xQueueReceive(_async_queue, &next_pkt, 0) == pdPASS){ + free(next_pkt); + next_pkt = NULL; + log_w("coalescing polls, async callback might be too slow!"); + } else + return true; + } else + return true; + } + return true; } static bool _remove_events_with_arg(void* arg) { @@ -311,6 +344,7 @@ static int8_t _tcp_connected(void* arg, tcp_pcb* pcb, int8_t err) { static int8_t _tcp_poll(void* arg, struct tcp_pcb* pcb) { // throttle polling events queing when event queue is getting filled up, let it handle _onack's + //log_d("qs:%u", uxQueueMessagesWaiting(_async_queue)); if (uxQueueMessagesWaiting(_async_queue) > (rand() % CONFIG_ASYNC_TCP_QUEUE_SIZE / 2 + CONFIG_ASYNC_TCP_QUEUE_SIZE / 4)) { log_d("throttling"); return ERR_OK; @@ -612,7 +646,7 @@ AsyncClient::AsyncClient(tcp_pcb* pcb) tcp_recv(_pcb, &_tcp_recv); tcp_sent(_pcb, &_tcp_sent); tcp_err(_pcb, &_tcp_error); - tcp_poll(_pcb, &_tcp_poll, 1); + tcp_poll(_pcb, &_tcp_poll, CONFIG_ASYNC_TCP_POLL_TIMER); if (!_allocate_closed_slot()) { _close(); } From 80b2733de54c06e367389b930ad0d257bfbb4680 Mon Sep 17 00:00:00 2001 From: Emil Muratov Date: Sat, 14 Dec 2024 23:32:26 +0900 Subject: [PATCH 134/150] make _async_service_task's watchdog constantly watching with periodic feed --- src/AsyncTCP.cpp | 29 ++++++++++++++++++----------- src/AsyncTCP.h | 7 +++++-- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index ae79d4c..00ac960 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -158,8 +158,14 @@ static inline bool _get_async_event(lwip_event_packet_t** e) { return false; } +#if CONFIG_ASYNC_TCP_USE_WDT + // need to return periodically to feed the dog + if (xQueueReceive(_async_queue, e, pdMS_TO_TICKS(1000)) != pdPASS) + return false; +#else if (xQueueReceive(_async_queue, e, portMAX_DELAY) != pdPASS) return false; +#endif /* Let's try to coalesce two (or more) consecutive poll events into one @@ -175,7 +181,7 @@ static inline bool _get_async_event(lwip_event_packet_t** e) { if (xQueueReceive(_async_queue, &next_pkt, 0) == pdPASS){ free(next_pkt); next_pkt = NULL; - log_w("coalescing polls, async callback might be too slow!"); + log_d("coalescing polls, async callback might be too slow!"); } else return true; } else @@ -255,22 +261,23 @@ static void _handle_async_event(lwip_event_packet_t* e) { } static void _async_service_task(void* pvParameters) { +#if CONFIG_ASYNC_TCP_USE_WDT + if (esp_task_wdt_add(NULL) != ESP_OK) { + log_w("Failed to add async task to WDT"); + } +#endif lwip_event_packet_t* packet = NULL; for (;;) { if (_get_async_event(&packet)) { -#if CONFIG_ASYNC_TCP_USE_WDT - if (esp_task_wdt_add(NULL) != ESP_OK) { - log_e("Failed to add async task to WDT"); - } -#endif _handle_async_event(packet); -#if CONFIG_ASYNC_TCP_USE_WDT - if (esp_task_wdt_delete(NULL) != ESP_OK) { - log_e("Failed to remove loop task from WDT"); - } -#endif } +#if CONFIG_ASYNC_TCP_USE_WDT + esp_task_wdt_reset(); +#endif } +#if CONFIG_ASYNC_TCP_USE_WDT + esp_task_wdt_delete(NULL); +#endif vTaskDelete(NULL); _async_service_task_handle = NULL; } diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index ab2609f..2df01c7 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -48,13 +48,16 @@ extern "C" { #include } #define CONFIG_ASYNC_TCP_RUNNING_CORE -1 // any available core - #define CONFIG_ASYNC_TCP_USE_WDT 0 #endif // If core is not defined, then we are running in Arduino or PIO #ifndef CONFIG_ASYNC_TCP_RUNNING_CORE #define CONFIG_ASYNC_TCP_RUNNING_CORE -1 // any available core - #define CONFIG_ASYNC_TCP_USE_WDT 1 // if enabled, adds between 33us and 200us per event +#endif + +// guard AsyncTCP task with watchdog +#ifndef CONFIG_ASYNC_TCP_USE_WDT + #define CONFIG_ASYNC_TCP_USE_WDT 1 #endif #ifndef CONFIG_ASYNC_TCP_STACK_SIZE From 7bfbb947d0a412559e213fdf321184b483e98597 Mon Sep 17 00:00:00 2001 From: Emil Muratov Date: Sun, 15 Dec 2024 12:04:52 +0900 Subject: [PATCH 135/150] queue deadlock and congestion aviodance - do not let `_remove_events_with_arg()` call to block on queue pertubation, otherwise it could deadlock - in any case do not block on adding LWIP_TCP_POLL event to the queue, it does not make much sense anyway due to poll events are repetitive - `_get_async_event()` will discard LWIP_TCP_POLL events when q gets filled up this will work in combination with throttling poll events when adding to the queue Poor designed apps and multiple parallel connections could flood the queue with interleaved poll events that can't be properly throttled or coalesced. So we can discard it in the eviction task after coalescing It will work in this way: - queue is up to 1/4 full - all events are entering the queue and serviced - queue is from 1/4 and up to 3/4 full - new poll events are throttled on enqueue with linear probability - queue is from 3/4 up to full top - all new poll events are ignored on enqueue and existing poll events already in the queue are discarded on eviction with linear probability giving away priority for all other events to be serviced. It is expected that on a new poll timer connection polls could reenter the queue --- src/AsyncTCP.cpp | 67 +++++++++++++++++------------ src/AsyncTCP.h | 109 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 126 insertions(+), 50 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 00ac960..722da63 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -145,12 +145,12 @@ static inline bool _init_async_event_queue() { return true; } -static inline bool _send_async_event(lwip_event_packet_t** e) { - return _async_queue && xQueueSend(_async_queue, e, portMAX_DELAY) == pdPASS; +static inline bool _send_async_event(lwip_event_packet_t** e, TickType_t wait = portMAX_DELAY) { + return _async_queue && xQueueSend(_async_queue, e, wait) == pdPASS; } -static inline bool _prepend_async_event(lwip_event_packet_t** e) { - return _async_queue && xQueueSendToFront(_async_queue, e, portMAX_DELAY) == pdPASS; +static inline bool _prepend_async_event(lwip_event_packet_t** e, TickType_t wait = portMAX_DELAY) { + return _async_queue && xQueueSendToFront(_async_queue, e, wait) == pdPASS; } static inline bool _get_async_event(lwip_event_packet_t** e) { @@ -167,6 +167,9 @@ static inline bool _get_async_event(lwip_event_packet_t** e) { return false; #endif + if ((*e)->event != LWIP_TCP_POLL) + return true; + /* Let's try to coalesce two (or more) consecutive poll events into one this usually happens with poor implemented user-callbacks that are runs too long and makes poll events to stack in the queue @@ -177,16 +180,31 @@ static inline bool _get_async_event(lwip_event_packet_t** e) { */ lwip_event_packet_t* next_pkt = NULL; while (xQueuePeek(_async_queue, &next_pkt, 0) == pdPASS){ - if (next_pkt->arg == (*e)->arg && next_pkt->event == LWIP_TCP_POLL && (*e)->event == LWIP_TCP_POLL){ + if (next_pkt->arg == (*e)->arg && next_pkt->event == LWIP_TCP_POLL){ if (xQueueReceive(_async_queue, &next_pkt, 0) == pdPASS){ free(next_pkt); next_pkt = NULL; - log_d("coalescing polls, async callback might be too slow!"); - } else - return true; - } else - return true; + log_d("coalescing polls, network congestion or async callbacks might be too slow!"); + continue; + } + } else { + /* + poor designed apps using asynctcp without proper dataflow control could flood the queue with interleaved pool/ack events. + We can try to mitigate it by discarding poll events when queue grows too much. + Let's discard poll events using linear probability curve starting from 3/4 of queue length + Poll events are periodic and connection could get another chance next time + */ + if (uxQueueMessagesWaiting(_async_queue) > (rand() % CONFIG_ASYNC_TCP_QUEUE_SIZE / 4 + CONFIG_ASYNC_TCP_QUEUE_SIZE * 3 / 4)) { + free(next_pkt); + next_pkt = NULL; + log_d("discarding poll due to queue congestion"); + // evict next event from a queue + return _get_async_event(e); + } + } + return true; } + // last resort return return true; } @@ -206,8 +224,11 @@ static bool _remove_events_with_arg(void* arg) { if ((int)first_packet->arg == (int)arg) { free(first_packet); first_packet = NULL; - // return first packet to the back of the queue - } else if (xQueueSend(_async_queue, &first_packet, portMAX_DELAY) != pdPASS) { + + // try to return first packet to the back of the queue + } else if (xQueueSend(_async_queue, &first_packet, 0) != pdPASS) { + // we can't wait here if queue is full, because this call has been done from the only consumer task of this queue + // otherwise it would deadlock, we have to discard the event return false; } } @@ -219,7 +240,9 @@ static bool _remove_events_with_arg(void* arg) { if ((int)packet->arg == (int)arg) { free(packet); packet = NULL; - } else if (xQueueSend(_async_queue, &packet, portMAX_DELAY) != pdPASS) { + } else if (xQueueSend(_async_queue, &packet, 0) != pdPASS) { + // we can't wait here if queue is full, because this call has been done from the only consumer task of this queue + // otherwise it would deadlock, we have to discard the event return false; } } @@ -362,7 +385,8 @@ static int8_t _tcp_poll(void* arg, struct tcp_pcb* pcb) { e->event = LWIP_TCP_POLL; e->arg = arg; e->poll.pcb = pcb; - if (!_send_async_event(&e)) { + // poll events are not critical 'cause those are repetitive, so we may not wait the queue in any case + if (!_send_async_event(&e, 0)) { free((void*)(e)); } return ERR_OK; @@ -684,7 +708,7 @@ AsyncClient& AsyncClient::operator=(const AsyncClient& other) { tcp_recv(_pcb, &_tcp_recv); tcp_sent(_pcb, &_tcp_sent); tcp_err(_pcb, &_tcp_error); - tcp_poll(_pcb, &_tcp_poll, 1); + tcp_poll(_pcb, &_tcp_poll, CONFIG_ASYNC_TCP_POLL_TIMER); } return *this; } @@ -782,7 +806,7 @@ bool AsyncClient::_connect(ip_addr_t addr, uint16_t port) { tcp_err(pcb, &_tcp_error); tcp_recv(pcb, &_tcp_recv); tcp_sent(pcb, &_tcp_sent); - tcp_poll(pcb, &_tcp_poll, 1); + tcp_poll(pcb, &_tcp_poll, CONFIG_ASYNC_TCP_POLL_TIMER); TCP_MUTEX_UNLOCK(); esp_err_t err = _tcp_connect(pcb, _closed_slot, &addr, port, (tcp_connected_fn)&_tcp_connected); @@ -1131,10 +1155,6 @@ void AsyncClient::_dns_found(struct ip_addr* ipaddr) { * Public Helper Methods * */ -void AsyncClient::stop() { - close(false); -} - bool AsyncClient::free() { if (!_pcb) { return true; @@ -1145,13 +1165,6 @@ bool AsyncClient::free() { return false; } -size_t AsyncClient::write(const char* data) { - if (data == NULL) { - return 0; - } - return write(data, strlen(data)); -} - size_t AsyncClient::write(const char* data, size_t size, uint8_t apiflags) { size_t will_send = add(data, size, apiflags); if (!will_send || !send()) { diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 2df01c7..17e3db9 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -109,34 +109,86 @@ class AsyncClient { bool connect(const IPv6Address& ip, uint16_t port); #endif bool connect(const char* host, uint16_t port); + /** + * @brief close connection + * + * @param now - ignored + */ void close(bool now = false); - void stop(); + // same as close() + void stop(){ close(false); }; int8_t abort(); bool free(); - bool canSend(); // ack is not pending - size_t space(); // space available in the TCP window - size_t add(const char* data, size_t size, uint8_t apiflags = ASYNC_WRITE_FLAG_COPY); // add for sending - bool send(); // send all data added with the method above + // ack is not pending + bool canSend(); + // TCP buffer space available + size_t space(); - // write equals add()+send() - size_t write(const char* data); - size_t write(const char* data, size_t size, uint8_t apiflags = ASYNC_WRITE_FLAG_COPY); // only when canSend() == true + /** + * @brief add data to be send (but do not send yet) + * @note add() would call lwip's tcp_write() + By default apiflags=ASYNC_WRITE_FLAG_COPY + You could try to use apiflags with this flag unset to pass data by reference and avoid copy to socket buffer, + but looks like it does not work for Arduino's lwip in ESP32/IDF at least + it is enforced in https://github.com/espressif/esp-lwip/blob/0606eed9d8b98a797514fdf6eabb4daf1c8c8cd9/src/core/tcp_out.c#L422C5-L422C30 + if LWIP_NETIF_TX_SINGLE_PBUF is set, and it is set indeed in IDF + https://github.com/espressif/esp-idf/blob/a0f798cfc4bbd624aab52b2c194d219e242d80c1/components/lwip/port/include/lwipopts.h#L744 + * + * @param data + * @param size + * @param apiflags + * @return size_t amount of data that has been copied + */ + size_t add(const char* data, size_t size, uint8_t apiflags = ASYNC_WRITE_FLAG_COPY); + + /** + * @brief send data previously add()'ed + * + * @return true on success + * @return false on error + */ + bool send(); + + /** + * @brief add and enqueue data for sending + * @note it is same as add() + send() + * @note only make sense when canSend() == true + * + * @param data + * @param size + * @param apiflags + * @return size_t + */ + size_t write(const char* data, size_t size, uint8_t apiflags = ASYNC_WRITE_FLAG_COPY); + + /** + * @brief add and enque data for sending + * @note treats data as null-terminated string + * + * @param data + * @return size_t + */ + size_t write(const char* data){ return data == NULL ? 0 : write(data, strlen(data)); }; uint8_t state(); bool connecting(); bool connected(); bool disconnecting(); bool disconnected(); - bool freeable(); // disconnected or disconnecting + + // disconnected or disconnecting + bool freeable(); uint16_t getMss(); uint32_t getRxTimeout(); - void setRxTimeout(uint32_t timeout); // no RX data timeout for the connection in seconds + // no RX data timeout for the connection in seconds + void setRxTimeout(uint32_t timeout); uint32_t getAckTimeout(); - void setAckTimeout(uint32_t timeout); // no ACK timeout for the last sent packet in milliseconds + // no ACK timeout for the last sent packet in milliseconds + void setAckTimeout(uint32_t timeout); void setNoDelay(bool nodelay); bool getNoDelay(); @@ -165,23 +217,34 @@ class AsyncClient { IPAddress localIP(); uint16_t localPort(); - void onConnect(AcConnectHandler cb, void* arg = 0); // on successful connect - void onDisconnect(AcConnectHandler cb, void* arg = 0); // disconnected - void onAck(AcAckHandler cb, void* arg = 0); // ack received - void onError(AcErrorHandler cb, void* arg = 0); // unsuccessful connect or error - void onData(AcDataHandler cb, void* arg = 0); // data received (called if onPacket is not used) - void onPacket(AcPacketHandler cb, void* arg = 0); // data received - void onTimeout(AcTimeoutHandler cb, void* arg = 0); // ack timeout - void onPoll(AcConnectHandler cb, void* arg = 0); // every 125ms when connected + // set callback - on successful connect + void onConnect(AcConnectHandler cb, void* arg = 0); + // set callback - disconnected + void onDisconnect(AcConnectHandler cb, void* arg = 0); + // set callback - ack received + void onAck(AcAckHandler cb, void* arg = 0); + // set callback - unsuccessful connect or error + void onError(AcErrorHandler cb, void* arg = 0); + // set callback - data received (called if onPacket is not used) + void onData(AcDataHandler cb, void* arg = 0); + // set callback - data received + void onPacket(AcPacketHandler cb, void* arg = 0); + // set callback - ack timeout + void onTimeout(AcTimeoutHandler cb, void* arg = 0); + // set callback - every 125ms when connected + void onPoll(AcConnectHandler cb, void* arg = 0); - void ackPacket(struct pbuf* pb); // ack pbuf from onPacket - size_t ack(size_t len); // ack data that you have not acked using the method below - void ackLater() { _ack_pcb = false; } // will not ack the current packet. Call from onData + // ack pbuf from onPacket + void ackPacket(struct pbuf* pb); + // ack data that you have not acked using the method below + size_t ack(size_t len); + // will not ack the current packet. Call from onData + void ackLater() { _ack_pcb = false; } const char* errorToString(int8_t error); const char* stateToString(); - // Do not use any of the functions below! + // internal callbacks - Do NOT call any of the functions below in user code! static int8_t _s_poll(void* arg, struct tcp_pcb* tpcb); static int8_t _s_recv(void* arg, struct tcp_pcb* tpcb, struct pbuf* pb, int8_t err); static int8_t _s_fin(void* arg, struct tcp_pcb* tpcb, int8_t err); From 269124956a06f5c7ae121d092d70db6d136b5fa0 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 15 Dec 2024 16:51:34 +0100 Subject: [PATCH 136/150] Applying clang formatting --- src/AsyncTCP.cpp | 12 ++++++------ src/AsyncTCP.h | 34 +++++++++++++++++----------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 722da63..12486a0 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -65,7 +65,7 @@ extern "C" { TCP poll interval is specified in terms of the TCP coarse timer interval, which is called twice a second https://github.com/espressif/esp-lwip/blob/2acf959a2bb559313cd2bf9306c24612ba3d0e19/src/core/tcp.c#L1895 */ -#define CONFIG_ASYNC_TCP_POLL_TIMER 1 +#define CONFIG_ASYNC_TCP_POLL_TIMER 1 /* * TCP/IP Event Task @@ -179,9 +179,9 @@ static inline bool _get_async_event(lwip_event_packet_t** e) { todo: implement some kind of fair dequeing or (better) simply punish user for a bad designed callbacks by resetting hog connections */ lwip_event_packet_t* next_pkt = NULL; - while (xQueuePeek(_async_queue, &next_pkt, 0) == pdPASS){ - if (next_pkt->arg == (*e)->arg && next_pkt->event == LWIP_TCP_POLL){ - if (xQueueReceive(_async_queue, &next_pkt, 0) == pdPASS){ + while (xQueuePeek(_async_queue, &next_pkt, 0) == pdPASS) { + if (next_pkt->arg == (*e)->arg && next_pkt->event == LWIP_TCP_POLL) { + if (xQueueReceive(_async_queue, &next_pkt, 0) == pdPASS) { free(next_pkt); next_pkt = NULL; log_d("coalescing polls, network congestion or async callbacks might be too slow!"); @@ -225,7 +225,7 @@ static bool _remove_events_with_arg(void* arg) { free(first_packet); first_packet = NULL; - // try to return first packet to the back of the queue + // try to return first packet to the back of the queue } else if (xQueueSend(_async_queue, &first_packet, 0) != pdPASS) { // we can't wait here if queue is full, because this call has been done from the only consumer task of this queue // otherwise it would deadlock, we have to discard the event @@ -374,7 +374,7 @@ static int8_t _tcp_connected(void* arg, tcp_pcb* pcb, int8_t err) { static int8_t _tcp_poll(void* arg, struct tcp_pcb* pcb) { // throttle polling events queing when event queue is getting filled up, let it handle _onack's - //log_d("qs:%u", uxQueueMessagesWaiting(_async_queue)); + // log_d("qs:%u", uxQueueMessagesWaiting(_async_queue)); if (uxQueueMessagesWaiting(_async_queue) > (rand() % CONFIG_ASYNC_TCP_QUEUE_SIZE / 2 + CONFIG_ASYNC_TCP_QUEUE_SIZE / 4)) { log_d("throttling"); return ERR_OK; diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 17e3db9..ee81ff5 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -57,7 +57,7 @@ extern "C" { // guard AsyncTCP task with watchdog #ifndef CONFIG_ASYNC_TCP_USE_WDT - #define CONFIG_ASYNC_TCP_USE_WDT 1 + #define CONFIG_ASYNC_TCP_USE_WDT 1 #endif #ifndef CONFIG_ASYNC_TCP_STACK_SIZE @@ -111,12 +111,12 @@ class AsyncClient { bool connect(const char* host, uint16_t port); /** * @brief close connection - * + * * @param now - ignored */ void close(bool now = false); // same as close() - void stop(){ close(false); }; + void stop() { close(false); }; int8_t abort(); bool free(); @@ -134,17 +134,17 @@ class AsyncClient { it is enforced in https://github.com/espressif/esp-lwip/blob/0606eed9d8b98a797514fdf6eabb4daf1c8c8cd9/src/core/tcp_out.c#L422C5-L422C30 if LWIP_NETIF_TX_SINGLE_PBUF is set, and it is set indeed in IDF https://github.com/espressif/esp-idf/blob/a0f798cfc4bbd624aab52b2c194d219e242d80c1/components/lwip/port/include/lwipopts.h#L744 - * - * @param data - * @param size - * @param apiflags + * + * @param data + * @param size + * @param apiflags * @return size_t amount of data that has been copied */ size_t add(const char* data, size_t size, uint8_t apiflags = ASYNC_WRITE_FLAG_COPY); /** * @brief send data previously add()'ed - * + * * @return true on success * @return false on error */ @@ -154,22 +154,22 @@ class AsyncClient { * @brief add and enqueue data for sending * @note it is same as add() + send() * @note only make sense when canSend() == true - * - * @param data - * @param size - * @param apiflags - * @return size_t + * + * @param data + * @param size + * @param apiflags + * @return size_t */ size_t write(const char* data, size_t size, uint8_t apiflags = ASYNC_WRITE_FLAG_COPY); /** * @brief add and enque data for sending * @note treats data as null-terminated string - * - * @param data - * @return size_t + * + * @param data + * @return size_t */ - size_t write(const char* data){ return data == NULL ? 0 : write(data, strlen(data)); }; + size_t write(const char* data) { return data == NULL ? 0 : write(data, strlen(data)); }; uint8_t state(); bool connecting(); From 1ee08d0a1ef6be2dc6793e801c7b73b4c5c57a6f Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 15 Dec 2024 17:00:32 +0100 Subject: [PATCH 137/150] update example --- examples/Client/Client.ino | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/Client/Client.ino b/examples/Client/Client.ino index 20d1bcf..202edb3 100644 --- a/examples/Client/Client.ino +++ b/examples/Client/Client.ino @@ -2,14 +2,14 @@ #include #include -// #define HOST "homeassistant.local" -// #define PORT 8123 - -// #define HOST "www.google.com" -// #define PORT 80 - +// Run a server at the root of the project with: +// > python3 -m http.server 3333 +// Now you can open a browser and test it works by visiting http://192.168.125.122:3333/ or http://192.168.125.122:3333/README.md #define HOST "192.168.125.122" -#define PORT 4000 +#define PORT 3333 + +// WiFi SSID to connect to +#define WIFI_SSID "IoT" // 16 slots on esp32 (CONFIG_LWIP_MAX_ACTIVE_TCP) #define MAX_CLIENTS CONFIG_LWIP_MAX_ACTIVE_TCP @@ -48,7 +48,7 @@ void makeRequest() { // Serial.printf("** data received by client: %" PRIu16 ": len=%u\n", client->localPort(), len); }); - client->write("GET / HTTP/1.1\r\nHost: " HOST "\r\nUser-Agent: ESP\r\nConnection: close\r\n\r\n"); + client->write("GET /README.md HTTP/1.1\r\nHost: " HOST "\r\nUser-Agent: ESP\r\nConnection: close\r\n\r\n"); }); if (client->connect(HOST, PORT)) { @@ -63,7 +63,7 @@ void setup() { continue; WiFi.mode(WIFI_STA); - WiFi.begin("IoT"); + WiFi.begin(WIFI_SSID); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); From a7c2468f542a61823469f0f5b64d61b0654d9f54 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 15 Dec 2024 17:00:32 +0100 Subject: [PATCH 138/150] update example --- examples/Client/Client.ino | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/Client/Client.ino b/examples/Client/Client.ino index 20d1bcf..202edb3 100644 --- a/examples/Client/Client.ino +++ b/examples/Client/Client.ino @@ -2,14 +2,14 @@ #include #include -// #define HOST "homeassistant.local" -// #define PORT 8123 - -// #define HOST "www.google.com" -// #define PORT 80 - +// Run a server at the root of the project with: +// > python3 -m http.server 3333 +// Now you can open a browser and test it works by visiting http://192.168.125.122:3333/ or http://192.168.125.122:3333/README.md #define HOST "192.168.125.122" -#define PORT 4000 +#define PORT 3333 + +// WiFi SSID to connect to +#define WIFI_SSID "IoT" // 16 slots on esp32 (CONFIG_LWIP_MAX_ACTIVE_TCP) #define MAX_CLIENTS CONFIG_LWIP_MAX_ACTIVE_TCP @@ -48,7 +48,7 @@ void makeRequest() { // Serial.printf("** data received by client: %" PRIu16 ": len=%u\n", client->localPort(), len); }); - client->write("GET / HTTP/1.1\r\nHost: " HOST "\r\nUser-Agent: ESP\r\nConnection: close\r\n\r\n"); + client->write("GET /README.md HTTP/1.1\r\nHost: " HOST "\r\nUser-Agent: ESP\r\nConnection: close\r\n\r\n"); }); if (client->connect(HOST, PORT)) { @@ -63,7 +63,7 @@ void setup() { continue; WiFi.mode(WIFI_STA); - WiFi.begin("IoT"); + WiFi.begin(WIFI_SSID); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); From c5af87aa55eefe7e9b461635ec46917b8245d125 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 15 Dec 2024 17:07:41 +0100 Subject: [PATCH 139/150] update example --- examples/Client/Client.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Client/Client.ino b/examples/Client/Client.ino index 202edb3..609af6d 100644 --- a/examples/Client/Client.ino +++ b/examples/Client/Client.ino @@ -45,7 +45,7 @@ void makeRequest() { }); client->onData([](void* arg, AsyncClient* client, void* data, size_t len) { - // Serial.printf("** data received by client: %" PRIu16 ": len=%u\n", client->localPort(), len); + Serial.printf("** data received by client: %" PRIu16 ": len=%u\n", client->localPort(), len); }); client->write("GET /README.md HTTP/1.1\r\nHost: " HOST "\r\nUser-Agent: ESP\r\nConnection: close\r\n\r\n"); From c10ba6b1c7815650a76cf198e8705b1b49b5b499 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 15 Dec 2024 17:07:41 +0100 Subject: [PATCH 140/150] update example --- examples/Client/Client.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Client/Client.ino b/examples/Client/Client.ino index 202edb3..609af6d 100644 --- a/examples/Client/Client.ino +++ b/examples/Client/Client.ino @@ -45,7 +45,7 @@ void makeRequest() { }); client->onData([](void* arg, AsyncClient* client, void* data, size_t len) { - // Serial.printf("** data received by client: %" PRIu16 ": len=%u\n", client->localPort(), len); + Serial.printf("** data received by client: %" PRIu16 ": len=%u\n", client->localPort(), len); }); client->write("GET /README.md HTTP/1.1\r\nHost: " HOST "\r\nUser-Agent: ESP\r\nConnection: close\r\n\r\n"); From b2f4477d47e00a3c1efa797856287f480a8bd9d1 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 15 Dec 2024 18:17:42 +0100 Subject: [PATCH 141/150] v3.3.0 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f64b62b..ef4fed4 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ The base classes on which everything else is built. They expose all possible sce ## Coordinates ``` -mathieucarbou/AsyncTCP @ ^3.2.15 +mathieucarbou/AsyncTCP @ ^3.3.0 ``` ## Important recommendations diff --git a/library.json b/library.json index 1ff0814..0b97aa6 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "AsyncTCP", - "version": "3.2.15", + "version": "3.3.0", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index a436126..94b8ee2 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=Async TCP includes=AsyncTCP.h -version=3.2.15 +version=3.3.0 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index ee81ff5..09633e7 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.2.15" +#define ASYNCTCP_VERSION "3.3.0" #define ASYNCTCP_VERSION_MAJOR 3 -#define ASYNCTCP_VERSION_MINOR 2 -#define ASYNCTCP_VERSION_REVISION 15 +#define ASYNCTCP_VERSION_MINOR 3 +#define ASYNCTCP_VERSION_REVISION 0 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From 611559e59d8ba30175d9f29308be36e8e894ce96 Mon Sep 17 00:00:00 2001 From: Emil Muratov Date: Mon, 16 Dec 2024 23:00:19 +0900 Subject: [PATCH 142/150] fix: _remove_events_with_arg() might probably leak mem on queue overflow it must free message's mem if failed to requeue the pointer --- src/AsyncTCP.cpp | 54 +++++++++++++++++++++++++++++------------------- src/AsyncTCP.h | 2 +- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 12486a0..0761144 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -187,35 +187,42 @@ static inline bool _get_async_event(lwip_event_packet_t** e) { log_d("coalescing polls, network congestion or async callbacks might be too slow!"); continue; } - } else { - /* - poor designed apps using asynctcp without proper dataflow control could flood the queue with interleaved pool/ack events. - We can try to mitigate it by discarding poll events when queue grows too much. - Let's discard poll events using linear probability curve starting from 3/4 of queue length - Poll events are periodic and connection could get another chance next time - */ - if (uxQueueMessagesWaiting(_async_queue) > (rand() % CONFIG_ASYNC_TCP_QUEUE_SIZE / 4 + CONFIG_ASYNC_TCP_QUEUE_SIZE * 3 / 4)) { - free(next_pkt); - next_pkt = NULL; - log_d("discarding poll due to queue congestion"); - // evict next event from a queue - return _get_async_event(e); - } } - return true; + + // quit while loop if next event can't be discarded + break; } + + /* + now we have to decide if to proceed with poll callback handler or discard it? + poor designed apps using asynctcp without proper dataflow control could flood the queue with interleaved pool/ack events. + I.e. on each poll app would try to generate more data to send, which in turn results in additional ack event triggering chain effect + for long connections. Or poll callback could take long time starving other connections. Anyway our goal is to keep the queue length + grows under control (if possible) and poll events are the safest to discard. + Let's discard poll events processing using linear-increasing probability curve when queue size grows over 3/4 + Poll events are periodic and connection could get another chance next time + */ + if (uxQueueMessagesWaiting(_async_queue) > (rand() % CONFIG_ASYNC_TCP_QUEUE_SIZE / 4 + CONFIG_ASYNC_TCP_QUEUE_SIZE * 3 / 4)) { + free(*e); + *e = NULL; + log_d("discarding poll due to queue congestion"); + // evict next event from a queue + return _get_async_event(e); + } + // last resort return return true; } static bool _remove_events_with_arg(void* arg) { - lwip_event_packet_t* first_packet = NULL; - lwip_event_packet_t* packet = NULL; - if (!_async_queue) { return false; } - // figure out which is the first packet so we can keep the order + + lwip_event_packet_t* first_packet = NULL; + lwip_event_packet_t* packet = NULL; + + // figure out which is the first non-matching packet so we can keep the order while (!first_packet) { if (xQueueReceive(_async_queue, &first_packet, 0) != pdPASS) { return false; @@ -224,11 +231,12 @@ static bool _remove_events_with_arg(void* arg) { if ((int)first_packet->arg == (int)arg) { free(first_packet); first_packet = NULL; - - // try to return first packet to the back of the queue } else if (xQueueSend(_async_queue, &first_packet, 0) != pdPASS) { + // try to return first packet to the back of the queue // we can't wait here if queue is full, because this call has been done from the only consumer task of this queue // otherwise it would deadlock, we have to discard the event + free(first_packet); + first_packet = NULL; return false; } } @@ -238,11 +246,15 @@ static bool _remove_events_with_arg(void* arg) { return false; } if ((int)packet->arg == (int)arg) { + // remove matching event free(packet); packet = NULL; + // otherwise try to requeue it } else if (xQueueSend(_async_queue, &packet, 0) != pdPASS) { // we can't wait here if queue is full, because this call has been done from the only consumer task of this queue // otherwise it would deadlock, we have to discard the event + free(packet); + packet = NULL; return false; } } diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 09633e7..fdf347a 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -241,7 +241,7 @@ class AsyncClient { // will not ack the current packet. Call from onData void ackLater() { _ack_pcb = false; } - const char* errorToString(int8_t error); + static const char* errorToString(int8_t error); const char* stateToString(); // internal callbacks - Do NOT call any of the functions below in user code! From 5b9a754c9586e02533fc53104224767b8f3f1d2c Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 16 Dec 2024 21:37:52 +0100 Subject: [PATCH 143/150] v3.3.1 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ef4fed4..d90814a 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ The base classes on which everything else is built. They expose all possible sce ## Coordinates ``` -mathieucarbou/AsyncTCP @ ^3.3.0 +mathieucarbou/AsyncTCP @ ^3.3.1 ``` ## Important recommendations diff --git a/library.json b/library.json index 0b97aa6..5d6e228 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "AsyncTCP", - "version": "3.3.0", + "version": "3.3.1", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index 94b8ee2..dd945f8 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=Async TCP includes=AsyncTCP.h -version=3.3.0 +version=3.3.1 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index fdf347a..6d69a91 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.3.0" +#define ASYNCTCP_VERSION "3.3.1" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 3 -#define ASYNCTCP_VERSION_REVISION 0 +#define ASYNCTCP_VERSION_REVISION 1 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From 22a6988a280f6645efe3dc26cf45258ed5ee5bd2 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 16 Dec 2024 23:54:32 +0100 Subject: [PATCH 144/150] pioarduino 53.03.10 --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index ec65a36..63e01c7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -26,7 +26,7 @@ platform = espressif32@6.9.0 platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip [env:arduino-310] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc3/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10/platform-espressif32.zip ; CI @@ -39,5 +39,5 @@ platform = https://github.com/pioarduino/platform-espressif32/releases/download/ board = ${sysenv.PIO_BOARD} [env:ci-arduino-310] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc3/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10/platform-espressif32.zip board = ${sysenv.PIO_BOARD} From 6783ae1068289bc653c18f77a8764247507b4ac7 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 7 Jan 2025 15:42:53 -0500 Subject: [PATCH 145/150] Remove libCompatMode from library.json Specifying libCompatMode in library.json prevents projects from overriding the library compatibility mode as needed. This prevents the library from being used in builds where Arduino is a component to ESP-IDF. --- library.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/library.json b/library.json index 5d6e228..b6032d4 100644 --- a/library.json +++ b/library.json @@ -22,9 +22,6 @@ "espressif32", "libretiny" ], - "build": { - "libCompatMode": 2 - }, "export": { "include": [ "examples", @@ -35,4 +32,4 @@ "README.md" ] } -} \ No newline at end of file +} From c3584edf815eec8101ddc23413164992e5220868 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 7 Jan 2025 22:09:31 +0100 Subject: [PATCH 146/150] v3.3.2 --- README.md | 2 +- library.json | 2 +- library.properties | 2 +- src/AsyncTCP.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d90814a..5e14ef0 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ The base classes on which everything else is built. They expose all possible sce ## Coordinates ``` -mathieucarbou/AsyncTCP @ ^3.3.1 +mathieucarbou/AsyncTCP @ ^3.3.2 ``` ## Important recommendations diff --git a/library.json b/library.json index b6032d4..1e5f045 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "AsyncTCP", - "version": "3.3.1", + "version": "3.3.2", "description": "Asynchronous TCP Library for ESP32", "keywords": "async,tcp", "repository": { diff --git a/library.properties b/library.properties index dd945f8..23e10ab 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=Async TCP includes=AsyncTCP.h -version=3.3.1 +version=3.3.2 author=Me-No-Dev maintainer=Mathieu Carbou sentence=Async TCP Library for ESP32 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 6d69a91..762b1b3 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -22,10 +22,10 @@ #ifndef ASYNCTCP_H_ #define ASYNCTCP_H_ -#define ASYNCTCP_VERSION "3.3.1" +#define ASYNCTCP_VERSION "3.3.2" #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 3 -#define ASYNCTCP_VERSION_REVISION 1 +#define ASYNCTCP_VERSION_REVISION 2 #define ASYNCTCP_FORK_mathieucarbou #include "IPAddress.h" From bb19551d6560af10859f037967e9b2a9e815affc Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 9 Jan 2025 15:18:18 +0100 Subject: [PATCH 147/150] Arduino core 3.1.1 based on IDF 5.3.2.241224 --- .github/workflows/ci.yml | 10 +++++----- platformio.ini | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fd79c93..2e4ae11 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,15 +59,15 @@ jobs: - env: ci-arduino-3 board: esp32-c6-devkitc-1 - - env: ci-arduino-310 + - env: ci-arduino-311 board: esp32dev - - env: ci-arduino-310 + - env: ci-arduino-311 board: esp32-s2-saola-1 - - env: ci-arduino-310 + - env: ci-arduino-311 board: esp32-s3-devkitc-1 - - env: ci-arduino-310 + - env: ci-arduino-311 board: esp32-c3-devkitc-02 - - env: ci-arduino-310 + - env: ci-arduino-311 board: esp32-c6-devkitc-1 steps: diff --git a/platformio.ini b/platformio.ini index 63e01c7..a19908a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,5 +1,5 @@ [platformio] -default_envs = arduino-2, arduino-3, arduino-310 +default_envs = arduino-2, arduino-3, arduino-311 lib_dir = . src_dir = examples/Client @@ -25,8 +25,8 @@ platform = espressif32@6.9.0 [env:arduino-3] platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip -[env:arduino-310] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10/platform-espressif32.zip +[env:arduino-311] +platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.11/platform-espressif32.zip ; CI @@ -38,6 +38,6 @@ board = ${sysenv.PIO_BOARD} platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip board = ${sysenv.PIO_BOARD} -[env:ci-arduino-310] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10/platform-espressif32.zip +[env:ci-arduino-311] +platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.11/platform-espressif32.zip board = ${sysenv.PIO_BOARD} From 4ece183a5c12889d99a606dc3fd53f90b90007e6 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 20 Jan 2025 15:25:05 +0100 Subject: [PATCH 148/150] Prepare move to https://github.com/organizations/ESP32Async --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- README.ESP32Async.md | 62 +++++++++++++++++++++++++++ README.md | 63 +--------------------------- library.json | 16 +++---- library.properties | 7 ++-- src/AsyncTCP.h | 2 +- 6 files changed, 76 insertions(+), 76 deletions(-) create mode 100644 README.ESP32Async.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 8e2c31c..935eb4f 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -9,7 +9,7 @@ assignees: '' **Please make sure to go through the recommendations before opening a bug report:** -[https://github.com/mathieucarbou/AsyncTCP?tab=readme-ov-file#important-recommendations](https://github.com/mathieucarbou/AsyncTCP?tab=readme-ov-file#important-recommendations) +[https://github.com/ESP32Async/AsyncTCP?tab=readme-ov-file#important-recommendations](https://github.com/ESP32Async/AsyncTCP?tab=readme-ov-file#important-recommendations) **Description** diff --git a/README.ESP32Async.md b/README.ESP32Async.md new file mode 100644 index 0000000..f0510fd --- /dev/null +++ b/README.ESP32Async.md @@ -0,0 +1,62 @@ +# AsyncTCP + +[![License: LGPL 3.0](https://img.shields.io/badge/License-LGPL%203.0-yellow.svg)](https://opensource.org/license/lgpl-3-0/) +[![Continuous Integration](https://github.com/ESP32Async/AsyncTCP/actions/workflows/ci.yml/badge.svg)](https://github.com/ESP32Async/AsyncTCP/actions/workflows/ci.yml) +[![PlatformIO Registry](https://badges.registry.platformio.org/packages/ESP32Async/library/AsyncTCP.svg)](https://registry.platformio.org/libraries/ESP32Async/AsyncTCP) + +Discord Server: [https://discord.gg/X7zpGdyUcY](https://discord.gg/X7zpGdyUcY) + +### Async TCP Library for ESP32 Arduino + +This is a fully asynchronous TCP library, aimed at enabling trouble-free, multi-connection network environment for Espressif's ESP32 MCUs. + +This library is the base for [ESPAsyncWebServer](https://github.com/ESP32Async/ESPAsyncWebServer) + +## AsyncClient and AsyncServer + +The base classes on which everything else is built. They expose all possible scenarios, but are really raw and require more skills to use. + +## Changes in this fork + +- Based on [ESPHome fork](https://github.com/esphome/AsyncTCP) + +- `library.properties` for Arduino IDE users +- Add `CONFIG_ASYNC_TCP_MAX_ACK_TIME` +- Add `CONFIG_ASYNC_TCP_PRIORITY` +- Add `CONFIG_ASYNC_TCP_QUEUE_SIZE` +- Add `setKeepAlive()` +- Arduino 3 / ESP-IDF 5 compatibility +- Better CI +- Better example +- Customizable macros +- Fix for "Required to lock TCPIP core functionality". Ref: https://github.com/ESP32Async/AsyncTCP/issues/27 and https://github.com/espressif/arduino-esp32/issues/10526 +- Fix for "ack timeout 4" client disconnects. +- Fix from https://github.com/me-no-dev/AsyncTCP/pull/173 (partially applied) +- Fix from https://github.com/me-no-dev/AsyncTCP/pull/184 +- IPv6 +- LIBRETINY support +- LibreTuya +- Reduce logging of non critical messages +- Use IPADDR6_INIT() macro to set connecting IPv6 address +- xTaskCreateUniversal function + +## Coordinates + +``` +ESP32Async/AsyncTCP @ ^3.3.2 +``` + +## Important recommendations + +Most of the crashes are caused by improper configuration of the library for the project. +Here are some recommendations to avoid them. + +I personally use the following configuration in my projects: + +```c++ + -D CONFIG_ASYNC_TCP_MAX_ACK_TIME=5000 // (keep default) + -D CONFIG_ASYNC_TCP_PRIORITY=10 // (keep default) + -D CONFIG_ASYNC_TCP_QUEUE_SIZE=64 // (keep default) + -D CONFIG_ASYNC_TCP_RUNNING_CORE=1 // force async_tcp task to be on same core as the app (default is core 0) + -D CONFIG_ASYNC_TCP_STACK_SIZE=4096 // reduce the stack size (default is 16K) +``` diff --git a/README.md b/README.md index 5e14ef0..c36f757 100644 --- a/README.md +++ b/README.md @@ -1,62 +1,3 @@ -# AsyncTCP +![https://avatars.githubusercontent.com/u/195753706?s=96&v=4](https://avatars.githubusercontent.com/u/195753706?s=96&v=4) -[![License: LGPL 3.0](https://img.shields.io/badge/License-LGPL%203.0-yellow.svg)](https://opensource.org/license/lgpl-3-0/) -[![Continuous Integration](https://github.com/mathieucarbou/AsyncTCP/actions/workflows/ci.yml/badge.svg)](https://github.com/mathieucarbou/AsyncTCP/actions/workflows/ci.yml) -[![PlatformIO Registry](https://badges.registry.platformio.org/packages/mathieucarbou/library/AsyncTCP.svg)](https://registry.platformio.org/libraries/mathieucarbou/AsyncTCP) - -A fork of the [AsyncTCP](https://github.com/me-no-dev/AsyncTCP) library by [@me-no-dev](https://github.com/me-no-dev). - -### Async TCP Library for ESP32 Arduino - -This is a fully asynchronous TCP library, aimed at enabling trouble-free, multi-connection network environment for Espressif's ESP32 MCUs. - -This library is the base for [ESPAsyncWebServer](https://github.com/mathieucarbou/ESPAsyncWebServer) - -## AsyncClient and AsyncServer - -The base classes on which everything else is built. They expose all possible scenarios, but are really raw and require more skills to use. - -## Changes in this fork - -- Based on [ESPHome fork](https://github.com/esphome/AsyncTCP) - -- `library.properties` for Arduino IDE users -- Add `CONFIG_ASYNC_TCP_MAX_ACK_TIME` -- Add `CONFIG_ASYNC_TCP_PRIORITY` -- Add `CONFIG_ASYNC_TCP_QUEUE_SIZE` -- Add `setKeepAlive()` -- Arduino 3 / ESP-IDF 5 compatibility -- Better CI -- Better example -- Customizable macros -- Fix for "Required to lock TCPIP core functionality". Ref: https://github.com/mathieucarbou/AsyncTCP/issues/27 and https://github.com/espressif/arduino-esp32/issues/10526 -- Fix for "ack timeout 4" client disconnects. -- Fix from https://github.com/me-no-dev/AsyncTCP/pull/173 (partially applied) -- Fix from https://github.com/me-no-dev/AsyncTCP/pull/184 -- IPv6 -- LIBRETINY support -- LibreTuya -- Reduce logging of non critical messages -- Use IPADDR6_INIT() macro to set connecting IPv6 address -- xTaskCreateUniversal function - -## Coordinates - -``` -mathieucarbou/AsyncTCP @ ^3.3.2 -``` - -## Important recommendations - -Most of the crashes are caused by improper configuration of the library for the project. -Here are some recommendations to avoid them. - -I personally use the following configuration in my projects: - -```c++ - -D CONFIG_ASYNC_TCP_MAX_ACK_TIME=5000 // (keep default) - -D CONFIG_ASYNC_TCP_PRIORITY=10 // (keep default) - -D CONFIG_ASYNC_TCP_QUEUE_SIZE=64 // (keep default) - -D CONFIG_ASYNC_TCP_RUNNING_CORE=1 // force async_tcp task to be on same core as the app (default is core 0) - -D CONFIG_ASYNC_TCP_STACK_SIZE=4096 // reduce the stack size (default is 16K) -``` +# Project moved to [ESP32Async](https://github.com/organizations/ESP32Async) organization at [https://github.com/ESP32Async/AsyncTCP](https://github.com/ESP32Async/AsyncTCP) diff --git a/library.json b/library.json index 1e5f045..7e41f19 100644 --- a/library.json +++ b/library.json @@ -5,17 +5,13 @@ "keywords": "async,tcp", "repository": { "type": "git", - "url": "https://github.com/mathieucarbou/AsyncTCP.git" + "url": "https://github.com/ESP32Async/AsyncTCP.git" + }, + "authors": + { + "name": "ESP32Async", + "maintainer": true }, - "authors": [ - { - "name": "Hristo Gochkov" - }, - { - "name": "Mathieu Carbou", - "maintainer": true - } - ], "license": "LGPL-3.0", "frameworks": "arduino", "platforms": [ diff --git a/library.properties b/library.properties index 23e10ab..6bde633 100644 --- a/library.properties +++ b/library.properties @@ -1,10 +1,11 @@ name=Async TCP includes=AsyncTCP.h version=3.3.2 -author=Me-No-Dev -maintainer=Mathieu Carbou +author=ESP32Async +maintainer=ESP32Async sentence=Async TCP Library for ESP32 paragraph=Async TCP Library for ESP32 category=Other -url=https://github.com/mathieucarbou/AsyncTCP.git +url=https://github.com/ESP32Async/AsyncTCP.git architectures=* +license=LGPL-3.0 diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index 762b1b3..431785f 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -26,7 +26,7 @@ #define ASYNCTCP_VERSION_MAJOR 3 #define ASYNCTCP_VERSION_MINOR 3 #define ASYNCTCP_VERSION_REVISION 2 -#define ASYNCTCP_FORK_mathieucarbou +#define ASYNCTCP_FORK_ESP32Async #include "IPAddress.h" #if ESP_IDF_VERSION_MAJOR < 5 From c82411d5dc0ab1699e6da9259810527c8e71c5e0 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 20 Jan 2025 15:46:05 +0100 Subject: [PATCH 149/150] Add discord server --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index c36f757..08e8c24 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ ![https://avatars.githubusercontent.com/u/195753706?s=96&v=4](https://avatars.githubusercontent.com/u/195753706?s=96&v=4) # Project moved to [ESP32Async](https://github.com/organizations/ESP32Async) organization at [https://github.com/ESP32Async/AsyncTCP](https://github.com/ESP32Async/AsyncTCP) + +Discord Server: [https://discord.gg/X7zpGdyUcY](https://discord.gg/X7zpGdyUcY) From 52332591fb89fe5c3d94d0346c883210b09122f0 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Mon, 20 Jan 2025 16:01:55 +0100 Subject: [PATCH 150/150] readme update --- README.ESP32Async.md | 4 +--- README.md | 8 ++++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/README.ESP32Async.md b/README.ESP32Async.md index f0510fd..b86bcfe 100644 --- a/README.ESP32Async.md +++ b/README.ESP32Async.md @@ -16,9 +16,7 @@ This library is the base for [ESPAsyncWebServer](https://github.com/ESP32Async/E The base classes on which everything else is built. They expose all possible scenarios, but are really raw and require more skills to use. -## Changes in this fork - -- Based on [ESPHome fork](https://github.com/esphome/AsyncTCP) +## Changes - `library.properties` for Arduino IDE users - Add `CONFIG_ASYNC_TCP_MAX_ACK_TIME` diff --git a/README.md b/README.md index 08e8c24..f66f505 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,11 @@ # Project moved to [ESP32Async](https://github.com/organizations/ESP32Async) organization at [https://github.com/ESP32Async/AsyncTCP](https://github.com/ESP32Async/AsyncTCP) Discord Server: [https://discord.gg/X7zpGdyUcY](https://discord.gg/X7zpGdyUcY) + +Please see the new links: + +- `ESP32Async/ESPAsyncWebServer @ 3.6.0` (ESP32, ESP8266, RP2040) +- `ESP32Async/AsyncTCP @ 3.3.2` (ESP32) +- `ESP32Async/ESPAsyncTCP @ 2.0.0` (ESP8266) +- `https://github.com/ESP32Async/AsyncTCPSock/archive/refs/tags/v1.0.3-dev.zip` (AsyncTCP alternative for ESP32) +- `khoih-prog/AsyncTCP_RP2040W @ 1.2.0` (RP2040)