Imported Upstream version 1.18.0
[platform/upstream/grpc.git] / src / core / ext / filters / client_channel / resolver / fake / fake_resolver.cc
1 //
2 // Copyright 2016 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 // This is similar to the sockaddr resolver, except that it supports a
18 // bunch of query args that are useful for dependency injection in tests.
19
20 #include <grpc/support/port_platform.h>
21
22 #include <limits.h>
23 #include <stdbool.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include <grpc/support/alloc.h>
29 #include <grpc/support/string_util.h>
30
31 #include "src/core/ext/filters/client_channel/parse_address.h"
32 #include "src/core/ext/filters/client_channel/resolver_registry.h"
33 #include "src/core/ext/filters/client_channel/server_address.h"
34 #include "src/core/lib/channel/channel_args.h"
35 #include "src/core/lib/gpr/host_port.h"
36 #include "src/core/lib/gpr/string.h"
37 #include "src/core/lib/gpr/useful.h"
38 #include "src/core/lib/iomgr/closure.h"
39 #include "src/core/lib/iomgr/combiner.h"
40 #include "src/core/lib/iomgr/resolve_address.h"
41 #include "src/core/lib/iomgr/unix_sockets_posix.h"
42 #include "src/core/lib/slice/slice_internal.h"
43 #include "src/core/lib/slice/slice_string_helpers.h"
44
45 #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
46
47 namespace grpc_core {
48
49 // This cannot be in an anonymous namespace, because it is a friend of
50 // FakeResolverResponseGenerator.
51 class FakeResolver : public Resolver {
52  public:
53   explicit FakeResolver(const ResolverArgs& args);
54
55   void NextLocked(grpc_channel_args** result,
56                   grpc_closure* on_complete) override;
57
58   void RequestReresolutionLocked() override;
59
60  private:
61   friend class FakeResolverResponseGenerator;
62
63   virtual ~FakeResolver();
64
65   void MaybeFinishNextLocked();
66
67   void ShutdownLocked() override;
68
69   // passed-in parameters
70   grpc_channel_args* channel_args_ = nullptr;
71   // If not NULL, the next set of resolution results to be returned to
72   // NextLocked()'s closure.
73   grpc_channel_args* next_results_ = nullptr;
74   // Results to use for the pretended re-resolution in
75   // RequestReresolutionLocked().
76   grpc_channel_args* reresolution_results_ = nullptr;
77   // pending next completion, or NULL
78   grpc_closure* next_completion_ = nullptr;
79   // target result address for next completion
80   grpc_channel_args** target_result_ = nullptr;
81   // if true, return failure
82   bool return_failure_ = false;
83 };
84
85 FakeResolver::FakeResolver(const ResolverArgs& args) : Resolver(args.combiner) {
86   channel_args_ = grpc_channel_args_copy(args.args);
87   FakeResolverResponseGenerator* response_generator =
88       FakeResolverResponseGenerator::GetFromArgs(args.args);
89   if (response_generator != nullptr) response_generator->resolver_ = this;
90 }
91
92 FakeResolver::~FakeResolver() {
93   grpc_channel_args_destroy(next_results_);
94   grpc_channel_args_destroy(reresolution_results_);
95   grpc_channel_args_destroy(channel_args_);
96 }
97
98 void FakeResolver::NextLocked(grpc_channel_args** target_result,
99                               grpc_closure* on_complete) {
100   GPR_ASSERT(next_completion_ == nullptr);
101   next_completion_ = on_complete;
102   target_result_ = target_result;
103   MaybeFinishNextLocked();
104 }
105
106 void FakeResolver::RequestReresolutionLocked() {
107   if (reresolution_results_ != nullptr || return_failure_) {
108     grpc_channel_args_destroy(next_results_);
109     next_results_ = grpc_channel_args_copy(reresolution_results_);
110     MaybeFinishNextLocked();
111   }
112 }
113
114 void FakeResolver::MaybeFinishNextLocked() {
115   if (next_completion_ != nullptr &&
116       (next_results_ != nullptr || return_failure_)) {
117     *target_result_ =
118         return_failure_ ? nullptr
119                         : grpc_channel_args_union(next_results_, channel_args_);
120     grpc_channel_args_destroy(next_results_);
121     next_results_ = nullptr;
122     GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_NONE);
123     next_completion_ = nullptr;
124     return_failure_ = false;
125   }
126 }
127
128 void FakeResolver::ShutdownLocked() {
129   if (next_completion_ != nullptr) {
130     *target_result_ = nullptr;
131     GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
132                                              "Resolver Shutdown"));
133     next_completion_ = nullptr;
134   }
135 }
136
137 //
138 // FakeResolverResponseGenerator
139 //
140
141 struct SetResponseClosureArg {
142   grpc_closure set_response_closure;
143   FakeResolverResponseGenerator* generator;
144   grpc_channel_args* response;
145   bool immediate = true;
146 };
147
148 void FakeResolverResponseGenerator::SetResponseLocked(void* arg,
149                                                       grpc_error* error) {
150   SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
151   FakeResolver* resolver = closure_arg->generator->resolver_;
152   grpc_channel_args_destroy(resolver->next_results_);
153   resolver->next_results_ = closure_arg->response;
154   resolver->MaybeFinishNextLocked();
155   Delete(closure_arg);
156 }
157
158 void FakeResolverResponseGenerator::SetResponse(grpc_channel_args* response) {
159   GPR_ASSERT(response != nullptr);
160   GPR_ASSERT(resolver_ != nullptr);
161   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
162   closure_arg->generator = this;
163   closure_arg->response = grpc_channel_args_copy(response);
164   GRPC_CLOSURE_SCHED(
165       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetResponseLocked,
166                         closure_arg,
167                         grpc_combiner_scheduler(resolver_->combiner())),
168       GRPC_ERROR_NONE);
169 }
170
171 void FakeResolverResponseGenerator::SetReresolutionResponseLocked(
172     void* arg, grpc_error* error) {
173   SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
174   FakeResolver* resolver = closure_arg->generator->resolver_;
175   grpc_channel_args_destroy(resolver->reresolution_results_);
176   resolver->reresolution_results_ = closure_arg->response;
177   Delete(closure_arg);
178 }
179
180 void FakeResolverResponseGenerator::SetReresolutionResponse(
181     grpc_channel_args* response) {
182   GPR_ASSERT(resolver_ != nullptr);
183   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
184   closure_arg->generator = this;
185   closure_arg->response =
186       response != nullptr ? grpc_channel_args_copy(response) : nullptr;
187   GRPC_CLOSURE_SCHED(
188       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
189                         SetReresolutionResponseLocked, closure_arg,
190                         grpc_combiner_scheduler(resolver_->combiner())),
191       GRPC_ERROR_NONE);
192 }
193
194 void FakeResolverResponseGenerator::SetFailureLocked(void* arg,
195                                                      grpc_error* error) {
196   SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
197   FakeResolver* resolver = closure_arg->generator->resolver_;
198   resolver->return_failure_ = true;
199   if (closure_arg->immediate) resolver->MaybeFinishNextLocked();
200   Delete(closure_arg);
201 }
202
203 void FakeResolverResponseGenerator::SetFailure() {
204   GPR_ASSERT(resolver_ != nullptr);
205   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
206   closure_arg->generator = this;
207   GRPC_CLOSURE_SCHED(
208       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
209                         closure_arg,
210                         grpc_combiner_scheduler(resolver_->combiner())),
211       GRPC_ERROR_NONE);
212 }
213
214 void FakeResolverResponseGenerator::SetFailureOnReresolution() {
215   GPR_ASSERT(resolver_ != nullptr);
216   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
217   closure_arg->generator = this;
218   closure_arg->immediate = false;
219   GRPC_CLOSURE_SCHED(
220       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
221                         closure_arg,
222                         grpc_combiner_scheduler(resolver_->combiner())),
223       GRPC_ERROR_NONE);
224 }
225
226 namespace {
227
228 static void* response_generator_arg_copy(void* p) {
229   FakeResolverResponseGenerator* generator =
230       static_cast<FakeResolverResponseGenerator*>(p);
231   // TODO(roth): We currently deal with this ref manually.  Once the
232   // new channel args code is converted to C++, find a way to track this ref
233   // in a cleaner way.
234   RefCountedPtr<FakeResolverResponseGenerator> copy = generator->Ref();
235   copy.release();
236   return p;
237 }
238
239 static void response_generator_arg_destroy(void* p) {
240   FakeResolverResponseGenerator* generator =
241       static_cast<FakeResolverResponseGenerator*>(p);
242   generator->Unref();
243 }
244
245 static int response_generator_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
246
247 static const grpc_arg_pointer_vtable response_generator_arg_vtable = {
248     response_generator_arg_copy, response_generator_arg_destroy,
249     response_generator_cmp};
250
251 }  // namespace
252
253 grpc_arg FakeResolverResponseGenerator::MakeChannelArg(
254     FakeResolverResponseGenerator* generator) {
255   grpc_arg arg;
256   arg.type = GRPC_ARG_POINTER;
257   arg.key = (char*)GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR;
258   arg.value.pointer.p = generator;
259   arg.value.pointer.vtable = &response_generator_arg_vtable;
260   return arg;
261 }
262
263 FakeResolverResponseGenerator* FakeResolverResponseGenerator::GetFromArgs(
264     const grpc_channel_args* args) {
265   const grpc_arg* arg =
266       grpc_channel_args_find(args, GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR);
267   if (arg == nullptr || arg->type != GRPC_ARG_POINTER) return nullptr;
268   return static_cast<FakeResolverResponseGenerator*>(arg->value.pointer.p);
269 }
270
271 //
272 // Factory
273 //
274
275 namespace {
276
277 class FakeResolverFactory : public ResolverFactory {
278  public:
279   OrphanablePtr<Resolver> CreateResolver(
280       const ResolverArgs& args) const override {
281     return OrphanablePtr<Resolver>(New<FakeResolver>(args));
282   }
283
284   const char* scheme() const override { return "fake"; }
285 };
286
287 }  // namespace
288
289 }  // namespace grpc_core
290
291 void grpc_resolver_fake_init() {
292   grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
293       grpc_core::UniquePtr<grpc_core::ResolverFactory>(
294           grpc_core::New<grpc_core::FakeResolverFactory>()));
295 }
296
297 void grpc_resolver_fake_shutdown() {}