22
22
23
23
*/
24
24
25
+ #include < cstring>
25
26
#include < list>
26
- #include < string.h>
27
+ #include < memory>
28
+ #include < type_traits>
29
+
27
30
#include < coredecls.h>
28
31
#include < PolledTimeout.h>
29
32
#include " ESP8266WiFi.h"
@@ -595,112 +598,105 @@ bool ESP8266WiFiGenericClass::isSleepLevelMax () {
595
598
// ------------------------------------------------ Generic Network function ---------------------------------------------
596
599
// -----------------------------------------------------------------------------------------------------------------------
597
600
598
- void wifi_dns_found_callback ( const char *name, const ip_addr_t *ipaddr, void *callback_arg);
601
+ namespace {
599
602
600
- static bool _dns_lookup_pending = false ;
603
+ struct _dns_found_result {
604
+ IPAddress addr;
605
+ bool done;
606
+ };
601
607
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 );
612
608
}
613
609
610
+ static void _dns_found_callback (const char *, const ip_addr_t *, void *);
614
611
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);
623
615
return 1 ;
624
616
}
625
617
618
+ static_assert (std::is_same_v<uint8_t , std::underlying_type_t <decltype (resolveType)>>, " " );
626
619
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;
644
660
}
661
+
662
+ break ;
645
663
}
646
664
647
- if (err == ERR_OK) {
665
+ if (err == ERR_OK) {
648
666
DEBUG_WIFI_GENERIC (" [hostByName] Host: %s IP: %s\n " , aHostname, aResult.toString ().c_str ());
649
667
return 1 ;
650
668
}
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
+
653
676
return 0 ;
654
677
}
655
678
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)
658
687
{
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
+ }
696
690
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
+ }
701
695
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);
704
700
}
705
701
#endif
706
702
@@ -710,16 +706,19 @@ int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResul
710
706
* @param ipaddr
711
707
* @param callback_arg
712
708
*/
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 )
714
710
{
715
- (void ) name;
716
- if (!_dns_lookup_pending) {
711
+ auto result = reinterpret_cast <_dns_found_result*>(arg);
712
+ if (result->done ) {
713
+ delete result;
717
714
return ;
718
715
}
719
- if (ipaddr) {
720
- (*reinterpret_cast <IPAddress*>(callback_arg)) = IPAddress (ipaddr);
716
+
717
+ if (ipaddr) {
718
+ result->addr = IPAddress (ipaddr);
721
719
}
722
- _dns_lookup_pending = false ; // resume hostByName
720
+
721
+ result->done = true ;
723
722
esp_schedule ();
724
723
}
725
724
0 commit comments