From f9de677d6c83fb88f265c57b94e35be483e5a1dc Mon Sep 17 00:00:00 2001 From: Zhenyu Wu Date: Tue, 24 Jul 2018 14:57:45 -0400 Subject: [PATCH 1/6] Do not account ack length before ssl handshake finish (#86) * Do not account ack length before ssl handshake finish * Add appropriate #ifdefs --- src/ESPAsyncTCP.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ESPAsyncTCP.cpp b/src/ESPAsyncTCP.cpp index c3fc6e7..a596229 100644 --- a/src/ESPAsyncTCP.cpp +++ b/src/ESPAsyncTCP.cpp @@ -366,10 +366,14 @@ void AsyncClient::_ssl_error(int8_t err){ #endif err_t AsyncClient::_sent(tcp_pcb* pcb, uint16_t len) { +#if ASYNC_TCP_SSL_ENABLED + if (_pcb_secure && !_handshake_done) + return ERR_OK; +#endif _rx_last_packet = millis(); - ASYNC_TCP_DEBUG("_sent: %u\n", len); _tx_unacked_len -= len; _tx_acked_len += len; + ASYNC_TCP_DEBUG("_sent: %u (%d %d)\n", len, _tx_unacked_len, _tx_acked_len); if(_tx_unacked_len == 0){ _pcb_busy = false; if(_sent_cb) From 649dd36f80ac26b1063f3222c62bf1ce5f67eb11 Mon Sep 17 00:00:00 2001 From: Zhenyu Wu Date: Tue, 24 Jul 2018 14:59:44 -0400 Subject: [PATCH 2/6] Fix improper recv callback return when ssl layer returned SSL_CLOSE_NOTIFY (#84) --- src/ESPAsyncTCP.cpp | 2 +- src/tcp_axtls.c | 1 + src/tcp_axtls.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ESPAsyncTCP.cpp b/src/ESPAsyncTCP.cpp index a596229..801d2ce 100644 --- a/src/ESPAsyncTCP.cpp +++ b/src/ESPAsyncTCP.cpp @@ -399,7 +399,7 @@ err_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, err_t err) { ASYNC_TCP_DEBUG("_recv err: %d\n", read_bytes); _close(); } - return read_bytes; + //return read_bytes; } return ERR_OK; } diff --git a/src/tcp_axtls.c b/src/tcp_axtls.c index 2a7b966..1e2f324 100755 --- a/src/tcp_axtls.c +++ b/src/tcp_axtls.c @@ -406,6 +406,7 @@ int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p) { } while (p->tot_len - fd_data->pbuf_offset > 0); tcp_recved(tcp, p->tot_len); + fd_data->tcp_pbuf = NULL; pbuf_free(p); return total_bytes; diff --git a/src/tcp_axtls.h b/src/tcp_axtls.h index 57a0e52..118e36f 100755 --- a/src/tcp_axtls.h +++ b/src/tcp_axtls.h @@ -40,6 +40,7 @@ extern "C" { #endif +#include #include "include/ssl.h" #define ERR_TCP_SSL_INVALID_SSL -101 From 0450e61738fee0ad0f4d07478b566e8667c55d93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Doanh=20V=C4=83n=20L=C6=B0=C6=A1ng?= Date: Wed, 25 Jul 2018 02:01:44 +0700 Subject: [PATCH 3/6] Fix call to tcp_recved after pcb has been closed (#75) I got exception 28 with this decode ``` Exception 28: LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads Decoding 27 results 0x4022b043: tcp_recved at /home/david/dev/esp8266/origin/tools/sdk/lwip2/builder/lwip2-src/src/core/tcp.c line 1690 0x40202757: uart_write_char at C:\Users\doanh\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.0\cores\esp8266/uart.c line 464 0x40247e81: scan_parse_beacon at ?? line ? 0x402120b0: AsyncMqttClient::_sendDisconnect() at D:\Documents\Arduino\libraries\async-mqtt-client-master\src/AsyncMqttClient.cpp line 96 0x4021213d: AsyncMqttClient::disconnect(bool) at D:\Documents\Arduino\libraries\async-mqtt-client-master\src/AsyncMqttClient.cpp line 96 0x4010502c: ets_timer_arm_new at ?? line ? 0x4021353d: AsyncMqttClient::_onPoll(AsyncClient*) at D:\Documents\Arduino\libraries\async-mqtt-client-master\src/AsyncMqttClient.cpp line 96 0x40213574: _M_invoke at D:\Documents\Arduino\libraries\async-mqtt-client-master\src/AsyncMqttClient.cpp line 96 0x4021444e: std::function ::operator()(void*, AsyncClient*) const at D:\Documents\Arduino\libraries\ESPAsyncTCP-master\src/ESPAsyncTCP.cpp line 659 0x402149b0: AsyncClient::_poll(tcp_pcb*) at D:\Documents\Arduino\libraries\ESPAsyncTCP-master\src/ESPAsyncTCP.cpp line 659 0x402149c4: AsyncClient::_s_poll(void*, tcp_pcb*) at D:\Documents\Arduino\libraries\ESPAsyncTCP-master\src/ESPAsyncTCP.cpp line 659 0x4022b3c8: tcp_slowtmr at /home/david/dev/esp8266/origin/tools/sdk/lwip2/builder/lwip2-src/src/core/tcp.c line 1690 0x4022b768: tcp_fasttmr at /home/david/dev/esp8266/origin/tools/sdk/lwip2/builder/lwip2-src/src/core/tcp.c line 1690 0x4022bcb4: tcpip_tcp_timer at /home/david/dev/esp8266/origin/tools/sdk/lwip2/builder/lwip2-src/src/core/timeouts.c line 126 0x4022bcb4: tcpip_tcp_timer at /home/david/dev/esp8266/origin/tools/sdk/lwip2/builder/lwip2-src/src/core/timeouts.c line 126 0x4022b7ac: tcp_tmr at /home/david/dev/esp8266/origin/tools/sdk/lwip2/builder/lwip2-src/src/core/tcp.c line 1690 0x4022bd38: cyclic_timer at /home/david/dev/esp8266/origin/tools/sdk/lwip2/builder/lwip2-src/src/core/timeouts.c line 165 0x4022bcbc: tcpip_tcp_timer at /home/david/dev/esp8266/origin/tools/sdk/lwip2/builder/lwip2-src/src/core/timeouts.c line 132 0x40104d9e: wdt_feed at ?? line ? 0x4022be04: sys_check_timeouts at /home/david/dev/esp8266/origin/tools/sdk/lwip2/builder/lwip2-src/src/core/timeouts.c line 351 0x4025f100: ets_timer_handler_isr at ?? line ? 0x4025f10d: ets_timer_handler_isr at ?? line ? 0x4025f152: ets_timer_handler_isr at ?? line ? 0x4021d267: loop_task at C:\Users\doanh\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.0\cores\esp8266/core_esp8266_main.cpp line 132 ``` so this fix can resolve this error --- src/ESPAsyncTCP.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ESPAsyncTCP.cpp b/src/ESPAsyncTCP.cpp index 801d2ce..d6f78d7 100644 --- a/src/ESPAsyncTCP.cpp +++ b/src/ESPAsyncTCP.cpp @@ -201,7 +201,8 @@ int8_t AsyncClient::abort(){ } void AsyncClient::close(bool now){ - tcp_recved(_pcb, _rx_ack_len); + if(_pcb) + tcp_recved(_pcb, _rx_ack_len); if(now) _close(); else From a313fc94e1924c26bb309f98d7f8893ce3b885b5 Mon Sep 17 00:00:00 2001 From: Iman Ahmadvand Date: Tue, 24 Jul 2018 23:34:38 +0430 Subject: [PATCH 4/6] Adding Client Server example (#76) * async client server example added * Rename client.ino to ClientServer.ino * Following Arduino sketch directory rules * prevent magic constants in AsyncClient::errorToString() --- examples/ClientServer/Client/Client.ino | 62 +++++++++++++++++++++ examples/ClientServer/Client/config.h | 23 ++++++++ examples/ClientServer/Server/Server.ino | 73 +++++++++++++++++++++++++ examples/ClientServer/Server/config.h | 23 ++++++++ src/ESPAsyncTCP.cpp | 58 +++++++++++++------- 5 files changed, 218 insertions(+), 21 deletions(-) create mode 100644 examples/ClientServer/Client/Client.ino create mode 100644 examples/ClientServer/Client/config.h create mode 100644 examples/ClientServer/Server/Server.ino create mode 100644 examples/ClientServer/Server/config.h diff --git a/examples/ClientServer/Client/Client.ino b/examples/ClientServer/Client/Client.ino new file mode 100644 index 0000000..6a6655b --- /dev/null +++ b/examples/ClientServer/Client/Client.ino @@ -0,0 +1,62 @@ +#include +#include + +extern "C" { +#include +#include +} + +#include "config.h" + +static os_timer_t intervalTimer; + +static void replyToServer(void* arg) { + AsyncClient* client = reinterpret_cast(arg); + + // send reply + if (client->space() > 32 && client->canSend()) { + char message[32]; + sprintf(message, "this is from %s", WiFi.localIP().toString().c_str()); + 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((char*)data, len); + + os_timer_arm(&intervalTimer, 2000, true); // schedule for reply to server at next 2s +} + +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); + + // connects to access point + WiFi.mode(WIFI_STA); + WiFi.begin(SSID, PASSWORD); + while (WiFi.status() != WL_CONNECTED) { + Serial.print('.'); + delay(500); + } + + AsyncClient* client = new AsyncClient; + client->onData(&handleData, client); + client->onConnect(&onConnect, client); + client->connect(SERVER_HOST_NAME, TCP_PORT); + + os_timer_disarm(&intervalTimer); + os_timer_setfn(&intervalTimer, &replyToServer, client); +} + +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/examples/ClientServer/Server/Server.ino b/examples/ClientServer/Server/Server.ino new file mode 100644 index 0000000..81edc0c --- /dev/null +++ b/examples/ClientServer/Server/Server.ino @@ -0,0 +1,73 @@ +#include +#include +#include +#include + +#include "config.h" + +static DNSServer DNS; + +static std::vector clients; // a list to hold all clients + + /* clients events */ +static void handleError(void* arg, AsyncClient* client, int8_t error) { + Serial.printf("\n connection error %s from client %s \n", client->errorToString(error), client->remoteIP().toString().c_str()); +} + +static void handleData(void* arg, AsyncClient* client, void *data, size_t len) { + Serial.printf("\n data received from client %s \n", client->remoteIP().toString().c_str()); + Serial.write((char*)data, len); + + // reply to client + if (client->space() > 32 && client->canSend()) { + char reply[32]; + sprintf(reply, "this is from %s", SERVER_HOST_NAME); + client->add(reply, strlen(reply)); + client->send(); + } +} + +static void handleDisconnect(void* arg, AsyncClient* client) { + Serial.printf("\n client %s disconnected \n", client->remoteIP().toString().c_str()); +} + +static void handleTimeOut(void* arg, AsyncClient* client, uint32_t time) { + Serial.printf("\n client ACK timeout ip: %s \n", client->remoteIP().toString().c_str()); +} + + +/* server events */ +static void handleNewClient(void* arg, AsyncClient* client) { + Serial.printf("\n new client has been connected to server, ip: %s", client->remoteIP().toString().c_str()); + + // add to list + clients.push_back(client); + + // register events + client->onData(&handleData, NULL); + client->onError(&handleError, NULL); + client->onDisconnect(&handleDisconnect, NULL); + client->onTimeout(&handleTimeOut, NULL); +} + +void setup() { + Serial.begin(115200); + delay(20); + + // create access point + while (!WiFi.softAP(SSID, PASSWORD, 6, false, 15)) { + delay(500); + } + + // start dns server + if (!DNS.start(DNS_PORT, SERVER_HOST_NAME, WiFi.softAPIP())) + Serial.printf("\n failed to start dns service \n"); + + AsyncServer* server = new AsyncServer(TCP_PORT); // start listening on tcp port 7050 + server->onClient(&handleNewClient, server); + server->begin(); +} + +void loop() { + DNS.processNextRequest(); +} diff --git a/examples/ClientServer/Server/config.h b/examples/ClientServer/Server/config.h new file mode 100644 index 0000000..cf51e91 --- /dev/null +++ b/examples/ClientServer/Server/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/ESPAsyncTCP.cpp b/src/ESPAsyncTCP.cpp index d6f78d7..7c3fd97 100644 --- a/src/ESPAsyncTCP.cpp +++ b/src/ESPAsyncTCP.cpp @@ -748,27 +748,43 @@ void AsyncClient::ackPacket(struct pbuf * pb){ pbuf_free(pb); } -const char * AsyncClient::errorToString(int8_t error){ - switch(error){ - case 0: return "OK"; - case -1: return "Out of memory error"; - case -2: return "Buffer error"; - case -3: return "Timeout"; - case -4: return "Routing problem"; - case -5: return "Operation in progress"; - case -6: return "Illegal value"; - case -7: return "Operation would block"; - case -8: return "Connection aborted"; - case -9: return "Connection reset"; - case -10: return "Connection closed"; - case -11: return "Not connected"; - case -12: return "Illegal argument"; - case -13: return "Address in use"; - case -14: return "Low-level netif error"; - case -15: return "Already connected"; - 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_ABRT: + return "Connection aborted"; + case ERR_RST: + return "Connection reset"; + case ERR_CLSD: + return "Connection closed"; + case ERR_CONN: + return "Not connected"; + case ERR_ARG: + return "Illegal argument"; + case ERR_USE: + return "Address in use"; + case ERR_IF: + return "Low-level netif error"; + case ERR_ISCONN: + return "Connection already established"; + default: + return "Unknown error"; + } } const char * AsyncClient::stateToString(){ From f5993150646e28eb276ab555c2c2c2b871568547 Mon Sep 17 00:00:00 2001 From: Lazar Obradovic Date: Tue, 24 Jul 2018 21:07:11 +0200 Subject: [PATCH 5/6] Bump lib version (#91) --- library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.json b/library.json index 76816d0..8f39000 100644 --- a/library.json +++ b/library.json @@ -12,7 +12,7 @@ "type": "git", "url": "https://github.com/me-no-dev/ESPAsyncTCP.git" }, - "version": "1.1.3", + "version": "1.2.0", "license": "LGPL-3.0", "frameworks": "arduino", "platforms": "espressif8266", From 7e9ed22ed0078097f895dfee6ebcec90046b81b9 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 24 Jul 2018 21:12:48 +0200 Subject: [PATCH 6/6] Bump version in Arduino and fix compilation erros --- examples/ClientServer/Client/Client.ino | 2 +- examples/ClientServer/Server/Server.ino | 2 +- library.properties | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/ClientServer/Client/Client.ino b/examples/ClientServer/Client/Client.ino index 6a6655b..b30d791 100644 --- a/examples/ClientServer/Client/Client.ino +++ b/examples/ClientServer/Client/Client.ino @@ -25,7 +25,7 @@ static void replyToServer(void* arg) { /* 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((char*)data, len); + Serial.write((uint8_t*)data, len); os_timer_arm(&intervalTimer, 2000, true); // schedule for reply to server at next 2s } diff --git a/examples/ClientServer/Server/Server.ino b/examples/ClientServer/Server/Server.ino index 81edc0c..c8c9b7f 100644 --- a/examples/ClientServer/Server/Server.ino +++ b/examples/ClientServer/Server/Server.ino @@ -16,7 +16,7 @@ static void handleError(void* arg, AsyncClient* client, int8_t error) { static void handleData(void* arg, AsyncClient* client, void *data, size_t len) { Serial.printf("\n data received from client %s \n", client->remoteIP().toString().c_str()); - Serial.write((char*)data, len); + Serial.write((uint8_t*)data, len); // reply to client if (client->space() > 32 && client->canSend()) { diff --git a/library.properties b/library.properties index 9330e4d..d8e1f9c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ESP AsyncTCP -version=1.1.0 +version=1.2.0 author=Me-No-Dev maintainer=Me-No-Dev sentence=Async TCP Library for ESP8266 and ESP31B