• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The gRPC Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #ifndef GRPC_SRC_CORE_LIB_EVENT_ENGINE_CF_ENGINE_DNS_SERVICE_RESOLVER_H
15 #define GRPC_SRC_CORE_LIB_EVENT_ENGINE_CF_ENGINE_DNS_SERVICE_RESOLVER_H
16 #include <grpc/support/port_platform.h>
17 
18 #ifdef GPR_APPLE
19 #include <AvailabilityMacros.h>
20 #ifdef AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER
21 
22 #include <CoreFoundation/CoreFoundation.h>
23 #include <dns_sd.h>
24 #include <grpc/event_engine/event_engine.h>
25 
26 #include "absl/container/flat_hash_map.h"
27 #include "absl/log/check.h"
28 #include "src/core/lib/event_engine/cf_engine/cf_engine.h"
29 #include "src/core/util/ref_counted.h"
30 #include "src/core/util/ref_counted_ptr.h"
31 
32 namespace grpc_event_engine {
33 namespace experimental {
34 
35 class DNSServiceResolverImpl
36     : public grpc_core::RefCounted<DNSServiceResolverImpl> {
37   struct DNSServiceRequest {
38     EventEngine::DNSResolver::LookupHostnameCallback on_resolve;
39     uint16_t port;
40     std::vector<EventEngine::ResolvedAddress> result;
41     bool has_ipv4_response = false;
42     bool has_ipv6_response = false;
43   };
44 
45  public:
DNSServiceResolverImpl(std::shared_ptr<CFEventEngine> engine)46   explicit DNSServiceResolverImpl(std::shared_ptr<CFEventEngine> engine)
47       : engine_(std::move((engine))) {}
~DNSServiceResolverImpl()48   ~DNSServiceResolverImpl() override {
49     CHECK(requests_.empty());
50     dispatch_release(queue_);
51   }
52 
53   void Shutdown();
54 
55   void LookupHostname(
56       EventEngine::DNSResolver::LookupHostnameCallback on_resolve,
57       absl::string_view name, absl::string_view default_port);
58 
59  private:
60   static void ResolveCallback(DNSServiceRef sdRef, DNSServiceFlags flags,
61                               uint32_t interfaceIndex,
62                               DNSServiceErrorType errorCode,
63                               const char* hostname,
64                               const struct sockaddr* address, uint32_t ttl,
65                               void* context);
66 
67  private:
68   std::shared_ptr<CFEventEngine> engine_;
69   // DNSServiceSetDispatchQueue requires a serial dispatch queue
70   dispatch_queue_t queue_ =
71       dispatch_queue_create("dns_service_resolver", nullptr);
72   grpc_core::Mutex request_mu_;
73   absl::flat_hash_map<DNSServiceRef, DNSServiceRequest> requests_
74       ABSL_GUARDED_BY(request_mu_);
75 };
76 
77 class DNSServiceResolver : public EventEngine::DNSResolver {
78  public:
DNSServiceResolver(std::shared_ptr<CFEventEngine> engine)79   explicit DNSServiceResolver(std::shared_ptr<CFEventEngine> engine)
80       : engine_(std::move(engine)),
81         impl_(grpc_core::MakeRefCounted<DNSServiceResolverImpl>(
82             std::move((engine_)))) {}
83 
~DNSServiceResolver()84   ~DNSServiceResolver() override { impl_->Shutdown(); }
85 
LookupHostname(EventEngine::DNSResolver::LookupHostnameCallback on_resolve,absl::string_view name,absl::string_view default_port)86   void LookupHostname(
87       EventEngine::DNSResolver::LookupHostnameCallback on_resolve,
88       absl::string_view name, absl::string_view default_port) override {
89     impl_->LookupHostname(std::move(on_resolve), name, default_port);
90   };
91 
LookupSRV(EventEngine::DNSResolver::LookupSRVCallback on_resolve,absl::string_view)92   void LookupSRV(EventEngine::DNSResolver::LookupSRVCallback on_resolve,
93                  absl::string_view /* name */) override {
94     engine_->Run([on_resolve = std::move(on_resolve)]() mutable {
95       on_resolve(absl::UnimplementedError(
96           "The DNS Service resolver does not support looking up SRV records"));
97     });
98   }
99 
LookupTXT(EventEngine::DNSResolver::LookupTXTCallback on_resolve,absl::string_view)100   void LookupTXT(EventEngine::DNSResolver::LookupTXTCallback on_resolve,
101                  absl::string_view /* name */) override {
102     engine_->Run([on_resolve = std::move(on_resolve)]() mutable {
103       on_resolve(absl::UnimplementedError(
104           "The DNS Service resolver does not support looking up TXT records"));
105     });
106   }
107 
108  private:
109   std::shared_ptr<CFEventEngine> engine_;
110   grpc_core::RefCountedPtr<DNSServiceResolverImpl> impl_;
111 };
112 
113 }  // namespace experimental
114 }  // namespace grpc_event_engine
115 
116 #endif  // AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER
117 #endif  // GPR_APPLE
118 
119 #endif  // GRPC_SRC_CORE_LIB_EVENT_ENGINE_CF_ENGINE_DNS_SERVICE_RESOLVER_H
120