2222
2323 */
2424
25+ #include < cstring>
2526#include < list>
26- #include < string.h>
27+ #include < memory>
28+ #include < type_traits>
29+
2730#include < coredecls.h>
2831#include < PolledTimeout.h>
2932#include " ESP8266WiFi.h"
@@ -595,112 +598,105 @@ bool ESP8266WiFiGenericClass::isSleepLevelMax () {
595598// ------------------------------------------------ Generic Network function ---------------------------------------------
596599// -----------------------------------------------------------------------------------------------------------------------
597600
598- void wifi_dns_found_callback ( const char *name, const ip_addr_t *ipaddr, void *callback_arg);
601+ namespace {
599602
600- static bool _dns_lookup_pending = false ;
603+ struct _dns_found_result {
604+ IPAddress addr;
605+ bool done;
606+ };
601607
602- /* *
603- * Resolve the given hostname to an IP address.
604- * @param aHostname Name to be resolved
605- * @param aResult IPAddress structure to store the returned IP address
606- * @return 1 if aIPAddrString was successfully converted to an IP address,
607- * else 0
608- */
609- int ESP8266WiFiGenericClass::hostByName (const char * aHostname, IPAddress& aResult)
610- {
611- return hostByName (aHostname, aResult, 10000 );
612608}
613609
610+ static void _dns_found_callback (const char *, const ip_addr_t *, void *);
614611
615- int ESP8266WiFiGenericClass::hostByName (const char * aHostname, IPAddress& aResult, uint32_t timeout_ms)
616- {
617- ip_addr_t addr;
618- aResult = static_cast <uint32_t >(INADDR_NONE);
619-
620- if (aResult.fromString (aHostname)) {
621- // Host name is a IP address use it!
622- DEBUG_WIFI_GENERIC (" [hostByName] Host: %s is a IP!\n " , aHostname);
612+ static int hostByNameImpl (const char * aHostname, IPAddress& aResult, uint32_t timeout_ms, DNSResolveType resolveType) {
613+ if (aResult.fromString (aHostname)) {
614+ DEBUG_WIFI_GENERIC (" [hostByName] Host: %s is IP!\n " , aHostname);
623615 return 1 ;
624616 }
625617
618+ static_assert (std::is_same_v<uint8_t , std::underlying_type_t <decltype (resolveType)>>, " " );
626619 DEBUG_WIFI_GENERIC (" [hostByName] request IP for: %s\n " , aHostname);
627- #if LWIP_IPV4 && LWIP_IPV6
628- err_t err = dns_gethostbyname_addrtype (aHostname, &addr, &wifi_dns_found_callback, &aResult,LWIP_DNS_ADDRTYPE_DEFAULT);
629- #else
630- err_t err = dns_gethostbyname (aHostname, &addr, &wifi_dns_found_callback, &aResult);
631- #endif
632- if (err == ERR_OK) {
633- aResult = IPAddress (&addr);
634- } else if (err == ERR_INPROGRESS) {
635- _dns_lookup_pending = true ;
636- // Will resume on timeout or when wifi_dns_found_callback fires.
637- // The final argument, intvl_ms, to esp_delay influences how frequently
638- // the scheduled recurrent functions (Schedule.h) are probed; here, to allow
639- // the ethernet driver perform work.
640- esp_delay (timeout_ms, []() { return _dns_lookup_pending; }, 1 );
641- _dns_lookup_pending = false ;
642- if (aResult.isSet ()) {
643- err = ERR_OK;
620+
621+ ip_addr_t addr;
622+ auto pending = std::make_unique<_dns_found_result>(
623+ _dns_found_result{
624+ .addr = IPADDR_NONE,
625+ .done = false ,
626+ });
627+
628+ err_t err = dns_gethostbyname_addrtype (aHostname,
629+ &addr, &_dns_found_callback, pending.get (),
630+ static_cast <uint8_t >(resolveType));
631+
632+ switch (err) {
633+ // Address already known
634+ case ERR_OK:
635+ aResult = addr;
636+ break ;
637+
638+ // We are no longer able to issue requests
639+ case ERR_MEM:
640+ break ;
641+
642+ // We need to wait for c/b to fire *or* we exit on our own timeout
643+ // (which also requires us to notify the c/b that it is supposed to delete the pending obj)
644+ case ERR_INPROGRESS:
645+ // Re-check every 10ms, we expect this to happen fast
646+ esp_delay (timeout_ms,
647+ [&]() {
648+ return !pending->done ;
649+ }, 10 );
650+
651+ if (pending->done ) {
652+ if ((pending->addr ).isSet ()) {
653+ aResult = pending->addr ;
654+ err = ERR_OK;
655+ }
656+ } else {
657+ pending->done = true ;
658+ pending.release ();
659+ err = ERR_TIMEOUT;
644660 }
661+
662+ break ;
645663 }
646664
647- if (err == ERR_OK) {
665+ if (err == ERR_OK) {
648666 DEBUG_WIFI_GENERIC (" [hostByName] Host: %s IP: %s\n " , aHostname, aResult.toString ().c_str ());
649667 return 1 ;
650668 }
651-
652- DEBUG_WIFI_GENERIC (" [hostByName] Host: %s lookup error: %s (%d)!\n " , aHostname, lwip_strerr (err), (int )err);
669+
670+ DEBUG_WIFI_GENERIC (" [hostByName] Host: %s lookup error: %s (%d)!\n " ,
671+ aHostname,
672+ (err == ERR_TIMEOUT) ? " Timeout" :
673+ (err == ERR_INPROGRESS) ? " No response" :
674+ " Unknown" , static_cast <int >(err));
675+
653676 return 0 ;
654677}
655678
656- #if LWIP_IPV4 && LWIP_IPV6
657- int ESP8266WiFiGenericClass::hostByName (const char * aHostname, IPAddress& aResult, uint32_t timeout_ms, DNSResolveType resolveType)
679+ /* *
680+ * Resolve the given hostname to an IP address.
681+ * @param aHostname Name to be resolved
682+ * @param aResult IPAddress structure to store the returned IP address
683+ * @return 1 if aIPAddrString was successfully converted to an IP address,
684+ * else 0
685+ */
686+ int ESP8266WiFiGenericClass::hostByName (const char * aHostname, IPAddress& aResult)
658687{
659- ip_addr_t addr;
660- err_t err;
661- aResult = static_cast <uint32_t >(INADDR_NONE);
662-
663- if (aResult.fromString (aHostname)) {
664- // Host name is a IP address use it!
665- DEBUG_WIFI_GENERIC (" [hostByName] Host: %s is a IP!\n " , aHostname);
666- return 1 ;
667- }
668-
669- DEBUG_WIFI_GENERIC (" [hostByName] request IP for: %s\n " , aHostname);
670- switch (resolveType)
671- {
672- // Use selected addrtype
673- case DNSResolveType::DNS_AddrType_IPv4:
674- case DNSResolveType::DNS_AddrType_IPv6:
675- case DNSResolveType::DNS_AddrType_IPv4_IPv6:
676- case DNSResolveType::DNS_AddrType_IPv6_IPv4:
677- err = dns_gethostbyname_addrtype (aHostname, &addr, &wifi_dns_found_callback, &aResult, (uint8_t ) resolveType);
678- break ;
679- default :
680- err = dns_gethostbyname_addrtype (aHostname, &addr, &wifi_dns_found_callback, &aResult, LWIP_DNS_ADDRTYPE_DEFAULT); // If illegal type, use default.
681- break ;
682- }
683-
684- if (err == ERR_OK) {
685- aResult = IPAddress (&addr);
686- } else if (err == ERR_INPROGRESS) {
687- _dns_lookup_pending = true ;
688- // will resume on timeout or when wifi_dns_found_callback fires
689- esp_delay (timeout_ms, []() { return _dns_lookup_pending; });
690- _dns_lookup_pending = false ;
691- // will return here when dns_found_callback fires
692- if (aResult.isSet ()) {
693- err = ERR_OK;
694- }
695- }
688+ return hostByNameImpl (aHostname, aResult, DNSDefaultTimeoutMs, DNSResolveTypeDefault);
689+ }
696690
697- if (err == ERR_OK) {
698- DEBUG_WIFI_GENERIC ( " [hostByName] Host: %s IP: %s \n " , aHostname, aResult. toString (). c_str ());
699- return 1 ;
700- }
691+ int ESP8266WiFiGenericClass::hostByName ( const char * aHostname, IPAddress& aResult, uint32_t timeout_ms)
692+ {
693+ return hostByNameImpl (aHostname, aResult, timeout_ms, DNSResolveTypeDefault) ;
694+ }
701695
702- DEBUG_WIFI_GENERIC (" [hostByName] Host: %s lookup error: %d!\n " , aHostname, (int )err);
703- return 0 ;
696+ #if LWIP_IPV4 && LWIP_IPV6
697+ int ESP8266WiFiGenericClass::hostByName (const char * aHostname, IPAddress& aResult, uint32_t timeout_ms, DNSResolveType resolveType)
698+ {
699+ return hostByNameImpl (aHostname, aResult, timeout_ms, resolveType);
704700}
705701#endif
706702
@@ -710,16 +706,19 @@ int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResul
710706 * @param ipaddr
711707 * @param callback_arg
712708 */
713- void wifi_dns_found_callback (const char *name , const ip_addr_t * ipaddr, void *callback_arg )
709+ static void _dns_found_callback (const char * , const ip_addr_t * ipaddr, void * arg )
714710{
715- (void ) name;
716- if (!_dns_lookup_pending) {
711+ auto result = reinterpret_cast <_dns_found_result*>(arg);
712+ if (result->done ) {
713+ delete result;
717714 return ;
718715 }
719- if (ipaddr) {
720- (*reinterpret_cast <IPAddress*>(callback_arg)) = IPAddress (ipaddr);
716+
717+ if (ipaddr) {
718+ result->addr = IPAddress (ipaddr);
721719 }
722- _dns_lookup_pending = false ; // resume hostByName
720+
721+ result->done = true ;
723722 esp_schedule ();
724723}
725724
0 commit comments