diff --git a/cores/esp32/Client.h b/cores/esp32/Client.h index 962cacc51da..c575cde0c66 100644 --- a/cores/esp32/Client.h +++ b/cores/esp32/Client.h @@ -22,6 +22,7 @@ #include "Print.h" #include "Stream.h" #include "IPAddress.h" +#include "IPv6Address.h" class Client: public Stream { diff --git a/libraries/WiFi/examples/WiFiTelnetToSerialIPv6/WiFiTelnetToSerialIPv6.ino b/libraries/WiFi/examples/WiFiTelnetToSerialIPv6/WiFiTelnetToSerialIPv6.ino new file mode 100644 index 00000000000..99b1c0c82e9 --- /dev/null +++ b/libraries/WiFi/examples/WiFiTelnetToSerialIPv6/WiFiTelnetToSerialIPv6.ino @@ -0,0 +1,132 @@ +/* + WiFiTelnetToSerial - Example Transparent UART to Telnet Server for ESP32 + + Copyright (c) 2017 Hristo Gochkov. All rights reserved. + This file is part of the ESP32 WiFi library for Arduino environment. + + 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 + +WiFiMulti wifiMulti; + +//Even this example state IPv6, it is dual stack and compatible with IPv4 too + +//how many clients should be able to telnet to this ESP32 +#define MAX_SRV_CLIENTS 1 +const char* ssid = "**********"; +const char* password = "**********"; + +WiFiServer server(23); +WiFiClient serverClients[MAX_SRV_CLIENTS]; + +void setup() { + Serial.begin(115200); + Serial.println("\nConnecting"); + + wifiMulti.IPv6(true); + wifiMulti.addAP(ssid, password); + wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2"); + wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3"); + + Serial.println("Connecting Wifi "); + for (int loops = 10; loops > 0; loops--) { + if (wifiMulti.run() == WL_CONNECTED) { + Serial.println(""); + Serial.print("WiFi connected "); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + break; + } + else { + Serial.println(loops); + delay(1000); + } + } + if (wifiMulti.run() != WL_CONNECTED) { + Serial.println("WiFi connect failed"); + delay(1000); + ESP.restart(); + } + + //start UART and the server + Serial1.begin(9600); + server.begin(); + server.setNoDelay(true); + + Serial.print("Ready! Use 'telnet "); + Serial.print(WiFi.localIP()); + Serial.println(" 23' to connect"); +} + +void loop() { + uint8_t i; + if (wifiMulti.run() == WL_CONNECTED) { + //check if there are any new clients + if (server.hasClient()){ + for(i = 0; i < MAX_SRV_CLIENTS; i++){ + //find free/disconnected spot + if (!serverClients[i] || !serverClients[i].connected()){ + if(serverClients[i]) serverClients[i].stop(); + serverClients[i] = server.available(); + if (!serverClients[i]) Serial.println("available broken"); + Serial.print("New client: "); + Serial.print(i); Serial.print(' '); + Serial.println(serverClients[i].remoteIP6()); + break; + } + } + if (i >= MAX_SRV_CLIENTS) { + //no free/disconnected spot so reject + server.available().stop(); + } + } + //check clients for data + for(i = 0; i < MAX_SRV_CLIENTS; i++){ + if (serverClients[i] && serverClients[i].connected()){ + if(serverClients[i].available()){ + //get data from the telnet client and push it to the UART + while(serverClients[i].available()) Serial1.write(serverClients[i].read()); + } + } + else { + if (serverClients[i]) { + serverClients[i].stop(); + } + } + } + //check UART for data + if(Serial1.available()){ + size_t len = Serial1.available(); + uint8_t sbuf[len]; + Serial1.readBytes(sbuf, len); + //push UART data to all connected telnet clients + for(i = 0; i < MAX_SRV_CLIENTS; i++){ + if (serverClients[i] && serverClients[i].connected()){ + serverClients[i].write(sbuf, len); + delay(1); + } + } + } + } + else { + Serial.println("WiFi not connected!"); + for(i = 0; i < MAX_SRV_CLIENTS; i++) { + if (serverClients[i]) serverClients[i].stop(); + } + delay(1000); + } +} diff --git a/libraries/WiFi/src/WiFiClient.cpp b/libraries/WiFi/src/WiFiClient.cpp index 69a691995bd..d9587f6ff95 100644 --- a/libraries/WiFi/src/WiFiClient.cpp +++ b/libraries/WiFi/src/WiFiClient.cpp @@ -210,22 +210,43 @@ int WiFiClient::connect(IPAddress ip, uint16_t port) { return connect(ip,port,_timeout); } + int WiFiClient::connect(IPAddress ip, uint16_t port, int32_t timeout) { + ip_addr_t dstip; + dstip = IPADDR_ANY_TYPE_INIT; + IP_ADDR4(&dstip, ip[0], ip[1], ip[2], ip[3]); + return connect(dstip, port, timeout); +} + +int WiFiClient::connect(ip_addr_t ip, uint16_t port, int32_t timeout) +{ + struct sockaddr_storage serveraddr; _timeout = timeout; - int sockfd = socket(AF_INET, SOCK_STREAM, 0); + int sockfd = -1; + + if (IP_IS_V6(&ip)) { + sockfd = socket(AF_INET6, SOCK_STREAM, 0); + struct sockaddr_in6 *tmpaddr = (struct sockaddr_in6 *)&serveraddr; + memset((char *) tmpaddr, 0, sizeof(struct sockaddr_in6)); + tmpaddr->sin6_family = AF_INET6; + inet6_addr_from_ip6addr(&tmpaddr->sin6_addr, ip_2_ip6(&ip)); + tmpaddr->sin6_port = htons(port); + } + if (sockfd == -1 && IP_IS_V4(&ip)) { + sockfd = socket(AF_INET, SOCK_STREAM, 0); + struct sockaddr_in *tmpaddr = (struct sockaddr_in *)&serveraddr; + memset((char *) tmpaddr, 0, sizeof(struct sockaddr_in)); + tmpaddr->sin_family = AF_INET; + tmpaddr->sin_addr.s_addr = ip4_addr_get_u32(&ip.u_addr.ip4); + 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); @@ -294,6 +315,13 @@ int WiFiClient::connect(const char *host, uint16_t port) int WiFiClient::connect(const char *host, uint16_t port, int32_t timeout) { + if (WiFiGenericClass::getStatusBits() & WIFI_WANT_IP6_BIT) { + ip_addr_t srv6; + if(!WiFiGenericClass::hostByName6(host, srv6)){ + return 0; + } + return connect(srv6, port, timeout); + } IPAddress srv((uint32_t)0); if(!WiFiGenericClass::hostByName(host, srv)){ return 0; @@ -561,8 +589,52 @@ 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)); + + // Old way, IPv4 + 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)) { + struct sockaddr_in addr4; + memset(&addr4, 0, sizeof(addr4)); + addr4.sin_family = AF_INET; + addr4.sin_port = saddr6->sin6_port; + memcpy(&addr4.sin_addr.s_addr, saddr6->sin6_addr.s6_addr+12, sizeof(addr4.sin_addr.s_addr)); + return IPAddress((uint32_t)(addr4.sin_addr.s_addr)); + } + log_e("WiFiClient::remoteIP IPv6 to IPv4 cannot convert"); + return (IPAddress(0,0,0,0)); + } + log_e("WiFiClient::remoteIP Not AF_INET or AF_INET6?"); + return (IPAddress(0,0,0,0)); +} + +IPv6Address WiFiClient::remoteIP6(int fd) const +{ + struct sockaddr_storage addr; + socklen_t len = sizeof addr; + getpeername(fd, (struct sockaddr*)&addr, &len); + + // IPv4 socket we can print as IPv6 mapped + if (((struct sockaddr*)&addr)->sa_family == AF_INET) { + uint8_t buffer[16] = { 0 }; + buffer[10] = 0xFF; + buffer[11] = 0xFF; + struct sockaddr_in *s = (struct sockaddr_in *)&addr; + memcpy(&buffer[12], (uint8_t*)&s->sin_addr.s_addr, 4); + return IPv6Address(buffer); + } + // IPv6 + if (((struct sockaddr*)&addr)->sa_family == AF_INET6) { + struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&addr; + return (IPv6Address(saddr6->sin6_addr.s6_addr)); + } + log_e("WiFiClient::remoteIP Not AF_INET or AF_INET6?"); + return (IPv6Address()); } uint16_t WiFiClient::remotePort(int fd) const @@ -579,6 +651,11 @@ IPAddress WiFiClient::remoteIP() const return remoteIP(fd()); } +IPv6Address WiFiClient::remoteIP6() const +{ + return remoteIP6(fd()); +} + uint16_t WiFiClient::remotePort() const { return remotePort(fd()); diff --git a/libraries/WiFi/src/WiFiClient.h b/libraries/WiFi/src/WiFiClient.h index 5aaa6ba115e..e66772f9c2d 100644 --- a/libraries/WiFi/src/WiFiClient.h +++ b/libraries/WiFi/src/WiFiClient.h @@ -24,6 +24,7 @@ #include "Arduino.h" #include "Client.h" #include +#include "lwip/ip_addr.h" class WiFiClientSocketHandle; class WiFiClientRxBuffer; @@ -49,6 +50,7 @@ class WiFiClient : public ESPLwIPClient WiFiClient(); WiFiClient(int fd); ~WiFiClient(); + int connect(ip_addr_t ip, uint16_t port, int32_t timeout); int connect(IPAddress ip, uint16_t port); int connect(IPAddress ip, uint16_t port, int32_t timeout); int connect(const char *host, uint16_t port); @@ -95,6 +97,8 @@ class WiFiClient : public ESPLwIPClient IPAddress remoteIP() const; IPAddress remoteIP(int fd) const; + IPv6Address remoteIP6() const; + IPv6Address remoteIP6(int fd) const; uint16_t remotePort() const; uint16_t remotePort(int fd) const; IPAddress localIP() const; @@ -106,4 +110,9 @@ class WiFiClient : public ESPLwIPClient using Print::write; }; +#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))) + #endif /* _WIFICLIENT_H_ */ diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index 5d31341481a..7b9b1c31b09 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -866,8 +866,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; log_w("Reason: %u - %s", reason, reason2str(reason)); @@ -1335,6 +1335,25 @@ static void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, v xEventGroupSetBits(_arduino_event_group, WIFI_DNS_DONE_BIT); } +/** + * 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 @@ -1362,6 +1381,36 @@ 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 62642b43dc7..6957e68d73e 100644 --- a/libraries/WiFi/src/WiFiGeneric.h +++ b/libraries/WiFi/src/WiFiGeneric.h @@ -138,6 +138,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, @@ -151,6 +152,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: @@ -209,6 +215,7 @@ class WiFiGenericClass public: static int hostByName(const char *aHostname, IPAddress &aResult); + static int hostByName6(const char *aHostname, ip_addr_t &aResult); static IPAddress calculateNetworkID(IPAddress ip, IPAddress subnet); static IPAddress calculateBroadcast(IPAddress ip, IPAddress subnet); diff --git a/libraries/WiFi/src/WiFiMulti.cpp b/libraries/WiFi/src/WiFiMulti.cpp index 3d69e481293..52c9b2bf41e 100644 --- a/libraries/WiFi/src/WiFiMulti.cpp +++ b/libraries/WiFi/src/WiFiMulti.cpp @@ -160,6 +160,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 +204,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 7734f5d79b5..dc8ff8ee6bc 100644 --- a/libraries/WiFi/src/WiFiSTA.cpp +++ b/libraries/WiFi/src/WiFiSTA.cpp @@ -726,6 +726,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 b8bb855c198..6892c996b30 100644 --- a/libraries/WiFi/src/WiFiSTA.h +++ b/libraries/WiFi/src/WiFiSTA.h @@ -84,6 +84,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 db21858125b..03e3c797e83 100644 --- a/libraries/WiFi/src/WiFiServer.cpp +++ b/libraries/WiFi/src/WiFiServer.cpp @@ -47,8 +47,8 @@ WiFiClient WiFiServer::available(){ _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 @@ -76,14 +76,14 @@ 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; + server.sin6_addr = _addr; + server.sin6_port = htons(_port); if(bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) return; if(listen(sockfd , _max_clients) < 0) @@ -106,8 +106,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 diff --git a/libraries/WiFi/src/WiFiServer.h b/libraries/WiFi/src/WiFiServer.h index 346986abad5..d516e5502d2 100644 --- a/libraries/WiFi/src/WiFiServer.h +++ b/libraries/WiFi/src/WiFiServer.h @@ -23,12 +23,14 @@ #include "Server.h" #include "WiFiClient.h" #include "IPAddress.h" +#include "lwip/inet.h" +#include "lwip/netdb.h" class WiFiServer : public Server { private: int sockfd; int _accepted_sockfd = -1; - IPAddress _addr; + in6_addr _addr; uint16_t _port; uint8_t _max_clients; bool _listening; @@ -37,12 +39,19 @@ 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) { + WiFiServer(uint16_t port=80, uint8_t max_clients=4):sockfd(-1),_accepted_sockfd(-1),_port(port),_max_clients(max_clients),_listening(false),_noDelay(false) { log_v("WiFiServer::WiFiServer(port=%d, ...)", port); + _addr = IN6ADDR_ANY_INIT; } - WiFiServer(const IPAddress& addr, uint16_t port=80, uint8_t max_clients=4):sockfd(-1),_accepted_sockfd(-1),_addr(addr),_port(port),_max_clients(max_clients),_listening(false),_noDelay(false) { + WiFiServer(const IPAddress& addr, uint16_t port=80, uint8_t max_clients=4):sockfd(-1),_accepted_sockfd(-1),_port(port),_max_clients(max_clients),_listening(false),_noDelay(false) { log_v("WiFiServer::WiFiServer(addr=%s, port=%d, ...)", addr.toString().c_str(), port); + char buffer[64] = { 0 }; + // Print IPv4 in IPv6 notation + sprintf(buffer, "::FFFF:%s", addr.toString().c_str()); + int rc = inet_pton(AF_INET6, buffer, &_addr); + if (rc != 1) { + log_e("WiFiServer::WiFiServer unable to resolve address, rc=%d", rc); + } } ~WiFiServer(){ end();} WiFiClient available(); diff --git a/libraries/WiFiClientSecure/src/ssl_client.cpp b/libraries/WiFiClientSecure/src/ssl_client.cpp index 6ab9b10570d..92d429e2669 100644 --- a/libraries/WiFiClientSecure/src/ssl_client.cpp +++ b/libraries/WiFiClientSecure/src/ssl_client.cpp @@ -60,6 +60,7 @@ int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t p int ret, flags; int enable = 1; log_v("Free internal heap before TLS %u", ESP.getFreeHeap()); + bool is_ipv4 = true; if (rootCABuff == NULL && pskIdent == NULL && psKey == NULL && !insecure && !useRootCABundle) { return -1; @@ -67,24 +68,45 @@ int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t p log_v("Starting socket"); ssl_client->socket = -1; + struct sockaddr_storage serveraddr; + ip_addr_t dstip; + IPAddress srv((uint32_t)0); + + if (WiFiGenericClass::getStatusBits() & WIFI_WANT_IP6_BIT) { + ip_addr_t srv6; + if(!WiFiGenericClass::hostByName6(host, srv6)){ + return -1; + } + if (IP_IS_V6(&srv6)) { + is_ipv4 = false; + ssl_client->socket = lwip_socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); + struct sockaddr_in6 *tmpaddr = (struct sockaddr_in6 *)&serveraddr; + memset((char *) tmpaddr, 0, sizeof(struct sockaddr_in6)); + tmpaddr->sin6_family = AF_INET6; + inet6_addr_from_ip6addr(&tmpaddr->sin6_addr, ip_2_ip6(&srv6)); + tmpaddr->sin6_port = htons(port); + } else { + srv = ip4_addr_get_u32(&srv6.u_addr.ip4); + } + } else { + if(!WiFiGenericClass::hostByName(host, srv)) + return -1; + } + if (is_ipv4 == true) { + ssl_client->socket = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + struct sockaddr_in *serv_addr = (struct sockaddr_in*)&serveraddr; + memset(serv_addr, 0, sizeof(serv_addr)); + serv_addr->sin_family = AF_INET; + serv_addr->sin_addr.s_addr = srv; + serv_addr->sin_port = htons(port); + } - ssl_client->socket = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (ssl_client->socket < 0) { log_e("ERROR opening socket"); return ssl_client->socket; } - IPAddress srv((uint32_t)0); - if(!WiFiGenericClass::hostByName(host, srv)){ - return -1; - } - fcntl( ssl_client->socket, F_SETFL, fcntl( ssl_client->socket, F_GETFL, 0 ) | O_NONBLOCK ); - struct sockaddr_in serv_addr; - memset(&serv_addr, 0, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = srv; - serv_addr.sin_port = htons(port); if(timeout <= 0){ timeout = 30000; // Milli seconds. @@ -97,7 +119,7 @@ int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t p tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; - int res = lwip_connect(ssl_client->socket, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); + int res = lwip_connect(ssl_client->socket, (struct sockaddr*)&serveraddr, sizeof(serveraddr)); if (res < 0 && errno != EINPROGRESS) { log_e("connect on fd %d, errno: %d, \"%s\"", ssl_client->socket, errno, strerror(errno)); close(ssl_client->socket);