From fea6abffe2ce35b7008c3bbc03f10c18206f0d5e Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Sun, 26 Nov 2023 21:55:29 +0100 Subject: [PATCH] Enable resolve to return multiple addresses --- esphome/components/mdns/mdns_component.h | 2 +- esphome/components/mdns/mdns_esp32.cpp | 26 ++++++++++++++++------ esphome/components/mdns/mdns_esp8266.cpp | 17 +++++++++----- esphome/components/mdns/mdns_libretiny.cpp | 11 ++------- esphome/components/mdns/mdns_rp2040.cpp | 17 +++++++++----- esphome/components/network/__init__.py | 2 +- esphome/components/network/resolver.cpp | 24 ++++++++++++-------- esphome/components/network/resolver.h | 7 +++--- 8 files changed, 66 insertions(+), 40 deletions(-) diff --git a/esphome/components/mdns/mdns_component.h b/esphome/components/mdns/mdns_component.h index fb56d4e46f..f86b122ccd 100644 --- a/esphome/components/mdns/mdns_component.h +++ b/esphome/components/mdns/mdns_component.h @@ -36,7 +36,7 @@ class MDNSComponent : public Component { void add_extra_service(MDNSService service) { services_extra_.push_back(std::move(service)); } - network::IPAddress resolve(const std::string &servicename); + std::vector resolve(const std::string &servicename); void on_shutdown() override; diff --git a/esphome/components/mdns/mdns_esp32.cpp b/esphome/components/mdns/mdns_esp32.cpp index 943f3dc854..cfc92f5d59 100644 --- a/esphome/components/mdns/mdns_esp32.cpp +++ b/esphome/components/mdns/mdns_esp32.cpp @@ -49,23 +49,35 @@ void MDNSComponent::setup() { } } -network::IPAddress MDNSComponent::resolve(const std::string &servicename) { - network::IPAddress resolved; +std::vector MDNSComponent::resolve(const std::string &servicename) { + std::vector resolved; mdns_result_t *results = nullptr; - esp_err_t err = mdns_query_ptr(servicename.c_str(), "_tcp", 3000, 20, &results); + mdns_ip_addr_t *a = nullptr; + esp_err_t err = mdns_query_ptr(("_" + servicename).c_str(), "_tcp", 3000, 20, &results); if (err) { ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); - return network::IPAddress(); + return {}; } if (!results) { ESP_LOGW(TAG, "No results found!"); - return network::IPAddress(); + return {}; + } + while (results) { + a = results->addr; + while (a) { + network::IPAddress ip_addr = network::IPAddress(&a->addr); + if (std::count(resolved.begin(), resolved.end(), ip_addr) == 0) { + resolved.push_back(ip_addr); + } + ESP_LOGVV(TAG, "Found MDS %s", ip_addr.str().c_str()); + a = a->next; + } + results = results->next; } - resolved = network::IPAddress(&results->addr->addr); mdns_query_results_free(results); - return network::IPAddress(resolved); + return resolved; } void MDNSComponent::on_shutdown() { diff --git a/esphome/components/mdns/mdns_esp8266.cpp b/esphome/components/mdns/mdns_esp8266.cpp index 56b810ce63..03d6610e43 100644 --- a/esphome/components/mdns/mdns_esp8266.cpp +++ b/esphome/components/mdns/mdns_esp8266.cpp @@ -10,6 +10,8 @@ namespace esphome { namespace mdns { +static const char *const TAG = "mdns"; + void MDNSComponent::setup() { global_mdns = this; this->compile_records_(); @@ -35,12 +37,17 @@ void MDNSComponent::setup() { } } } -network::IPAddress MDNSComponent::resolve(const std::string &servicename) { - int n = MDNS.queryService(servicename.c_str(), "tcp"); - if (n > 0) { - return network::IPAddress(MDNS.IP(0)); +std::vector MDNSComponent::resolve(const std::string &servicename) { + std::vector resolved; + uint8_t n = MDNS.queryService(servicename.c_str(), "tcp"); + for (uint8_t i = 0; i < n; i++) { + network::IPAddress ip_addr = network::IPAddress(MDNS.IP(i)); + if (std::count(resolved.begin(), resolved.end(), ip_addr) == 0) { + resolved.push_back(ip_addr); + } + ESP_LOGVV(TAG, "Found mDNS %s", ip_addr.str().c_str()); } - return network::IPAddress(); + return resolved; } void MDNSComponent::loop() { MDNS.update(); } diff --git a/esphome/components/mdns/mdns_libretiny.cpp b/esphome/components/mdns/mdns_libretiny.cpp index 4380a32198..b40159472a 100644 --- a/esphome/components/mdns/mdns_libretiny.cpp +++ b/esphome/components/mdns/mdns_libretiny.cpp @@ -36,15 +36,8 @@ void MDNSComponent::setup() { } } -/* - // Libre tiny doesn't have a "full" mDNS implementation - network::IPAddress MDNSComponent::resolve(const std::string &servicename) { - int n = MDNS.queryService(servicename.c_str(), "tcp"); - if (n > 0) { - return network::IPAddress(MDNS.IP(0)); - } - return network::IPAddress(); -}*/ +// Libre tiny doesn't have a "full" mDNS implementation +std::vector MDNSComponent::resolve(const std::string &servicename) { return {}; } void MDNSComponent::on_shutdown() {} diff --git a/esphome/components/mdns/mdns_rp2040.cpp b/esphome/components/mdns/mdns_rp2040.cpp index 874a011ee1..f55292c6a5 100644 --- a/esphome/components/mdns/mdns_rp2040.cpp +++ b/esphome/components/mdns/mdns_rp2040.cpp @@ -10,6 +10,8 @@ namespace esphome { namespace mdns { +static const char *const TAG = "mdns"; + void MDNSComponent::setup() { global_mdns = this; this->compile_records_(); @@ -36,12 +38,17 @@ void MDNSComponent::setup() { } } -network::IPAddress MDNSComponent::resolve(const std::string &servicename) { - int n = MDNS.queryService(servicename.c_str(), "tcp"); - if (n > 0) { - return network::IPAddress(MDNS.IP(0)); +std::vector MDNSComponent::resolve(const std::string &servicename) { + std::vector resolved; + uint8_t n = MDNS.queryService(servicename.c_str(), "tcp"); + for (uint8_t i = 0; i < n; i++) { + network::IPAddress ip_addr_ = network::IPAddress(MDNS.IP(i)); + if (std::count(resolved.begin(), resolved.end(), ip_addr_) == 0) { + resolved.push_back(ip_addr_); + } + ESP_LOGVV(TAG, "Found mDNS %s", ip_addr_.str().c_str()); } - return network::IPAddress(); + return resolved; } void MDNSComponent::loop() { MDNS.update(); } diff --git a/esphome/components/network/__init__.py b/esphome/components/network/__init__.py index 43cd62b3ab..5974131f27 100644 --- a/esphome/components/network/__init__.py +++ b/esphome/components/network/__init__.py @@ -54,7 +54,7 @@ async def to_code(config): else: hosts = [] - map_ = cg.std_ns.class_("map").template(cg.std_string, IPAddress) + map_ = cg.std_ns.class_("multimap").template(cg.std_string, IPAddress) cg.new_Pvariable(config[CONF_NETWORK_ID], map_(hosts)) cg.add_define("ENABLE_IPV6", config[CONF_ENABLE_IPV6]) if CORE.using_esp_idf: diff --git a/esphome/components/network/resolver.cpp b/esphome/components/network/resolver.cpp index 712abb806d..1d1f2016b1 100644 --- a/esphome/components/network/resolver.cpp +++ b/esphome/components/network/resolver.cpp @@ -1,3 +1,4 @@ +#include #include "resolver.h" #include "lwip/dns.h" #include "esphome/core/log.h" @@ -20,18 +21,23 @@ namespace network { static const char *const TAG = "resolver"; Resolver::Resolver() { global_resolver = this; } -Resolver::Resolver(std::map hosts) : hosts_(std::move(hosts)) { +Resolver::Resolver(std::multimap hosts) : hosts_(std::move(hosts)) { global_resolver = this; } -network::IPAddress Resolver::resolve(const std::string &hostname) { +// TODO(HeMan): resolve needs to return multiple IP addresses +std::vector Resolver::resolve(const std::string &hostname) { if (this->hosts_.count(hostname) > 0) { - ESP_LOGVV(TAG, "Found %s in hosts section", hostname.c_str()); - return this->hosts_[hostname]; + std::vector resolved; + for (auto a = hosts_.find(hostname); a != hosts_.end(); a++) { + resolved.push_back(a->second); + ESP_LOGVV(TAG, "Found %s in hosts section", hostname.c_str()); + } + return resolved; } #ifdef USE_MDNS ESP_LOGV(TAG, "Looking for %s with mDNS", hostname.c_str()); - network::IPAddress resolved_mdns = mdns::global_mdns->resolve(hostname); - if (resolved_mdns.is_set()) { + std::vector resolved_mdns = mdns::global_mdns->resolve(hostname); + if (!resolved_mdns.empty()) { ESP_LOGVV(TAG, "Found %s in mDNS", hostname.c_str()); return resolved_mdns; } @@ -41,7 +47,7 @@ network::IPAddress Resolver::resolve(const std::string &hostname) { err_t err = dns_gethostbyname_addrtype(hostname.c_str(), &addr, Resolver::dns_found_callback, this, ESPHOME_DNS_ADDRTYPE); if (err == ERR_OK) { - return network::IPAddress(&addr); + return {network::IPAddress(&addr)}; } this->connect_begin_ = millis(); while (!this->dns_resolved_ && !this->dns_resolve_error_ && (millis() - this->connect_begin_ < 2000)) { @@ -51,7 +57,7 @@ network::IPAddress Resolver::resolve(const std::string &hostname) { ESP_LOGVV(TAG, "Found %s in DNS", hostname.c_str()); this->dns_resolved_ = true; this->ip_ = network::IPAddress(&addr); - return this->ip_; + return {this->ip_}; } case ERR_INPROGRESS: { // wait for callback @@ -73,7 +79,7 @@ network::IPAddress Resolver::resolve(const std::string &hostname) { if (!this->dns_resolved_) { ESP_LOGVV(TAG, "Not resolved"); } - return this->ip_; + return {this->ip_}; } void Resolver::dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg) { diff --git a/esphome/components/network/resolver.h b/esphome/components/network/resolver.h index fcb422ad89..5ef6c48d27 100644 --- a/esphome/components/network/resolver.h +++ b/esphome/components/network/resolver.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include "ip_address.h" namespace esphome { @@ -9,13 +10,13 @@ namespace network { class Resolver { public: Resolver(); - Resolver(std::map hosts); + Resolver(std::multimap hosts); ~Resolver(); - network::IPAddress resolve(const std::string &hostname); + std::vector resolve(const std::string &hostname); protected: static void dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg); - std::map hosts_; + std::multimap hosts_; network::IPAddress ip_; bool dns_resolved_{false}; bool dns_resolve_error_{false};