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