From 7b42a93077864c9a5d906ccc2d2a92b6bf6e78f3 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 21 Nov 2023 18:17:04 +0100 Subject: [PATCH 01/21] IPv6 for Arduino 3.0.0 --- libraries/WiFi/src/WiFiClient.cpp | 64 +++++++++-- libraries/WiFi/src/WiFiGeneric.cpp | 58 +++++++++- libraries/WiFi/src/WiFiGeneric.h | 7 ++ libraries/WiFi/src/WiFiMulti.cpp | 7 ++ libraries/WiFi/src/WiFiMulti.h | 2 + libraries/WiFi/src/WiFiSTA.cpp | 13 +++ libraries/WiFi/src/WiFiSTA.h | 1 + libraries/WiFi/src/WiFiServer.cpp | 28 +++-- libraries/WiFi/src/WiFiServer.h | 1 - libraries/WiFi/src/WiFiUdp.cpp | 168 +++++++++++++++++++++++------ 10 files changed, 290 insertions(+), 59 deletions(-) diff --git a/libraries/WiFi/src/WiFiClient.cpp b/libraries/WiFi/src/WiFiClient.cpp index 864c33322f3..d8f1a31a62b 100644 --- a/libraries/WiFi/src/WiFiClient.cpp +++ b/libraries/WiFi/src/WiFiClient.cpp @@ -23,6 +23,11 @@ #include #include +#define IN6_IS_ADDR_V4MAPPED(a) \ + ((((__const uint32_t *) (a))[0] == 0) \ + && (((__const uint32_t *) (a))[1] == 0) \ + && (((__const uint32_t *) (a))[2] == htonl (0xffff))) + #define WIFI_CLIENT_DEF_CONN_TIMEOUT_MS (3000) #define WIFI_CLIENT_MAX_WRITE_RETRY (10) #define WIFI_CLIENT_SELECT_TIMEOUT_US (1000000) @@ -219,22 +224,33 @@ int WiFiClient::connect(IPAddress ip, uint16_t port) { return connect(ip,port,_timeout); } + int WiFiClient::connect(IPAddress ip, uint16_t port, int32_t timeout_ms) { + struct sockaddr_storage serveraddr = {}; _timeout = timeout_ms; - int sockfd = socket(AF_INET, SOCK_STREAM, 0); + int sockfd = -1; + + if (ip.type() == IPv6) { + struct sockaddr_in6 *tmpaddr = (struct sockaddr_in6 *)&serveraddr; + sockfd = socket(AF_INET6, SOCK_STREAM, 0); + tmpaddr->sin6_family = AF_INET6; + memcpy(tmpaddr->sin6_addr.un.u8_addr, &ip[0], 16); + tmpaddr->sin6_port = htons(port); + tmpaddr->sin6_scope_id = ip.zone(); + } else { + struct sockaddr_in *tmpaddr = (struct sockaddr_in *)&serveraddr; + sockfd = socket(AF_INET, SOCK_STREAM, 0); + tmpaddr->sin_family = AF_INET; + tmpaddr->sin_addr.s_addr = ip; + tmpaddr->sin_port = htons(port); + } if (sockfd < 0) { log_e("socket: %d", errno); return 0; } fcntl( sockfd, F_SETFL, fcntl( sockfd, F_GETFL, 0 ) | O_NONBLOCK ); - uint32_t ip_addr = ip; - struct sockaddr_in serveraddr; - memset((char *) &serveraddr, 0, sizeof(serveraddr)); - serveraddr.sin_family = AF_INET; - memcpy((void *)&serveraddr.sin_addr.s_addr, (const void *)(&ip_addr), 4); - serveraddr.sin_port = htons(port); fd_set fdset; struct timeval tv; FD_ZERO(&fdset); @@ -303,6 +319,19 @@ int WiFiClient::connect(const char *host, uint16_t port) int WiFiClient::connect(const char *host, uint16_t port, int32_t timeout_ms) { + if (WiFiGenericClass::getStatusBits() & WIFI_WANT_IP6_BIT) { + ip_addr_t srv6; + if(!WiFiGenericClass::hostByName6(host, srv6)){ + return 0; + } + if (srv6.type == IPADDR_TYPE_V4) { + IPAddress ip(srv6.u_addr.ip4.addr); + return connect(ip, port, timeout_ms); + } else { + IPAddress ip(IPv6, (uint8_t*)&srv6.u_addr.ip6.addr[0]); + return connect(ip, port, timeout_ms); + } + } IPAddress srv((uint32_t)0); if(!WiFiGenericClass::hostByName(host, srv)){ return 0; @@ -574,8 +603,24 @@ IPAddress WiFiClient::remoteIP(int fd) const struct sockaddr_storage addr; socklen_t len = sizeof addr; getpeername(fd, (struct sockaddr*)&addr, &len); - struct sockaddr_in *s = (struct sockaddr_in *)&addr; - return IPAddress((uint32_t)(s->sin_addr.s_addr)); + + // IPv4 socket, old way + if (((struct sockaddr*)&addr)->sa_family == AF_INET) { + struct sockaddr_in *s = (struct sockaddr_in *)&addr; + return IPAddress((uint32_t)(s->sin_addr.s_addr)); + } + + // IPv6, but it might be IPv4 mapped address + if (((struct sockaddr*)&addr)->sa_family == AF_INET6) { + struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&addr; + if (IN6_IS_ADDR_V4MAPPED(saddr6->sin6_addr.un.u32_addr)) { + return IPAddress(IPv4, (uint8_t*)saddr6->sin6_addr.s6_addr+12); + } else { + return IPAddress(IPv6, (uint8_t*)(saddr6->sin6_addr.s6_addr), saddr6->sin6_scope_id); + } + } + log_e("WiFiClient::remoteIP Not AF_INET or AF_INET6?"); + return (IPAddress(0,0,0,0)); } uint16_t WiFiClient::remotePort(int fd) const @@ -638,4 +683,3 @@ int WiFiClient::fd() const return clientSocketHandle->fd(); } } - diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index 8ef803064c4..c43bf46bc30 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -1055,8 +1055,8 @@ esp_err_t WiFiGenericClass::_eventCallback(arduino_event_t *event) } else if(event->event_id == ARDUINO_EVENT_WIFI_STA_CONNECTED) { WiFiSTAClass::_setStatus(WL_IDLE_STATUS); setStatusBits(STA_CONNECTED_BIT); - - //esp_netif_create_ip6_linklocal(esp_netifs[ESP_IF_WIFI_STA]); + if (getStatusBits() & WIFI_WANT_IP6_BIT) + esp_netif_create_ip6_linklocal(esp_netifs[ESP_IF_WIFI_STA]); } else if(event->event_id == ARDUINO_EVENT_WIFI_STA_DISCONNECTED) { uint8_t reason = event->event_info.wifi_sta_disconnected.reason; // Reason 0 causes crash, use reason 1 (UNSPECIFIED) instead @@ -1577,8 +1577,27 @@ static esp_err_t wifi_gethostbyname_tcpip_ctx(void *param) } /** - * Resolve the given hostname to an IP address. If passed hostname is an IP address, it will be parsed into IPAddress structure. - * @param aHostname Name to be resolved or string containing IP address + * IPv6 compatible DNS callback + * @param name + * @param ipaddr + * @param callback_arg + */ +static void wifi_dns6_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg) +{ + struct dns_api_msg *msg = (struct dns_api_msg *)callback_arg; + + if(ipaddr && !msg->result) { + msg->ip_addr = *ipaddr; + msg->result = 1; + } else { + msg->result = -1; + } + xEventGroupSetBits(_arduino_event_group, WIFI_DNS_DONE_BIT); +} + +/** + * Resolve the given hostname to an IP address. + * @param aHostname Name to be resolved * @param aResult IPAddress structure to store the returned IP address * @return 1 if aIPAddrString was successfully converted to an IP address, * else error code @@ -1608,6 +1627,37 @@ int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult) return (uint32_t)aResult != 0; } +/** + * Resolve the given hostname to an IP6 address. + * @param aHostname Name to be resolved + * @param aResult IPv6Address structure to store the returned IP address + * @return 1 if aHostname was successfully converted to an IP address, + * else error code + */ +int WiFiGenericClass::hostByName6(const char* aHostname, ip_addr_t& aResult) +{ + ip_addr_t addr; + struct dns_api_msg arg; + + memset(&arg, 0x0, sizeof(arg)); + waitStatusBits(WIFI_DNS_IDLE_BIT, 16000); + clearStatusBits(WIFI_DNS_IDLE_BIT | WIFI_DNS_DONE_BIT); + + err_t err = dns_gethostbyname_addrtype(aHostname, &addr, &wifi_dns6_found_callback, + &arg, LWIP_DNS_ADDRTYPE_IPV6_IPV4); + if(err == ERR_OK) { + aResult = addr; + } else if(err == ERR_INPROGRESS) { + waitStatusBits(WIFI_DNS_DONE_BIT, 15000); //real internal timeout in lwip library is 14[s] + clearStatusBits(WIFI_DNS_DONE_BIT); + if (arg.result == 1) { + aResult = arg.ip_addr; + } + } + setStatusBits(WIFI_DNS_IDLE_BIT); + return (uint32_t)err == ERR_OK || (err == ERR_INPROGRESS && arg.result == 1); +} + IPAddress WiFiGenericClass::calculateNetworkID(IPAddress ip, IPAddress subnet) { IPAddress networkID; diff --git a/libraries/WiFi/src/WiFiGeneric.h b/libraries/WiFi/src/WiFiGeneric.h index 38396f5a72e..ce723409eca 100644 --- a/libraries/WiFi/src/WiFiGeneric.h +++ b/libraries/WiFi/src/WiFiGeneric.h @@ -141,6 +141,7 @@ static const int WIFI_SCANNING_BIT = BIT11; static const int WIFI_SCAN_DONE_BIT= BIT12; static const int WIFI_DNS_IDLE_BIT = BIT13; static const int WIFI_DNS_DONE_BIT = BIT14; +static const int WIFI_WANT_IP6_BIT = BIT15; typedef enum { WIFI_RX_ANT0 = 0, @@ -154,6 +155,11 @@ typedef enum { WIFI_TX_ANT_AUTO } wifi_tx_ant_t; +struct dns_api_msg { + ip_addr_t ip_addr; + int result; +}; + class WiFiGenericClass { public: @@ -196,6 +202,7 @@ class WiFiGenericClass static const char * getHostname(); static bool setHostname(const char * hostname); static bool hostname(const String& aHostname) { return setHostname(aHostname.c_str()); } + static int hostByName6(const char *aHostname, ip_addr_t& aResult); static esp_err_t _eventCallback(arduino_event_t *event); diff --git a/libraries/WiFi/src/WiFiMulti.cpp b/libraries/WiFi/src/WiFiMulti.cpp index 3d69e481293..9e7f03c6531 100644 --- a/libraries/WiFi/src/WiFiMulti.cpp +++ b/libraries/WiFi/src/WiFiMulti.cpp @@ -30,6 +30,7 @@ WiFiMulti::WiFiMulti() { + ipv6_support = false; } WiFiMulti::~WiFiMulti() @@ -160,6 +161,8 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout) log_i("[WIFI] Connecting BSSID: %02X:%02X:%02X:%02X:%02X:%02X SSID: %s Channel: %d (%d)", bestBSSID[0], bestBSSID[1], bestBSSID[2], bestBSSID[3], bestBSSID[4], bestBSSID[5], bestNetwork.ssid, bestChannel, bestNetworkDb); WiFi.begin(bestNetwork.ssid, bestNetwork.passphrase, bestChannel, bestBSSID); + if (ipv6_support == true) + WiFi.IPv6(true); status = WiFi.status(); auto startTime = millis(); @@ -202,3 +205,7 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout) return status; } + +void WiFiMulti::IPv6(bool state) { + ipv6_support = state; +} diff --git a/libraries/WiFi/src/WiFiMulti.h b/libraries/WiFi/src/WiFiMulti.h index 38ddb5d9f95..bbeb78dc860 100644 --- a/libraries/WiFi/src/WiFiMulti.h +++ b/libraries/WiFi/src/WiFiMulti.h @@ -42,10 +42,12 @@ class WiFiMulti bool addAP(const char* ssid, const char *passphrase = NULL); + void IPv6(bool state); uint8_t run(uint32_t connectTimeout=5000); private: std::vector APlist; + bool ipv6_support; }; #endif /* WIFICLIENTMULTI_H_ */ diff --git a/libraries/WiFi/src/WiFiSTA.cpp b/libraries/WiFi/src/WiFiSTA.cpp index 505940015f9..ca3fb6b5e40 100644 --- a/libraries/WiFi/src/WiFiSTA.cpp +++ b/libraries/WiFi/src/WiFiSTA.cpp @@ -816,6 +816,19 @@ bool WiFiSTAClass::enableIpV6() return esp_netif_create_ip6_linklocal(get_esp_interface_netif(ESP_IF_WIFI_STA)) == ESP_OK; } +/** + * Enable IPv6 support on the station interface. + * @return true on success + */ +bool WiFiSTAClass::IPv6(bool state) +{ + if (state) + WiFiGenericClass::setStatusBits(WIFI_WANT_IP6_BIT); + else + WiFiGenericClass::clearStatusBits(WIFI_WANT_IP6_BIT); + return true; +} + /** * Get the station interface IPv6 address. * @return IPv6Address diff --git a/libraries/WiFi/src/WiFiSTA.h b/libraries/WiFi/src/WiFiSTA.h index 07f01922cef..12e2f0bd4a4 100644 --- a/libraries/WiFi/src/WiFiSTA.h +++ b/libraries/WiFi/src/WiFiSTA.h @@ -94,6 +94,7 @@ class WiFiSTAClass uint8_t subnetCIDR(); bool enableIpV6(); + bool IPv6(bool state); IPv6Address localIPv6(); // STA WiFi info diff --git a/libraries/WiFi/src/WiFiServer.cpp b/libraries/WiFi/src/WiFiServer.cpp index ef59cf14d6d..d3f2b0b0120 100644 --- a/libraries/WiFi/src/WiFiServer.cpp +++ b/libraries/WiFi/src/WiFiServer.cpp @@ -51,8 +51,8 @@ WiFiClient WiFiServer::accept(){ _accepted_sockfd = -1; } else { - struct sockaddr_in _client; - int cs = sizeof(struct sockaddr_in); + struct sockaddr_in6 _client; + int cs = sizeof(struct sockaddr_in6); #ifdef ESP_IDF_VERSION_MAJOR client_sock = lwip_accept(sockfd, (struct sockaddr *)&_client, (socklen_t*)&cs); #else @@ -80,14 +80,23 @@ void WiFiServer::begin(uint16_t port, int enable){ if(port){ _port = port; } - struct sockaddr_in server; - sockfd = socket(AF_INET , SOCK_STREAM, 0); + struct sockaddr_in6 server; + sockfd = socket(AF_INET6 , SOCK_STREAM, 0); if (sockfd < 0) return; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); - server.sin_family = AF_INET; - server.sin_addr.s_addr = _addr; - server.sin_port = htons(_port); + server.sin6_family = AF_INET6; + if (_addr.type() == IPv4) { + // log_e("---------------- IPv4"); + memcpy(server.sin6_addr.s6_addr+11, (uint8_t*)&_addr[0], 4); + server.sin6_addr.s6_addr[10] = 0xFF; + server.sin6_addr.s6_addr[11] = 0xFF; + } else { + // log_e("---------------- IPv6"); + memcpy(server.sin6_addr.s6_addr, (uint8_t*)&_addr[0], 16); + } + memset(server.sin6_addr.s6_addr, 0x0, 16); + server.sin6_port = htons(_port); if(bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) return; if(listen(sockfd , _max_clients) < 0) @@ -110,8 +119,8 @@ bool WiFiServer::hasClient() { if (_accepted_sockfd >= 0) { return true; } - struct sockaddr_in _client; - int cs = sizeof(struct sockaddr_in); + struct sockaddr_in6 _client; + int cs = sizeof(struct sockaddr_in6); #ifdef ESP_IDF_VERSION_MAJOR _accepted_sockfd = lwip_accept(sockfd, (struct sockaddr *)&_client, (socklen_t*)&cs); #else @@ -140,4 +149,3 @@ void WiFiServer::close(){ void WiFiServer::stop(){ end(); } - diff --git a/libraries/WiFi/src/WiFiServer.h b/libraries/WiFi/src/WiFiServer.h index b9db726b9b7..2c2ebc0b8f2 100644 --- a/libraries/WiFi/src/WiFiServer.h +++ b/libraries/WiFi/src/WiFiServer.h @@ -37,7 +37,6 @@ class WiFiServer : public Server { public: void listenOnLocalhost(){} - // _addr(INADDR_ANY) is the same as _addr() ==> 0.0.0.0 WiFiServer(uint16_t port=80, uint8_t max_clients=4):sockfd(-1),_accepted_sockfd(-1),_addr(),_port(port),_max_clients(max_clients),_listening(false),_noDelay(false) { log_v("WiFiServer::WiFiServer(port=%d, ...)", port); } diff --git a/libraries/WiFi/src/WiFiUdp.cpp b/libraries/WiFi/src/WiFiUdp.cpp index 6b053bbbd14..7c503cec2f3 100644 --- a/libraries/WiFi/src/WiFiUdp.cpp +++ b/libraries/WiFi/src/WiFiUdp.cpp @@ -51,7 +51,11 @@ uint8_t WiFiUDP::begin(IPAddress address, uint16_t port){ } tx_buffer_len = 0; +#if LWIP_IPV6 + if ((udp_server=socket(address.isV6() ? AF_INET6 : AF_INET, SOCK_DGRAM, 0)) == -1){ +#else if ((udp_server=socket(AF_INET, SOCK_DGRAM, 0)) == -1){ +#endif log_e("could not create socket: %d", errno); return 0; } @@ -63,12 +67,30 @@ uint8_t WiFiUDP::begin(IPAddress address, uint16_t port){ return 0; } - struct sockaddr_in addr; - memset((char *) &addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(server_port); - addr.sin_addr.s_addr = (in_addr_t)address; - if(bind(udp_server , (struct sockaddr*)&addr, sizeof(addr)) == -1){ + struct sockaddr_storage serveraddr = {}; + size_t sock_size = 0; +#if LWIP_IPV6 + if (address.isV6()) { + struct sockaddr_in6 *tmpaddr = (struct sockaddr_in6 *)&serveraddr; + ip_addr_t * ip_addr = (ip_addr_t*) address; + memset((char *) tmpaddr, 0, sizeof(struct sockaddr_in)); + tmpaddr->sin6_family = AF_INET6; + tmpaddr->sin6_port = htons(server_port); + tmpaddr->sin6_scope_id = ip_addr->u_addr.ip6.zone; + inet6_addr_from_ip6addr(&tmpaddr->sin6_addr, ip_2_ip6(ip_addr)); + tmpaddr->sin6_flowinfo = 0; + sock_size = sizeof(sockaddr_in6); + } else +#endif + if (1) { + struct sockaddr_in *tmpaddr = (struct sockaddr_in *)&serveraddr; + memset((char *) tmpaddr, 0, sizeof(struct sockaddr_in)); + tmpaddr->sin_family = AF_INET; + tmpaddr->sin_port = htons(server_port); + tmpaddr->sin_addr.s_addr = (in_addr_t)address; + sock_size = sizeof(sockaddr_in); + } + if(bind(udp_server , (sockaddr*)&serveraddr, sock_size) == -1){ log_e("could not bind socket: %d", errno); stop(); return 0; @@ -78,23 +100,47 @@ uint8_t WiFiUDP::begin(IPAddress address, uint16_t port){ } uint8_t WiFiUDP::begin(uint16_t p){ - return begin(IPAddress(INADDR_ANY), p); + return begin(IPAddress(), p); } uint8_t WiFiUDP::beginMulticast(IPAddress a, uint16_t p){ - if(begin(IPAddress(INADDR_ANY), p)){ - if((uint32_t)a != 0){ - struct ip_mreq mreq; - mreq.imr_multiaddr.s_addr = (in_addr_t)a; - mreq.imr_interface.s_addr = INADDR_ANY; - if (setsockopt(udp_server, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { + if(begin(IPAddress(), p)){ + ip_addr_t * ip_addr = (ip_addr_t*) a; + if (ip_addr_ismulticast(ip_addr)) { +#if LWIP_IPV6 + if (IP_IS_V6_VAL(*ip_addr)) { + struct ipv6_mreq mreq; + bool joined = false; + inet6_addr_from_ip6addr(&mreq.ipv6mr_multiaddr, ip_2_ip6(ip_addr)); + + // iterate on each interface + for (netif* intf = netif_list; intf != nullptr; intf = intf->next) { + mreq.ipv6mr_interface = intf->num + 1; + if (intf->name[0] != 'l' || intf->name[1] != 'o') { // skip 'lo' local interface + int ret = setsockopt(udp_server, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)); + if (ret >= 0) { joined = true; } + } + } + if (!joined) { log_e("could not join igmp: %d", errno); stop(); return 0; + } + } else +#endif + if (1) { + struct ip_mreq mreq; + mreq.imr_multiaddr.s_addr = (in_addr_t)a; + mreq.imr_interface.s_addr = INADDR_ANY; + if (setsockopt(udp_server, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { + log_e("could not join igmp: %d", errno); + stop(); + return 0; + } } multicast_ip = a; + return 1; } - return 1; } return 0; } @@ -112,19 +158,37 @@ void WiFiUDP::stop(){ } if(udp_server == -1) return; - if((uint32_t)multicast_ip != 0){ - struct ip_mreq mreq; - mreq.imr_multiaddr.s_addr = (in_addr_t)multicast_ip; - mreq.imr_interface.s_addr = (in_addr_t)0; - setsockopt(udp_server, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)); - multicast_ip = IPAddress(INADDR_ANY); + ip_addr_t * mcast_addr = (ip_addr_t*) multicast_ip; + if (!ip_addr_isany(mcast_addr)) { +#if LWIP_IPV6 + if (IP_IS_V6(mcast_addr)) { + struct ipv6_mreq mreq; + inet6_addr_from_ip6addr(&mreq.ipv6mr_multiaddr, ip_2_ip6(mcast_addr)); + + // iterate on each interface + for (netif* intf = netif_list; intf != nullptr; intf = intf->next) { + mreq.ipv6mr_interface = intf->num + 1; + if (intf->name[0] != 'l' || intf->name[1] != 'o') { // skip 'lo' local interface + int ret = setsockopt(udp_server, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq, sizeof(mreq)); + } + } + } else +#endif + if (1) { + struct ip_mreq mreq; + mreq.imr_multiaddr.s_addr = (in_addr_t)multicast_ip; + mreq.imr_interface.s_addr = (in_addr_t)0; + setsockopt(udp_server, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)); + } + // now common code for v4/v6 + multicast_ip = IPAddress(); } close(udp_server); udp_server = -1; } int WiFiUDP::beginMulticastPacket(){ - if(!server_port || multicast_ip == IPAddress(INADDR_ANY)) + if(!server_port || multicast_ip == IPAddress()) return 0; remote_ip = multicast_ip; remote_port = server_port; @@ -176,14 +240,29 @@ int WiFiUDP::beginPacket(const char *host, uint16_t port){ } int WiFiUDP::endPacket(){ - struct sockaddr_in recipient; - recipient.sin_addr.s_addr = (uint32_t)remote_ip; - recipient.sin_family = AF_INET; - recipient.sin_port = htons(remote_port); - int sent = sendto(udp_server, tx_buffer, tx_buffer_len, 0, (struct sockaddr*) &recipient, sizeof(recipient)); - if(sent < 0){ - log_e("could not send data: %d", errno); - return 0; + + if (remote_ip.isV4()) { + struct sockaddr_in recipient; + recipient.sin_addr.s_addr = (uint32_t)remote_ip; + recipient.sin_family = AF_INET; + recipient.sin_port = htons(remote_port); + int sent = sendto(udp_server, tx_buffer, tx_buffer_len, 0, (struct sockaddr*) &recipient, sizeof(recipient)); + if(sent < 0){ + log_e("could not send data: %d", errno); + return 0; + } + } else { + struct sockaddr_in6 recipient; + recipient.sin6_flowinfo = 0; + recipient.sin6_addr = *(in6_addr*)(ip_addr_t*)remote_ip; + recipient.sin6_family = AF_INET6; + recipient.sin6_port = htons(remote_port); + recipient.sin6_scope_id = remote_ip.zone(); + int sent = sendto(udp_server, tx_buffer, tx_buffer_len, 0, (struct sockaddr*) &recipient, sizeof(recipient)); + if(sent < 0){ + log_e("could not send data: %d", errno); + return 0; + } } return 1; } @@ -207,13 +286,14 @@ size_t WiFiUDP::write(const uint8_t *buffer, size_t size){ int WiFiUDP::parsePacket(){ if(rx_buffer) return 0; - struct sockaddr_in si_other; - int slen = sizeof(si_other) , len; + struct sockaddr_storage si_other_storage; // enough storage for v4 and v6 + socklen_t slen = sizeof(sockaddr_storage); + int len; char *buf = (char *)malloc(1460); if(!buf) { return 0; } - if ((len = recvfrom(udp_server, buf, 1460, MSG_DONTWAIT, (struct sockaddr *) &si_other, (socklen_t *)&slen)) == -1){ + if ((len = recvfrom(udp_server, buf, 1460, MSG_DONTWAIT, (struct sockaddr *) &si_other_storage, (socklen_t *)&slen)) == -1){ free(buf); if(errno == EWOULDBLOCK){ return 0; @@ -221,8 +301,28 @@ int WiFiUDP::parsePacket(){ log_e("could not receive data: %d", errno); return 0; } - remote_ip = IPAddress(si_other.sin_addr.s_addr); - remote_port = ntohs(si_other.sin_port); + if (si_other_storage.ss_family == AF_INET) { + struct sockaddr_in &si_other = (sockaddr_in&) si_other_storage; + remote_ip = IPAddress(si_other.sin_addr.s_addr); + remote_port = ntohs(si_other.sin_port); + } +#if LWIP_IPV6 + else if (si_other_storage.ss_family == AF_INET6) { + struct sockaddr_in6 &si_other = (sockaddr_in6&) si_other_storage; + remote_ip = IPAddress(IPv6, (uint8_t*)&si_other.sin6_addr, si_other.sin6_scope_id); // force IPv6 + ip_addr_t *ip_addr = (ip_addr_t*) remote_ip; + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ + if (IP_IS_V6_VAL(*ip_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(ip_addr))) { + unmap_ipv4_mapped_ipv6(ip_2_ip4(ip_addr), ip_2_ip6(ip_addr)); + IP_SET_TYPE_VAL(*ip_addr, IPADDR_TYPE_V4); + } + remote_port = ntohs(si_other.sin6_port); + } +#endif // LWIP_IPV6=1 + else { + remote_ip = *IP_ADDR_ANY; + remote_port = 0; + } if (len > 0) { rx_buffer = new(std::nothrow) cbuf(len); rx_buffer->write(buf, len); From 12be3695e098f9f330045fe60060e6285b4d0397 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Tue, 21 Nov 2023 21:10:49 +0100 Subject: [PATCH 02/21] Fix warning in WifiUdp --- libraries/WiFi/src/WiFiUdp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/WiFi/src/WiFiUdp.cpp b/libraries/WiFi/src/WiFiUdp.cpp index 7c503cec2f3..511ee3e6126 100644 --- a/libraries/WiFi/src/WiFiUdp.cpp +++ b/libraries/WiFi/src/WiFiUdp.cpp @@ -169,7 +169,7 @@ void WiFiUDP::stop(){ for (netif* intf = netif_list; intf != nullptr; intf = intf->next) { mreq.ipv6mr_interface = intf->num + 1; if (intf->name[0] != 'l' || intf->name[1] != 'o') { // skip 'lo' local interface - int ret = setsockopt(udp_server, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq, sizeof(mreq)); + setsockopt(udp_server, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq, sizeof(mreq)); } } } else From 5987211a7f9cf51d4b719569fd398edef67061d0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 22 Nov 2023 16:01:24 +0100 Subject: [PATCH 03/21] remove comment / formating From b8cc73c108743598a35b97db59ac712c88c6f9d7 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Mon, 18 Dec 2023 17:53:20 +0200 Subject: [PATCH 04/21] Add zone to IPAddress and update WiFiUDP and WiFiGeneric --- cores/esp32/IPAddress.cpp | 326 ++++++++++++++++------------- cores/esp32/IPAddress.h | 89 ++++---- libraries/WiFi/src/WiFiGeneric.cpp | 9 +- libraries/WiFi/src/WiFiGeneric.h | 6 +- libraries/WiFi/src/WiFiUdp.cpp | 58 ++--- 5 files changed, 267 insertions(+), 221 deletions(-) diff --git a/cores/esp32/IPAddress.cpp b/cores/esp32/IPAddress.cpp index 002dccb3fcd..bfa481274e1 100644 --- a/cores/esp32/IPAddress.cpp +++ b/cores/esp32/IPAddress.cpp @@ -1,38 +1,39 @@ /* - IPAddress.cpp - Base class that provides IPAddress - Copyright (c) 2011 Adrian McEwen. All right reserved. + IPAddress.cpp - Base class that provides IPAddress + Copyright (c) 2011 Adrian McEwen. All right reserved. - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ -#include -#include -#include -#include +#include "IPAddress.h" +#include "Print.h" +#include "lwip/netif.h" IPAddress::IPAddress() : IPAddress(IPv4) {} IPAddress::IPAddress(IPType ip_type) { _type = ip_type; + _zone = IP6_NO_ZONE; memset(_address.bytes, 0, sizeof(_address.bytes)); } IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) { _type = IPv4; + _zone = IP6_NO_ZONE; memset(_address.bytes, 0, sizeof(_address.bytes)); _address.bytes[IPADDRESS_V4_BYTES_INDEX] = first_octet; _address.bytes[IPADDRESS_V4_BYTES_INDEX + 1] = second_octet; @@ -40,7 +41,7 @@ IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_oc _address.bytes[IPADDRESS_V4_BYTES_INDEX + 3] = fourth_octet; } -IPAddress::IPAddress(uint8_t o1, uint8_t o2, uint8_t o3, uint8_t o4, uint8_t o5, uint8_t o6, uint8_t o7, uint8_t o8, uint8_t o9, uint8_t o10, uint8_t o11, uint8_t o12, uint8_t o13, uint8_t o14, uint8_t o15, uint8_t o16) { +IPAddress::IPAddress(uint8_t o1, uint8_t o2, uint8_t o3, uint8_t o4, uint8_t o5, uint8_t o6, uint8_t o7, uint8_t o8, uint8_t o9, uint8_t o10, uint8_t o11, uint8_t o12, uint8_t o13, uint8_t o14, uint8_t o15, uint8_t o16, uint8_t z) { _type = IPv6; _address.bytes[0] = o1; _address.bytes[1] = o2; @@ -58,6 +59,7 @@ IPAddress::IPAddress(uint8_t o1, uint8_t o2, uint8_t o3, uint8_t o4, uint8_t o5, _address.bytes[13] = o14; _address.bytes[14] = o15; _address.bytes[15] = o16; + _zone = z; } IPAddress::IPAddress(uint32_t address) @@ -78,14 +80,16 @@ IPAddress::IPAddress(uint32_t address) IPAddress::IPAddress(const uint8_t *address) : IPAddress(IPv4, address) {} -IPAddress::IPAddress(IPType ip_type, const uint8_t *address) +IPAddress::IPAddress(IPType ip_type, const uint8_t *address, uint8_t z) { _type = ip_type; if (ip_type == IPv4) { memset(_address.bytes, 0, sizeof(_address.bytes)); memcpy(&_address.bytes[IPADDRESS_V4_BYTES_INDEX], address, sizeof(uint32_t)); + _zone = 0; } else { memcpy(_address.bytes, address, sizeof(_address.bytes)); + _zone = z; } } @@ -94,121 +98,9 @@ IPAddress::IPAddress(const char *address) fromString(address); } -IPAddress& IPAddress::operator=(const uint8_t *address) -{ - // IPv4 only conversion from byte pointer - _type = IPv4; - memset(_address.bytes, 0, sizeof(_address.bytes)); - memcpy(&_address.bytes[IPADDRESS_V4_BYTES_INDEX], address, sizeof(uint32_t)); - return *this; -} - -IPAddress& IPAddress::operator=(const char *address) +IPAddress::IPAddress(const IPAddress& address) { - fromString(address); - return *this; -} - -IPAddress& IPAddress::operator=(uint32_t address) -{ - // IPv4 conversion - // See note on conversion/comparison and uint32_t - _type = IPv4; - memset(_address.bytes, 0, sizeof(_address.bytes)); - _address.dword[IPADDRESS_V4_DWORD_INDEX] = address; - return *this; -} - -bool IPAddress::operator==(const IPAddress& addr) const -{ - return (addr._type == _type) - && (memcmp(addr._address.bytes, _address.bytes, sizeof(_address.bytes)) == 0); -} - -bool IPAddress::operator==(const uint8_t* addr) const -{ - // IPv4 only comparison to byte pointer - // Can't support IPv6 as we know our type, but not the length of the pointer - return _type == IPv4 && memcmp(addr, &_address.bytes[IPADDRESS_V4_BYTES_INDEX], sizeof(uint32_t)) == 0; -} - -uint8_t IPAddress::operator[](int index) const { - if (_type == IPv4) { - return _address.bytes[IPADDRESS_V4_BYTES_INDEX + index]; - } - return _address.bytes[index]; -} - -uint8_t& IPAddress::operator[](int index) { - if (_type == IPv4) { - return _address.bytes[IPADDRESS_V4_BYTES_INDEX + index]; - } - return _address.bytes[index]; -} - -size_t IPAddress::printTo(Print& p) const -{ - size_t n = 0; - - if (_type == IPv6) { - // IPv6 IETF canonical format: compress left-most longest run of two or more zero fields, lower case - int8_t longest_start = -1; - int8_t longest_length = 1; - int8_t current_start = -1; - int8_t current_length = 0; - for (int8_t f = 0; f < 8; f++) { - if (_address.bytes[f * 2] == 0 && _address.bytes[f * 2 + 1] == 0) { - if (current_start == -1) { - current_start = f; - current_length = 1; - } else { - current_length++; - } - if (current_length > longest_length) { - longest_start = current_start; - longest_length = current_length; - } - } else { - current_start = -1; - } - } - for (int f = 0; f < 8; f++) { - if (f < longest_start || f >= longest_start + longest_length) { - uint8_t c1 = _address.bytes[f * 2] >> 4; - uint8_t c2 = _address.bytes[f * 2] & 0xf; - uint8_t c3 = _address.bytes[f * 2 + 1] >> 4; - uint8_t c4 = _address.bytes[f * 2 + 1] & 0xf; - if (c1 > 0) { - n += p.print((char)(c1 < 10 ? '0' + c1 : 'a' + c1 - 10)); - } - if (c1 > 0 || c2 > 0) { - n += p.print((char)(c2 < 10 ? '0' + c2 : 'a' + c2 - 10)); - } - if (c1 > 0 || c2 > 0 || c3 > 0) { - n += p.print((char)(c3 < 10 ? '0' + c3 : 'a' + c3 - 10)); - } - n += p.print((char)(c4 < 10 ? '0' + c4 : 'a' + c4 - 10)); - if (f < 7) { - n += p.print(':'); - } - } else if (f == longest_start) { - if (longest_start == 0) { - n += p.print(':'); - } - n += p.print(':'); - } - } - return n; - } - - // IPv4 - for (int i =0; i < 3; i++) - { - n += p.print(_address.bytes[IPADDRESS_V4_BYTES_INDEX + i], DEC); - n += p.print('.'); - } - n += p.print(_address.bytes[IPADDRESS_V4_BYTES_INDEX + 3], DEC); - return n; + *this = address; } String IPAddress::toString4() const @@ -220,10 +112,13 @@ String IPAddress::toString4() const String IPAddress::toString6() const { - StreamString s; - s.reserve(40); - printTo(s); - return s; + char szRet[40]; + snprintf(szRet, sizeof(szRet), "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + _address.bytes[0], _address.bytes[1], _address.bytes[2], _address.bytes[3], + _address.bytes[4], _address.bytes[5], _address.bytes[6], _address.bytes[7], + _address.bytes[8], _address.bytes[9], _address.bytes[10], _address.bytes[11], + _address.bytes[12], _address.bytes[13], _address.bytes[14], _address.bytes[15]); + return String(szRet); } String IPAddress::toString() const @@ -235,10 +130,8 @@ String IPAddress::toString() const } } -bool IPAddress::fromString(const char *address) -{ - if (!fromString4(address)) - { +bool IPAddress::fromString(const char *address) { + if (!fromString4(address)) { return fromString6(address); } return true; @@ -336,6 +229,12 @@ bool IPAddress::fromString6(const char *address) { colons++; acc = 0; } + else if (c == '%') { + _zone = netif_name_to_index(address); + while(*address != '\0'){ + address++; + } + } else // Invalid char return false; @@ -364,5 +263,144 @@ bool IPAddress::fromString6(const char *address) { return true; } -// declared one time - as external in IPAddress.h -IPAddress INADDR_NONE(0, 0, 0, 0); +IPAddress& IPAddress::operator=(const uint8_t *address) +{ + // IPv4 only conversion from byte pointer + _type = IPv4; + memset(_address.bytes, 0, sizeof(_address.bytes)); + memcpy(&_address.bytes[IPADDRESS_V4_BYTES_INDEX], address, sizeof(uint32_t)); + return *this; +} + +IPAddress& IPAddress::operator=(const char *address) +{ + fromString(address); + return *this; +} + +IPAddress& IPAddress::operator=(uint32_t address) +{ + // IPv4 conversion + // See note on conversion/comparison and uint32_t + _type = IPv4; + memset(_address.bytes, 0, sizeof(_address.bytes)); + _address.dword[IPADDRESS_V4_DWORD_INDEX] = address; + return *this; +} + +IPAddress& IPAddress::operator=(const IPAddress& address){ + _type = address.type(); + _zone = address.zone(); + memcpy(_address.bytes, address._address.bytes, sizeof(_address.bytes)); + return *this; +} + +bool IPAddress::operator==(const IPAddress& addr) const { + return (addr._type == _type) + && (memcmp(addr._address.bytes, _address.bytes, sizeof(_address.bytes)) == 0); +} + +bool IPAddress::operator==(const uint8_t* addr) const +{ + // IPv4 only comparison to byte pointer + // Can't support IPv6 as we know our type, but not the length of the pointer + return _type == IPv4 && memcmp(addr, &_address.bytes[IPADDRESS_V4_BYTES_INDEX], sizeof(uint32_t)) == 0; +} + +uint8_t IPAddress::operator[](int index) const { + if (_type == IPv4) { + return _address.bytes[IPADDRESS_V4_BYTES_INDEX + index]; + } + return _address.bytes[index]; +} + +uint8_t& IPAddress::operator[](int index) { + if (_type == IPv4) { + return _address.bytes[IPADDRESS_V4_BYTES_INDEX + index]; + } + return _address.bytes[index]; +} + +size_t IPAddress::printTo(Print& p) const +{ + size_t n = 0; + + if (_type == IPv6) { + // IPv6 IETF canonical format: compress left-most longest run of two or more zero fields, lower case + int8_t longest_start = -1; + int8_t longest_length = 1; + int8_t current_start = -1; + int8_t current_length = 0; + for (int8_t f = 0; f < 8; f++) { + if (_address.bytes[f * 2] == 0 && _address.bytes[f * 2 + 1] == 0) { + if (current_start == -1) { + current_start = f; + current_length = 1; + } else { + current_length++; + } + if (current_length > longest_length) { + longest_start = current_start; + longest_length = current_length; + } + } else { + current_start = -1; + } + } + for (int f = 0; f < 8; f++) { + if (f < longest_start || f >= longest_start + longest_length) { + uint8_t c1 = _address.bytes[f * 2] >> 4; + uint8_t c2 = _address.bytes[f * 2] & 0xf; + uint8_t c3 = _address.bytes[f * 2 + 1] >> 4; + uint8_t c4 = _address.bytes[f * 2 + 1] & 0xf; + if (c1 > 0) { + n += p.print((char)(c1 < 10 ? '0' + c1 : 'a' + c1 - 10)); + } + if (c1 > 0 || c2 > 0) { + n += p.print((char)(c2 < 10 ? '0' + c2 : 'a' + c2 - 10)); + } + if (c1 > 0 || c2 > 0 || c3 > 0) { + n += p.print((char)(c3 < 10 ? '0' + c3 : 'a' + c3 - 10)); + } + n += p.print((char)(c4 < 10 ? '0' + c4 : 'a' + c4 - 10)); + if (f < 7) { + n += p.print(':'); + } + } else if (f == longest_start) { + if (longest_start == 0) { + n += p.print(':'); + } + n += p.print(':'); + } + } + return n; + } + + // IPv4 + for (int i =0; i < 3; i++) + { + n += p.print(_address.bytes[IPADDRESS_V4_BYTES_INDEX + i], DEC); + n += p.print('.'); + } + n += p.print(_address.bytes[IPADDRESS_V4_BYTES_INDEX + 3], DEC); + return n; +} + +void IPAddress::to_ip_addr_t(ip_addr_t* addr){ + if(_type == IPv6){ + addr->type = IPADDR_TYPE_V6; + addr->u_addr.ip6.addr[0] = _address.dword[0]; + addr->u_addr.ip6.addr[1] = _address.dword[1]; + addr->u_addr.ip6.addr[2] = _address.dword[2]; + addr->u_addr.ip6.addr[3] = _address.dword[3]; +#if LWIP_IPV6_SCOPES + addr->u_addr.ip6.zone = _zone; +#endif /* LWIP_IPV6_SCOPES */ + } else { + addr->type = IPADDR_TYPE_V4; + addr->u_addr.ip4.addr = _address.dword[IPADDRESS_V4_DWORD_INDEX]; + } +} + +const IPAddress IN6ADDR_ANY(IPv6); +const IPAddress INADDR_NONE(0,0,0,0); diff --git a/cores/esp32/IPAddress.h b/cores/esp32/IPAddress.h index 329ca92afe9..c5a8316116b 100644 --- a/cores/esp32/IPAddress.h +++ b/cores/esp32/IPAddress.h @@ -1,82 +1,82 @@ /* - IPAddress.h - Base class that provides IPAddress - Copyright (c) 2011 Adrian McEwen. All right reserved. + IPAddress.h - Base class that provides IPAddress + Copyright (c) 2011 Adrian McEwen. All right reserved. - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ -#ifndef IPAddress_h -#define IPAddress_h +#pragma once #include -#include -#include - -// A class to make it easier to handle and pass around IP addresses +#include "Printable.h" +#include "WString.h" +#include "lwip/ip_addr.h" #define IPADDRESS_V4_BYTES_INDEX 12 #define IPADDRESS_V4_DWORD_INDEX 3 -enum IPType -{ +// A class to make it easier to handle and pass around IP addresses + +enum IPType { IPv4, IPv6 }; -class IPAddress: public Printable -{ +class IPAddress : public Printable { private: union { uint8_t bytes[16]; uint32_t dword[4]; } _address; IPType _type; + uint8_t _zone; // Access the raw byte array containing the address. Because this returns a pointer // to the internal structure rather than a copy of the address this function should only // be used when you know that the usage of the returned uint8_t* will be transient and not // stored. - uint8_t* raw_address() - { - return _type == IPv4 ? &_address.bytes[IPADDRESS_V4_BYTES_INDEX] : _address.bytes; - } + uint8_t* raw_address() { return _type == IPv4 ? &_address.bytes[IPADDRESS_V4_BYTES_INDEX] : _address.bytes; } public: // Constructors + + // Default IPv4 IPAddress(); IPAddress(IPType ip_type); IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); - IPAddress(uint8_t o1, uint8_t o2, uint8_t o3, uint8_t o4, uint8_t o5, uint8_t o6, uint8_t o7, uint8_t o8, uint8_t o9, uint8_t o10, uint8_t o11, uint8_t o12, uint8_t o13, uint8_t o14, uint8_t o15, uint8_t o16); + IPAddress(uint8_t o1, uint8_t o2, uint8_t o3, uint8_t o4, uint8_t o5, uint8_t o6, uint8_t o7, uint8_t o8, uint8_t o9, uint8_t o10, uint8_t o11, uint8_t o12, uint8_t o13, uint8_t o14, uint8_t o15, uint8_t o16, uint8_t z=0); + // IPv4; see implementation note IPAddress(uint32_t address); + // Default IPv4 IPAddress(const uint8_t *address); - IPAddress(IPType ip_type, const uint8_t *address); + IPAddress(IPType ip_type, const uint8_t *address, uint8_t z=0); // If IPv4 fails tries IPv6 see fromString function IPAddress(const char *address); - virtual ~IPAddress() {} + IPAddress(const IPAddress& address); bool fromString(const char *address); bool fromString(const String &address) { return fromString(address.c_str()); } - // Overloaded cast operator to allow IPAddress objects to be used where a - // uint32_t is expected - operator uint32_t() const - { - return _type == IPv4 ? _address.dword[IPADDRESS_V4_DWORD_INDEX] : 0; - } + // Overloaded cast operator to allow IPAddress objects to be used where a uint32_t is expected + // NOTE: IPv4 only; see implementation note + operator uint32_t() const { return _type == IPv4 ? _address.dword[IPADDRESS_V4_DWORD_INDEX] : 0; }; bool operator==(const IPAddress& addr) const; + bool operator!=(const IPAddress& addr) const { return !(*this == addr); }; + + // NOTE: IPv4 only; we don't know the length of the pointer bool operator==(const uint8_t* addr) const; // Overloaded index operator to allow getting and setting individual octets of the address @@ -84,22 +84,25 @@ class IPAddress: public Printable uint8_t& operator[](int index); // Overloaded copy operators to allow initialisation of IPAddress objects from other types + // NOTE: IPv4 only IPAddress& operator=(const uint8_t *address); + // NOTE: IPv4 only; see implementation note IPAddress& operator=(uint32_t address); // If IPv4 fails tries IPv6 see fromString function IPAddress& operator=(const char *address); + IPAddress& operator=(const IPAddress& address); virtual size_t printTo(Print& p) const; String toString() const; IPType type() const { return _type; } - friend class EthernetClass; + void to_ip_addr_t(ip_addr_t* addr); + uint8_t zone() const { return (type() == IPv6)?_zone:0; } + friend class UDP; friend class Client; friend class Server; - friend class DhcpClass; - friend class DNSClient; protected: bool fromString4(const char *address); @@ -108,7 +111,5 @@ class IPAddress: public Printable String toString6() const; }; -// changed to extern because const declaration creates copies in BSS of INADDR_NONE for each CPP unit that includes it -extern IPAddress INADDR_NONE; -extern IPAddress IN6ADDR_ANY; -#endif +extern const IPAddress IN6ADDR_ANY; +extern const IPAddress INADDR_NONE; diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index c43bf46bc30..c1419f44912 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -1546,6 +1546,11 @@ bool WiFiGenericClass::setDualAntennaConfig(uint8_t gpio_ant1, uint8_t gpio_ant2 // ------------------------------------------------ Generic Network function --------------------------------------------- // ----------------------------------------------------------------------------------------------------------------------- +struct dns_api_msg6 { + ip_addr_t ip_addr; + int result; +}; + /** * DNS callback * @param name @@ -1584,7 +1589,7 @@ static esp_err_t wifi_gethostbyname_tcpip_ctx(void *param) */ static void wifi_dns6_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg) { - struct dns_api_msg *msg = (struct dns_api_msg *)callback_arg; + struct dns_api_msg6 *msg = (struct dns_api_msg6 *)callback_arg; if(ipaddr && !msg->result) { msg->ip_addr = *ipaddr; @@ -1637,7 +1642,7 @@ int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult) int WiFiGenericClass::hostByName6(const char* aHostname, ip_addr_t& aResult) { ip_addr_t addr; - struct dns_api_msg arg; + struct dns_api_msg6 arg; memset(&arg, 0x0, sizeof(arg)); waitStatusBits(WIFI_DNS_IDLE_BIT, 16000); diff --git a/libraries/WiFi/src/WiFiGeneric.h b/libraries/WiFi/src/WiFiGeneric.h index ce723409eca..60b60fbef03 100644 --- a/libraries/WiFi/src/WiFiGeneric.h +++ b/libraries/WiFi/src/WiFiGeneric.h @@ -32,6 +32,7 @@ #include "esp_netif_types.h" #include "esp_eth_driver.h" #include "wifi_provisioning/manager.h" +#include "lwip/ip_addr.h" ESP_EVENT_DECLARE_BASE(ARDUINO_EVENTS); @@ -155,11 +156,6 @@ typedef enum { WIFI_TX_ANT_AUTO } wifi_tx_ant_t; -struct dns_api_msg { - ip_addr_t ip_addr; - int result; -}; - class WiFiGenericClass { public: diff --git a/libraries/WiFi/src/WiFiUdp.cpp b/libraries/WiFi/src/WiFiUdp.cpp index 511ee3e6126..683ff90067c 100644 --- a/libraries/WiFi/src/WiFiUdp.cpp +++ b/libraries/WiFi/src/WiFiUdp.cpp @@ -52,7 +52,7 @@ uint8_t WiFiUDP::begin(IPAddress address, uint16_t port){ tx_buffer_len = 0; #if LWIP_IPV6 - if ((udp_server=socket(address.isV6() ? AF_INET6 : AF_INET, SOCK_DGRAM, 0)) == -1){ + if ((udp_server=socket((address.type() == IPv6) ? AF_INET6 : AF_INET, SOCK_DGRAM, 0)) == -1){ #else if ((udp_server=socket(AF_INET, SOCK_DGRAM, 0)) == -1){ #endif @@ -70,19 +70,20 @@ uint8_t WiFiUDP::begin(IPAddress address, uint16_t port){ struct sockaddr_storage serveraddr = {}; size_t sock_size = 0; #if LWIP_IPV6 - if (address.isV6()) { + if (address.type() == IPv6) { struct sockaddr_in6 *tmpaddr = (struct sockaddr_in6 *)&serveraddr; - ip_addr_t * ip_addr = (ip_addr_t*) address; + ip_addr_t addr; + address.to_ip_addr_t(&addr); memset((char *) tmpaddr, 0, sizeof(struct sockaddr_in)); tmpaddr->sin6_family = AF_INET6; tmpaddr->sin6_port = htons(server_port); - tmpaddr->sin6_scope_id = ip_addr->u_addr.ip6.zone; - inet6_addr_from_ip6addr(&tmpaddr->sin6_addr, ip_2_ip6(ip_addr)); + tmpaddr->sin6_scope_id = addr.u_addr.ip6.zone; + inet6_addr_from_ip6addr(&tmpaddr->sin6_addr, ip_2_ip6(&addr)); tmpaddr->sin6_flowinfo = 0; sock_size = sizeof(sockaddr_in6); } else #endif - if (1) { + { struct sockaddr_in *tmpaddr = (struct sockaddr_in *)&serveraddr; memset((char *) tmpaddr, 0, sizeof(struct sockaddr_in)); tmpaddr->sin_family = AF_INET; @@ -103,15 +104,16 @@ uint8_t WiFiUDP::begin(uint16_t p){ return begin(IPAddress(), p); } -uint8_t WiFiUDP::beginMulticast(IPAddress a, uint16_t p){ +uint8_t WiFiUDP::beginMulticast(IPAddress address, uint16_t p){ if(begin(IPAddress(), p)){ - ip_addr_t * ip_addr = (ip_addr_t*) a; - if (ip_addr_ismulticast(ip_addr)) { + ip_addr_t addr; + address.to_ip_addr_t(&addr); + if (ip_addr_ismulticast(&addr)) { #if LWIP_IPV6 - if (IP_IS_V6_VAL(*ip_addr)) { + if (address.type() == IPv6) { struct ipv6_mreq mreq; bool joined = false; - inet6_addr_from_ip6addr(&mreq.ipv6mr_multiaddr, ip_2_ip6(ip_addr)); + inet6_addr_from_ip6addr(&mreq.ipv6mr_multiaddr, ip_2_ip6(&addr)); // iterate on each interface for (netif* intf = netif_list; intf != nullptr; intf = intf->next) { @@ -128,9 +130,9 @@ uint8_t WiFiUDP::beginMulticast(IPAddress a, uint16_t p){ } } else #endif - if (1) { + { struct ip_mreq mreq; - mreq.imr_multiaddr.s_addr = (in_addr_t)a; + mreq.imr_multiaddr.s_addr = (in_addr_t)address; mreq.imr_interface.s_addr = INADDR_ANY; if (setsockopt(udp_server, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { log_e("could not join igmp: %d", errno); @@ -138,7 +140,7 @@ uint8_t WiFiUDP::beginMulticast(IPAddress a, uint16_t p){ return 0; } } - multicast_ip = a; + multicast_ip = address; return 1; } } @@ -158,12 +160,13 @@ void WiFiUDP::stop(){ } if(udp_server == -1) return; - ip_addr_t * mcast_addr = (ip_addr_t*) multicast_ip; - if (!ip_addr_isany(mcast_addr)) { + ip_addr_t addr; + multicast_ip.to_ip_addr_t(&addr); + if (!ip_addr_isany(&addr)) { #if LWIP_IPV6 - if (IP_IS_V6(mcast_addr)) { + if (multicast_ip.type() == IPv6) { struct ipv6_mreq mreq; - inet6_addr_from_ip6addr(&mreq.ipv6mr_multiaddr, ip_2_ip6(mcast_addr)); + inet6_addr_from_ip6addr(&mreq.ipv6mr_multiaddr, ip_2_ip6(&addr)); // iterate on each interface for (netif* intf = netif_list; intf != nullptr; intf = intf->next) { @@ -174,7 +177,7 @@ void WiFiUDP::stop(){ } } else #endif - if (1) { + { struct ip_mreq mreq; mreq.imr_multiaddr.s_addr = (in_addr_t)multicast_ip; mreq.imr_interface.s_addr = (in_addr_t)0; @@ -240,8 +243,10 @@ int WiFiUDP::beginPacket(const char *host, uint16_t port){ } int WiFiUDP::endPacket(){ + ip_addr_t addr; + remote_ip.to_ip_addr_t(&addr); - if (remote_ip.isV4()) { + if (remote_ip.type() == IPv4) { struct sockaddr_in recipient; recipient.sin_addr.s_addr = (uint32_t)remote_ip; recipient.sin_family = AF_INET; @@ -254,7 +259,7 @@ int WiFiUDP::endPacket(){ } else { struct sockaddr_in6 recipient; recipient.sin6_flowinfo = 0; - recipient.sin6_addr = *(in6_addr*)(ip_addr_t*)remote_ip; + recipient.sin6_addr = *(in6_addr*)(ip_addr_t*)(&addr); recipient.sin6_family = AF_INET6; recipient.sin6_port = htons(remote_port); recipient.sin6_scope_id = remote_ip.zone(); @@ -310,17 +315,18 @@ int WiFiUDP::parsePacket(){ else if (si_other_storage.ss_family == AF_INET6) { struct sockaddr_in6 &si_other = (sockaddr_in6&) si_other_storage; remote_ip = IPAddress(IPv6, (uint8_t*)&si_other.sin6_addr, si_other.sin6_scope_id); // force IPv6 - ip_addr_t *ip_addr = (ip_addr_t*) remote_ip; + ip_addr_t addr; + remote_ip.to_ip_addr_t(&addr); /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ - if (IP_IS_V6_VAL(*ip_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(ip_addr))) { - unmap_ipv4_mapped_ipv6(ip_2_ip4(ip_addr), ip_2_ip6(ip_addr)); - IP_SET_TYPE_VAL(*ip_addr, IPADDR_TYPE_V4); + if (remote_ip.type() == IPv6 && ip6_addr_isipv4mappedipv6(ip_2_ip6(&addr))) { + unmap_ipv4_mapped_ipv6(ip_2_ip4(&addr), ip_2_ip6(&addr)); + IP_SET_TYPE_VAL(addr, IPADDR_TYPE_V4); } remote_port = ntohs(si_other.sin6_port); } #endif // LWIP_IPV6=1 else { - remote_ip = *IP_ADDR_ANY; + remote_ip = ip_addr_any.u_addr.ip4.addr; remote_port = 0; } if (len > 0) { From 305d2766e51321ba2f6bbba67e10a70ef09dd185 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 19 Dec 2023 00:45:33 +0200 Subject: [PATCH 05/21] Add from ip_addr_t conversion and better toString implementation --- cores/esp32/IPAddress.cpp | 51 +++++++++++++++++++++----------------- cores/esp32/IPAddress.h | 7 +++--- cores/esp32/StreamString.h | 3 ++- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/cores/esp32/IPAddress.cpp b/cores/esp32/IPAddress.cpp index bfa481274e1..bd88a1a1096 100644 --- a/cores/esp32/IPAddress.cpp +++ b/cores/esp32/IPAddress.cpp @@ -20,6 +20,7 @@ #include "IPAddress.h" #include "Print.h" #include "lwip/netif.h" +#include "StreamString.h" IPAddress::IPAddress() : IPAddress(IPv4) {} @@ -103,31 +104,11 @@ IPAddress::IPAddress(const IPAddress& address) *this = address; } -String IPAddress::toString4() const -{ - char szRet[16]; - snprintf(szRet, sizeof(szRet), "%u.%u.%u.%u", _address.bytes[IPADDRESS_V4_BYTES_INDEX], _address.bytes[IPADDRESS_V4_BYTES_INDEX + 1], _address.bytes[IPADDRESS_V4_BYTES_INDEX + 2], _address.bytes[IPADDRESS_V4_BYTES_INDEX + 3]); - return String(szRet); -} - -String IPAddress::toString6() const -{ - char szRet[40]; - snprintf(szRet, sizeof(szRet), "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", - _address.bytes[0], _address.bytes[1], _address.bytes[2], _address.bytes[3], - _address.bytes[4], _address.bytes[5], _address.bytes[6], _address.bytes[7], - _address.bytes[8], _address.bytes[9], _address.bytes[10], _address.bytes[11], - _address.bytes[12], _address.bytes[13], _address.bytes[14], _address.bytes[15]); - return String(szRet); -} - String IPAddress::toString() const { - if (_type == IPv4) { - return toString4(); - } else { - return toString6(); - } + StreamString s; + printTo(s); + return String(s); } bool IPAddress::fromString(const char *address) { @@ -373,6 +354,13 @@ size_t IPAddress::printTo(Print& p) const n += p.print(':'); } } + // add a zone if zone-id is non-zero + if(_zone > 0){ + n += p.print('%'); + char if_name[NETIF_NAMESIZE]; + netif_index_to_name(_zone, if_name); + n += p.print(if_name); + } return n; } @@ -402,5 +390,22 @@ void IPAddress::to_ip_addr_t(ip_addr_t* addr){ } } +IPAddress& IPAddress::from_ip_addr_t(ip_addr_t* addr){ + if(addr->type == IPADDR_TYPE_V6){ + _type = IPv6; + _address.dword[0] = addr->u_addr.ip6.addr[0]; + _address.dword[1] = addr->u_addr.ip6.addr[1]; + _address.dword[2] = addr->u_addr.ip6.addr[2]; + _address.dword[3] = addr->u_addr.ip6.addr[3]; +#if LWIP_IPV6_SCOPES + _zone = addr->u_addr.ip6.zone; +#endif /* LWIP_IPV6_SCOPES */ + } else { + _type = IPv4; + _address.dword[IPADDRESS_V4_DWORD_INDEX] = addr->u_addr.ip4.addr; + } + return *this; +} + const IPAddress IN6ADDR_ANY(IPv6); const IPAddress INADDR_NONE(0,0,0,0); diff --git a/cores/esp32/IPAddress.h b/cores/esp32/IPAddress.h index c5a8316116b..2eedec83df5 100644 --- a/cores/esp32/IPAddress.h +++ b/cores/esp32/IPAddress.h @@ -97,9 +97,12 @@ class IPAddress : public Printable { IPType type() const { return _type; } - void to_ip_addr_t(ip_addr_t* addr); uint8_t zone() const { return (type() == IPv6)?_zone:0; } + // LwIP conversions + void to_ip_addr_t(ip_addr_t* addr); + IPAddress& from_ip_addr_t(ip_addr_t* addr); + friend class UDP; friend class Client; friend class Server; @@ -107,8 +110,6 @@ class IPAddress : public Printable { protected: bool fromString4(const char *address); bool fromString6(const char *address); - String toString4() const; - String toString6() const; }; extern const IPAddress IN6ADDR_ANY; diff --git a/cores/esp32/StreamString.h b/cores/esp32/StreamString.h index dbdf3fb0097..fa983786c70 100644 --- a/cores/esp32/StreamString.h +++ b/cores/esp32/StreamString.h @@ -21,7 +21,8 @@ #ifndef STREAMSTRING_H_ #define STREAMSTRING_H_ - +#include "Stream.h" +#include "WString.h" class StreamString: public Stream, public String { From 41fb1a1215d842f1977353e0e891b1f4d95c96de Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 19 Dec 2023 00:50:07 +0200 Subject: [PATCH 06/21] Use constant for IPAddress offset @sgryphon is this better? --- libraries/WiFi/src/WiFiClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/WiFi/src/WiFiClient.cpp b/libraries/WiFi/src/WiFiClient.cpp index d8f1a31a62b..195acbd7c40 100644 --- a/libraries/WiFi/src/WiFiClient.cpp +++ b/libraries/WiFi/src/WiFiClient.cpp @@ -614,7 +614,7 @@ IPAddress WiFiClient::remoteIP(int fd) const if (((struct sockaddr*)&addr)->sa_family == AF_INET6) { struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&addr; if (IN6_IS_ADDR_V4MAPPED(saddr6->sin6_addr.un.u32_addr)) { - return IPAddress(IPv4, (uint8_t*)saddr6->sin6_addr.s6_addr+12); + return IPAddress(IPv4, (uint8_t*)saddr6->sin6_addr.s6_addr+IPADDRESS_V4_BYTES_INDEX); } else { return IPAddress(IPv6, (uint8_t*)(saddr6->sin6_addr.s6_addr), saddr6->sin6_scope_id); } From b37ce6c772a1aeddd998cde7119958c220f8fe65 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 19 Dec 2023 01:54:32 +0200 Subject: [PATCH 07/21] Combine hostByName to support both IPv6 and IPv4 results --- libraries/WiFi/src/WiFiClient.cpp | 15 +--- libraries/WiFi/src/WiFiGeneric.cpp | 112 ++++++++++------------------- libraries/WiFi/src/WiFiGeneric.h | 3 +- 3 files changed, 39 insertions(+), 91 deletions(-) diff --git a/libraries/WiFi/src/WiFiClient.cpp b/libraries/WiFi/src/WiFiClient.cpp index 195acbd7c40..99b153c7629 100644 --- a/libraries/WiFi/src/WiFiClient.cpp +++ b/libraries/WiFi/src/WiFiClient.cpp @@ -319,21 +319,8 @@ int WiFiClient::connect(const char *host, uint16_t port) int WiFiClient::connect(const char *host, uint16_t port, int32_t timeout_ms) { - if (WiFiGenericClass::getStatusBits() & WIFI_WANT_IP6_BIT) { - ip_addr_t srv6; - if(!WiFiGenericClass::hostByName6(host, srv6)){ - return 0; - } - if (srv6.type == IPADDR_TYPE_V4) { - IPAddress ip(srv6.u_addr.ip4.addr); - return connect(ip, port, timeout_ms); - } else { - IPAddress ip(IPv6, (uint8_t*)&srv6.u_addr.ip6.addr[0]); - return connect(ip, port, timeout_ms); - } - } IPAddress srv((uint32_t)0); - if(!WiFiGenericClass::hostByName(host, srv)){ + if(!WiFiGenericClass::hostByName(host, srv, (WiFiGenericClass::getStatusBits() & WIFI_WANT_IP6_BIT))){ return 0; } return connect(srv, port, timeout_ms); diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index c1419f44912..d0075170b76 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -1546,10 +1546,12 @@ bool WiFiGenericClass::setDualAntennaConfig(uint8_t gpio_ant1, uint8_t gpio_ant2 // ------------------------------------------------ Generic Network function --------------------------------------------- // ----------------------------------------------------------------------------------------------------------------------- -struct dns_api_msg6 { - ip_addr_t ip_addr; +typedef struct gethostbynameParameters { + const char *hostname; + ip_addr_t addr; + uint8_t addr_type; int result; -}; +} gethostbynameParameters_t; /** * DNS callback @@ -1559,18 +1561,18 @@ struct dns_api_msg6 { */ static void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg) { + gethostbynameParameters_t *parameters = static_cast(callback_arg); if(ipaddr) { - (*reinterpret_cast(callback_arg)) = ipaddr->u_addr.ip4.addr; + if(parameters->result == 0){ + memcpy(&(parameters->addr), ipaddr, sizeof(ip_addr_t)); + parameters->result = 1; + } + } else { + parameters->result = -1; } xEventGroupSetBits(_arduino_event_group, WIFI_DNS_DONE_BIT); } -typedef struct gethostbynameParameters { - const char *hostname; - ip_addr_t addr; - void *callback_arg; -} gethostbynameParameters_t; - /** * Callback to execute dns_gethostbyname in lwIP's TCP/IP context * @param param Parameters for dns_gethostbyname call @@ -1578,26 +1580,7 @@ typedef struct gethostbynameParameters { static esp_err_t wifi_gethostbyname_tcpip_ctx(void *param) { gethostbynameParameters_t *parameters = static_cast(param); - return dns_gethostbyname(parameters->hostname, ¶meters->addr, &wifi_dns_found_callback, parameters->callback_arg); -} - -/** - * IPv6 compatible DNS callback - * @param name - * @param ipaddr - * @param callback_arg - */ -static void wifi_dns6_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg) -{ - struct dns_api_msg6 *msg = (struct dns_api_msg6 *)callback_arg; - - if(ipaddr && !msg->result) { - msg->ip_addr = *ipaddr; - msg->result = 1; - } else { - msg->result = -1; - } - xEventGroupSetBits(_arduino_event_group, WIFI_DNS_DONE_BIT); + return dns_gethostbyname_addrtype(parameters->hostname, ¶meters->addr, &wifi_dns_found_callback, parameters, parameters->addr_type); } /** @@ -1607,60 +1590,39 @@ static void wifi_dns6_found_callback(const char *name, const ip_addr_t *ipaddr, * @return 1 if aIPAddrString was successfully converted to an IP address, * else error code */ -int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult) +int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult, bool preferV6) { - if (!aResult.fromString(aHostname)) - { - gethostbynameParameters_t params; - params.hostname = aHostname; - params.callback_arg = &aResult; - aResult = static_cast(0); + err_t err = ERR_OK; + gethostbynameParameters_t params; + + aResult = static_cast(0); + params.hostname = aHostname; + params.addr_type = preferV6?LWIP_DNS_ADDRTYPE_IPV6_IPV4:LWIP_DNS_ADDRTYPE_IPV4_IPV6; + params.result = 0; + aResult.to_ip_addr_t(&(params.addr)); + + if (!aResult.fromString(aHostname)) { waitStatusBits(WIFI_DNS_IDLE_BIT, 16000); clearStatusBits(WIFI_DNS_IDLE_BIT | WIFI_DNS_DONE_BIT); - err_t err = esp_netif_tcpip_exec(wifi_gethostbyname_tcpip_ctx, ¶ms); - if(err == ERR_OK && params.addr.u_addr.ip4.addr) { - aResult = params.addr.u_addr.ip4.addr; - } else if(err == ERR_INPROGRESS) { + + err = esp_netif_tcpip_exec(wifi_gethostbyname_tcpip_ctx, ¶ms); + if (err == ERR_OK) { + aResult.from_ip_addr_t(&(params.addr)); + } else if (err == ERR_INPROGRESS) { waitStatusBits(WIFI_DNS_DONE_BIT, 15000); //real internal timeout in lwip library is 14[s] clearStatusBits(WIFI_DNS_DONE_BIT); + if (params.result == 1) { + aResult.from_ip_addr_t(&(params.addr)); + err = ERR_OK; + } } setStatusBits(WIFI_DNS_IDLE_BIT); - if((uint32_t)aResult == 0){ - log_e("DNS Failed for %s", aHostname); - } } - return (uint32_t)aResult != 0; -} - -/** - * Resolve the given hostname to an IP6 address. - * @param aHostname Name to be resolved - * @param aResult IPv6Address structure to store the returned IP address - * @return 1 if aHostname was successfully converted to an IP address, - * else error code - */ -int WiFiGenericClass::hostByName6(const char* aHostname, ip_addr_t& aResult) -{ - ip_addr_t addr; - struct dns_api_msg6 arg; - - memset(&arg, 0x0, sizeof(arg)); - waitStatusBits(WIFI_DNS_IDLE_BIT, 16000); - clearStatusBits(WIFI_DNS_IDLE_BIT | WIFI_DNS_DONE_BIT); - - err_t err = dns_gethostbyname_addrtype(aHostname, &addr, &wifi_dns6_found_callback, - &arg, LWIP_DNS_ADDRTYPE_IPV6_IPV4); - if(err == ERR_OK) { - aResult = addr; - } else if(err == ERR_INPROGRESS) { - waitStatusBits(WIFI_DNS_DONE_BIT, 15000); //real internal timeout in lwip library is 14[s] - clearStatusBits(WIFI_DNS_DONE_BIT); - if (arg.result == 1) { - aResult = arg.ip_addr; - } + if (err == ERR_OK) { + return 1; } - setStatusBits(WIFI_DNS_IDLE_BIT); - return (uint32_t)err == ERR_OK || (err == ERR_INPROGRESS && arg.result == 1); + log_e("DNS Failed for '%s' with error '%d' and result '%d'", aHostname, err, params.result); + return err; } IPAddress WiFiGenericClass::calculateNetworkID(IPAddress ip, IPAddress subnet) { diff --git a/libraries/WiFi/src/WiFiGeneric.h b/libraries/WiFi/src/WiFiGeneric.h index 60b60fbef03..90db296d188 100644 --- a/libraries/WiFi/src/WiFiGeneric.h +++ b/libraries/WiFi/src/WiFiGeneric.h @@ -198,7 +198,6 @@ class WiFiGenericClass static const char * getHostname(); static bool setHostname(const char * hostname); static bool hostname(const String& aHostname) { return setHostname(aHostname.c_str()); } - static int hostByName6(const char *aHostname, ip_addr_t& aResult); static esp_err_t _eventCallback(arduino_event_t *event); @@ -219,7 +218,7 @@ class WiFiGenericClass static bool _isReconnectableReason(uint8_t reason); public: - static int hostByName(const char *aHostname, IPAddress &aResult); + static int hostByName(const char *aHostname, IPAddress &aResult, bool preferV6=false); static IPAddress calculateNetworkID(IPAddress ip, IPAddress subnet); static IPAddress calculateBroadcast(IPAddress ip, IPAddress subnet); From e333afb0a1e86aa9bb2655543226c74c3d0f0cee Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 11 Jan 2024 12:26:34 +0200 Subject: [PATCH 08/21] implement logic to use v6 dns only when global v6 address is assigned and remove IPv6Address --- CMakeLists.txt | 1 - cores/esp32/IPv6Address.cpp | 90 --------------------------- cores/esp32/IPv6Address.h | 94 ----------------------------- docs/source/api/wifi.rst | 4 +- libraries/AsyncUDP/src/AsyncUDP.cpp | 70 ++++----------------- libraries/AsyncUDP/src/AsyncUDP.h | 12 +--- libraries/ESPmDNS/src/ESPmDNS.cpp | 8 +-- libraries/ESPmDNS/src/ESPmDNS.h | 3 +- libraries/Ethernet/src/ETH.cpp | 49 +++++++++++++-- libraries/Ethernet/src/ETH.h | 5 +- libraries/WiFi/src/WiFi.h | 1 - libraries/WiFi/src/WiFiAP.cpp | 16 ++--- libraries/WiFi/src/WiFiAP.h | 2 +- libraries/WiFi/src/WiFiClient.cpp | 2 +- libraries/WiFi/src/WiFiGeneric.cpp | 51 +++++++++++++--- libraries/WiFi/src/WiFiGeneric.h | 10 ++- libraries/WiFi/src/WiFiMulti.cpp | 4 +- libraries/WiFi/src/WiFiSTA.cpp | 48 ++++++++------- libraries/WiFi/src/WiFiSTA.h | 6 +- 19 files changed, 166 insertions(+), 310 deletions(-) delete mode 100644 cores/esp32/IPv6Address.cpp delete mode 100644 cores/esp32/IPv6Address.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0834ae1ec34..e121aaf3e3c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,7 +51,6 @@ set(CORE_SRCS cores/esp32/FunctionalInterrupt.cpp cores/esp32/HardwareSerial.cpp cores/esp32/IPAddress.cpp - cores/esp32/IPv6Address.cpp cores/esp32/libb64/cdecode.c cores/esp32/libb64/cencode.c cores/esp32/main.cpp diff --git a/cores/esp32/IPv6Address.cpp b/cores/esp32/IPv6Address.cpp deleted file mode 100644 index 7d3c0de5f53..00000000000 --- a/cores/esp32/IPv6Address.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - IPv6Address.cpp - Base class that provides IPv6Address - Copyright (c) 2011 Adrian McEwen. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include - -IPv6Address::IPv6Address() -{ - memset(_address.bytes, 0, sizeof(_address.bytes)); -} - -IPv6Address::IPv6Address(const uint8_t *address) -{ - memcpy(_address.bytes, address, sizeof(_address.bytes)); -} - -IPv6Address::IPv6Address(const uint32_t *address) -{ - memcpy(_address.bytes, (const uint8_t *)address, sizeof(_address.bytes)); -} - -IPv6Address& IPv6Address::operator=(const uint8_t *address) -{ - memcpy(_address.bytes, address, sizeof(_address.bytes)); - return *this; -} - -bool IPv6Address::operator==(const uint8_t* addr) const -{ - return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0; -} - -size_t IPv6Address::printTo(Print& p) const -{ - size_t n = 0; - for(int i = 0; i < 16; i+=2) { - if(i){ - n += p.print(':'); - } - n += p.printf("%02x", _address.bytes[i]); - n += p.printf("%02x", _address.bytes[i+1]); - - } - return n; -} - -String IPv6Address::toString() const -{ - char szRet[40]; - sprintf(szRet,"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", - _address.bytes[0], _address.bytes[1], _address.bytes[2], _address.bytes[3], - _address.bytes[4], _address.bytes[5], _address.bytes[6], _address.bytes[7], - _address.bytes[8], _address.bytes[9], _address.bytes[10], _address.bytes[11], - _address.bytes[12], _address.bytes[13], _address.bytes[14], _address.bytes[15]); - return String(szRet); -} - -bool IPv6Address::fromString(const char *address) -{ - //format 0011:2233:4455:6677:8899:aabb:ccdd:eeff - if(strlen(address) != 39){ - return false; - } - char * pos = (char *)address; - size_t i = 0; - for(i = 0; i < 16; i+=2) { - if(!sscanf(pos, "%2hhx", &_address.bytes[i]) || !sscanf(pos+2, "%2hhx", &_address.bytes[i+1])){ - return false; - } - pos += 5; - } - return true; -} diff --git a/cores/esp32/IPv6Address.h b/cores/esp32/IPv6Address.h deleted file mode 100644 index e61d0e7b371..00000000000 --- a/cores/esp32/IPv6Address.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - IPv6Address.h - Base class that provides IPv6Address - Copyright (c) 2011 Adrian McEwen. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef IPv6Address_h -#define IPv6Address_h - -#include -#include -#include - -// A class to make it easier to handle and pass around IP addresses - -class IPv6Address: public Printable -{ -private: - union { - uint8_t bytes[16]; // IPv4 address - uint32_t dword[4]; - } _address; - - // Access the raw byte array containing the address. Because this returns a pointer - // to the internal structure rather than a copy of the address this function should only - // be used when you know that the usage of the returned uint8_t* will be transient and not - // stored. - uint8_t* raw_address() - { - return _address.bytes; - } - -public: - // Constructors - IPv6Address(); - IPv6Address(const uint8_t *address); - IPv6Address(const uint32_t *address); - virtual ~IPv6Address() {} - - bool fromString(const char *address); - bool fromString(const String &address) { return fromString(address.c_str()); } - - operator const uint8_t*() const - { - return _address.bytes; - } - operator const uint32_t*() const - { - return _address.dword; - } - bool operator==(const IPv6Address& addr) const - { - return (_address.dword[0] == addr._address.dword[0]) - && (_address.dword[1] == addr._address.dword[1]) - && (_address.dword[2] == addr._address.dword[2]) - && (_address.dword[3] == addr._address.dword[3]); - } - bool operator==(const uint8_t* addr) const; - - // Overloaded index operator to allow getting and setting individual octets of the address - uint8_t operator[](int index) const - { - return _address.bytes[index]; - } - uint8_t& operator[](int index) - { - return _address.bytes[index]; - } - - // Overloaded copy operators to allow initialisation of IPv6Address objects from other types - IPv6Address& operator=(const uint8_t *address); - - virtual size_t printTo(Print& p) const; - String toString() const; - - friend class UDP; - friend class Client; - friend class Server; -}; - -#endif diff --git a/docs/source/api/wifi.rst b/docs/source/api/wifi.rst index c906cdaa588..f5f2fe03f2e 100644 --- a/docs/source/api/wifi.rst +++ b/docs/source/api/wifi.rst @@ -345,9 +345,9 @@ Function to get the IPv6 address. .. code-block:: arduino - IPv6Address softAPIPv6(); + IPAddress softAPIPv6(); -The function will return the AP IPv6 address in ``IPv6Address`` format. +The function will return the AP IPv6 address in ``IPAddress`` format. softAPgetHostname ***************** diff --git a/libraries/AsyncUDP/src/AsyncUDP.cpp b/libraries/AsyncUDP/src/AsyncUDP.cpp index e533755da7a..1c650f1a721 100644 --- a/libraries/AsyncUDP/src/AsyncUDP.cpp +++ b/libraries/AsyncUDP/src/AsyncUDP.cpp @@ -424,12 +424,12 @@ IPAddress AsyncUDPPacket::localIP() return IPAddress(_localIp.u_addr.ip4.addr); } -IPv6Address AsyncUDPPacket::localIPv6() +IPAddress AsyncUDPPacket::localIPv6() { if(_localIp.type != IPADDR_TYPE_V6){ - return IPv6Address(); + return IPAddress(IPv6); } - return IPv6Address(_localIp.u_addr.ip6.addr); + return IPAddress(IPv6, (const uint8_t *)_localIp.u_addr.ip6.addr, _localIp.u_addr.ip6.zone); } uint16_t AsyncUDPPacket::localPort() @@ -445,12 +445,12 @@ IPAddress AsyncUDPPacket::remoteIP() return IPAddress(_remoteIp.u_addr.ip4.addr); } -IPv6Address AsyncUDPPacket::remoteIPv6() +IPAddress AsyncUDPPacket::remoteIPv6() { if(_remoteIp.type != IPADDR_TYPE_V6){ - return IPv6Address(); + return IPAddress(IPv6); } - return IPv6Address(_remoteIp.u_addr.ip6.addr); + return IPAddress(IPv6, (const uint8_t *)_remoteIp.u_addr.ip6.addr, _remoteIp.u_addr.ip6.zone); } uint16_t AsyncUDPPacket::remotePort() @@ -739,32 +739,28 @@ bool AsyncUDP::listen(uint16_t port) bool AsyncUDP::listen(const IPAddress addr, uint16_t port) { ip_addr_t laddr; - laddr.type = IPADDR_TYPE_V4; - laddr.u_addr.ip4.addr = addr; + addr.to_ip_addr_t(&laddr); return listen(&laddr, port); } bool AsyncUDP::listenMulticast(const IPAddress addr, uint16_t port, uint8_t ttl, tcpip_adapter_if_t tcpip_if) { ip_addr_t laddr; - laddr.type = IPADDR_TYPE_V4; - laddr.u_addr.ip4.addr = addr; + addr.to_ip_addr_t(&laddr); return listenMulticast(&laddr, port, ttl, tcpip_if); } bool AsyncUDP::connect(const IPAddress addr, uint16_t port) { ip_addr_t daddr; - daddr.type = IPADDR_TYPE_V4; - daddr.u_addr.ip4.addr = addr; + addr.to_ip_addr_t(&daddr); return connect(&daddr, port); } size_t AsyncUDP::writeTo(const uint8_t *data, size_t len, const IPAddress addr, uint16_t port, tcpip_adapter_if_t tcpip_if) { ip_addr_t daddr; - daddr.type = IPADDR_TYPE_V4; - daddr.u_addr.ip4.addr = addr; + addr.to_ip_addr_t(&daddr); return writeTo(data, len, &daddr, port, tcpip_if); } @@ -776,44 +772,12 @@ IPAddress AsyncUDP::listenIP() return IPAddress(_pcb->remote_ip.u_addr.ip4.addr); } -bool AsyncUDP::listen(const IPv6Address addr, uint16_t port) -{ - ip_addr_t laddr; - laddr.type = IPADDR_TYPE_V6; - memcpy((uint8_t*)(laddr.u_addr.ip6.addr), (const uint8_t*)addr, 16); - return listen(&laddr, port); -} - -bool AsyncUDP::listenMulticast(const IPv6Address addr, uint16_t port, uint8_t ttl, tcpip_adapter_if_t tcpip_if) -{ - ip_addr_t laddr; - laddr.type = IPADDR_TYPE_V6; - memcpy((uint8_t*)(laddr.u_addr.ip6.addr), (const uint8_t*)addr, 16); - return listenMulticast(&laddr, port, ttl, tcpip_if); -} - -bool AsyncUDP::connect(const IPv6Address addr, uint16_t port) -{ - ip_addr_t daddr; - daddr.type = IPADDR_TYPE_V6; - memcpy((uint8_t*)(daddr.u_addr.ip6.addr), (const uint8_t*)addr, 16); - return connect(&daddr, port); -} - -size_t AsyncUDP::writeTo(const uint8_t *data, size_t len, const IPv6Address addr, uint16_t port, tcpip_adapter_if_t tcpip_if) -{ - ip_addr_t daddr; - daddr.type = IPADDR_TYPE_V6; - memcpy((uint8_t*)(daddr.u_addr.ip6.addr), (const uint8_t*)addr, 16); - return writeTo(data, len, &daddr, port, tcpip_if); -} - -IPv6Address AsyncUDP::listenIPv6() +IPAddress AsyncUDP::listenIPv6() { if(!_pcb || _pcb->remote_ip.type != IPADDR_TYPE_V6){ - return IPv6Address(); + return IPAddress(IPv6); } - return IPv6Address(_pcb->remote_ip.u_addr.ip6.addr); + return IPAddress(IPv6, (const uint8_t *)_pcb->remote_ip.u_addr.ip6.addr, _pcb->remote_ip.u_addr.ip6.zone); } size_t AsyncUDP::write(const uint8_t *data, size_t len) @@ -866,14 +830,6 @@ size_t AsyncUDP::sendTo(AsyncUDPMessage &message, const IPAddress addr, uint16_t return writeTo(message.data(), message.length(), addr, port, tcpip_if); } -size_t AsyncUDP::sendTo(AsyncUDPMessage &message, const IPv6Address addr, uint16_t port, tcpip_adapter_if_t tcpip_if) -{ - if(!message) { - return 0; - } - return writeTo(message.data(), message.length(), addr, port, tcpip_if); -} - size_t AsyncUDP::send(AsyncUDPMessage &message) { if(!message) { diff --git a/libraries/AsyncUDP/src/AsyncUDP.h b/libraries/AsyncUDP/src/AsyncUDP.h index c9f365d1197..31d075191df 100644 --- a/libraries/AsyncUDP/src/AsyncUDP.h +++ b/libraries/AsyncUDP/src/AsyncUDP.h @@ -2,7 +2,6 @@ #define ESPASYNCUDP_H #include "IPAddress.h" -#include "IPv6Address.h" #include "Print.h" #include "Stream.h" #include @@ -81,10 +80,10 @@ class AsyncUDPPacket : public Stream tcpip_adapter_if_t interface(); IPAddress localIP(); - IPv6Address localIPv6(); + IPAddress localIPv6(); uint16_t localPort(); IPAddress remoteIP(); - IPv6Address remoteIPv6(); + IPAddress remoteIPv6(); uint16_t remotePort(); void remoteMac(uint8_t * mac); @@ -121,22 +120,18 @@ class AsyncUDP : public Print bool listen(const ip_addr_t *addr, uint16_t port); bool listen(const IPAddress addr, uint16_t port); - bool listen(const IPv6Address addr, uint16_t port); bool listen(uint16_t port); bool listenMulticast(const ip_addr_t *addr, uint16_t port, uint8_t ttl=1, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX); bool listenMulticast(const IPAddress addr, uint16_t port, uint8_t ttl=1, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX); - bool listenMulticast(const IPv6Address addr, uint16_t port, uint8_t ttl=1, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX); bool connect(const ip_addr_t *addr, uint16_t port); bool connect(const IPAddress addr, uint16_t port); - bool connect(const IPv6Address addr, uint16_t port); void close(); size_t writeTo(const uint8_t *data, size_t len, const ip_addr_t *addr, uint16_t port, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX); size_t writeTo(const uint8_t *data, size_t len, const IPAddress addr, uint16_t port, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX); - size_t writeTo(const uint8_t *data, size_t len, const IPv6Address addr, uint16_t port, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX); size_t write(const uint8_t *data, size_t len); size_t write(uint8_t data); @@ -147,14 +142,13 @@ class AsyncUDP : public Print size_t sendTo(AsyncUDPMessage &message, const ip_addr_t *addr, uint16_t port, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX); size_t sendTo(AsyncUDPMessage &message, const IPAddress addr, uint16_t port, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX); - size_t sendTo(AsyncUDPMessage &message, const IPv6Address addr, uint16_t port, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX); size_t send(AsyncUDPMessage &message); size_t broadcastTo(AsyncUDPMessage &message, uint16_t port, tcpip_adapter_if_t tcpip_if=TCPIP_ADAPTER_IF_MAX); size_t broadcast(AsyncUDPMessage &message); IPAddress listenIP(); - IPv6Address listenIPv6(); + IPAddress listenIPv6(); bool connected(); esp_err_t lastErr(); operator bool(); diff --git a/libraries/ESPmDNS/src/ESPmDNS.cpp b/libraries/ESPmDNS/src/ESPmDNS.cpp index bccc4de5758..faef0427ea1 100644 --- a/libraries/ESPmDNS/src/ESPmDNS.cpp +++ b/libraries/ESPmDNS/src/ESPmDNS.cpp @@ -281,20 +281,20 @@ IPAddress MDNSResponder::IP(int idx) { return IPAddress(); } -IPv6Address MDNSResponder::IPv6(int idx) { +IPAddress MDNSResponder::IPv6(int idx) { mdns_result_t * result = _getResult(idx); if(!result){ log_e("Result %d not found", idx); - return IPv6Address(); + return IPAddress(IPv6); } mdns_ip_addr_t * addr = result->addr; while(addr){ if(addr->addr.type == MDNS_IP_PROTOCOL_V6){ - return IPv6Address(addr->addr.u_addr.ip6.addr); + return IPAddress(IPv6, (const uint8_t *)addr->addr.u_addr.ip6.addr, addr->addr.u_addr.ip6.zone); } addr = addr->next; } - return IPv6Address(); + return IPAddress(IPv6); } uint16_t MDNSResponder::port(int idx) { diff --git a/libraries/ESPmDNS/src/ESPmDNS.h b/libraries/ESPmDNS/src/ESPmDNS.h index 6a5cb56ffba..ea7ef14f6ef 100644 --- a/libraries/ESPmDNS/src/ESPmDNS.h +++ b/libraries/ESPmDNS/src/ESPmDNS.h @@ -42,7 +42,6 @@ License (MIT license): #define ESP32MDNS_H #include "Arduino.h" -#include "IPv6Address.h" #include "mdns.h" #include "esp_interface.h" @@ -109,7 +108,7 @@ class MDNSResponder { String hostname(int idx); IPAddress IP(int idx); - IPv6Address IPv6(int idx); + IPAddress IPv6(int idx); uint16_t port(int idx); int numTxt(int idx); bool hasTxt(int idx, const char * key); diff --git a/libraries/Ethernet/src/ETH.cpp b/libraries/Ethernet/src/ETH.cpp index 40c408ee69a..fa30735d9a4 100644 --- a/libraries/Ethernet/src/ETH.cpp +++ b/libraries/Ethernet/src/ETH.cpp @@ -861,24 +861,41 @@ bool ETHClass::setHostname(const char * hostname) return esp_netif_set_hostname(_esp_netif, hostname) == 0; } -bool ETHClass::enableIpV6() +bool ETHClass::enableIPv6(bool en) { if(_esp_netif == NULL){ return false; } return esp_netif_create_ip6_linklocal(_esp_netif) == 0; + // if (en) + // WiFiGenericClass::setStatusBits(ETH_WANT_IP6_BIT); + // else + // WiFiGenericClass::clearStatusBits(ETH_WANT_IP6_BIT); + // return true; } -IPv6Address ETHClass::localIPv6() +IPAddress ETHClass::localIPv6() { if(_esp_netif == NULL){ - return IPv6Address(); + return IPAddress(IPv6); } static esp_ip6_addr_t addr; if(esp_netif_get_ip6_linklocal(_esp_netif, &addr)){ - return IPv6Address(); + return IPAddress(IPv6); } - return IPv6Address(addr.addr); + return IPAddress(IPv6, (const uint8_t *)addr.addr, addr.zone); +} + +IPAddress ETHClass::globalIPv6() +{ + if(_esp_netif == NULL){ + return IPAddress(IPv6); + } + static esp_ip6_addr_t addr; + if(esp_netif_get_ip6_global(_esp_netif, &addr)){ + return IPAddress(IPv6); + } + return IPAddress(IPv6, (const uint8_t *)addr.addr, addr.zone); } const char * ETHClass::ifkey(void) @@ -1031,6 +1048,28 @@ void ETHClass::printInfo(Print & out){ out.print(dnsIP()); out.println(); + const char * types[] = { "UNKNOWN", "GLOBAL", "LINK_LOCAL", "SITE_LOCAL", "UNIQUE_LOCAL", "IPV4_MAPPED_IPV6" }; + esp_ip6_addr_t if_ip6[5]; + int v6addrs = esp_netif_get_all_ip6(_esp_netif, if_ip6); + for (int i = 0; i < v6addrs; ++i){ + out.print(" "); + out.print("inet6 "); + IPAddress(IPv6, (const uint8_t *)if_ip6[i].addr, if_ip6[i].zone).printTo(out); + out.print(" type "); + out.print(types[esp_netif_ip6_get_addr_type(&if_ip6[i])]); + out.println(); + } + + // out.print(" "); + // out.print("inet6 "); + // localIPv6().printTo(out); + // out.println(); + + // out.print(" "); + // out.print("inet6 "); + // globalIPv6().printTo(out); + // out.println(); + out.println(); } diff --git a/libraries/Ethernet/src/ETH.h b/libraries/Ethernet/src/ETH.h index 7ef39ef561f..7159ebd4574 100644 --- a/libraries/Ethernet/src/ETH.h +++ b/libraries/Ethernet/src/ETH.h @@ -145,8 +145,9 @@ class ETHClass { IPAddress broadcastIP(); IPAddress networkID(); uint8_t subnetCIDR(); - bool enableIpV6(); - IPv6Address localIPv6(); + bool enableIPv6(bool en=true); + IPAddress localIPv6(); + IPAddress globalIPv6(); const char * ifkey(void); const char * desc(void); String impl_name(void); diff --git a/libraries/WiFi/src/WiFi.h b/libraries/WiFi/src/WiFi.h index 457f913ae8e..30b9e31f744 100644 --- a/libraries/WiFi/src/WiFi.h +++ b/libraries/WiFi/src/WiFi.h @@ -26,7 +26,6 @@ #include "Print.h" #include "IPAddress.h" -#include "IPv6Address.h" #include "WiFiType.h" #include "WiFiSTA.h" diff --git a/libraries/WiFi/src/WiFiAP.cpp b/libraries/WiFi/src/WiFiAP.cpp index a88547f9a89..84e508ee491 100644 --- a/libraries/WiFi/src/WiFiAP.cpp +++ b/libraries/WiFi/src/WiFiAP.cpp @@ -421,16 +421,18 @@ bool WiFiAPClass::softAPenableIpV6() /** * Get the softAP interface IPv6 address. - * @return IPv6Address softAP IPv6 + * @return IPAddress softAP IPv6 */ -IPv6Address WiFiAPClass::softAPIPv6() + +IPAddress WiFiAPClass::softAPIPv6() { - esp_ip6_addr_t addr; + static esp_ip6_addr_t addr; if(WiFiGenericClass::getMode() == WIFI_MODE_NULL){ - return IPv6Address(); + return IPAddress(IPv6); } - if(esp_netif_get_ip6_linklocal(get_esp_interface_netif(ESP_IF_WIFI_AP), &addr)) { - return IPv6Address(); + if(esp_netif_get_ip6_linklocal(get_esp_interface_netif(ESP_IF_WIFI_STA), &addr)){ + return IPAddress(IPv6); } - return IPv6Address(addr.addr); + return IPAddress(IPv6, (const uint8_t *)addr.addr, addr.zone); } + diff --git a/libraries/WiFi/src/WiFiAP.h b/libraries/WiFi/src/WiFiAP.h index 626a5b5b350..5e6e187a5c7 100644 --- a/libraries/WiFi/src/WiFiAP.h +++ b/libraries/WiFi/src/WiFiAP.h @@ -57,7 +57,7 @@ class WiFiAPClass uint8_t softAPSubnetCIDR(); bool softAPenableIpV6(); - IPv6Address softAPIPv6(); + IPAddress softAPIPv6(); const char * softAPgetHostname(); bool softAPsetHostname(const char * hostname); diff --git a/libraries/WiFi/src/WiFiClient.cpp b/libraries/WiFi/src/WiFiClient.cpp index 99b153c7629..4127bcad3de 100644 --- a/libraries/WiFi/src/WiFiClient.cpp +++ b/libraries/WiFi/src/WiFiClient.cpp @@ -320,7 +320,7 @@ int WiFiClient::connect(const char *host, uint16_t port) int WiFiClient::connect(const char *host, uint16_t port, int32_t timeout_ms) { IPAddress srv((uint32_t)0); - if(!WiFiGenericClass::hostByName(host, srv, (WiFiGenericClass::getStatusBits() & WIFI_WANT_IP6_BIT))){ + if(!WiFiGenericClass::hostByName(host, srv)){ return 0; } return connect(srv, port, timeout_ms); diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index d0075170b76..3069b22f8af 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -1051,12 +1051,13 @@ esp_err_t WiFiGenericClass::_eventCallback(arduino_event_t *event) } } else if(event->event_id == ARDUINO_EVENT_WIFI_STA_STOP) { WiFiSTAClass::_setStatus(WL_STOPPED); - clearStatusBits(STA_STARTED_BIT | STA_CONNECTED_BIT | STA_HAS_IP_BIT | STA_HAS_IP6_BIT); + clearStatusBits(STA_STARTED_BIT | STA_CONNECTED_BIT | STA_HAS_IP_BIT | STA_HAS_IP6_BIT | STA_HAS_IP6_GLOBAL_BIT); } else if(event->event_id == ARDUINO_EVENT_WIFI_STA_CONNECTED) { + if (getStatusBits() & STA_WANT_IP6_BIT){ + esp_netif_create_ip6_linklocal(get_esp_interface_netif(ESP_IF_WIFI_STA)); + } WiFiSTAClass::_setStatus(WL_IDLE_STATUS); setStatusBits(STA_CONNECTED_BIT); - if (getStatusBits() & WIFI_WANT_IP6_BIT) - esp_netif_create_ip6_linklocal(esp_netifs[ESP_IF_WIFI_STA]); } else if(event->event_id == ARDUINO_EVENT_WIFI_STA_DISCONNECTED) { uint8_t reason = event->event_info.wifi_sta_disconnected.reason; // Reason 0 causes crash, use reason 1 (UNSPECIFIED) instead @@ -1074,7 +1075,7 @@ esp_err_t WiFiGenericClass::_eventCallback(arduino_event_t *event) } else { WiFiSTAClass::_setStatus(WL_DISCONNECTED); } - clearStatusBits(STA_CONNECTED_BIT | STA_HAS_IP_BIT | STA_HAS_IP6_BIT); + clearStatusBits(STA_CONNECTED_BIT | STA_HAS_IP_BIT | STA_HAS_IP6_BIT | STA_HAS_IP6_GLOBAL_BIT); bool DoReconnect = false; if(reason == WIFI_REASON_ASSOC_LEAVE) { //Voluntarily disconnected. Don't reconnect! @@ -1126,11 +1127,14 @@ esp_err_t WiFiGenericClass::_eventCallback(arduino_event_t *event) } else if(event->event_id == ARDUINO_EVENT_ETH_START) { setStatusBits(ETH_STARTED_BIT); } else if(event->event_id == ARDUINO_EVENT_ETH_STOP) { - clearStatusBits(ETH_STARTED_BIT | ETH_CONNECTED_BIT | ETH_HAS_IP_BIT | ETH_HAS_IP6_BIT); + clearStatusBits(ETH_STARTED_BIT | ETH_CONNECTED_BIT | ETH_HAS_IP_BIT | ETH_HAS_IP6_BIT | ETH_HAS_IP6_GLOBAL_BIT); } else if(event->event_id == ARDUINO_EVENT_ETH_CONNECTED) { + if (getStatusBits() & ETH_WANT_IP6_BIT){ + esp_netif_create_ip6_linklocal(get_esp_interface_netif(ESP_IF_ETH)); + } setStatusBits(ETH_CONNECTED_BIT); } else if(event->event_id == ARDUINO_EVENT_ETH_DISCONNECTED) { - clearStatusBits(ETH_CONNECTED_BIT | ETH_HAS_IP_BIT | ETH_HAS_IP6_BIT); + clearStatusBits(ETH_CONNECTED_BIT | ETH_HAS_IP_BIT | ETH_HAS_IP6_BIT | ETH_HAS_IP6_GLOBAL_BIT); } else if(event->event_id == ARDUINO_EVENT_ETH_GOT_IP) { #if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG uint8_t * ip = (uint8_t *)&(event->event_info.got_ip.ip_info.ip.addr); @@ -1147,10 +1151,16 @@ esp_err_t WiFiGenericClass::_eventCallback(arduino_event_t *event) } else if(event->event_id == ARDUINO_EVENT_WIFI_STA_GOT_IP6) { setStatusBits(STA_CONNECTED_BIT | STA_HAS_IP6_BIT); + if(esp_netif_ip6_get_addr_type((esp_ip6_addr_t*)&(event->event_info.got_ip6.ip6_info.ip)) == ESP_IP6_ADDR_IS_GLOBAL){ + setStatusBits(STA_HAS_IP6_GLOBAL_BIT); + } } else if(event->event_id == ARDUINO_EVENT_WIFI_AP_GOT_IP6) { setStatusBits(AP_HAS_IP6_BIT); } else if(event->event_id == ARDUINO_EVENT_ETH_GOT_IP6) { setStatusBits(ETH_CONNECTED_BIT | ETH_HAS_IP6_BIT); + if(esp_netif_ip6_get_addr_type((esp_ip6_addr_t*)&(event->event_info.got_ip6.ip6_info.ip)) == ESP_IP6_ADDR_IS_GLOBAL){ + setStatusBits(ETH_HAS_IP6_GLOBAL_BIT); + } } else if(event->event_id == ARDUINO_EVENT_SC_GOT_SSID_PSWD) { WiFi.begin( (const char *)event->event_info.sc_got_ssid_pswd.ssid, @@ -1567,6 +1577,15 @@ static void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, v memcpy(&(parameters->addr), ipaddr, sizeof(ip_addr_t)); parameters->result = 1; } + IPAddress addr; + addr.from_ip_addr_t((ip_addr_t *)ipaddr); + Serial.print("dns_found "); + addr.printTo(Serial); + if(ipaddr->type == IPADDR_TYPE_V6){ + Serial.print(" type "); + Serial.print((int)esp_netif_ip6_get_addr_type((esp_ip6_addr_t*)&(ipaddr->u_addr.ip6))); + } + Serial.println(); } else { parameters->result = -1; } @@ -1595,9 +1614,20 @@ int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult, bool err_t err = ERR_OK; gethostbynameParameters_t params; + // This should generally check if we have a global address assigned to one of the interfaces. + // If such address is not assigned, there is no point in trying to get V6 from DNS as we will not be able to reach it. + // That is of course, if 'preferV6' is not set to true + static bool hasGlobalV6 = false; + bool hasGlobalV6Now = (getStatusBits() & NET_HAS_IP6_GLOBAL_BIT) != 0; + if(hasGlobalV6 != hasGlobalV6Now){ + hasGlobalV6 = hasGlobalV6Now; + dns_clear_cache(); + log_d("Clearing DNS cache"); + } + aResult = static_cast(0); params.hostname = aHostname; - params.addr_type = preferV6?LWIP_DNS_ADDRTYPE_IPV6_IPV4:LWIP_DNS_ADDRTYPE_IPV4_IPV6; + params.addr_type = (preferV6 || hasGlobalV6)?LWIP_DNS_ADDRTYPE_IPV6_IPV4:LWIP_DNS_ADDRTYPE_IPV4; params.result = 0; aResult.to_ip_addr_t(&(params.addr)); @@ -1608,6 +1638,13 @@ int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult, bool err = esp_netif_tcpip_exec(wifi_gethostbyname_tcpip_ctx, ¶ms); if (err == ERR_OK) { aResult.from_ip_addr_t(&(params.addr)); + Serial.print("dns_cache "); + aResult.printTo(Serial); + if(params.addr.type == IPADDR_TYPE_V6){ + Serial.print(" type "); + Serial.print((int)esp_netif_ip6_get_addr_type((esp_ip6_addr_t*)&(params.addr.u_addr.ip6))); + } + Serial.println(); } else if (err == ERR_INPROGRESS) { waitStatusBits(WIFI_DNS_DONE_BIT, 15000); //real internal timeout in lwip library is 14[s] clearStatusBits(WIFI_DNS_DONE_BIT); diff --git a/libraries/WiFi/src/WiFiGeneric.h b/libraries/WiFi/src/WiFiGeneric.h index 90db296d188..c74c386a1eb 100644 --- a/libraries/WiFi/src/WiFiGeneric.h +++ b/libraries/WiFi/src/WiFiGeneric.h @@ -138,11 +138,18 @@ static const int ETH_STARTED_BIT = BIT7; static const int ETH_CONNECTED_BIT = BIT8; static const int ETH_HAS_IP_BIT = BIT9; static const int ETH_HAS_IP6_BIT = BIT10; + static const int WIFI_SCANNING_BIT = BIT11; static const int WIFI_SCAN_DONE_BIT= BIT12; static const int WIFI_DNS_IDLE_BIT = BIT13; static const int WIFI_DNS_DONE_BIT = BIT14; -static const int WIFI_WANT_IP6_BIT = BIT15; + +static const int STA_WANT_IP6_BIT = BIT15; +static const int ETH_WANT_IP6_BIT = BIT16; + +static const int STA_HAS_IP6_GLOBAL_BIT = BIT17; +static const int ETH_HAS_IP6_GLOBAL_BIT = BIT18; +static const int NET_HAS_IP6_GLOBAL_BIT = STA_HAS_IP6_GLOBAL_BIT | ETH_HAS_IP6_GLOBAL_BIT; typedef enum { WIFI_RX_ANT0 = 0, @@ -228,6 +235,7 @@ class WiFiGenericClass friend class WiFiSTAClass; friend class WiFiScanClass; friend class WiFiAPClass; + friend class ETHClass; }; #endif /* ESP32WIFIGENERIC_H_ */ diff --git a/libraries/WiFi/src/WiFiMulti.cpp b/libraries/WiFi/src/WiFiMulti.cpp index 9e7f03c6531..320c5c68c46 100644 --- a/libraries/WiFi/src/WiFiMulti.cpp +++ b/libraries/WiFi/src/WiFiMulti.cpp @@ -160,9 +160,9 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout) if(bestNetwork.ssid) { log_i("[WIFI] Connecting BSSID: %02X:%02X:%02X:%02X:%02X:%02X SSID: %s Channel: %d (%d)", bestBSSID[0], bestBSSID[1], bestBSSID[2], bestBSSID[3], bestBSSID[4], bestBSSID[5], bestNetwork.ssid, bestChannel, bestNetworkDb); - WiFi.begin(bestNetwork.ssid, bestNetwork.passphrase, bestChannel, bestBSSID); if (ipv6_support == true) - WiFi.IPv6(true); + WiFi.enableIPv6(); + WiFi.begin(bestNetwork.ssid, bestNetwork.passphrase, bestChannel, bestBSSID); status = WiFi.status(); auto startTime = millis(); diff --git a/libraries/WiFi/src/WiFiSTA.cpp b/libraries/WiFi/src/WiFiSTA.cpp index ca3fb6b5e40..23f62b82cfa 100644 --- a/libraries/WiFi/src/WiFiSTA.cpp +++ b/libraries/WiFi/src/WiFiSTA.cpp @@ -806,43 +806,49 @@ int8_t WiFiSTAClass::RSSI(void) /** * Enable IPv6 on the station interface. + * Should be called before WiFi.begin() + * * @return true on success */ -bool WiFiSTAClass::enableIpV6() +bool WiFiSTAClass::enableIPv6(bool en) { - if(WiFiGenericClass::getMode() == WIFI_MODE_NULL){ - return false; - } - return esp_netif_create_ip6_linklocal(get_esp_interface_netif(ESP_IF_WIFI_STA)) == ESP_OK; + if (en) + WiFiGenericClass::setStatusBits(STA_WANT_IP6_BIT); + else + WiFiGenericClass::clearStatusBits(STA_WANT_IP6_BIT); + return true; } /** - * Enable IPv6 support on the station interface. - * @return true on success + * Get the station interface link-local IPv6 address. + * @return IPAddress */ -bool WiFiSTAClass::IPv6(bool state) +IPAddress WiFiSTAClass::localIPv6() { - if (state) - WiFiGenericClass::setStatusBits(WIFI_WANT_IP6_BIT); - else - WiFiGenericClass::clearStatusBits(WIFI_WANT_IP6_BIT); - return true; + static esp_ip6_addr_t addr; + if(WiFiGenericClass::getMode() == WIFI_MODE_NULL){ + return IPAddress(IPv6); + } + if(esp_netif_get_ip6_linklocal(get_esp_interface_netif(ESP_IF_WIFI_STA), &addr)){ + return IPAddress(IPv6); + } + return IPAddress(IPv6, (const uint8_t *)addr.addr, addr.zone); } /** - * Get the station interface IPv6 address. - * @return IPv6Address + * Get the station interface global IPv6 address. + * @return IPAddress */ -IPv6Address WiFiSTAClass::localIPv6() +IPAddress WiFiSTAClass::globalIPv6() { - esp_ip6_addr_t addr; + static esp_ip6_addr_t addr; if(WiFiGenericClass::getMode() == WIFI_MODE_NULL){ - return IPv6Address(); + return IPAddress(IPv6); } - if(esp_netif_get_ip6_linklocal(get_esp_interface_netif(ESP_IF_WIFI_STA), &addr)) { - return IPv6Address(); + if(esp_netif_get_ip6_global(get_esp_interface_netif(ESP_IF_WIFI_STA), &addr)){ + return IPAddress(IPv6); } - return IPv6Address(addr.addr); + return IPAddress(IPv6, (const uint8_t *)addr.addr, addr.zone); } diff --git a/libraries/WiFi/src/WiFiSTA.h b/libraries/WiFi/src/WiFiSTA.h index 12e2f0bd4a4..4fbb789aa04 100644 --- a/libraries/WiFi/src/WiFiSTA.h +++ b/libraries/WiFi/src/WiFiSTA.h @@ -93,9 +93,9 @@ class WiFiSTAClass IPAddress networkID(); uint8_t subnetCIDR(); - bool enableIpV6(); - bool IPv6(bool state); - IPv6Address localIPv6(); + bool enableIPv6(bool en=true); + IPAddress localIPv6(); + IPAddress globalIPv6(); // STA WiFi info static wl_status_t status(); From c7e63e66e5199d38f592b4c702363a1f49bd682f Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 11 Jan 2024 12:31:25 +0200 Subject: [PATCH 09/21] Rename softAPenableIPv6 --- docs/source/api/wifi.rst | 4 ++-- .../examples/WiFiBlueToothSwitch/WiFiBlueToothSwitch.ino | 2 +- libraries/WiFi/examples/WiFiIPv6/WiFiIPv6.ino | 6 +++--- libraries/WiFi/src/WiFiAP.cpp | 2 +- libraries/WiFi/src/WiFiAP.h | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/source/api/wifi.rst b/docs/source/api/wifi.rst index f5f2fe03f2e..86bf306a3f4 100644 --- a/docs/source/api/wifi.rst +++ b/docs/source/api/wifi.rst @@ -327,14 +327,14 @@ Get the softAP subnet mask. IPAddress softAPSubnetMask(); -softAPenableIpV6 +softAPenableIPv6 **************** Function used to enable the IPv6 support. .. code-block:: arduino - bool softAPenableIpV6(); + bool softAPenableIPv6(); The function will return ``true`` if the configuration is successful. diff --git a/libraries/WiFi/examples/WiFiBlueToothSwitch/WiFiBlueToothSwitch.ino b/libraries/WiFi/examples/WiFiBlueToothSwitch/WiFiBlueToothSwitch.ino index 771a531a480..be9aa239627 100644 --- a/libraries/WiFi/examples/WiFiBlueToothSwitch/WiFiBlueToothSwitch.ino +++ b/libraries/WiFi/examples/WiFiBlueToothSwitch/WiFiBlueToothSwitch.ino @@ -89,7 +89,6 @@ void WiFiEvent(WiFiEvent_t event){ break; case ARDUINO_EVENT_WIFI_STA_CONNECTED: Serial.println("STA Connected"); - WiFi.enableIpV6(); break; case ARDUINO_EVENT_WIFI_STA_GOT_IP6: Serial.print("STA IPv6: "); @@ -114,6 +113,7 @@ void setup() { Serial.begin(115200); pinMode(0, INPUT_PULLUP); WiFi.onEvent(WiFiEvent); // Will call WiFiEvent() from another thread. + WiFi.enableIPv6(); Serial.print("ESP32 SDK: "); Serial.println(ESP.getSdkVersion()); Serial.println("Press the button to select the next mode"); diff --git a/libraries/WiFi/examples/WiFiIPv6/WiFiIPv6.ino b/libraries/WiFi/examples/WiFiIPv6/WiFiIPv6.ino index 3dcba56eec2..2db8dabb5d1 100644 --- a/libraries/WiFi/examples/WiFiIPv6/WiFiIPv6.ino +++ b/libraries/WiFi/examples/WiFiIPv6/WiFiIPv6.ino @@ -71,15 +71,13 @@ void WiFiEvent(WiFiEvent_t event){ //can set ap hostname here WiFi.softAPsetHostname(AP_SSID); //enable ap ipv6 here - WiFi.softAPenableIpV6(); + WiFi.softAPenableIPv6(); break; case ARDUINO_EVENT_WIFI_STA_START: //set sta hostname here WiFi.setHostname(AP_SSID); break; case ARDUINO_EVENT_WIFI_STA_CONNECTED: - //enable sta ipv6 here - WiFi.enableIpV6(); break; case ARDUINO_EVENT_WIFI_STA_GOT_IP6: Serial.print("STA IPv6: "); @@ -108,6 +106,8 @@ void setup(){ WiFi.onEvent(WiFiEvent); // Will call WiFiEvent() from another thread. WiFi.mode(WIFI_MODE_APSTA); WiFi.softAP(AP_SSID); + //enable sta ipv6 here + WiFi.enableIPv6(); WiFi.begin(STA_SSID, STA_PASS); } diff --git a/libraries/WiFi/src/WiFiAP.cpp b/libraries/WiFi/src/WiFiAP.cpp index 84e508ee491..79917daeb6e 100644 --- a/libraries/WiFi/src/WiFiAP.cpp +++ b/libraries/WiFi/src/WiFiAP.cpp @@ -411,7 +411,7 @@ bool WiFiAPClass::softAPsetHostname(const char * hostname) * Enable IPv6 on the softAP interface. * @return true on success */ -bool WiFiAPClass::softAPenableIpV6() +bool WiFiAPClass::softAPenableIPv6() { if(WiFiGenericClass::getMode() == WIFI_MODE_NULL){ return false; diff --git a/libraries/WiFi/src/WiFiAP.h b/libraries/WiFi/src/WiFiAP.h index 5e6e187a5c7..9c2d1b96aeb 100644 --- a/libraries/WiFi/src/WiFiAP.h +++ b/libraries/WiFi/src/WiFiAP.h @@ -56,7 +56,7 @@ class WiFiAPClass IPAddress softAPSubnetMask(); uint8_t softAPSubnetCIDR(); - bool softAPenableIpV6(); + bool softAPenableIPv6(); IPAddress softAPIPv6(); const char * softAPgetHostname(); From 55aaa6f210a83ac73c79ed4c32df967e8d454f51 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 11 Jan 2024 12:37:22 +0200 Subject: [PATCH 10/21] Rename mDNS methods --- .../ESPmDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino | 2 +- libraries/ESPmDNS/src/ESPmDNS.cpp | 4 ++-- libraries/ESPmDNS/src/ESPmDNS.h | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/ESPmDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino b/libraries/ESPmDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino index 6f2dfddfb3b..9e582b3236a 100644 --- a/libraries/ESPmDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino +++ b/libraries/ESPmDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino @@ -70,7 +70,7 @@ void browseService(const char * service, const char * proto){ Serial.print(": "); Serial.print(MDNS.hostname(i)); Serial.print(" ("); - Serial.print(MDNS.IP(i)); + Serial.print(MDNS.address(i)); Serial.print(":"); Serial.print(MDNS.port(i)); Serial.println(")"); diff --git a/libraries/ESPmDNS/src/ESPmDNS.cpp b/libraries/ESPmDNS/src/ESPmDNS.cpp index faef0427ea1..21d93aa4e2a 100644 --- a/libraries/ESPmDNS/src/ESPmDNS.cpp +++ b/libraries/ESPmDNS/src/ESPmDNS.cpp @@ -265,7 +265,7 @@ String MDNSResponder::hostname(int idx) { return String(result->hostname); } -IPAddress MDNSResponder::IP(int idx) { +IPAddress MDNSResponder::address(int idx) { mdns_result_t * result = _getResult(idx); if(!result){ log_e("Result %d not found", idx); @@ -281,7 +281,7 @@ IPAddress MDNSResponder::IP(int idx) { return IPAddress(); } -IPAddress MDNSResponder::IPv6(int idx) { +IPAddress MDNSResponder::addressV6(int idx) { mdns_result_t * result = _getResult(idx); if(!result){ log_e("Result %d not found", idx); diff --git a/libraries/ESPmDNS/src/ESPmDNS.h b/libraries/ESPmDNS/src/ESPmDNS.h index ea7ef14f6ef..01ca7518d2f 100644 --- a/libraries/ESPmDNS/src/ESPmDNS.h +++ b/libraries/ESPmDNS/src/ESPmDNS.h @@ -107,8 +107,8 @@ class MDNSResponder { } String hostname(int idx); - IPAddress IP(int idx); - IPAddress IPv6(int idx); + IPAddress address(int idx); + IPAddress addressV6(int idx); uint16_t port(int idx); int numTxt(int idx); bool hasTxt(int idx, const char * key); From c4f366c9667a6d2fb2e7f7869765fddf233970bf Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 11 Jan 2024 12:43:50 +0200 Subject: [PATCH 11/21] fix IPAddress method to work with const address --- cores/esp32/IPAddress.cpp | 2 +- cores/esp32/IPAddress.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cores/esp32/IPAddress.cpp b/cores/esp32/IPAddress.cpp index bd88a1a1096..13502ee05d3 100644 --- a/cores/esp32/IPAddress.cpp +++ b/cores/esp32/IPAddress.cpp @@ -374,7 +374,7 @@ size_t IPAddress::printTo(Print& p) const return n; } -void IPAddress::to_ip_addr_t(ip_addr_t* addr){ +void IPAddress::to_ip_addr_t(ip_addr_t* addr) const { if(_type == IPv6){ addr->type = IPADDR_TYPE_V6; addr->u_addr.ip6.addr[0] = _address.dword[0]; diff --git a/cores/esp32/IPAddress.h b/cores/esp32/IPAddress.h index 2eedec83df5..88b1bf627f0 100644 --- a/cores/esp32/IPAddress.h +++ b/cores/esp32/IPAddress.h @@ -100,7 +100,7 @@ class IPAddress : public Printable { uint8_t zone() const { return (type() == IPv6)?_zone:0; } // LwIP conversions - void to_ip_addr_t(ip_addr_t* addr); + void to_ip_addr_t(ip_addr_t* addr) const; IPAddress& from_ip_addr_t(ip_addr_t* addr); friend class UDP; From 701d35f20e587f1e874794b08bf630ba86eb636c Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 11 Jan 2024 16:02:45 +0200 Subject: [PATCH 12/21] Some cleanup and do not print zone in IPAddress --- cores/esp32/IPAddress.cpp | 12 ++-- docs/source/api/wifi.rst | 2 +- libraries/Ethernet/src/ETH.cpp | 47 ++++++++-------- libraries/WiFi/examples/WiFiIPv6/WiFiIPv6.ino | 4 +- libraries/WiFi/src/WiFiAP.cpp | 15 +++-- libraries/WiFi/src/WiFiAP.h | 2 +- libraries/WiFi/src/WiFiGeneric.cpp | 55 +++++++++++++------ libraries/WiFi/src/WiFiGeneric.h | 52 ++++++++++-------- libraries/WiFi/src/WiFiMulti.cpp | 3 +- libraries/WiFi/src/WiFiSTA.cpp | 11 ++-- 10 files changed, 120 insertions(+), 83 deletions(-) diff --git a/cores/esp32/IPAddress.cpp b/cores/esp32/IPAddress.cpp index 13502ee05d3..69ccc2ec881 100644 --- a/cores/esp32/IPAddress.cpp +++ b/cores/esp32/IPAddress.cpp @@ -355,12 +355,12 @@ size_t IPAddress::printTo(Print& p) const } } // add a zone if zone-id is non-zero - if(_zone > 0){ - n += p.print('%'); - char if_name[NETIF_NAMESIZE]; - netif_index_to_name(_zone, if_name); - n += p.print(if_name); - } + // if(_zone > 0){ + // n += p.print('%'); + // char if_name[NETIF_NAMESIZE]; + // netif_index_to_name(_zone, if_name); + // n += p.print(if_name); + // } return n; } diff --git a/docs/source/api/wifi.rst b/docs/source/api/wifi.rst index 86bf306a3f4..ea6e86cd3eb 100644 --- a/docs/source/api/wifi.rst +++ b/docs/source/api/wifi.rst @@ -334,7 +334,7 @@ Function used to enable the IPv6 support. .. code-block:: arduino - bool softAPenableIPv6(); + bool softAPenableIPv6(bool enable=true); The function will return ``true`` if the configuration is successful. diff --git a/libraries/Ethernet/src/ETH.cpp b/libraries/Ethernet/src/ETH.cpp index fa30735d9a4..9587b22719d 100644 --- a/libraries/Ethernet/src/ETH.cpp +++ b/libraries/Ethernet/src/ETH.cpp @@ -401,13 +401,13 @@ bool ETHClass::beginSPI(eth_phy_type_t type, uint8_t phy_addr, int cs, int irq, // Init SPI bus if(_pin_sck >= 0 && _pin_miso >= 0 && _pin_mosi >= 0){ - spi_bus_config_t buscfg = { - .mosi_io_num = _pin_mosi, - .miso_io_num = _pin_miso, - .sclk_io_num = _pin_sck, - .quadwp_io_num = -1, - .quadhd_io_num = -1, - }; + spi_bus_config_t buscfg; + memset(&buscfg, 0, sizeof(spi_bus_config_t)); + buscfg.mosi_io_num = _pin_mosi; + buscfg.miso_io_num = _pin_miso; + buscfg.sclk_io_num = _pin_sck; + buscfg.quadwp_io_num = -1; + buscfg.quadhd_io_num = -1; ret = spi_bus_initialize(spi_host, &buscfg, SPI_DMA_CH_AUTO); if(ret != ESP_OK){ log_e("SPI bus initialize failed: %d", ret); @@ -433,13 +433,13 @@ bool ETHClass::beginSPI(eth_phy_type_t type, uint8_t phy_addr, int cs, int irq, phy_config.reset_gpio_num = _pin_rst; // Configure SPI interface for specific SPI module - spi_device_interface_config_t spi_devcfg = { - .mode = 0, - .clock_speed_hz = _spi_freq_mhz * 1000 * 1000, - .input_delay_ns = 20, - .spics_io_num = _pin_cs, - .queue_size = 20, - }; + spi_device_interface_config_t spi_devcfg; + memset(&spi_devcfg, 0, sizeof(spi_device_interface_config_t)); + spi_devcfg.mode = 0; + spi_devcfg.clock_speed_hz = _spi_freq_mhz * 1000 * 1000; + spi_devcfg.input_delay_ns = 20; + spi_devcfg.spics_io_num = _pin_cs; + spi_devcfg.queue_size = 20; esp_eth_mac_t *mac = NULL; esp_eth_phy_t *phy = NULL; @@ -863,15 +863,16 @@ bool ETHClass::setHostname(const char * hostname) bool ETHClass::enableIPv6(bool en) { - if(_esp_netif == NULL){ - return false; + // if(_esp_netif == NULL){ + // return false; + // } + // return esp_netif_create_ip6_linklocal(_esp_netif) == 0; + if (en) { + WiFiGenericClass::setStatusBits(ETH_WANT_IP6_BIT); + } else { + WiFiGenericClass::clearStatusBits(ETH_WANT_IP6_BIT); } - return esp_netif_create_ip6_linklocal(_esp_netif) == 0; - // if (en) - // WiFiGenericClass::setStatusBits(ETH_WANT_IP6_BIT); - // else - // WiFiGenericClass::clearStatusBits(ETH_WANT_IP6_BIT); - // return true; + return true; } IPAddress ETHClass::localIPv6() @@ -1048,7 +1049,7 @@ void ETHClass::printInfo(Print & out){ out.print(dnsIP()); out.println(); - const char * types[] = { "UNKNOWN", "GLOBAL", "LINK_LOCAL", "SITE_LOCAL", "UNIQUE_LOCAL", "IPV4_MAPPED_IPV6" }; + static const char * types[] = { "UNKNOWN", "GLOBAL", "LINK_LOCAL", "SITE_LOCAL", "UNIQUE_LOCAL", "IPV4_MAPPED_IPV6" }; esp_ip6_addr_t if_ip6[5]; int v6addrs = esp_netif_get_all_ip6(_esp_netif, if_ip6); for (int i = 0; i < v6addrs; ++i){ diff --git a/libraries/WiFi/examples/WiFiIPv6/WiFiIPv6.ino b/libraries/WiFi/examples/WiFiIPv6/WiFiIPv6.ino index 2db8dabb5d1..c7edd384d82 100644 --- a/libraries/WiFi/examples/WiFiIPv6/WiFiIPv6.ino +++ b/libraries/WiFi/examples/WiFiIPv6/WiFiIPv6.ino @@ -70,8 +70,6 @@ void WiFiEvent(WiFiEvent_t event){ case ARDUINO_EVENT_WIFI_AP_START: //can set ap hostname here WiFi.softAPsetHostname(AP_SSID); - //enable ap ipv6 here - WiFi.softAPenableIPv6(); break; case ARDUINO_EVENT_WIFI_STA_START: //set sta hostname here @@ -105,6 +103,8 @@ void setup(){ WiFi.disconnect(true); WiFi.onEvent(WiFiEvent); // Will call WiFiEvent() from another thread. WiFi.mode(WIFI_MODE_APSTA); + //enable ap ipv6 here + WiFi.softAPenableIPv6(); WiFi.softAP(AP_SSID); //enable sta ipv6 here WiFi.enableIPv6(); diff --git a/libraries/WiFi/src/WiFiAP.cpp b/libraries/WiFi/src/WiFiAP.cpp index 79917daeb6e..b02b929bce9 100644 --- a/libraries/WiFi/src/WiFiAP.cpp +++ b/libraries/WiFi/src/WiFiAP.cpp @@ -411,12 +411,18 @@ bool WiFiAPClass::softAPsetHostname(const char * hostname) * Enable IPv6 on the softAP interface. * @return true on success */ -bool WiFiAPClass::softAPenableIPv6() +bool WiFiAPClass::softAPenableIPv6(bool enable) { - if(WiFiGenericClass::getMode() == WIFI_MODE_NULL){ - return false; + if (enable) { + WiFiGenericClass::setStatusBits(AP_WANT_IP6_BIT); + } else { + WiFiGenericClass::clearStatusBits(AP_WANT_IP6_BIT); } - return esp_netif_create_ip6_linklocal(get_esp_interface_netif(ESP_IF_WIFI_AP)) == ESP_OK; + return true; + // if(WiFiGenericClass::getMode() == WIFI_MODE_NULL){ + // return false; + // } + // return esp_netif_create_ip6_linklocal(get_esp_interface_netif(ESP_IF_WIFI_AP)) == ESP_OK; } /** @@ -430,6 +436,7 @@ IPAddress WiFiAPClass::softAPIPv6() if(WiFiGenericClass::getMode() == WIFI_MODE_NULL){ return IPAddress(IPv6); } + if(esp_netif_get_ip6_linklocal(get_esp_interface_netif(ESP_IF_WIFI_STA), &addr)){ return IPAddress(IPv6); } diff --git a/libraries/WiFi/src/WiFiAP.h b/libraries/WiFi/src/WiFiAP.h index 9c2d1b96aeb..a07fab54335 100644 --- a/libraries/WiFi/src/WiFiAP.h +++ b/libraries/WiFi/src/WiFiAP.h @@ -56,7 +56,7 @@ class WiFiAPClass IPAddress softAPSubnetMask(); uint8_t softAPSubnetCIDR(); - bool softAPenableIPv6(); + bool softAPenableIPv6(bool enable=true); IPAddress softAPIPv6(); const char * softAPgetHostname(); diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index 3069b22f8af..f79e6debee1 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -42,6 +42,7 @@ extern "C" { #include "lwip/opt.h" #include "lwip/err.h" #include "lwip/dns.h" +#include "lwip/netif.h" #include "dhcpserver/dhcpserver.h" #include "dhcpserver/dhcpserver_options.h" @@ -459,7 +460,13 @@ static void _arduino_event_cb(void* arg, esp_event_base_t event_base, int32_t ev } else if (event_base == IP_EVENT && event_id == IP_EVENT_GOT_IP6) { ip_event_got_ip6_t * event = (ip_event_got_ip6_t*)event_data; esp_interface_t iface = get_esp_netif_interface(event->esp_netif); - log_v("IF[%d] Got IPv6: IP Index: %d, Zone: %d, " IPV6STR, iface, event->ip_index, event->ip6_info.ip.zone, IPV62STR(event->ip6_info.ip)); +#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE + char if_name[NETIF_NAMESIZE] = {0,}; + netif_index_to_name(event->ip6_info.ip.zone, if_name); + esp_ip6_addr_type_t addr_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip); + static const char * addr_types[] = { "UNKNOWN", "GLOBAL", "LINK_LOCAL", "SITE_LOCAL", "UNIQUE_LOCAL", "IPV4_MAPPED_IPV6" }; + log_v("IF %s Got IPv6: Interface: %d, IP Index: %d, Type: %s, Zone: %d (%s), Address: " IPV6STR, esp_netif_get_desc(event->esp_netif), iface, event->ip_index, addr_types[addr_type], event->ip6_info.ip.zone, if_name, IPV62STR(event->ip6_info.ip)); +#endif memcpy(&arduino_event.event_info.got_ip6, event_data, sizeof(ip_event_got_ip6_t)); if(iface == ESP_IF_WIFI_STA){ arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_GOT_IP6; @@ -554,6 +561,8 @@ static void _arduino_event_cb(void* arg, esp_event_base_t event_base, int32_t ev } } +static uint32_t _initial_bits = NET_DNS_IDLE_BIT; + static bool _start_network_event_task(){ if(!_arduino_event_group){ _arduino_event_group = xEventGroupCreate(); @@ -561,7 +570,7 @@ static bool _start_network_event_task(){ log_e("Network Event Group Create Failed!"); return false; } - xEventGroupSetBits(_arduino_event_group, WIFI_DNS_IDLE_BIT); + xEventGroupSetBits(_arduino_event_group, _initial_bits); } if(!_arduino_event_queue){ _arduino_event_queue = xQueueCreate(32, sizeof(arduino_event_t*)); @@ -909,21 +918,23 @@ bool WiFiGenericClass::setHostname(const char * hostname) int WiFiGenericClass::setStatusBits(int bits){ if(!_arduino_event_group){ - return 0; + _initial_bits |= bits; + return _initial_bits; } return xEventGroupSetBits(_arduino_event_group, bits); } int WiFiGenericClass::clearStatusBits(int bits){ if(!_arduino_event_group){ - return 0; + _initial_bits &= ~bits; + return _initial_bits; } return xEventGroupClearBits(_arduino_event_group, bits); } int WiFiGenericClass::getStatusBits(){ if(!_arduino_event_group){ - return 0; + return _initial_bits; } return xEventGroupGetBits(_arduino_event_group); } @@ -1114,6 +1125,9 @@ esp_err_t WiFiGenericClass::_eventCallback(arduino_event_t *event) } else if(event->event_id == ARDUINO_EVENT_WIFI_AP_START) { setStatusBits(AP_STARTED_BIT); + if (getStatusBits() & AP_WANT_IP6_BIT){ + esp_netif_create_ip6_linklocal(get_esp_interface_netif(ESP_IF_WIFI_AP)); + } } else if(event->event_id == ARDUINO_EVENT_WIFI_AP_STOP) { clearStatusBits(AP_STARTED_BIT | AP_HAS_CLIENT_BIT); } else if(event->event_id == ARDUINO_EVENT_WIFI_AP_STACONNECTED) { @@ -1150,16 +1164,25 @@ esp_err_t WiFiGenericClass::_eventCallback(arduino_event_t *event) clearStatusBits(ETH_HAS_IP_BIT); } else if(event->event_id == ARDUINO_EVENT_WIFI_STA_GOT_IP6) { - setStatusBits(STA_CONNECTED_BIT | STA_HAS_IP6_BIT); - if(esp_netif_ip6_get_addr_type((esp_ip6_addr_t*)&(event->event_info.got_ip6.ip6_info.ip)) == ESP_IP6_ADDR_IS_GLOBAL){ + setStatusBits(STA_CONNECTED_BIT); + esp_ip6_addr_type_t addr_type = esp_netif_ip6_get_addr_type((esp_ip6_addr_t*)&(event->event_info.got_ip6.ip6_info.ip)); + if(addr_type == ESP_IP6_ADDR_IS_GLOBAL){ setStatusBits(STA_HAS_IP6_GLOBAL_BIT); + } else if(addr_type == ESP_IP6_ADDR_IS_LINK_LOCAL){ + setStatusBits(STA_HAS_IP6_BIT); } } else if(event->event_id == ARDUINO_EVENT_WIFI_AP_GOT_IP6) { - setStatusBits(AP_HAS_IP6_BIT); + esp_ip6_addr_type_t addr_type = esp_netif_ip6_get_addr_type((esp_ip6_addr_t*)&(event->event_info.got_ip6.ip6_info.ip)); + if(addr_type == ESP_IP6_ADDR_IS_LINK_LOCAL){ + setStatusBits(AP_HAS_IP6_BIT); + } } else if(event->event_id == ARDUINO_EVENT_ETH_GOT_IP6) { - setStatusBits(ETH_CONNECTED_BIT | ETH_HAS_IP6_BIT); - if(esp_netif_ip6_get_addr_type((esp_ip6_addr_t*)&(event->event_info.got_ip6.ip6_info.ip)) == ESP_IP6_ADDR_IS_GLOBAL){ + setStatusBits(ETH_CONNECTED_BIT); + esp_ip6_addr_type_t addr_type = esp_netif_ip6_get_addr_type((esp_ip6_addr_t*)&(event->event_info.got_ip6.ip6_info.ip)); + if(addr_type == ESP_IP6_ADDR_IS_GLOBAL){ setStatusBits(ETH_HAS_IP6_GLOBAL_BIT); + } else if(addr_type == ESP_IP6_ADDR_IS_LINK_LOCAL){ + setStatusBits(ETH_HAS_IP6_BIT); } } else if(event->event_id == ARDUINO_EVENT_SC_GOT_SSID_PSWD) { WiFi.begin( @@ -1589,7 +1612,7 @@ static void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, v } else { parameters->result = -1; } - xEventGroupSetBits(_arduino_event_group, WIFI_DNS_DONE_BIT); + xEventGroupSetBits(_arduino_event_group, NET_DNS_DONE_BIT); } /** @@ -1632,8 +1655,8 @@ int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult, bool aResult.to_ip_addr_t(&(params.addr)); if (!aResult.fromString(aHostname)) { - waitStatusBits(WIFI_DNS_IDLE_BIT, 16000); - clearStatusBits(WIFI_DNS_IDLE_BIT | WIFI_DNS_DONE_BIT); + waitStatusBits(NET_DNS_IDLE_BIT, 16000); + clearStatusBits(NET_DNS_IDLE_BIT | NET_DNS_DONE_BIT); err = esp_netif_tcpip_exec(wifi_gethostbyname_tcpip_ctx, ¶ms); if (err == ERR_OK) { @@ -1646,14 +1669,14 @@ int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult, bool } Serial.println(); } else if (err == ERR_INPROGRESS) { - waitStatusBits(WIFI_DNS_DONE_BIT, 15000); //real internal timeout in lwip library is 14[s] - clearStatusBits(WIFI_DNS_DONE_BIT); + waitStatusBits(NET_DNS_DONE_BIT, 15000); //real internal timeout in lwip library is 14[s] + clearStatusBits(NET_DNS_DONE_BIT); if (params.result == 1) { aResult.from_ip_addr_t(&(params.addr)); err = ERR_OK; } } - setStatusBits(WIFI_DNS_IDLE_BIT); + setStatusBits(NET_DNS_IDLE_BIT); } if (err == ERR_OK) { return 1; diff --git a/libraries/WiFi/src/WiFiGeneric.h b/libraries/WiFi/src/WiFiGeneric.h index c74c386a1eb..3de43905416 100644 --- a/libraries/WiFi/src/WiFiGeneric.h +++ b/libraries/WiFi/src/WiFiGeneric.h @@ -112,6 +112,34 @@ typedef void (*WiFiEventSysCb)(arduino_event_t *event); typedef size_t wifi_event_id_t; +// General Flags +static const int NET_DNS_IDLE_BIT = BIT0; +static const int NET_DNS_DONE_BIT = BIT1; +// WiFi Scan Flags +static const int WIFI_SCANNING_BIT = BIT2; +static const int WIFI_SCAN_DONE_BIT = BIT3; +// AP Flags +static const int AP_STARTED_BIT = BIT4; +static const int AP_HAS_IP6_BIT = BIT5; +static const int AP_HAS_CLIENT_BIT = BIT6; +static const int AP_WANT_IP6_BIT = BIT7; +// STA Flags +static const int STA_STARTED_BIT = BIT8; +static const int STA_CONNECTED_BIT = BIT9; +static const int STA_HAS_IP_BIT = BIT10; +static const int STA_HAS_IP6_BIT = BIT11; +static const int STA_HAS_IP6_GLOBAL_BIT = BIT12; +static const int STA_WANT_IP6_BIT = BIT13; +// ETH Flags +static const int ETH_STARTED_BIT = BIT14; +static const int ETH_CONNECTED_BIT = BIT15; +static const int ETH_HAS_IP_BIT = BIT16; +static const int ETH_HAS_IP6_BIT = BIT17; +static const int ETH_HAS_IP6_GLOBAL_BIT = BIT18; +static const int ETH_WANT_IP6_BIT = BIT19; +// Masks +static const int NET_HAS_IP6_GLOBAL_BIT = STA_HAS_IP6_GLOBAL_BIT | ETH_HAS_IP6_GLOBAL_BIT; + typedef enum { WIFI_POWER_19_5dBm = 78,// 19.5dBm WIFI_POWER_19dBm = 76,// 19dBm @@ -127,30 +155,6 @@ typedef enum { WIFI_POWER_MINUS_1dBm = -4// -1dBm } wifi_power_t; -static const int AP_STARTED_BIT = BIT0; -static const int AP_HAS_IP6_BIT = BIT1; -static const int AP_HAS_CLIENT_BIT = BIT2; -static const int STA_STARTED_BIT = BIT3; -static const int STA_CONNECTED_BIT = BIT4; -static const int STA_HAS_IP_BIT = BIT5; -static const int STA_HAS_IP6_BIT = BIT6; -static const int ETH_STARTED_BIT = BIT7; -static const int ETH_CONNECTED_BIT = BIT8; -static const int ETH_HAS_IP_BIT = BIT9; -static const int ETH_HAS_IP6_BIT = BIT10; - -static const int WIFI_SCANNING_BIT = BIT11; -static const int WIFI_SCAN_DONE_BIT= BIT12; -static const int WIFI_DNS_IDLE_BIT = BIT13; -static const int WIFI_DNS_DONE_BIT = BIT14; - -static const int STA_WANT_IP6_BIT = BIT15; -static const int ETH_WANT_IP6_BIT = BIT16; - -static const int STA_HAS_IP6_GLOBAL_BIT = BIT17; -static const int ETH_HAS_IP6_GLOBAL_BIT = BIT18; -static const int NET_HAS_IP6_GLOBAL_BIT = STA_HAS_IP6_GLOBAL_BIT | ETH_HAS_IP6_GLOBAL_BIT; - typedef enum { WIFI_RX_ANT0 = 0, WIFI_RX_ANT1, diff --git a/libraries/WiFi/src/WiFiMulti.cpp b/libraries/WiFi/src/WiFiMulti.cpp index 320c5c68c46..908ec5fc331 100644 --- a/libraries/WiFi/src/WiFiMulti.cpp +++ b/libraries/WiFi/src/WiFiMulti.cpp @@ -160,8 +160,9 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout) if(bestNetwork.ssid) { log_i("[WIFI] Connecting BSSID: %02X:%02X:%02X:%02X:%02X:%02X SSID: %s Channel: %d (%d)", bestBSSID[0], bestBSSID[1], bestBSSID[2], bestBSSID[3], bestBSSID[4], bestBSSID[5], bestNetwork.ssid, bestChannel, bestNetworkDb); - if (ipv6_support == true) + if (ipv6_support == true) { WiFi.enableIPv6(); + } WiFi.begin(bestNetwork.ssid, bestNetwork.passphrase, bestChannel, bestBSSID); status = WiFi.status(); diff --git a/libraries/WiFi/src/WiFiSTA.cpp b/libraries/WiFi/src/WiFiSTA.cpp index 23f62b82cfa..d58bd58da8e 100644 --- a/libraries/WiFi/src/WiFiSTA.cpp +++ b/libraries/WiFi/src/WiFiSTA.cpp @@ -812,11 +812,12 @@ int8_t WiFiSTAClass::RSSI(void) */ bool WiFiSTAClass::enableIPv6(bool en) { - if (en) - WiFiGenericClass::setStatusBits(STA_WANT_IP6_BIT); - else - WiFiGenericClass::clearStatusBits(STA_WANT_IP6_BIT); - return true; + if (en) { + WiFiGenericClass::setStatusBits(STA_WANT_IP6_BIT); + } else { + WiFiGenericClass::clearStatusBits(STA_WANT_IP6_BIT); + } + return true; } /** From cb381f2948dd474b800e3e9944d61638c08c84f9 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 11 Jan 2024 17:08:35 +0200 Subject: [PATCH 13/21] rename WiFiMulti method --- libraries/WiFi/src/WiFiMulti.cpp | 2 +- libraries/WiFi/src/WiFiMulti.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/WiFi/src/WiFiMulti.cpp b/libraries/WiFi/src/WiFiMulti.cpp index 908ec5fc331..22ec1ea46f9 100644 --- a/libraries/WiFi/src/WiFiMulti.cpp +++ b/libraries/WiFi/src/WiFiMulti.cpp @@ -207,6 +207,6 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout) return status; } -void WiFiMulti::IPv6(bool state) { +void WiFiMulti::enableIPv6(bool state) { ipv6_support = state; } diff --git a/libraries/WiFi/src/WiFiMulti.h b/libraries/WiFi/src/WiFiMulti.h index bbeb78dc860..d8551fab9dd 100644 --- a/libraries/WiFi/src/WiFiMulti.h +++ b/libraries/WiFi/src/WiFiMulti.h @@ -42,7 +42,7 @@ class WiFiMulti bool addAP(const char* ssid, const char *passphrase = NULL); - void IPv6(bool state); + void enableIPv6(bool state); uint8_t run(uint32_t connectTimeout=5000); private: From 726496c176d048f1bbae8a79ac9b2faa723e53ce Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 11 Jan 2024 22:47:24 +0200 Subject: [PATCH 14/21] Fix AP DHCPS not properly working on recent IDF --- libraries/WiFi/src/WiFiGeneric.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index f79e6debee1..2a47094df36 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -192,16 +192,17 @@ esp_err_t set_esp_interface_ip(esp_interface_t interface, IPAddress local_ip=IPA lease.start_ip.addr = _byte_swap32(lease.start_ip.addr); lease.end_ip.addr = _byte_swap32(lease.end_ip.addr); log_v("DHCP Server Range: %s to %s", IPAddress(lease.start_ip.addr).toString().c_str(), IPAddress(lease.end_ip.addr).toString().c_str()); - err = esp_netif_dhcps_option( - esp_netif, - ESP_NETIF_OP_SET, - ESP_NETIF_SUBNET_MASK, - (void*)&info.netmask.addr, sizeof(info.netmask.addr) - ); - if(err){ - log_e("DHCPS Set Netmask Failed! 0x%04x", err); - return err; - } + // Following block is commented because it breaks AP DHCPS on recent ESP-IDF + // err = esp_netif_dhcps_option( + // esp_netif, + // ESP_NETIF_OP_SET, + // ESP_NETIF_SUBNET_MASK, + // (void*)&info.netmask.addr, sizeof(info.netmask.addr) + // ); + // if(err){ + // log_e("DHCPS Set Netmask Failed! 0x%04x", err); + // return err; + // } err = esp_netif_dhcps_option( esp_netif, ESP_NETIF_OP_SET, From 9012f647735647d29f5542fb5599fcbdc29bddb4 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 11 Jan 2024 23:19:57 +0200 Subject: [PATCH 15/21] Add option to print the zone at the end of IPv6 @TD-er --- cores/esp32/IPAddress.cpp | 22 ++++++++++++++-------- cores/esp32/IPAddress.h | 3 ++- libraries/Ethernet/src/ETH.cpp | 2 +- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/cores/esp32/IPAddress.cpp b/cores/esp32/IPAddress.cpp index 69ccc2ec881..b701616826d 100644 --- a/cores/esp32/IPAddress.cpp +++ b/cores/esp32/IPAddress.cpp @@ -67,6 +67,7 @@ IPAddress::IPAddress(uint32_t address) { // IPv4 only _type = IPv4; + _zone = IP6_NO_ZONE; memset(_address.bytes, 0, sizeof(_address.bytes)); _address.dword[IPADDRESS_V4_DWORD_INDEX] = address; @@ -104,10 +105,10 @@ IPAddress::IPAddress(const IPAddress& address) *this = address; } -String IPAddress::toString() const +String IPAddress::toString(bool includeZone) const { StreamString s; - printTo(s); + printTo(s, includeZone); return String(s); } @@ -303,6 +304,11 @@ uint8_t& IPAddress::operator[](int index) { } size_t IPAddress::printTo(Print& p) const +{ + return printTo(p, false); +} + +size_t IPAddress::printTo(Print& p, bool includeZone) const { size_t n = 0; @@ -355,12 +361,12 @@ size_t IPAddress::printTo(Print& p) const } } // add a zone if zone-id is non-zero - // if(_zone > 0){ - // n += p.print('%'); - // char if_name[NETIF_NAMESIZE]; - // netif_index_to_name(_zone, if_name); - // n += p.print(if_name); - // } + if(_zone > 0 && includeZone){ + n += p.print('%'); + char if_name[NETIF_NAMESIZE]; + netif_index_to_name(_zone, if_name); + n += p.print(if_name); + } return n; } diff --git a/cores/esp32/IPAddress.h b/cores/esp32/IPAddress.h index 88b1bf627f0..e8df9b488ea 100644 --- a/cores/esp32/IPAddress.h +++ b/cores/esp32/IPAddress.h @@ -93,7 +93,8 @@ class IPAddress : public Printable { IPAddress& operator=(const IPAddress& address); virtual size_t printTo(Print& p) const; - String toString() const; + size_t printTo(Print& p, bool includeZone) const; + String toString(bool includeZone = false) const; IPType type() const { return _type; } diff --git a/libraries/Ethernet/src/ETH.cpp b/libraries/Ethernet/src/ETH.cpp index 9587b22719d..0ace36c69d5 100644 --- a/libraries/Ethernet/src/ETH.cpp +++ b/libraries/Ethernet/src/ETH.cpp @@ -1055,7 +1055,7 @@ void ETHClass::printInfo(Print & out){ for (int i = 0; i < v6addrs; ++i){ out.print(" "); out.print("inet6 "); - IPAddress(IPv6, (const uint8_t *)if_ip6[i].addr, if_ip6[i].zone).printTo(out); + IPAddress(IPv6, (const uint8_t *)if_ip6[i].addr, if_ip6[i].zone).printTo(out, true); out.print(" type "); out.print(types[esp_netif_ip6_get_addr_type(&if_ip6[i])]); out.println(); From 58520a7e0f8940af0c36216de0a7d4de9bce7613 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Fri, 12 Jan 2024 00:20:45 +0200 Subject: [PATCH 16/21] remove log prints from hostByName --- libraries/WiFi/src/WiFiGeneric.cpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index 2a47094df36..a7fa5957e33 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -1601,15 +1601,6 @@ static void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, v memcpy(&(parameters->addr), ipaddr, sizeof(ip_addr_t)); parameters->result = 1; } - IPAddress addr; - addr.from_ip_addr_t((ip_addr_t *)ipaddr); - Serial.print("dns_found "); - addr.printTo(Serial); - if(ipaddr->type == IPADDR_TYPE_V6){ - Serial.print(" type "); - Serial.print((int)esp_netif_ip6_get_addr_type((esp_ip6_addr_t*)&(ipaddr->u_addr.ip6))); - } - Serial.println(); } else { parameters->result = -1; } @@ -1662,13 +1653,6 @@ int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult, bool err = esp_netif_tcpip_exec(wifi_gethostbyname_tcpip_ctx, ¶ms); if (err == ERR_OK) { aResult.from_ip_addr_t(&(params.addr)); - Serial.print("dns_cache "); - aResult.printTo(Serial); - if(params.addr.type == IPADDR_TYPE_V6){ - Serial.print(" type "); - Serial.print((int)esp_netif_ip6_get_addr_type((esp_ip6_addr_t*)&(params.addr.u_addr.ip6))); - } - Serial.println(); } else if (err == ERR_INPROGRESS) { waitStatusBits(NET_DNS_DONE_BIT, 15000); //real internal timeout in lwip library is 14[s] clearStatusBits(NET_DNS_DONE_BIT); From aad10411dea925d6429c310103c6d2f2d9fbce15 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Fri, 12 Jan 2024 12:26:54 +0200 Subject: [PATCH 17/21] Use correct array length for listing IPv6 addresses --- libraries/Ethernet/src/ETH.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Ethernet/src/ETH.cpp b/libraries/Ethernet/src/ETH.cpp index 0ace36c69d5..92d91b40a1a 100644 --- a/libraries/Ethernet/src/ETH.cpp +++ b/libraries/Ethernet/src/ETH.cpp @@ -1050,7 +1050,7 @@ void ETHClass::printInfo(Print & out){ out.println(); static const char * types[] = { "UNKNOWN", "GLOBAL", "LINK_LOCAL", "SITE_LOCAL", "UNIQUE_LOCAL", "IPV4_MAPPED_IPV6" }; - esp_ip6_addr_t if_ip6[5]; + esp_ip6_addr_t if_ip6[CONFIG_LWIP_IPV6_NUM_ADDRESSES]; int v6addrs = esp_netif_get_all_ip6(_esp_netif, if_ip6); for (int i = 0; i < v6addrs; ++i){ out.print(" "); From a2a6bd80c1d19985ae631c334ba1c021a914ac52 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Sun, 14 Jan 2024 12:54:17 +0200 Subject: [PATCH 18/21] Implement some Tasmota requirements Added constructor that takes `const ip_addr_t *`. Added `addr_type()` getter Organize header to highlight the Espressif additions to IPAddress --- cores/esp32/IPAddress.cpp | 15 ++++++++++++++- cores/esp32/IPAddress.h | 12 +++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/cores/esp32/IPAddress.cpp b/cores/esp32/IPAddress.cpp index b701616826d..159d37b15cc 100644 --- a/cores/esp32/IPAddress.cpp +++ b/cores/esp32/IPAddress.cpp @@ -380,6 +380,10 @@ size_t IPAddress::printTo(Print& p, bool includeZone) const return n; } +IPAddress::IPAddress(const ip_addr_t *addr){ + from_ip_addr_t(addr); +} + void IPAddress::to_ip_addr_t(ip_addr_t* addr) const { if(_type == IPv6){ addr->type = IPADDR_TYPE_V6; @@ -396,7 +400,7 @@ void IPAddress::to_ip_addr_t(ip_addr_t* addr) const { } } -IPAddress& IPAddress::from_ip_addr_t(ip_addr_t* addr){ +IPAddress& IPAddress::from_ip_addr_t(const ip_addr_t* addr){ if(addr->type == IPADDR_TYPE_V6){ _type = IPv6; _address.dword[0] = addr->u_addr.ip6.addr[0]; @@ -413,5 +417,14 @@ IPAddress& IPAddress::from_ip_addr_t(ip_addr_t* addr){ return *this; } +esp_ip6_addr_type_t IPAddress::addr_type(){ + if(_type != IPv6){ + return ESP_IP6_ADDR_IS_UNKNOWN; + } + ip_addr_t addr; + to_ip_addr_t(&addr); + return esp_netif_ip6_get_addr_type((esp_ip6_addr_t*)(&(addr.u_addr.ip6))); +} + const IPAddress IN6ADDR_ANY(IPv6); const IPAddress INADDR_NONE(0,0,0,0); diff --git a/cores/esp32/IPAddress.h b/cores/esp32/IPAddress.h index e8df9b488ea..b6851590c32 100644 --- a/cores/esp32/IPAddress.h +++ b/cores/esp32/IPAddress.h @@ -23,6 +23,7 @@ #include "Printable.h" #include "WString.h" #include "lwip/ip_addr.h" +#include "esp_netif_ip_addr.h" #define IPADDRESS_V4_BYTES_INDEX 12 #define IPADDRESS_V4_DWORD_INDEX 3 @@ -93,16 +94,17 @@ class IPAddress : public Printable { IPAddress& operator=(const IPAddress& address); virtual size_t printTo(Print& p) const; - size_t printTo(Print& p, bool includeZone) const; String toString(bool includeZone = false) const; IPType type() const { return _type; } - uint8_t zone() const { return (type() == IPv6)?_zone:0; } - - // LwIP conversions + // Espresif LwIP conversions + IPAddress(const ip_addr_t *addr); void to_ip_addr_t(ip_addr_t* addr) const; - IPAddress& from_ip_addr_t(ip_addr_t* addr); + IPAddress& from_ip_addr_t(const ip_addr_t* addr); + esp_ip6_addr_type_t addr_type(); + uint8_t zone() const { return (type() == IPv6)?_zone:0; } + size_t printTo(Print& p, bool includeZone) const; friend class UDP; friend class Client; From 1fb442dc5bc88f86d2850b9c1bf894bdb4fe7b98 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Mon, 15 Jan 2024 01:01:29 +0200 Subject: [PATCH 19/21] add 'const' to IPAddress::addr_type() --- cores/esp32/IPAddress.cpp | 2 +- cores/esp32/IPAddress.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cores/esp32/IPAddress.cpp b/cores/esp32/IPAddress.cpp index 159d37b15cc..0fa5affdea7 100644 --- a/cores/esp32/IPAddress.cpp +++ b/cores/esp32/IPAddress.cpp @@ -417,7 +417,7 @@ IPAddress& IPAddress::from_ip_addr_t(const ip_addr_t* addr){ return *this; } -esp_ip6_addr_type_t IPAddress::addr_type(){ +esp_ip6_addr_type_t IPAddress::addr_type() const { if(_type != IPv6){ return ESP_IP6_ADDR_IS_UNKNOWN; } diff --git a/cores/esp32/IPAddress.h b/cores/esp32/IPAddress.h index b6851590c32..0a3efd01c8d 100644 --- a/cores/esp32/IPAddress.h +++ b/cores/esp32/IPAddress.h @@ -102,7 +102,7 @@ class IPAddress : public Printable { IPAddress(const ip_addr_t *addr); void to_ip_addr_t(ip_addr_t* addr) const; IPAddress& from_ip_addr_t(const ip_addr_t* addr); - esp_ip6_addr_type_t addr_type(); + esp_ip6_addr_type_t addr_type() const; uint8_t zone() const { return (type() == IPv6)?_zone:0; } size_t printTo(Print& p, bool includeZone) const; From 0df3aaad6c4e343547d82c8fba46e8dc276bbbba Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Mon, 15 Jan 2024 12:16:23 +0200 Subject: [PATCH 20/21] Fix WiFiUdp not updating mapped v4 address --- libraries/WiFi/src/WiFiGeneric.cpp | 15 ++++++++++++--- libraries/WiFi/src/WiFiUdp.cpp | 1 + 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index a7fa5957e33..2fade00e450 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -1066,7 +1066,10 @@ esp_err_t WiFiGenericClass::_eventCallback(arduino_event_t *event) clearStatusBits(STA_STARTED_BIT | STA_CONNECTED_BIT | STA_HAS_IP_BIT | STA_HAS_IP6_BIT | STA_HAS_IP6_GLOBAL_BIT); } else if(event->event_id == ARDUINO_EVENT_WIFI_STA_CONNECTED) { if (getStatusBits() & STA_WANT_IP6_BIT){ - esp_netif_create_ip6_linklocal(get_esp_interface_netif(ESP_IF_WIFI_STA)); + esp_err_t err = esp_netif_create_ip6_linklocal(get_esp_interface_netif(ESP_IF_WIFI_STA)); + if(err != ESP_OK){ + log_e("Failed to enable IPv6 Link Local on STA: [%d] %s", err, esp_err_to_name(err)); + } } WiFiSTAClass::_setStatus(WL_IDLE_STATUS); setStatusBits(STA_CONNECTED_BIT); @@ -1127,7 +1130,10 @@ esp_err_t WiFiGenericClass::_eventCallback(arduino_event_t *event) } else if(event->event_id == ARDUINO_EVENT_WIFI_AP_START) { setStatusBits(AP_STARTED_BIT); if (getStatusBits() & AP_WANT_IP6_BIT){ - esp_netif_create_ip6_linklocal(get_esp_interface_netif(ESP_IF_WIFI_AP)); + esp_err_t err = esp_netif_create_ip6_linklocal(get_esp_interface_netif(ESP_IF_WIFI_AP)); + if(err != ESP_OK){ + log_e("Failed to enable IPv6 Link Local on AP: [%d] %s", err, esp_err_to_name(err)); + } } } else if(event->event_id == ARDUINO_EVENT_WIFI_AP_STOP) { clearStatusBits(AP_STARTED_BIT | AP_HAS_CLIENT_BIT); @@ -1145,7 +1151,10 @@ esp_err_t WiFiGenericClass::_eventCallback(arduino_event_t *event) clearStatusBits(ETH_STARTED_BIT | ETH_CONNECTED_BIT | ETH_HAS_IP_BIT | ETH_HAS_IP6_BIT | ETH_HAS_IP6_GLOBAL_BIT); } else if(event->event_id == ARDUINO_EVENT_ETH_CONNECTED) { if (getStatusBits() & ETH_WANT_IP6_BIT){ - esp_netif_create_ip6_linklocal(get_esp_interface_netif(ESP_IF_ETH)); + esp_err_t err = esp_netif_create_ip6_linklocal(get_esp_interface_netif(ESP_IF_ETH)); + if(err != ESP_OK){ + log_e("Failed to enable IPv6 Link Local on ETH: [%d] %s", err, esp_err_to_name(err)); + } } setStatusBits(ETH_CONNECTED_BIT); } else if(event->event_id == ARDUINO_EVENT_ETH_DISCONNECTED) { diff --git a/libraries/WiFi/src/WiFiUdp.cpp b/libraries/WiFi/src/WiFiUdp.cpp index 683ff90067c..5d8b513a2d8 100644 --- a/libraries/WiFi/src/WiFiUdp.cpp +++ b/libraries/WiFi/src/WiFiUdp.cpp @@ -321,6 +321,7 @@ int WiFiUDP::parsePacket(){ if (remote_ip.type() == IPv6 && ip6_addr_isipv4mappedipv6(ip_2_ip6(&addr))) { unmap_ipv4_mapped_ipv6(ip_2_ip4(&addr), ip_2_ip6(&addr)); IP_SET_TYPE_VAL(addr, IPADDR_TYPE_V4); + remote_ip.from_ip_addr_t(&addr); } remote_port = ntohs(si_other.sin6_port); } From 416187320c3cbaa28e5429245dff17999edfed96 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Mon, 15 Jan 2024 14:23:18 +0200 Subject: [PATCH 21/21] Update WiFiServer.cpp --- libraries/WiFi/src/WiFiServer.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/WiFi/src/WiFiServer.cpp b/libraries/WiFi/src/WiFiServer.cpp index d3f2b0b0120..9d79b5f7c46 100644 --- a/libraries/WiFi/src/WiFiServer.cpp +++ b/libraries/WiFi/src/WiFiServer.cpp @@ -87,12 +87,10 @@ void WiFiServer::begin(uint16_t port, int enable){ setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); server.sin6_family = AF_INET6; if (_addr.type() == IPv4) { - // log_e("---------------- IPv4"); memcpy(server.sin6_addr.s6_addr+11, (uint8_t*)&_addr[0], 4); server.sin6_addr.s6_addr[10] = 0xFF; server.sin6_addr.s6_addr[11] = 0xFF; } else { - // log_e("---------------- IPv6"); memcpy(server.sin6_addr.s6_addr, (uint8_t*)&_addr[0], 16); } memset(server.sin6_addr.s6_addr, 0x0, 16);