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); }