From 73030ab2f28864ddcd2878c8e94a77e620be3d95 Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Tue, 23 Apr 2024 18:10:59 +0800 Subject: [PATCH] dns: use undeprecated c-ares APIs c-ares marked some APIs deprecated in 1.28.1. in this change, we conditionally use the undeprecated APIs when they are available. please note, we don't specify the minimal supported c-ares version in our building system. in which, ares_fds() and ares_process() are not changed yet, because we need to change the way how to poll the events for name resolution. this would need more thoughts before moving forward. Refs #2197 Signed-off-by: Kefu Chai --- src/net/dns.cc | 97 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/src/net/dns.cc b/src/net/dns.cc index 09aee14486d..c3744d75115 100644 --- a/src/net/dns.cc +++ b/src/net/dns.cc @@ -262,6 +262,31 @@ class net::dns_resolver::impl // The following pragma is needed to work around a false-positive warning // in Gcc 11 (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96003). #pragma GCC diagnostic ignored "-Wnonnull" +#if ARES_VERSION >= 0x011000 + + ares_addrinfo_hints hints = { + .ai_flags = ARES_AI_CANONNAME, + .ai_family = af, + .ai_socktype = 0, + .ai_protocol = 0, + }; + ares_getaddrinfo(_channel, p->name.c_str(), nullptr, &hints, [](void* arg, int status, int timeouts, ares_addrinfo* addrinfo) { + // we do potentially allocating operations below, so wrap the pointer in a + // unique here. + std::unique_ptr p(reinterpret_cast(arg)); + + switch (status) { + default: + dns_log.debug("Query failed: {}", status); + p->set_exception(std::system_error(status, ares_errorc, p->name)); + break; + case ARES_SUCCESS: + p->set_value(make_hostent(addrinfo)); + break; + } + + }, reinterpret_cast(p)); +#else ares_gethostbyname(_channel, p->name.c_str(), af, [](void* arg, int status, int timeouts, ::hostent* host) { // we do potentially allocating operations below, so wrap the pointer in a // unique here. @@ -278,7 +303,7 @@ class net::dns_resolver::impl } }, reinterpret_cast(p)); - +#endif poll_sockets(); @@ -343,6 +368,47 @@ class net::dns_resolver::impl dns_call call(*this); +#if ARES_VERSION >= 0x011c00 + ares_query_dnsrec(_channel, query.c_str(), ARES_CLASS_IN, ARES_REC_TYPE_SRV, + [](void* arg, ares_status_t status, size_t timeouts, + const ares_dns_record *dnsrec) { + auto p = std::unique_ptr>( + reinterpret_cast *>(arg)); + if (status != ARES_SUCCESS) { + dns_log.debug("Query failed: {}", fmt::underlying(status)); + p->set_exception(std::system_error(status, ares_errorc)); + return; + } + const size_t rr_count = ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER); + srv_records replies; + for (size_t i = 0; i < rr_count; i++) { + const ares_dns_rr_t* rr = ares_dns_record_rr_get( + const_cast(dnsrec), + ARES_SECTION_ANSWER, i); + if (!rr) { + // not likely, but still.. + status = ARES_EBADRESP; + break; + } + if (ares_dns_rr_get_class(rr) != ARES_CLASS_IN || + ares_dns_rr_get_type(rr) != ARES_REC_TYPE_SRV) { + continue; + } + replies.push_back({ + ares_dns_rr_get_u16(rr, ARES_RR_SRV_PRIORITY), + ares_dns_rr_get_u16(rr, ARES_RR_SRV_WEIGHT), + ares_dns_rr_get_u16(rr, ARES_RR_SRV_PORT), + sstring{ares_dns_rr_get_str(rr, ARES_RR_SRV_TARGET)} + }); + } + if (status != ARES_SUCCESS) { + dns_log.debug("Parse failed: {}", fmt::underlying(status)); + p->set_exception(std::system_error(status, ares_errorc)); + return; + } + p->set_value(std::move(replies)); + }, reinterpret_cast(p.release()), nullptr); +#else ares_query(_channel, query.c_str(), ns_c_in, ns_t_srv, [](void* arg, int status, int timeouts, unsigned char* buf, int len) { @@ -367,6 +433,7 @@ class net::dns_resolver::impl } ares_free_data(start); }, reinterpret_cast(p.release())); +#endif poll_sockets(); @@ -482,6 +549,34 @@ class net::dns_resolver::impl return records; } +#if ARES_VERSION >= 0x011000 + static hostent make_hostent(const ares_addrinfo* ai) { + hostent e; + if (!ai) { + return e; + } + for (auto cname = ai->cnames; cname != nullptr; cname = cname->next) { + if (cname->alias == nullptr) { + continue; + } + e.names.emplace_back(cname->alias); + } + for (auto node = ai->nodes; node != nullptr; node = node->ai_next) { + switch (node->ai_family) { + case AF_INET: + e.addr_list.emplace_back(reinterpret_cast(node->ai_addr)->sin_addr); + break; + case AF_INET6: + e.addr_list.emplace_back(reinterpret_cast(node->ai_addr)->sin6_addr); + break; + } + } + + dns_log.debug("Query success: {}/{}", e.names.front(), e.addr_list.front()); + + return e; + } +#endif static hostent make_hostent(const ::hostent& host) { hostent e; e.names.emplace_back(host.h_name);