diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 89ff6ee3..ad309ccd 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -674,7 +674,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; @@ -684,11 +684,7 @@ bool AsyncClient::connect(IPAddress ip, uint16_t port){ return false; } - ip_addr_t addr; - addr.type = IPADDR_TYPE_V4; - addr.u_addr.ip4.addr = ip; - - 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; @@ -699,11 +695,26 @@ 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; @@ -714,6 +725,9 @@ 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(addr.type == IPADDR_TYPE_V6) { + return connect(IPv6Address(addr.u_addr.ip6.addr), port); + } return connect(IPAddress(addr.u_addr.ip4.addr), port); } else if(err == ERR_INPROGRESS) { _connect_port = port; @@ -980,6 +994,8 @@ 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); + } 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); @@ -1071,6 +1087,15 @@ uint32_t AsyncClient::getRemoteAddress() { return _pcb->remote_ip.u_addr.ip4.addr; } +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; @@ -1085,6 +1110,15 @@ uint32_t AsyncClient::getLocalAddress() { return _pcb->local_ip.u_addr.ip4.addr; } +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; @@ -1096,6 +1130,10 @@ IPAddress AsyncClient::remoteIP() { return IPAddress(getRemoteAddress()); } +IPv6Address AsyncClient::remoteIP6() { + return IPv6Address(getRemoteAddress6().addr); +} + uint16_t AsyncClient::remotePort() { return getRemotePort(); } @@ -1104,6 +1142,10 @@ IPAddress AsyncClient::localIP() { return IPAddress(getLocalAddress()); } +IPv6Address AsyncClient::localIP6() { + return IPv6Address(getLocalAddress6().addr); +} + uint16_t AsyncClient::localPort() { return getLocalPort(); } @@ -1236,6 +1278,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) @@ -1243,9 +1286,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) @@ -1270,16 +1326,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; - local_addr.type = IPADDR_TYPE_V4; + 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); err = _tcp_bind(_pcb, &local_addr, _port); if (err != ERR_OK) { diff --git a/src/AsyncTCP.h b/src/AsyncTCP.h index ac87deda..f2654606 100644 --- a/src/AsyncTCP.h +++ b/src/AsyncTCP.h @@ -23,11 +23,14 @@ #define ASYNCTCP_H_ #include "IPAddress.h" +#include "IPv6Address.h" #include "sdkconfig.h" #include extern "C" { #include "freertos/semphr.h" #include "lwip/pbuf.h" + #include "lwip/ip_addr.h" + #include "lwip/ip6_addr.h" } //If core is not defined, then we are running in Arduino or PIO @@ -66,7 +69,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(); @@ -100,15 +104,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 @@ -140,6 +148,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; @@ -188,6 +198,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); @@ -203,7 +214,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;