add ipv6 support for arduino v3

This commit is contained in:
proddy
2024-04-27 13:59:43 +02:00
parent e43b7dec1b
commit 9b47cf0e0e
3 changed files with 122 additions and 48 deletions

View File

@@ -1,4 +1,5 @@
# AsyncTCP # AsyncTCP
![Build Status](https://github.com/esphome/AsyncTCP/actions/workflows/push.yml/badge.svg) ![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). 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) This library is the base for [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer)
## AsyncClient and AsyncServer ## 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. The base classes on which everything else is built. They expose all possible scenarios, but are really raw and require more skills to use.

View File

@@ -718,7 +718,7 @@ bool AsyncClient::_connect(ip_addr_t addr, uint16_t port) {
return false; return false;
} }
tcp_pcb * pcb = tcp_new_ip_type(addr.type); tcp_pcb * pcb = tcp_new_ip_type(IPADDR_TYPE_ANY);
if (!pcb) { if (!pcb) {
log_e("pcb == NULL"); log_e("pcb == NULL");
return false; return false;
@@ -735,12 +735,19 @@ bool AsyncClient::_connect(ip_addr_t addr, uint16_t port) {
bool AsyncClient::connect(IPAddress ip, uint16_t port) { bool AsyncClient::connect(IPAddress ip, uint16_t port) {
ip_addr_t addr; 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.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); return _connect(addr, port);
} }
#if LWIP_IPV6 && ESP_IDF_VERSION_MAJOR < 5
bool AsyncClient::connect(IPv6Address ip, uint16_t port) { bool AsyncClient::connect(IPv6Address ip, uint16_t port) {
ip_addr_t addr; ip_addr_t addr;
addr.type = IPADDR_TYPE_V6; addr.type = IPADDR_TYPE_V6;
@@ -748,6 +755,7 @@ bool AsyncClient::connect(IPv6Address ip, uint16_t port) {
return _connect(addr, port); return _connect(addr, port);
} }
#endif
bool AsyncClient::connect(const char * host, uint16_t port) { bool AsyncClient::connect(const char * host, uint16_t port) {
ip_addr_t addr; 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); err_t err = dns_gethostbyname(host, &addr, (dns_found_callback)&_tcp_dns_found, this);
if (err == ERR_OK) { if (err == ERR_OK) {
#if ESP_IDF_VERSION_MAJOR < 5
#if LWIP_IPV6
if (addr.type == IPADDR_TYPE_V6) { if (addr.type == IPADDR_TYPE_V6) {
return connect(IPv6Address(addr.u_addr.ip6.addr), port); return connect(IPv6Address(addr.u_addr.ip6.addr), port);
} }
#if LWIP_IPV6
return connect(IPAddress(addr.u_addr.ip4.addr), port); return connect(IPAddress(addr.u_addr.ip4.addr), port);
#else #else
return connect(IPAddress(addr.addr), port); return connect(IPAddress(addr.addr), port);
#endif
#else
return _connect(addr, port);
#endif #endif
} else if (err == ERR_INPROGRESS) { } else if (err == ERR_INPROGRESS) {
_connect_port = port; _connect_port = port;
@@ -1031,10 +1043,17 @@ int8_t AsyncClient::_poll(tcp_pcb * pcb) {
} }
void AsyncClient::_dns_found(struct ip_addr * ipaddr) { void AsyncClient::_dns_found(struct ip_addr * ipaddr) {
if (ipaddr && ipaddr->u_addr.ip4.addr) { #if ESP_IDF_VERSION_MAJOR < 5
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) { } else if (ipaddr && ipaddr->u_addr.ip6.addr) {
connect(IPv6Address(ipaddr->u_addr.ip6.addr), _connect_port); connect(IPv6Address(ipaddr->u_addr.ip6.addr), _connect_port);
#endif
#else
if (ipaddr) {
connect(IPAddress(ipaddr), _connect_port);
#endif
} else { } else {
if (_error_cb) { if (_error_cb) {
_error_cb(_error_cb_arg, this, -55); _error_cb(_error_cb_arg, this, -55);
@@ -1130,6 +1149,7 @@ uint32_t AsyncClient::getRemoteAddress() {
#endif #endif
} }
#if LWIP_IPV6
ip6_addr_t AsyncClient::getRemoteAddress6() { ip6_addr_t AsyncClient::getRemoteAddress6() {
if (!_pcb) { if (!_pcb) {
ip6_addr_t nulladdr; ip6_addr_t nulladdr;
@@ -1139,6 +1159,33 @@ ip6_addr_t AsyncClient::getRemoteAddress6() {
return _pcb->remote_ip.u_addr.ip6; 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<const ip_addr_t *>(&_pcb->remote_ip)) : IPAddress(IPType::IPv6);
}
IPAddress AsyncClient::localIP6() {
return _pcb ? IPAddress(dynamic_cast<const ip_addr_t *>(&_pcb->local_ip)) : IPAddress(IPType::IPv6);
}
#endif
#endif
uint16_t AsyncClient::getRemotePort() { uint16_t AsyncClient::getRemotePort() {
if (!_pcb) { if (!_pcb) {
return 0; return 0;
@@ -1157,15 +1204,6 @@ uint32_t AsyncClient::getLocalAddress() {
#endif #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() { uint16_t AsyncClient::getLocalPort() {
if (!_pcb) { if (!_pcb) {
return 0; return 0;
@@ -1174,11 +1212,11 @@ uint16_t AsyncClient::getLocalPort() {
} }
IPAddress AsyncClient::remoteIP() { IPAddress AsyncClient::remoteIP() {
#if ESP_IDF_VERSION_MAJOR < 5
return IPAddress(getRemoteAddress()); return IPAddress(getRemoteAddress());
} #else
return _pcb ? IPAddress(dynamic_cast<const ip_addr_t *>(&_pcb->remote_ip)) : IPAddress();
IPv6Address AsyncClient::remoteIP6() { #endif
return IPv6Address(getRemoteAddress6().addr);
} }
uint16_t AsyncClient::remotePort() { uint16_t AsyncClient::remotePort() {
@@ -1186,12 +1224,13 @@ uint16_t AsyncClient::remotePort() {
} }
IPAddress AsyncClient::localIP() { IPAddress AsyncClient::localIP() {
#if ESP_IDF_VERSION_MAJOR < 5
return IPAddress(getLocalAddress()); return IPAddress(getLocalAddress());
#else
return _pcb ? IPAddress(dynamic_cast<const ip_addr_t *>(&_pcb->local_ip)) : IPAddress();
#endif
} }
IPv6Address AsyncClient::localIP6() {
return IPv6Address(getLocalAddress6().addr);
}
uint16_t AsyncClient::localPort() { uint16_t AsyncClient::localPort() {
return getLocalPort(); 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) AsyncServer::AsyncServer(IPAddress addr, uint16_t port)
: _port(port) : _port(port)
#if ESP_IDF_VERSION_MAJOR < 5
, _bind4(true) , _bind4(true)
#else
, _bind4(addr.type() != IPType::IPv6)
, _bind6(addr.type() == IPType::IPv6)
#endif
, _addr(addr) , _addr(addr)
, _noDelay(false) , _noDelay(false)
, _pcb(0) , _pcb(0)
@@ -1363,6 +1407,7 @@ AsyncServer::AsyncServer(IPAddress addr, uint16_t port)
, _connect_cb_arg(0) { , _connect_cb_arg(0) {
} }
#if ESP_IDF_VERSION_MAJOR < 5
AsyncServer::AsyncServer(IPv6Address addr, uint16_t port) AsyncServer::AsyncServer(IPv6Address addr, uint16_t port)
: _port(port) : _port(port)
, _bind6(true) , _bind6(true)
@@ -1372,13 +1417,16 @@ AsyncServer::AsyncServer(IPv6Address addr, uint16_t port)
, _connect_cb(0) , _connect_cb(0)
, _connect_cb_arg(0) { , _connect_cb_arg(0) {
} }
#endif
AsyncServer::AsyncServer(uint16_t port) AsyncServer::AsyncServer(uint16_t port)
: _port(port) : _port(port)
, _bind4(true) , _bind4(true)
, _bind6(true) , _bind6(true)
, _addr((uint32_t)IPADDR_ANY) , _addr((uint32_t)IPADDR_ANY)
#if ESP_IDF_VERSION_MAJOR < 5
, _addr6() , _addr6()
#endif
, _noDelay(false) , _noDelay(false)
, _pcb(0) , _pcb(0)
, _connect_cb(0) , _connect_cb(0)
@@ -1420,9 +1468,17 @@ void AsyncServer::begin() {
} }
ip_addr_t local_addr; ip_addr_t local_addr;
local_addr.type = bind_type; #if ESP_IDF_VERSION_MAJOR < 5
local_addr.u_addr.ip4.addr = (uint32_t)_addr; // ip_addr_set_ip4_u32(&local_addr, _addr);
memcpy(local_addr.u_addr.ip6.addr, static_cast<const uint32_t *>(_addr6), sizeof(uint32_t) * 4); 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<const uint32_t*>(_addr6), sizeof(uint32_t) * 4); */
#else
_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) { if (err != ERR_OK) {

View File

@@ -23,16 +23,18 @@
#define ASYNCTCP_H_ #define ASYNCTCP_H_
#include "IPAddress.h" #include "IPAddress.h"
#if ESP_IDF_VERSION_MAJOR < 5
#include "IPv6Address.h" #include "IPv6Address.h"
#endif
#include <functional> #include <functional>
#include "lwip/ip_addr.h"
#include "lwip/ip6_addr.h"
#ifndef LIBRETINY #ifndef LIBRETINY
#include "sdkconfig.h" #include "sdkconfig.h"
extern "C" { extern "C" {
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "lwip/pbuf.h" #include "lwip/pbuf.h"
#include "lwip/ip_addr.h"
#include "lwip/ip6_addr.h"
} }
#else #else
extern "C" { extern "C" {
@@ -46,20 +48,21 @@ extern "C" {
//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 #ifndef CONFIG_ASYNC_TCP_RUNNING_CORE
#define CONFIG_ASYNC_TCP_RUNNING_CORE -1 //any available 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 #endif
#ifndef CONFIG_ASYNC_TCP_TASK_PRIORITY #ifndef CONFIG_ASYNC_TCP_TASK_PRIORITY
#define CONFIG_ASYNC_TCP_TASK_PRIORITY 5 #define CONFIG_ASYNC_TCP_TASK_PRIORITY 5
#endif #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 #ifndef CONFIG_ASYNC_TCP_STACK_SIZE
#define CONFIG_ASYNC_TCP_STACK_SIZE 5120 #define CONFIG_ASYNC_TCP_STACK_SIZE 5120
#endif #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 #ifndef CONFIG_ASYNC_TCP_QUEUE
#define CONFIG_ASYNC_TCP_QUEUE 32 #define CONFIG_ASYNC_TCP_QUEUE 32
#endif #endif
@@ -93,8 +96,10 @@ class AsyncClient {
bool operator!=(const AsyncClient & other) { bool operator!=(const AsyncClient & other) {
return !(*this == other); return !(*this == other);
} }
bool connect(IPAddress ip, uint16_t port); bool connect(IPAddress ip, uint16_t port);
bool connect(IPv6Address 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); bool connect(const char * host, uint16_t port);
void close(bool now = false); void close(bool now = false);
void stop(); void stop();
@@ -128,20 +133,27 @@ class AsyncClient {
void setNoDelay(bool nodelay); void setNoDelay(bool nodelay);
bool getNoDelay(); bool getNoDelay();
uint32_t getRemoteAddress(); uint32_t getRemoteAddress();
uint16_t getRemotePort();
uint32_t getLocalAddress();
uint16_t getLocalPort();
#if LWIP_IPV6
ip6_addr_t getRemoteAddress6(); ip6_addr_t getRemoteAddress6();
uint16_t getRemotePort();
uint32_t getLocalAddress();
ip6_addr_t getLocalAddress6(); 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 //compatibility
IPAddress remoteIP(); IPAddress remoteIP();
IPv6Address remoteIP6(); uint16_t remotePort();
uint16_t remotePort(); IPAddress localIP();
IPAddress localIP(); uint16_t localPort();
IPv6Address localIP6();
uint16_t localPort();
void onConnect(AcConnectHandler cb, void * arg = 0); //on successful connect void onConnect(AcConnectHandler cb, void * arg = 0); //on successful connect
void onDisconnect(AcConnectHandler cb, void * arg = 0); //disconnected void onDisconnect(AcConnectHandler cb, void * arg = 0); //disconnected
@@ -227,7 +239,9 @@ class AsyncClient {
class AsyncServer { class AsyncServer {
public: public:
AsyncServer(IPAddress addr, uint16_t port); AsyncServer(IPAddress addr, uint16_t port);
#if ESP_IDF_VERSION_MAJOR < 5
AsyncServer(IPv6Address addr, uint16_t port); AsyncServer(IPv6Address addr, uint16_t port);
#endif
AsyncServer(uint16_t port); AsyncServer(uint16_t port);
~AsyncServer(); ~AsyncServer();
void onClient(AcConnectHandler cb, void * arg); void onClient(AcConnectHandler cb, void * arg);
@@ -242,11 +256,13 @@ class AsyncServer {
static int8_t _s_accepted(void * arg, AsyncClient * client); static int8_t _s_accepted(void * arg, AsyncClient * client);
protected: protected:
uint16_t _port; uint16_t _port;
bool _bind4 = false; bool _bind4 = false;
bool _bind6 = false; bool _bind6 = false;
IPAddress _addr; IPAddress _addr;
IPv6Address _addr6; #if ESP_IDF_VERSION_MAJOR < 5
IPv6Address _addr6;
#endif
bool _noDelay; bool _noDelay;
tcp_pcb * _pcb; tcp_pcb * _pcb;
AcConnectHandler _connect_cb; AcConnectHandler _connect_cb;