xref: /aosp_15_r20/external/grpc-grpc/src/core/lib/event_engine/ares_resolver.h (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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_ARES_RESOLVER_H
15 #define GRPC_SRC_CORE_LIB_EVENT_ENGINE_ARES_RESOLVER_H
16 
17 #include <grpc/support/port_platform.h>
18 
19 #include <utility>
20 
21 #include "src/core/lib/debug/trace.h"
22 
23 #if GRPC_ARES == 1
24 
25 #include <list>
26 #include <memory>
27 
28 #include <ares.h>
29 
30 #include "absl/base/thread_annotations.h"
31 #include "absl/container/flat_hash_map.h"
32 #include "absl/status/status.h"
33 #include "absl/status/statusor.h"
34 #include "absl/strings/string_view.h"
35 #include "absl/types/optional.h"
36 #include "absl/types/variant.h"
37 
38 #include <grpc/event_engine/event_engine.h>
39 #include <grpc/support/log.h>
40 
41 #include "src/core/lib/event_engine/grpc_polled_fd.h"
42 #include "src/core/lib/event_engine/ref_counted_dns_resolver_interface.h"
43 #include "src/core/lib/gprpp/orphanable.h"
44 #include "src/core/lib/gprpp/sync.h"
45 
46 namespace grpc_event_engine {
47 namespace experimental {
48 
49 extern grpc_core::TraceFlag grpc_trace_ares_resolver;
50 
51 #define GRPC_ARES_RESOLVER_TRACE_LOG(format, ...)                              \
52   do {                                                                         \
53     if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_ares_resolver)) {                   \
54       gpr_log(GPR_INFO, "(EventEngine c-ares resolver) " format, __VA_ARGS__); \
55     }                                                                          \
56   } while (0)
57 
58 class AresResolver : public RefCountedDNSResolverInterface {
59  public:
60   static absl::StatusOr<grpc_core::OrphanablePtr<AresResolver>>
61   CreateAresResolver(absl::string_view dns_server,
62                      std::unique_ptr<GrpcPolledFdFactory> polled_fd_factory,
63                      std::shared_ptr<EventEngine> event_engine);
64 
65   // Do not instantiate directly -- use CreateAresResolver() instead.
66   AresResolver(std::unique_ptr<GrpcPolledFdFactory> polled_fd_factory,
67                std::shared_ptr<EventEngine> event_engine, ares_channel channel);
68   ~AresResolver() override;
69   void Orphan() override ABSL_LOCKS_EXCLUDED(mutex_);
70 
71   void LookupHostname(EventEngine::DNSResolver::LookupHostnameCallback callback,
72                       absl::string_view name, absl::string_view default_port)
73       ABSL_LOCKS_EXCLUDED(mutex_) override;
74   void LookupSRV(EventEngine::DNSResolver::LookupSRVCallback callback,
75                  absl::string_view name) ABSL_LOCKS_EXCLUDED(mutex_) override;
76   void LookupTXT(EventEngine::DNSResolver::LookupTXTCallback callback,
77                  absl::string_view name) ABSL_LOCKS_EXCLUDED(mutex_) override;
78 
79  private:
80   // A FdNode saves (not owns) a live socket/fd which c-ares creates, and owns a
81   // GrpcPolledFd object which has a platform-agnostic interface to interact
82   // with the poller. The liveness of the socket means that c-ares needs us to
83   // monitor r/w events on this socket and notifies c-ares when such events have
84   // happened which we achieve through the GrpcPolledFd object. FdNode also
85   // handles the shutdown (maybe due to socket no longer used, finished request,
86   // cancel or timeout) and the destruction of the poller handle. Note that
87   // FdNode does not own the socket and it's the c-ares' responsibility to
88   // close the socket (possibly through ares_destroy).
89   struct FdNode {
90     FdNode() = default;
FdNodeFdNode91     FdNode(ares_socket_t as, std::unique_ptr<GrpcPolledFd> pf)
92         : as(as), polled_fd(std::move(pf)) {}
93     ares_socket_t as;
94     std::unique_ptr<GrpcPolledFd> polled_fd;
95     // true if the readable closure has been registered
96     bool readable_registered = false;
97     // true if the writable closure has been registered
98     bool writable_registered = false;
99     bool already_shutdown = false;
100   };
101   using FdNodeList = std::list<std::unique_ptr<FdNode>>;
102 
103   using CallbackType =
104       absl::variant<EventEngine::DNSResolver::LookupHostnameCallback,
105                     EventEngine::DNSResolver::LookupSRVCallback,
106                     EventEngine::DNSResolver::LookupTXTCallback>;
107 
108   void CheckSocketsLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
109   void MaybeStartTimerLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
110   void OnReadable(FdNode* fd_node, absl::Status status)
111       ABSL_LOCKS_EXCLUDED(mutex_);
112   void OnWritable(FdNode* fd_node, absl::Status status)
113       ABSL_LOCKS_EXCLUDED(mutex_);
114   void OnAresBackupPollAlarm() ABSL_LOCKS_EXCLUDED(mutex_);
115 
116   // These callbacks are invoked from the c-ares library, so disable thread
117   // safety analysis. We are guaranteed to be holding mutex_.
118   static void OnHostbynameDoneLocked(void* arg, int status, int /*timeouts*/,
119                                      struct hostent* hostent)
120       ABSL_NO_THREAD_SAFETY_ANALYSIS;
121   static void OnSRVQueryDoneLocked(void* arg, int status, int /*timeouts*/,
122                                    unsigned char* abuf,
123                                    int alen) ABSL_NO_THREAD_SAFETY_ANALYSIS;
124   static void OnTXTDoneLocked(void* arg, int status, int /*timeouts*/,
125                               unsigned char* buf,
126                               int len) ABSL_NO_THREAD_SAFETY_ANALYSIS;
127 
128   grpc_core::Mutex mutex_;
129   bool shutting_down_ ABSL_GUARDED_BY(mutex_) = false;
130   ares_channel channel_ ABSL_GUARDED_BY(mutex_);
131   FdNodeList fd_node_list_ ABSL_GUARDED_BY(mutex_);
132   int id_ ABSL_GUARDED_BY(mutex_) = 0;
133   absl::flat_hash_map<int, CallbackType> callback_map_ ABSL_GUARDED_BY(mutex_);
134   absl::optional<EventEngine::TaskHandle> ares_backup_poll_alarm_handle_
135       ABSL_GUARDED_BY(mutex_);
136   std::unique_ptr<GrpcPolledFdFactory> polled_fd_factory_;
137   std::shared_ptr<EventEngine> event_engine_;
138 };
139 
140 }  // namespace experimental
141 }  // namespace grpc_event_engine
142 
143 // Exposed in this header for C-core tests only
144 extern void (*event_engine_grpc_ares_test_only_inject_config)(
145     ares_channel* channel);
146 
147 // Exposed in this header for C-core tests only
148 extern bool g_event_engine_grpc_ares_test_only_force_tcp;
149 
150 #endif  // GRPC_ARES == 1
151 #endif  // GRPC_SRC_CORE_LIB_EVENT_ENGINE_ARES_RESOLVER_H
152