diff --git a/libraries/ESP8266WiFi/examples/IPv6/IPv6.ino b/libraries/ESP8266WiFi/examples/IPv6/IPv6.ino index 1c7b1c081c..48bd5a449b 100644 --- a/libraries/ESP8266WiFi/examples/IPv6/IPv6.ino +++ b/libraries/ESP8266WiFi/examples/IPv6/IPv6.ino @@ -1,4 +1,3 @@ - /* arduino IPv6 example released to public domain @@ -27,7 +26,8 @@ #define STAPSK "your-password" #endif -#define FQDN F("www.google.com") // with both IPv4 & IPv6 addresses +#define FQDN F("www.google.com") // with both IPv4 & IPv6 addresses +#define FQDN2 F("www.yahoo.com") // with both IPv4 & IPv6 addresses #define FQDN6 F("ipv6.google.com") // does not resolve in IPv4 #define STATUSDELAY_MS 10000 #define TCP_PORT 23 @@ -50,6 +50,21 @@ void fqdn(Print& out, const String& fqdn) { } } +#if LWIP_IPV4 && LWIP_IPV6 +void fqdn_rt(Print& out, const String& fqdn, DNSResolveType resolveType) { + out.print(F("resolving ")); + out.print(fqdn); + out.print(F(": ")); + IPAddress result; + if (WiFi.hostByName(fqdn.c_str(), result, 10000, resolveType)) { + result.printTo(out); + out.println(); + } else { + out.println(F("timeout or not found")); + } +} +#endif + void status(Print& out) { out.println(F("------------------------------")); out.println(ESP.getFullVersion()); @@ -85,7 +100,10 @@ void status(Print& out) { // an example is provided with a fqdn which does not resolve with IPv4 fqdn(out, FQDN); fqdn(out, FQDN6); - +#if LWIP_IPV4 && LWIP_IPV6 + fqdn_rt(out, FQDN, DNSResolveType::DNS_AddrType_IPv4_IPv6); // IPv4 before IPv6 + fqdn_rt(out, FQDN2, DNSResolveType::DNS_AddrType_IPv6_IPv4); // IPv6 before IPv4 +#endif out.println(F("------------------------------")); } diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp index 4b2eb54ce7..41d771fb6a 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp @@ -608,7 +608,7 @@ int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResul int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult, uint32_t timeout_ms) { ip_addr_t addr; - aResult = static_cast(0); + aResult = static_cast(INADDR_NONE); if(aResult.fromString(aHostname)) { // Host name is a IP address use it! @@ -617,7 +617,61 @@ int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResul } DEBUG_WIFI_GENERIC("[hostByName] request IP for: %s\n", aHostname); +#if LWIP_IPV4 && LWIP_IPV6 + err_t err = dns_gethostbyname_addrtype(aHostname, &addr, &wifi_dns_found_callback, &aResult,LWIP_DNS_ADDRTYPE_DEFAULT); +#else err_t err = dns_gethostbyname(aHostname, &addr, &wifi_dns_found_callback, &aResult); +#endif + if(err == ERR_OK) { + aResult = IPAddress(&addr); + } else if(err == ERR_INPROGRESS) { + _dns_lookup_pending = true; + delay(timeout_ms); + // will resume on timeout or when wifi_dns_found_callback fires + _dns_lookup_pending = false; + // will return here when dns_found_callback fires + if(aResult.isSet()) { + err = ERR_OK; + } + } + + if(err != 0) { + DEBUG_WIFI_GENERIC("[hostByName] Host: %s lookup error: %d!\n", aHostname, (int)err); + } else { + DEBUG_WIFI_GENERIC("[hostByName] Host: %s IP: %s\n", aHostname, aResult.toString().c_str()); + } + + return (err == ERR_OK) ? 1 : 0; +} + +#if LWIP_IPV4 && LWIP_IPV6 +int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult, uint32_t timeout_ms, DNSResolveType resolveType) +{ + ip_addr_t addr; + err_t err; + aResult = static_cast(INADDR_NONE); + + if(aResult.fromString(aHostname)) { + // Host name is a IP address use it! + DEBUG_WIFI_GENERIC("[hostByName] Host: %s is a IP!\n", aHostname); + return 1; + } + + DEBUG_WIFI_GENERIC("[hostByName] request IP for: %s\n", aHostname); + switch(resolveType) + { + // Use selected addrtype + case DNSResolveType::DNS_AddrType_IPv4: + case DNSResolveType::DNS_AddrType_IPv6: + case DNSResolveType::DNS_AddrType_IPv4_IPv6: + case DNSResolveType::DNS_AddrType_IPv6_IPv4: + err = dns_gethostbyname_addrtype(aHostname, &addr, &wifi_dns_found_callback, &aResult, (uint8_t) resolveType); + break; + default: + err = dns_gethostbyname_addrtype(aHostname, &addr, &wifi_dns_found_callback, &aResult, LWIP_DNS_ADDRTYPE_DEFAULT); // If illegal type, use default. + break; + } + if(err == ERR_OK) { aResult = IPAddress(&addr); } else if(err == ERR_INPROGRESS) { @@ -639,6 +693,7 @@ int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResul return (err == ERR_OK) ? 1 : 0; } +#endif /** * DNS callback diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.h b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.h index 1f5ec5c995..b5f307aeda 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.h +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.h @@ -42,6 +42,14 @@ typedef std::shared_ptr WiFiEventHandler; typedef void (*WiFiEventCb)(WiFiEvent_t); +enum class DNSResolveType: uint8_t +{ + DNS_AddrType_IPv4 = 0, // LWIP_DNS_ADDRTYPE_IPV4 = 0 + DNS_AddrType_IPv6, // LWIP_DNS_ADDRTYPE_IPV6 = 1 + DNS_AddrType_IPv4_IPv6, // LWIP_DNS_ADDRTYPE_IPV4_IPV6 = 2 + DNS_AddrType_IPv6_IPv4 // LWIP_DNS_ADDRTYPE_IPV6_IPV4 = 3 +}; + struct WiFiState; class ESP8266WiFiGenericClass { @@ -113,6 +121,9 @@ class ESP8266WiFiGenericClass { public: int hostByName(const char* aHostname, IPAddress& aResult); int hostByName(const char* aHostname, IPAddress& aResult, uint32_t timeout_ms); +#if LWIP_IPV4 && LWIP_IPV6 + int hostByName(const char* aHostname, IPAddress& aResult, uint32_t timeout_ms, DNSResolveType resolveType); +#endif bool getPersistent(); protected: