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