From 9b47cf0e0e5ccc2340edd18fbbc4fab360d3e986 Mon Sep 17 00:00:00 2001 From: proddy Date: Sat, 27 Apr 2024 13:59:43 +0200 Subject: [PATCH] add ipv6 support for arduino v3 --- lib/AsyncTCP/README.md | 2 + lib/AsyncTCP/src/AsyncTCP.cpp | 106 ++++++++++++++++++++++++++-------- lib/AsyncTCP/src/AsyncTCP.h | 62 ++++++++++++-------- 3 files changed, 122 insertions(+), 48 deletions(-) diff --git a/lib/AsyncTCP/README.md b/lib/AsyncTCP/README.md index 17b145b3c..5eb47541b 100644 --- a/lib/AsyncTCP/README.md +++ b/lib/AsyncTCP/README.md @@ -1,4 +1,5 @@ # AsyncTCP + ![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). @@ -9,4 +10,5 @@ This is a fully asynchronous TCP library, aimed at enabling trouble-free, multi- This library is the base for [ESPAsyncWebServer](https://github.com/me-no-dev/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. diff --git a/lib/AsyncTCP/src/AsyncTCP.cpp b/lib/AsyncTCP/src/AsyncTCP.cpp index 75b3ca5c7..06673f818 100644 --- a/lib/AsyncTCP/src/AsyncTCP.cpp +++ b/lib/AsyncTCP/src/AsyncTCP.cpp @@ -718,7 +718,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; @@ -735,12 +735,19 @@ 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; +#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 return _connect(addr, port); } +#if LWIP_IPV6 && ESP_IDF_VERSION_MAJOR < 5 bool AsyncClient::connect(IPv6Address ip, uint16_t port) { ip_addr_t addr; addr.type = IPADDR_TYPE_V6; @@ -748,6 +755,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; @@ -759,13 +767,17 @@ 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); } -#if LWIP_IPV6 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; @@ -1031,10 +1043,17 @@ 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 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) { _error_cb(_error_cb_arg, this, -55); @@ -1130,6 +1149,7 @@ uint32_t AsyncClient::getRemoteAddress() { #endif } +#if LWIP_IPV6 ip6_addr_t AsyncClient::getRemoteAddress6() { if (!_pcb) { ip6_addr_t nulladdr; @@ -1139,6 +1159,33 @@ 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; +} +#if ESP_IDF_VERSION_MAJOR < 5 +IPv6Address AsyncClient::remoteIP6() { + return IPv6Address(getRemoteAddress6().addr); +} + +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() { if (!_pcb) { return 0; @@ -1157,15 +1204,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; @@ -1174,11 +1212,11 @@ uint16_t AsyncClient::getLocalPort() { } IPAddress AsyncClient::remoteIP() { +#if ESP_IDF_VERSION_MAJOR < 5 return IPAddress(getRemoteAddress()); -} - -IPv6Address AsyncClient::remoteIP6() { - return IPv6Address(getRemoteAddress6().addr); +#else + return _pcb ? IPAddress(dynamic_cast(&_pcb->remote_ip)) : IPAddress(); +#endif } uint16_t AsyncClient::remotePort() { @@ -1186,12 +1224,13 @@ 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 } -IPv6Address AsyncClient::localIP6() { - return IPv6Address(getLocalAddress6().addr); -} uint16_t AsyncClient::localPort() { return getLocalPort(); @@ -1355,7 +1394,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) @@ -1363,6 +1407,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) @@ -1372,13 +1417,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) @@ -1420,9 +1468,17 @@ void AsyncServer::begin() { } ip_addr_t 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 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) { @@ -1497,4 +1553,4 @@ int8_t AsyncServer::_s_accept(void * arg, tcp_pcb * pcb, int8_t err) { int8_t AsyncServer::_s_accepted(void * arg, AsyncClient * client) { return reinterpret_cast(arg)->_accepted(client); -} +} \ No newline at end of file diff --git a/lib/AsyncTCP/src/AsyncTCP.h b/lib/AsyncTCP/src/AsyncTCP.h index ec21f6fd2..3d9c61f72 100644 --- a/lib/AsyncTCP/src/AsyncTCP.h +++ b/lib/AsyncTCP/src/AsyncTCP.h @@ -23,16 +23,18 @@ #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" #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" { @@ -46,20 +48,21 @@ extern "C" { //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 0 //if enabled, adds between 33us and 200us per event +// Note default was 1 and previously set to 0 for EMS-ESP32 +#define CONFIG_ASYNC_TCP_USE_WDT 1 //if enabled, adds between 33us and 200us per event #endif #ifndef CONFIG_ASYNC_TCP_TASK_PRIORITY #define CONFIG_ASYNC_TCP_TASK_PRIORITY 5 #endif -// stack usage measured: ESP32: ~2.3K, ESP32S3: ~3.5k +// EMS-ESP32: stack usage measured: ESP32: ~2.3K, ESP32S3: ~3.5k #ifndef CONFIG_ASYNC_TCP_STACK_SIZE #define CONFIG_ASYNC_TCP_STACK_SIZE 5120 #endif -// maybe enlarge queue to 64 or 128 see https://github.com/emsesp/EMS-ESP32/issues/177 +// EMS-ESP32: maybe enlarge queue to 64 or 128 see https://github.com/emsesp/EMS-ESP32/issues/177 #ifndef CONFIG_ASYNC_TCP_QUEUE #define CONFIG_ASYNC_TCP_QUEUE 32 #endif @@ -93,8 +96,10 @@ class AsyncClient { bool operator!=(const AsyncClient & other) { return !(*this == other); } - bool connect(IPAddress ip, uint16_t port); - bool connect(IPv6Address ip, uint16_t port); + 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(); @@ -128,20 +133,27 @@ class AsyncClient { void setNoDelay(bool nodelay); bool getNoDelay(); - uint32_t getRemoteAddress(); + uint32_t getRemoteAddress(); + uint16_t getRemotePort(); + uint32_t getLocalAddress(); + uint16_t getLocalPort(); +#if LWIP_IPV6 ip6_addr_t getRemoteAddress6(); - uint16_t getRemotePort(); - uint32_t getLocalAddress(); ip6_addr_t getLocalAddress6(); - uint16_t getLocalPort(); +#if ESP_IDF_VERSION_MAJOR < 5 + IPv6Address remoteIP6(); + IPv6Address localIP6(); +#else + IPAddress remoteIP6(); + IPAddress localIP6(); +#endif +#endif //compatibility - IPAddress remoteIP(); - IPv6Address remoteIP6(); - uint16_t remotePort(); - IPAddress localIP(); - IPv6Address localIP6(); - uint16_t localPort(); + 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 @@ -227,7 +239,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); @@ -242,11 +256,13 @@ class AsyncServer { static int8_t _s_accepted(void * arg, AsyncClient * client); protected: - uint16_t _port; - bool _bind4 = false; - bool _bind6 = false; - IPAddress _addr; - IPv6Address _addr6; + uint16_t _port; + 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; @@ -257,4 +273,4 @@ class AsyncServer { }; -#endif /* ASYNCTCP_H_ */ +#endif /* ASYNCTCP_H_ */ \ No newline at end of file