• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include <grpc/impl/channel_arg_names.h>
18 #include <grpc/support/alloc.h>
19 #include <grpc/support/port_platform.h>
20 #include <stdint.h>
21 
22 #include <algorithm>
23 #include <functional>
24 #include <memory>
25 #include <string>
26 #include <utility>
27 #include <vector>
28 
29 #include "absl/base/thread_annotations.h"
30 #include "absl/log/log.h"
31 #include "absl/status/status.h"
32 #include "absl/status/statusor.h"
33 #include "absl/strings/match.h"
34 #include "absl/strings/string_view.h"
35 #include "absl/strings/strip.h"
36 #include "absl/types/optional.h"
37 #include "src/core/config/core_configuration.h"
38 #include "src/core/lib/debug/trace.h"
39 #include "src/core/lib/iomgr/closure.h"
40 #include "src/core/lib/iomgr/error.h"
41 #include "src/core/lib/iomgr/iomgr_fwd.h"
42 #include "src/core/lib/iomgr/pollset_set.h"
43 #include "src/core/lib/iomgr/resolved_address.h"
44 #include "src/core/resolver/dns/event_engine/service_config_helper.h"
45 #include "src/core/resolver/resolver.h"
46 #include "src/core/resolver/resolver_factory.h"
47 #include "src/core/service_config/service_config.h"
48 #include "src/core/util/debug_location.h"
49 #include "src/core/util/orphanable.h"
50 #include "src/core/util/ref_counted_ptr.h"
51 #include "src/core/util/status_helper.h"
52 #include "src/core/util/sync.h"
53 #include "src/core/util/time.h"
54 #include "src/core/util/uri.h"
55 
56 #if GRPC_ARES == 1
57 
58 #include <address_sorting/address_sorting.h>
59 
60 #include "absl/strings/str_cat.h"
61 #include "src/core/config/config_vars.h"
62 #include "src/core/lib/channel/channel_args.h"
63 #include "src/core/lib/iomgr/resolve_address.h"
64 #include "src/core/lib/transport/error_utils.h"
65 #include "src/core/load_balancing/grpclb/grpclb_balancer_addresses.h"
66 #include "src/core/resolver/dns/c_ares/grpc_ares_wrapper.h"
67 #include "src/core/resolver/endpoint_addresses.h"
68 #include "src/core/resolver/polling_resolver.h"
69 #include "src/core/service_config/service_config_impl.h"
70 #include "src/core/util/backoff.h"
71 
72 #define GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS 1
73 #define GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER 1.6
74 #define GRPC_DNS_RECONNECT_MAX_BACKOFF_SECONDS 120
75 #define GRPC_DNS_RECONNECT_JITTER 0.2
76 
77 namespace grpc_core {
78 
79 namespace {
80 
81 class AresClientChannelDNSResolver final : public PollingResolver {
82  public:
83   AresClientChannelDNSResolver(ResolverArgs args,
84                                Duration min_time_between_resolutions);
85 
86   OrphanablePtr<Orphanable> StartRequest() override;
87 
88  private:
89   class AresRequestWrapper final
90       : public InternallyRefCounted<AresRequestWrapper> {
91    public:
AresRequestWrapper(RefCountedPtr<AresClientChannelDNSResolver> resolver)92     explicit AresRequestWrapper(
93         RefCountedPtr<AresClientChannelDNSResolver> resolver)
94         : resolver_(std::move(resolver)) {
95       // TODO(hork): replace this callback bookkeeping with promises.
96       // Locking to prevent completion before all records are queried
97       MutexLock lock(&on_resolved_mu_);
98       Ref(DEBUG_LOCATION, "OnHostnameResolved").release();
99       GRPC_CLOSURE_INIT(&on_hostname_resolved_, OnHostnameResolved, this,
100                         nullptr);
101       hostname_request_.reset(grpc_dns_lookup_hostname_ares(
102           resolver_->authority().c_str(), resolver_->name_to_resolve().c_str(),
103           kDefaultSecurePort, resolver_->interested_parties(),
104           &on_hostname_resolved_, &addresses_, resolver_->query_timeout_ms_));
105       GRPC_TRACE_VLOG(cares_resolver, 2)
106           << "(c-ares resolver) resolver:" << resolver_.get()
107           << " Started resolving hostnames. hostname_request_:"
108           << hostname_request_.get();
109       if (resolver_->enable_srv_queries_) {
110         Ref(DEBUG_LOCATION, "OnSRVResolved").release();
111         GRPC_CLOSURE_INIT(&on_srv_resolved_, OnSRVResolved, this, nullptr);
112         srv_request_.reset(grpc_dns_lookup_srv_ares(
113             resolver_->authority().c_str(),
114             resolver_->name_to_resolve().c_str(),
115             resolver_->interested_parties(), &on_srv_resolved_,
116             &balancer_addresses_, resolver_->query_timeout_ms_));
117         GRPC_TRACE_VLOG(cares_resolver, 2)
118             << "(c-ares resolver) resolver:" << resolver_.get()
119             << " Started resolving SRV records. srv_request_:"
120             << srv_request_.get();
121       }
122       if (resolver_->request_service_config_) {
123         Ref(DEBUG_LOCATION, "OnTXTResolved").release();
124         GRPC_CLOSURE_INIT(&on_txt_resolved_, OnTXTResolved, this, nullptr);
125         txt_request_.reset(grpc_dns_lookup_txt_ares(
126             resolver_->authority().c_str(),
127             resolver_->name_to_resolve().c_str(),
128             resolver_->interested_parties(), &on_txt_resolved_,
129             &service_config_json_, resolver_->query_timeout_ms_));
130         GRPC_TRACE_VLOG(cares_resolver, 2)
131             << "(c-ares resolver) resolver:" << resolver_.get()
132             << " Started resolving TXT records. txt_request_:"
133             << txt_request_.get();
134       }
135     }
136 
~AresRequestWrapper()137     ~AresRequestWrapper() override {
138       gpr_free(service_config_json_);
139       resolver_.reset(DEBUG_LOCATION, "dns-resolving");
140     }
141 
142     // Note that thread safety cannot be analyzed due to this being invoked from
143     // OrphanablePtr<>, and there's no way to pass the lock annotation through
144     // there.
Orphan()145     void Orphan() override ABSL_NO_THREAD_SAFETY_ANALYSIS {
146       {
147         MutexLock lock(&on_resolved_mu_);
148         if (hostname_request_ != nullptr) {
149           grpc_cancel_ares_request(hostname_request_.get());
150         }
151         if (srv_request_ != nullptr) {
152           grpc_cancel_ares_request(srv_request_.get());
153         }
154         if (txt_request_ != nullptr) {
155           grpc_cancel_ares_request(txt_request_.get());
156         }
157       }
158       Unref(DEBUG_LOCATION, "Orphan");
159     }
160 
161    private:
162     static void OnHostnameResolved(void* arg, grpc_error_handle error);
163     static void OnSRVResolved(void* arg, grpc_error_handle error);
164     static void OnTXTResolved(void* arg, grpc_error_handle error);
165     absl::optional<Result> OnResolvedLocked(grpc_error_handle error)
166         ABSL_EXCLUSIVE_LOCKS_REQUIRED(on_resolved_mu_);
167 
168     Mutex on_resolved_mu_;
169     RefCountedPtr<AresClientChannelDNSResolver> resolver_;
170     grpc_closure on_hostname_resolved_;
171     std::unique_ptr<grpc_ares_request> hostname_request_
172         ABSL_GUARDED_BY(on_resolved_mu_);
173     grpc_closure on_srv_resolved_;
174     std::unique_ptr<grpc_ares_request> srv_request_
175         ABSL_GUARDED_BY(on_resolved_mu_);
176     grpc_closure on_txt_resolved_;
177     std::unique_ptr<grpc_ares_request> txt_request_
178         ABSL_GUARDED_BY(on_resolved_mu_);
179     // Output fields from ares request.
180     std::unique_ptr<EndpointAddressesList> addresses_
181         ABSL_GUARDED_BY(on_resolved_mu_);
182     std::unique_ptr<EndpointAddressesList> balancer_addresses_
183         ABSL_GUARDED_BY(on_resolved_mu_);
184     char* service_config_json_ ABSL_GUARDED_BY(on_resolved_mu_) = nullptr;
185   };
186 
187   ~AresClientChannelDNSResolver() override;
188 
189   /// whether to request the service config
190   const bool request_service_config_;
191   // whether or not to enable SRV DNS queries
192   const bool enable_srv_queries_;
193   // timeout in milliseconds for active DNS queries
194   const int query_timeout_ms_;
195 };
196 
AresClientChannelDNSResolver(ResolverArgs args,Duration min_time_between_resolutions)197 AresClientChannelDNSResolver::AresClientChannelDNSResolver(
198     ResolverArgs args, Duration min_time_between_resolutions)
199     : PollingResolver(std::move(args), min_time_between_resolutions,
200                       BackOff::Options()
201                           .set_initial_backoff(Duration::Seconds(
202                               GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS))
203                           .set_multiplier(GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER)
204                           .set_jitter(GRPC_DNS_RECONNECT_JITTER)
205                           .set_max_backoff(Duration::Seconds(
206                               GRPC_DNS_RECONNECT_MAX_BACKOFF_SECONDS)),
207                       &cares_resolver_trace),
208       request_service_config_(
209           !channel_args()
210                .GetBool(GRPC_ARG_SERVICE_CONFIG_DISABLE_RESOLUTION)
211                .value_or(true)),
212       enable_srv_queries_(channel_args()
213                               .GetBool(GRPC_ARG_DNS_ENABLE_SRV_QUERIES)
214                               .value_or(false)),
215       query_timeout_ms_(
216           std::max(0, channel_args()
217                           .GetInt(GRPC_ARG_DNS_ARES_QUERY_TIMEOUT_MS)
218                           .value_or(GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS))) {}
219 
~AresClientChannelDNSResolver()220 AresClientChannelDNSResolver::~AresClientChannelDNSResolver() {
221   GRPC_TRACE_VLOG(cares_resolver, 2)
222       << "(c-ares resolver) resolver:" << this
223       << " destroying AresClientChannelDNSResolver";
224 }
225 
StartRequest()226 OrphanablePtr<Orphanable> AresClientChannelDNSResolver::StartRequest() {
227   return MakeOrphanable<AresRequestWrapper>(
228       RefAsSubclass<AresClientChannelDNSResolver>(DEBUG_LOCATION,
229                                                   "dns-resolving"));
230 }
231 
OnHostnameResolved(void * arg,grpc_error_handle error)232 void AresClientChannelDNSResolver::AresRequestWrapper::OnHostnameResolved(
233     void* arg, grpc_error_handle error) {
234   auto* self = static_cast<AresRequestWrapper*>(arg);
235   absl::optional<Result> result;
236   {
237     MutexLock lock(&self->on_resolved_mu_);
238     self->hostname_request_.reset();
239     result = self->OnResolvedLocked(error);
240   }
241   if (result.has_value()) {
242     self->resolver_->OnRequestComplete(std::move(*result));
243   }
244   self->Unref(DEBUG_LOCATION, "OnHostnameResolved");
245 }
246 
OnSRVResolved(void * arg,grpc_error_handle error)247 void AresClientChannelDNSResolver::AresRequestWrapper::OnSRVResolved(
248     void* arg, grpc_error_handle error) {
249   auto* self = static_cast<AresRequestWrapper*>(arg);
250   absl::optional<Result> result;
251   {
252     MutexLock lock(&self->on_resolved_mu_);
253     self->srv_request_.reset();
254     result = self->OnResolvedLocked(error);
255   }
256   if (result.has_value()) {
257     self->resolver_->OnRequestComplete(std::move(*result));
258   }
259   self->Unref(DEBUG_LOCATION, "OnSRVResolved");
260 }
261 
OnTXTResolved(void * arg,grpc_error_handle error)262 void AresClientChannelDNSResolver::AresRequestWrapper::OnTXTResolved(
263     void* arg, grpc_error_handle error) {
264   auto* self = static_cast<AresRequestWrapper*>(arg);
265   absl::optional<Result> result;
266   {
267     MutexLock lock(&self->on_resolved_mu_);
268     self->txt_request_.reset();
269     result = self->OnResolvedLocked(error);
270   }
271   if (result.has_value()) {
272     self->resolver_->OnRequestComplete(std::move(*result));
273   }
274   self->Unref(DEBUG_LOCATION, "OnTXTResolved");
275 }
276 
277 // Returns a Result if resolution is complete.
278 // callers must release the lock and call OnRequestComplete if a Result is
279 // returned. This is because OnRequestComplete may Orphan the resolver, which
280 // requires taking the lock.
281 absl::optional<AresClientChannelDNSResolver::Result>
OnResolvedLocked(grpc_error_handle error)282 AresClientChannelDNSResolver::AresRequestWrapper::OnResolvedLocked(
283     grpc_error_handle error) ABSL_EXCLUSIVE_LOCKS_REQUIRED(on_resolved_mu_) {
284   if (hostname_request_ != nullptr || srv_request_ != nullptr ||
285       txt_request_ != nullptr) {
286     GRPC_TRACE_VLOG(cares_resolver, 2)
287         << "(c-ares resolver) resolver:" << this
288         << " OnResolved() waiting for results (hostname: "
289         << (hostname_request_ != nullptr ? "waiting" : "done")
290         << ", srv: " << (srv_request_ != nullptr ? "waiting" : "done")
291         << ", txt: " << (txt_request_ != nullptr ? "waiting" : "done") << ")";
292     return absl::nullopt;
293   }
294   GRPC_TRACE_VLOG(cares_resolver, 2)
295       << "(c-ares resolver) resolver:" << this << " OnResolved() proceeding";
296   Result result;
297   result.args = resolver_->channel_args();
298   // TODO(roth): Change logic to be able to report failures for addresses
299   // and service config independently of each other.
300   if (addresses_ != nullptr || balancer_addresses_ != nullptr) {
301     if (addresses_ != nullptr) {
302       result.addresses = std::move(*addresses_);
303     } else {
304       result.addresses.emplace();
305     }
306     if (service_config_json_ != nullptr) {
307       auto service_config_string = ChooseServiceConfig(service_config_json_);
308       if (!service_config_string.ok()) {
309         result.service_config = absl::UnavailableError(
310             absl::StrCat("failed to parse service config: ",
311                          StatusToString(service_config_string.status())));
312       } else if (!service_config_string->empty()) {
313         GRPC_TRACE_VLOG(cares_resolver, 2)
314             << "(c-ares resolver) resolver:" << this
315             << " selected service config choice: " << *service_config_string;
316         result.service_config = ServiceConfigImpl::Create(
317             resolver_->channel_args(), *service_config_string);
318         if (!result.service_config.ok()) {
319           result.service_config = absl::UnavailableError(
320               absl::StrCat("failed to parse service config: ",
321                            result.service_config.status().message()));
322         }
323       }
324     }
325     if (balancer_addresses_ != nullptr) {
326       result.args =
327           SetGrpcLbBalancerAddresses(result.args, *balancer_addresses_);
328     }
329   } else {
330     GRPC_TRACE_VLOG(cares_resolver, 2)
331         << "(c-ares resolver) resolver:" << this
332         << " dns resolution failed: " << StatusToString(error);
333     std::string error_message;
334     grpc_error_get_str(error, StatusStrProperty::kDescription, &error_message);
335     absl::Status status = absl::UnavailableError(
336         absl::StrCat("DNS resolution failed for ", resolver_->name_to_resolve(),
337                      ": ", error_message));
338     result.addresses = status;
339     result.service_config = status;
340   }
341 
342   return std::move(result);
343 }
344 
345 //
346 // Factory
347 //
348 
349 class AresClientChannelDNSResolverFactory final : public ResolverFactory {
350  public:
scheme() const351   absl::string_view scheme() const override { return "dns"; }
352 
IsValidUri(const URI & uri) const353   bool IsValidUri(const URI& uri) const override {
354     if (absl::StripPrefix(uri.path(), "/").empty()) {
355       LOG(ERROR) << "no server name supplied in dns URI";
356       return false;
357     }
358     return true;
359   }
360 
CreateResolver(ResolverArgs args) const361   OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
362     Duration min_time_between_resolutions = std::max(
363         Duration::Zero(), args.args
364                               .GetDurationFromIntMillis(
365                                   GRPC_ARG_DNS_MIN_TIME_BETWEEN_RESOLUTIONS_MS)
366                               .value_or(Duration::Seconds(30)));
367     return MakeOrphanable<AresClientChannelDNSResolver>(
368         std::move(args), min_time_between_resolutions);
369   }
370 };
371 
372 class AresDNSResolver final : public DNSResolver {
373  public:
374   // Abstract class that centralizes common request handling logic via the
375   // template method pattern.
376   // This requires a two-phase initialization, where 1) a request is created via
377   // a subclass constructor, and 2) the request is initiated via Run()
378   class AresRequest {
379    public:
~AresRequest()380     virtual ~AresRequest() {
381       GRPC_TRACE_VLOG(cares_resolver, 2)
382           << "(c-ares resolver) AresRequest:" << this
383           << " dtor ares_request_:" << grpc_ares_request_.get();
384       resolver_->UnregisterRequest(task_handle());
385       grpc_pollset_set_destroy(pollset_set_);
386     }
387 
388     // Initiates the low-level c-ares request and returns its handle.
389     virtual std::unique_ptr<grpc_ares_request> MakeRequestLocked() = 0;
390     // Called on ares resolution, but not upon cancellation.
391     // After execution, the AresRequest will perform any final cleanup and
392     // delete itself.
393     virtual void OnComplete(grpc_error_handle error) = 0;
394 
395     // Called to initiate the request.
Run()396     void Run() {
397       MutexLock lock(&mu_);
398       grpc_ares_request_ = MakeRequestLocked();
399     }
400 
Cancel()401     bool Cancel() {
402       MutexLock lock(&mu_);
403       if (grpc_ares_request_ != nullptr) {
404         GRPC_TRACE_VLOG(cares_resolver, 2)
405             << "(c-ares resolver) AresRequest:" << this
406             << " Cancel ares_request_:" << grpc_ares_request_.get();
407         if (completed_) return false;
408         // OnDnsLookupDone will still be run
409         completed_ = true;
410         grpc_cancel_ares_request(grpc_ares_request_.get());
411       } else {
412         completed_ = true;
413         OnDnsLookupDone(this, absl::CancelledError());
414       }
415       grpc_pollset_set_del_pollset_set(pollset_set_, interested_parties_);
416       return true;
417     }
418 
task_handle()419     TaskHandle task_handle() {
420       return {reinterpret_cast<intptr_t>(this), aba_token_};
421     }
422 
423    protected:
AresRequest(absl::string_view name,absl::string_view name_server,Duration timeout,grpc_pollset_set * interested_parties,AresDNSResolver * resolver,intptr_t aba_token)424     AresRequest(absl::string_view name, absl::string_view name_server,
425                 Duration timeout, grpc_pollset_set* interested_parties,
426                 AresDNSResolver* resolver, intptr_t aba_token)
427         : name_(name),
428           name_server_(name_server),
429           timeout_(timeout),
430           interested_parties_(interested_parties),
431           completed_(false),
432           resolver_(resolver),
433           aba_token_(aba_token),
434           pollset_set_(grpc_pollset_set_create()) {
435       GRPC_CLOSURE_INIT(&on_dns_lookup_done_, OnDnsLookupDone, this,
436                         grpc_schedule_on_exec_ctx);
437       grpc_pollset_set_add_pollset_set(pollset_set_, interested_parties_);
438     }
439 
pollset_set()440     grpc_pollset_set* pollset_set() { return pollset_set_; };
on_dns_lookup_done()441     grpc_closure* on_dns_lookup_done() { return &on_dns_lookup_done_; };
name()442     const std::string& name() { return name_; }
name_server()443     const std::string& name_server() { return name_server_; }
timeout()444     const Duration& timeout() { return timeout_; }
445 
446    private:
447     // Called by ares when lookup has completed or when cancelled. It is always
448     // called exactly once, and it triggers self-deletion.
OnDnsLookupDone(void * arg,grpc_error_handle error)449     static void OnDnsLookupDone(void* arg, grpc_error_handle error) {
450       AresRequest* r = static_cast<AresRequest*>(arg);
451       auto deleter = std::unique_ptr<AresRequest>(r);
452       {
453         MutexLock lock(&r->mu_);
454         grpc_pollset_set_del_pollset_set(r->pollset_set_,
455                                          r->interested_parties_);
456         if (r->completed_) {
457           return;
458         }
459         r->completed_ = true;
460       }
461       r->OnComplete(error);
462     }
463 
464     // the name to resolve
465     const std::string name_;
466     // the name server to query
467     const std::string name_server_;
468     // request-specific timeout
469     Duration timeout_;
470     // mutex to synchronize access to this object (but not to the ares_request
471     // object itself).
472     Mutex mu_;
473     // parties interested in our I/O
474     grpc_pollset_set* const interested_parties_;
475     // underlying cares_request that the query is performed on
476     std::unique_ptr<grpc_ares_request> grpc_ares_request_ ABSL_GUARDED_BY(mu_);
477     // Set when the callback is either cancelled or executed.
478     // It is not the subclasses' responsibility to set this flag.
479     bool completed_ ABSL_GUARDED_BY(mu_);
480     // Parent resolver that created this request
481     AresDNSResolver* resolver_;
482     // Unique token to help distinguish this request from others that may later
483     // be created in the same memory location.
484     intptr_t aba_token_;
485     // closure to call when the ares resolution request completes. Subclasses
486     // should use this as the ares callback in MakeRequestLocked()
487     grpc_closure on_dns_lookup_done_ ABSL_GUARDED_BY(mu_);
488     // locally owned pollset_set, required to support cancellation of requests
489     // while ares still needs a valid pollset_set. Subclasses should give this
490     // pollset to ares in MakeRequestLocked();
491     grpc_pollset_set* pollset_set_;
492   };
493 
494   class AresHostnameRequest final : public AresRequest {
495    public:
AresHostnameRequest(absl::string_view name,absl::string_view default_port,absl::string_view name_server,Duration timeout,grpc_pollset_set * interested_parties,std::function<void (absl::StatusOr<std::vector<grpc_resolved_address>>)> on_resolve_address_done,AresDNSResolver * resolver,intptr_t aba_token)496     AresHostnameRequest(
497         absl::string_view name, absl::string_view default_port,
498         absl::string_view name_server, Duration timeout,
499         grpc_pollset_set* interested_parties,
500         std::function<void(absl::StatusOr<std::vector<grpc_resolved_address>>)>
501             on_resolve_address_done,
502         AresDNSResolver* resolver, intptr_t aba_token)
503         : AresRequest(name, name_server, timeout, interested_parties, resolver,
504                       aba_token),
505           default_port_(default_port),
506           on_resolve_address_done_(std::move(on_resolve_address_done)) {
507       GRPC_TRACE_VLOG(cares_resolver, 2)
508           << "(c-ares resolver) AresHostnameRequest:" << this << " ctor";
509     }
510 
MakeRequestLocked()511     std::unique_ptr<grpc_ares_request> MakeRequestLocked() override {
512       auto ares_request =
513           std::unique_ptr<grpc_ares_request>(grpc_dns_lookup_hostname_ares(
514               name_server().c_str(), name().c_str(), default_port_.c_str(),
515               pollset_set(), on_dns_lookup_done(), &addresses_,
516               timeout().millis()));
517       GRPC_TRACE_VLOG(cares_resolver, 2)
518           << "(c-ares resolver) AresHostnameRequest:" << this
519           << " Start ares_request_:" << ares_request.get();
520       return ares_request;
521     }
522 
OnComplete(grpc_error_handle error)523     void OnComplete(grpc_error_handle error) override {
524       GRPC_TRACE_VLOG(cares_resolver, 2)
525           << "(c-ares resolver) AresHostnameRequest:" << this << " OnComplete";
526       if (!error.ok()) {
527         on_resolve_address_done_(grpc_error_to_absl_status(error));
528         return;
529       }
530       std::vector<grpc_resolved_address> resolved_addresses;
531       if (addresses_ != nullptr) {
532         resolved_addresses.reserve(addresses_->size());
533         for (const auto& server_address : *addresses_) {
534           resolved_addresses.push_back(server_address.address());
535         }
536       }
537       on_resolve_address_done_(std::move(resolved_addresses));
538     }
539 
540     // the default port to use if name doesn't have one
541     const std::string default_port_;
542     // user-provided completion callback
543     const std::function<void(
544         absl::StatusOr<std::vector<grpc_resolved_address>>)>
545         on_resolve_address_done_;
546     // currently resolving addresses
547     std::unique_ptr<EndpointAddressesList> addresses_;
548   };
549 
550   class AresSRVRequest final : public AresRequest {
551    public:
AresSRVRequest(absl::string_view name,absl::string_view name_server,Duration timeout,grpc_pollset_set * interested_parties,std::function<void (absl::StatusOr<std::vector<grpc_resolved_address>>)> on_resolve_address_done,AresDNSResolver * resolver,intptr_t aba_token)552     AresSRVRequest(
553         absl::string_view name, absl::string_view name_server, Duration timeout,
554         grpc_pollset_set* interested_parties,
555         std::function<void(absl::StatusOr<std::vector<grpc_resolved_address>>)>
556             on_resolve_address_done,
557         AresDNSResolver* resolver, intptr_t aba_token)
558         : AresRequest(name, name_server, timeout, interested_parties, resolver,
559                       aba_token),
560           on_resolve_address_done_(std::move(on_resolve_address_done)) {
561       GRPC_TRACE_VLOG(cares_resolver, 2)
562           << "(c-ares resolver) AresSRVRequest:" << this << " ctor";
563     }
564 
MakeRequestLocked()565     std::unique_ptr<grpc_ares_request> MakeRequestLocked() override {
566       auto ares_request =
567           std::unique_ptr<grpc_ares_request>(grpc_dns_lookup_srv_ares(
568               name_server().c_str(), name().c_str(), pollset_set(),
569               on_dns_lookup_done(), &balancer_addresses_, timeout().millis()));
570       GRPC_TRACE_VLOG(cares_resolver, 2)
571           << "(c-ares resolver) AresSRVRequest:" << this
572           << " Start ares_request_:" << ares_request.get();
573       return ares_request;
574     }
575 
OnComplete(grpc_error_handle error)576     void OnComplete(grpc_error_handle error) override {
577       GRPC_TRACE_VLOG(cares_resolver, 2)
578           << "(c-ares resolver) AresSRVRequest:" << this << " OnComplete";
579       if (!error.ok()) {
580         on_resolve_address_done_(grpc_error_to_absl_status(error));
581         return;
582       }
583       std::vector<grpc_resolved_address> resolved_addresses;
584       if (balancer_addresses_ != nullptr) {
585         resolved_addresses.reserve(balancer_addresses_->size());
586         for (const auto& server_address : *balancer_addresses_) {
587           resolved_addresses.push_back(server_address.address());
588         }
589       }
590       on_resolve_address_done_(std::move(resolved_addresses));
591     }
592 
593     // user-provided completion callback
594     const std::function<void(
595         absl::StatusOr<std::vector<grpc_resolved_address>>)>
596         on_resolve_address_done_;
597     // currently resolving addresses
598     std::unique_ptr<EndpointAddressesList> balancer_addresses_;
599   };
600 
601   class AresTXTRequest final : public AresRequest {
602    public:
AresTXTRequest(absl::string_view name,absl::string_view name_server,Duration timeout,grpc_pollset_set * interested_parties,std::function<void (absl::StatusOr<std::string>)> on_resolved,AresDNSResolver * resolver,intptr_t aba_token)603     AresTXTRequest(absl::string_view name, absl::string_view name_server,
604                    Duration timeout, grpc_pollset_set* interested_parties,
605                    std::function<void(absl::StatusOr<std::string>)> on_resolved,
606                    AresDNSResolver* resolver, intptr_t aba_token)
607         : AresRequest(name, name_server, timeout, interested_parties, resolver,
608                       aba_token),
609           on_resolved_(std::move(on_resolved)) {
610       GRPC_TRACE_VLOG(cares_resolver, 2)
611           << "(c-ares resolver) AresTXTRequest:" << this << " ctor";
612     }
613 
~AresTXTRequest()614     ~AresTXTRequest() override { gpr_free(service_config_json_); }
615 
MakeRequestLocked()616     std::unique_ptr<grpc_ares_request> MakeRequestLocked() override {
617       auto ares_request =
618           std::unique_ptr<grpc_ares_request>(grpc_dns_lookup_txt_ares(
619               name_server().c_str(), name().c_str(), pollset_set(),
620               on_dns_lookup_done(), &service_config_json_, timeout().millis()));
621       GRPC_TRACE_VLOG(cares_resolver, 2)
622           << "(c-ares resolver) AresSRVRequest:" << this
623           << " Start ares_request_:" << ares_request.get();
624       return ares_request;
625     }
626 
OnComplete(grpc_error_handle error)627     void OnComplete(grpc_error_handle error) override {
628       GRPC_TRACE_VLOG(cares_resolver, 2)
629           << "(c-ares resolver) AresSRVRequest:" << this << " OnComplete";
630       if (!error.ok()) {
631         on_resolved_(grpc_error_to_absl_status(error));
632         return;
633       }
634       on_resolved_(service_config_json_);
635     }
636 
637     // service config from the TXT record
638     char* service_config_json_ = nullptr;
639     // user-provided completion callback
640     const std::function<void(absl::StatusOr<std::string>)> on_resolved_;
641   };
642 
LookupHostname(std::function<void (absl::StatusOr<std::vector<grpc_resolved_address>>)> on_resolved,absl::string_view name,absl::string_view default_port,Duration timeout,grpc_pollset_set * interested_parties,absl::string_view name_server)643   TaskHandle LookupHostname(
644       std::function<void(absl::StatusOr<std::vector<grpc_resolved_address>>)>
645           on_resolved,
646       absl::string_view name, absl::string_view default_port, Duration timeout,
647       grpc_pollset_set* interested_parties,
648       absl::string_view name_server) override {
649     MutexLock lock(&mu_);
650     auto* request = new AresHostnameRequest(
651         name, default_port, name_server, timeout, interested_parties,
652         std::move(on_resolved), this, aba_token_++);
653     request->Run();
654     auto handle = request->task_handle();
655     open_requests_.insert(handle);
656     return handle;
657   }
658 
LookupHostnameBlocking(absl::string_view name,absl::string_view default_port)659   absl::StatusOr<std::vector<grpc_resolved_address>> LookupHostnameBlocking(
660       absl::string_view name, absl::string_view default_port) override {
661     // TODO(apolcyn): change this to wrap the async version of the c-ares
662     // API with a promise, and remove the reference to the previous resolver.
663     return default_resolver_->LookupHostnameBlocking(name, default_port);
664   }
665 
LookupSRV(std::function<void (absl::StatusOr<std::vector<grpc_resolved_address>>)> on_resolved,absl::string_view name,Duration timeout,grpc_pollset_set * interested_parties,absl::string_view name_server)666   TaskHandle LookupSRV(
667       std::function<void(absl::StatusOr<std::vector<grpc_resolved_address>>)>
668           on_resolved,
669       absl::string_view name, Duration timeout,
670       grpc_pollset_set* interested_parties,
671       absl::string_view name_server) override {
672     MutexLock lock(&mu_);
673     auto* request =
674         new AresSRVRequest(name, name_server, timeout, interested_parties,
675                            std::move(on_resolved), this, aba_token_++);
676     request->Run();
677     auto handle = request->task_handle();
678     open_requests_.insert(handle);
679     return handle;
680   };
681 
LookupTXT(std::function<void (absl::StatusOr<std::string>)> on_resolved,absl::string_view name,Duration timeout,grpc_pollset_set * interested_parties,absl::string_view name_server)682   TaskHandle LookupTXT(
683       std::function<void(absl::StatusOr<std::string>)> on_resolved,
684       absl::string_view name, Duration timeout,
685       grpc_pollset_set* interested_parties,
686       absl::string_view name_server) override {
687     MutexLock lock(&mu_);
688     auto* request =
689         new AresTXTRequest(name, name_server, timeout, interested_parties,
690                            std::move(on_resolved), this, aba_token_++);
691     request->Run();
692     auto handle = request->task_handle();
693     open_requests_.insert(handle);
694     return handle;
695   };
696 
Cancel(TaskHandle handle)697   bool Cancel(TaskHandle handle) override {
698     MutexLock lock(&mu_);
699     if (!open_requests_.contains(handle)) {
700       // Unknown request, possibly completed already, or an invalid handle.
701       GRPC_TRACE_VLOG(cares_resolver, 2)
702           << "(c-ares resolver) AresDNSResolver:" << this
703           << " attempt to cancel unknown TaskHandle:" << HandleToString(handle);
704       return false;
705     }
706     auto* request = reinterpret_cast<AresRequest*>(handle.keys[0]);
707     GRPC_TRACE_VLOG(cares_resolver, 2)
708         << "(c-ares resolver) AresDNSResolver:" << this
709         << " cancel ares_request:" << request;
710     return request->Cancel();
711   }
712 
713  private:
714   // Called exclusively from the AresRequest destructor.
UnregisterRequest(TaskHandle handle)715   void UnregisterRequest(TaskHandle handle) {
716     MutexLock lock(&mu_);
717     open_requests_.erase(handle);
718   }
719 
720   // the previous default DNS resolver, used to delegate blocking DNS calls to
721   std::shared_ptr<DNSResolver> default_resolver_ = GetDNSResolver();
722   Mutex mu_;
723   TaskHandleSet open_requests_ ABSL_GUARDED_BY(mu_);
724   intptr_t aba_token_ ABSL_GUARDED_BY(mu_) = 0;
725 };
726 
727 }  // namespace
728 
ShouldUseAresDnsResolver(absl::string_view resolver_env)729 bool ShouldUseAresDnsResolver(absl::string_view resolver_env) {
730   return resolver_env.empty() || absl::EqualsIgnoreCase(resolver_env, "ares");
731 }
732 
RegisterAresDnsResolver(CoreConfiguration::Builder * builder)733 void RegisterAresDnsResolver(CoreConfiguration::Builder* builder) {
734   builder->resolver_registry()->RegisterResolverFactory(
735       std::make_unique<AresClientChannelDNSResolverFactory>());
736 }
737 
738 }  // namespace grpc_core
739 
grpc_resolver_dns_ares_init()740 void grpc_resolver_dns_ares_init() {
741   if (grpc_core::ShouldUseAresDnsResolver(
742           grpc_core::ConfigVars::Get().DnsResolver())) {
743     address_sorting_init();
744     grpc_error_handle error = grpc_ares_init();
745     if (!error.ok()) {
746       GRPC_LOG_IF_ERROR("grpc_ares_init() failed", error);
747       return;
748     }
749     grpc_core::ResetDNSResolver(std::make_unique<grpc_core::AresDNSResolver>());
750   }
751 }
752 
grpc_resolver_dns_ares_shutdown()753 void grpc_resolver_dns_ares_shutdown() {
754   if (grpc_core::ShouldUseAresDnsResolver(
755           grpc_core::ConfigVars::Get().DnsResolver())) {
756     address_sorting_shutdown();
757     grpc_ares_cleanup();
758   }
759 }
760 
grpc_resolver_dns_ares_reset_dns_resolver()761 void grpc_resolver_dns_ares_reset_dns_resolver() {
762   if (grpc_core::ShouldUseAresDnsResolver(
763           grpc_core::ConfigVars::Get().DnsResolver())) {
764     grpc_core::ResetDNSResolver(std::make_unique<grpc_core::AresDNSResolver>());
765   }
766 }
767 
768 #else  // GRPC_ARES == 1
769 
770 namespace grpc_core {
ShouldUseAresDnsResolver(absl::string_view)771 bool ShouldUseAresDnsResolver(absl::string_view /* resolver_env */) {
772   return false;
773 }
RegisterAresDnsResolver(CoreConfiguration::Builder *)774 void RegisterAresDnsResolver(CoreConfiguration::Builder*) {}
775 }  // namespace grpc_core
776 
grpc_resolver_dns_ares_init()777 void grpc_resolver_dns_ares_init() {}
778 
grpc_resolver_dns_ares_shutdown()779 void grpc_resolver_dns_ares_shutdown() {}
780 
grpc_resolver_dns_ares_reset_dns_resolver()781 void grpc_resolver_dns_ares_reset_dns_resolver() {}
782 
783 #endif  // GRPC_ARES == 1
784