bba9bb749c74d374e052c9249fa1a20051e252a5
[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/string.h"
36 #include "src/core/lib/gpr/useful.h"
37 #include "src/core/lib/iomgr/closure.h"
38 #include "src/core/lib/iomgr/combiner.h"
39 #include "src/core/lib/iomgr/resolve_address.h"
40 #include "src/core/lib/iomgr/unix_sockets_posix.h"
41 #include "src/core/lib/slice/slice_internal.h"
42 #include "src/core/lib/slice/slice_string_helpers.h"
43
44 #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
45
46 namespace grpc_core {
47
48 // This cannot be in an anonymous namespace, because it is a friend of
49 // FakeResolverResponseGenerator.
50 class FakeResolver : public Resolver {
51  public:
52   explicit FakeResolver(ResolverArgs args);
53
54   void StartLocked() override;
55
56   void RequestReresolutionLocked() override;
57
58  private:
59   friend class FakeResolverResponseGenerator;
60
61   virtual ~FakeResolver();
62
63   void ShutdownLocked() override {
64     shutdown_ = true;
65     if (response_generator_ != nullptr) {
66       response_generator_->SetFakeResolver(nullptr);
67       response_generator_.reset();
68     }
69   }
70
71   void MaybeSendResultLocked();
72
73   static void ReturnReresolutionResult(void* arg, grpc_error* error);
74
75   // passed-in parameters
76   grpc_channel_args* channel_args_ = nullptr;
77   RefCountedPtr<FakeResolverResponseGenerator> response_generator_;
78   // If has_next_result_ is true, next_result_ is the next resolution result
79   // to be returned.
80   bool has_next_result_ = false;
81   Result next_result_;
82   // Result to use for the pretended re-resolution in
83   // RequestReresolutionLocked().
84   bool has_reresolution_result_ = false;
85   Result reresolution_result_;
86   // True after the call to StartLocked().
87   bool started_ = false;
88   // True after the call to ShutdownLocked().
89   bool shutdown_ = false;
90   // if true, return failure
91   bool return_failure_ = false;
92   // pending re-resolution
93   grpc_closure reresolution_closure_;
94   bool reresolution_closure_pending_ = false;
95 };
96
97 FakeResolver::FakeResolver(ResolverArgs args)
98     : Resolver(args.combiner, std::move(args.result_handler)),
99       response_generator_(
100           FakeResolverResponseGenerator::GetFromArgs(args.args)) {
101   // Channels sharing the same subchannels may have different resolver response
102   // generators. If we don't remove this arg, subchannel pool will create new
103   // subchannels for the same address instead of reusing existing ones because
104   // of different values of this channel arg.
105   const char* args_to_remove[] = {GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR};
106   channel_args_ = grpc_channel_args_copy_and_remove(
107       args.args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove));
108   if (response_generator_ != nullptr) {
109     response_generator_->SetFakeResolver(Ref());
110   }
111 }
112
113 FakeResolver::~FakeResolver() { grpc_channel_args_destroy(channel_args_); }
114
115 void FakeResolver::StartLocked() {
116   started_ = true;
117   MaybeSendResultLocked();
118 }
119
120 void FakeResolver::RequestReresolutionLocked() {
121   if (has_reresolution_result_ || return_failure_) {
122     next_result_ = reresolution_result_;
123     has_next_result_ = true;
124     // Return the result in a different closure, so that we don't call
125     // back into the LB policy while it's still processing the previous
126     // update.
127     if (!reresolution_closure_pending_) {
128       reresolution_closure_pending_ = true;
129       Ref().release();  // ref held by closure
130       GRPC_CLOSURE_INIT(&reresolution_closure_, ReturnReresolutionResult, this,
131                         nullptr);
132       combiner()->Run(&reresolution_closure_, GRPC_ERROR_NONE);
133     }
134   }
135 }
136
137 void FakeResolver::MaybeSendResultLocked() {
138   if (!started_ || shutdown_) return;
139   if (return_failure_) {
140     // TODO(roth): Change resolver result generator to be able to inject
141     // the error to be returned.
142     result_handler()->ReturnError(grpc_error_set_int(
143         GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resolver transient failure"),
144         GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
145     return_failure_ = false;
146   } else if (has_next_result_) {
147     Result result;
148     result.addresses = std::move(next_result_.addresses);
149     result.service_config = std::move(next_result_.service_config);
150     // TODO(roth): Use std::move() once grpc_error is converted to C++.
151     result.service_config_error = next_result_.service_config_error;
152     next_result_.service_config_error = GRPC_ERROR_NONE;
153     // When both next_results_ and channel_args_ contain an arg with the same
154     // name, only the one in next_results_ will be kept since next_results_ is
155     // before channel_args_.
156     result.args = grpc_channel_args_union(next_result_.args, channel_args_);
157     result_handler()->ReturnResult(std::move(result));
158     has_next_result_ = false;
159   }
160 }
161
162 void FakeResolver::ReturnReresolutionResult(void* arg, grpc_error* /*error*/) {
163   FakeResolver* self = static_cast<FakeResolver*>(arg);
164   self->reresolution_closure_pending_ = false;
165   self->MaybeSendResultLocked();
166   self->Unref();
167 }
168
169 //
170 // FakeResolverResponseGenerator
171 //
172
173 FakeResolverResponseGenerator::FakeResolverResponseGenerator() {}
174
175 FakeResolverResponseGenerator::~FakeResolverResponseGenerator() {}
176
177 struct SetResponseClosureArg {
178   grpc_closure set_response_closure;
179   RefCountedPtr<FakeResolver> resolver;
180   Resolver::Result result;
181   bool has_result = false;
182   bool immediate = true;
183 };
184
185 void FakeResolverResponseGenerator::SetResponseLocked(void* arg,
186                                                       grpc_error* /*error*/) {
187   SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
188   auto& resolver = closure_arg->resolver;
189   if (!resolver->shutdown_) {
190     resolver->next_result_ = std::move(closure_arg->result);
191     resolver->has_next_result_ = true;
192     resolver->MaybeSendResultLocked();
193   }
194   Delete(closure_arg);
195 }
196
197 void FakeResolverResponseGenerator::SetResponse(Resolver::Result result) {
198   RefCountedPtr<FakeResolver> resolver;
199   {
200     MutexLock lock(&mu_);
201     if (resolver_ == nullptr) {
202       has_result_ = true;
203       result_ = std::move(result);
204       return;
205     }
206     resolver = resolver_->Ref();
207   }
208   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
209   closure_arg->resolver = std::move(resolver);
210   closure_arg->result = std::move(result);
211   closure_arg->resolver->combiner()->Run(
212       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetResponseLocked,
213                         closure_arg, nullptr),
214       GRPC_ERROR_NONE);
215 }
216
217 void FakeResolverResponseGenerator::SetReresolutionResponseLocked(
218     void* arg, grpc_error* /*error*/) {
219   SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
220   auto& resolver = closure_arg->resolver;
221   if (!resolver->shutdown_) {
222     resolver->reresolution_result_ = std::move(closure_arg->result);
223     resolver->has_reresolution_result_ = closure_arg->has_result;
224   }
225   Delete(closure_arg);
226 }
227
228 void FakeResolverResponseGenerator::SetReresolutionResponse(
229     Resolver::Result result) {
230   RefCountedPtr<FakeResolver> resolver;
231   {
232     MutexLock lock(&mu_);
233     GPR_ASSERT(resolver_ != nullptr);
234     resolver = resolver_->Ref();
235   }
236   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
237   closure_arg->resolver = std::move(resolver);
238   closure_arg->result = std::move(result);
239   closure_arg->has_result = true;
240   closure_arg->resolver->combiner()->Run(
241       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
242                         SetReresolutionResponseLocked, closure_arg, nullptr),
243       GRPC_ERROR_NONE);
244 }
245
246 void FakeResolverResponseGenerator::UnsetReresolutionResponse() {
247   RefCountedPtr<FakeResolver> resolver;
248   {
249     MutexLock lock(&mu_);
250     GPR_ASSERT(resolver_ != nullptr);
251     resolver = resolver_->Ref();
252   }
253   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
254   closure_arg->resolver = std::move(resolver);
255   closure_arg->resolver->combiner()->Run(
256       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
257                         SetReresolutionResponseLocked, closure_arg, nullptr),
258       GRPC_ERROR_NONE);
259 }
260
261 void FakeResolverResponseGenerator::SetFailureLocked(void* arg,
262                                                      grpc_error* /*error*/) {
263   SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
264   auto& resolver = closure_arg->resolver;
265   if (!resolver->shutdown_) {
266     resolver->return_failure_ = true;
267     if (closure_arg->immediate) resolver->MaybeSendResultLocked();
268   }
269   Delete(closure_arg);
270 }
271
272 void FakeResolverResponseGenerator::SetFailure() {
273   RefCountedPtr<FakeResolver> resolver;
274   {
275     MutexLock lock(&mu_);
276     GPR_ASSERT(resolver_ != nullptr);
277     resolver = resolver_->Ref();
278   }
279   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
280   closure_arg->resolver = std::move(resolver);
281   closure_arg->resolver->combiner()->Run(
282       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
283                         closure_arg, nullptr),
284       GRPC_ERROR_NONE);
285 }
286
287 void FakeResolverResponseGenerator::SetFailureOnReresolution() {
288   RefCountedPtr<FakeResolver> resolver;
289   {
290     MutexLock lock(&mu_);
291     GPR_ASSERT(resolver_ != nullptr);
292     resolver = resolver_->Ref();
293   }
294   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
295   closure_arg->resolver = std::move(resolver);
296   closure_arg->immediate = false;
297   closure_arg->resolver->combiner()->Run(
298       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
299                         closure_arg, nullptr),
300       GRPC_ERROR_NONE);
301 }
302
303 void FakeResolverResponseGenerator::SetFakeResolver(
304     RefCountedPtr<FakeResolver> resolver) {
305   MutexLock lock(&mu_);
306   resolver_ = std::move(resolver);
307   if (resolver_ == nullptr) return;
308   if (has_result_) {
309     SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
310     closure_arg->resolver = resolver_->Ref();
311     closure_arg->result = std::move(result_);
312     resolver_->combiner()->Run(
313         GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetResponseLocked,
314                           closure_arg, nullptr),
315         GRPC_ERROR_NONE);
316     has_result_ = false;
317   }
318 }
319
320 namespace {
321
322 static void* response_generator_arg_copy(void* p) {
323   FakeResolverResponseGenerator* generator =
324       static_cast<FakeResolverResponseGenerator*>(p);
325   // TODO(roth): We currently deal with this ref manually.  Once the
326   // new channel args code is converted to C++, find a way to track this ref
327   // in a cleaner way.
328   RefCountedPtr<FakeResolverResponseGenerator> copy = generator->Ref();
329   copy.release();
330   return p;
331 }
332
333 static void response_generator_arg_destroy(void* p) {
334   FakeResolverResponseGenerator* generator =
335       static_cast<FakeResolverResponseGenerator*>(p);
336   generator->Unref();
337 }
338
339 static int response_generator_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
340
341 static const grpc_arg_pointer_vtable response_generator_arg_vtable = {
342     response_generator_arg_copy, response_generator_arg_destroy,
343     response_generator_cmp};
344
345 }  // namespace
346
347 grpc_arg FakeResolverResponseGenerator::MakeChannelArg(
348     FakeResolverResponseGenerator* generator) {
349   grpc_arg arg;
350   arg.type = GRPC_ARG_POINTER;
351   arg.key = (char*)GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR;
352   arg.value.pointer.p = generator;
353   arg.value.pointer.vtable = &response_generator_arg_vtable;
354   return arg;
355 }
356
357 RefCountedPtr<FakeResolverResponseGenerator>
358 FakeResolverResponseGenerator::GetFromArgs(const grpc_channel_args* args) {
359   const grpc_arg* arg =
360       grpc_channel_args_find(args, GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR);
361   if (arg == nullptr || arg->type != GRPC_ARG_POINTER) return nullptr;
362   return static_cast<FakeResolverResponseGenerator*>(arg->value.pointer.p)
363       ->Ref();
364 }
365
366 //
367 // Factory
368 //
369
370 namespace {
371
372 class FakeResolverFactory : public ResolverFactory {
373  public:
374   bool IsValidUri(const grpc_uri* /*uri*/) const override { return true; }
375
376   OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
377     return MakeOrphanable<FakeResolver>(std::move(args));
378   }
379
380   const char* scheme() const override { return "fake"; }
381 };
382
383 }  // namespace
384
385 }  // namespace grpc_core
386
387 void grpc_resolver_fake_init() {
388   grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
389       grpc_core::MakeUnique<grpc_core::FakeResolverFactory>());
390 }
391
392 void grpc_resolver_fake_shutdown() {}