Enable resolve to return multiple addresses

This commit is contained in:
Jimmy Hedman 2023-11-26 21:55:29 +01:00
parent cb5a3a9dab
commit fea6abffe2
No known key found for this signature in database
8 changed files with 66 additions and 40 deletions

View File

@ -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<network::IPAddress> resolve(const std::string &servicename);
void on_shutdown() override;

View File

@ -49,23 +49,35 @@ void MDNSComponent::setup() {
}
}
network::IPAddress MDNSComponent::resolve(const std::string &servicename) {
network::IPAddress resolved;
std::vector<network::IPAddress> MDNSComponent::resolve(const std::string &servicename) {
std::vector<network::IPAddress> 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() {

View File

@ -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<network::IPAddress> MDNSComponent::resolve(const std::string &servicename) {
std::vector<network::IPAddress> 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(); }

View File

@ -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<network::IPAddress> MDNSComponent::resolve(const std::string &servicename) { return {}; }
void MDNSComponent::on_shutdown() {}

View File

@ -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<network::IPAddress> MDNSComponent::resolve(const std::string &servicename) {
std::vector<network::IPAddress> 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(); }

View File

@ -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:

View File

@ -1,3 +1,4 @@
#include <vector>
#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<std::string, network::IPAddress> hosts) : hosts_(std::move(hosts)) {
Resolver::Resolver(std::multimap<std::string, network::IPAddress> 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<network::IPAddress> 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<network::IPAddress> 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<network::IPAddress> 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) {

View File

@ -1,6 +1,7 @@
#pragma once
#include <string>
#include <vector>
#include <map>
#include "ip_address.h"
namespace esphome {
@ -9,13 +10,13 @@ namespace network {
class Resolver {
public:
Resolver();
Resolver(std::map<std::string, network::IPAddress> hosts);
Resolver(std::multimap<std::string, network::IPAddress> hosts);
~Resolver();
network::IPAddress resolve(const std::string &hostname);
std::vector<network::IPAddress> resolve(const std::string &hostname);
protected:
static void dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg);
std::map<std::string, network::IPAddress> hosts_;
std::multimap<std::string, network::IPAddress> hosts_;
network::IPAddress ip_;
bool dns_resolved_{false};
bool dns_resolve_error_{false};