• 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/lb_policy_factory.h"
32 #include "src/core/ext/filters/client_channel/parse_address.h"
33 #include "src/core/ext/filters/client_channel/resolver_registry.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/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(const ResolverArgs& args);
53 
54   void NextLocked(grpc_channel_args** result,
55                   grpc_closure* on_complete) override;
56 
57   void RequestReresolutionLocked() override;
58 
59  private:
60   friend class FakeResolverResponseGenerator;
61 
62   virtual ~FakeResolver();
63 
64   void MaybeFinishNextLocked();
65 
66   void ShutdownLocked() override;
67 
68   // passed-in parameters
69   grpc_channel_args* channel_args_ = nullptr;
70   // If not NULL, the next set of resolution results to be returned to
71   // NextLocked()'s closure.
72   grpc_channel_args* next_results_ = nullptr;
73   // Results to use for the pretended re-resolution in
74   // RequestReresolutionLocked().
75   grpc_channel_args* reresolution_results_ = nullptr;
76   // pending next completion, or NULL
77   grpc_closure* next_completion_ = nullptr;
78   // target result address for next completion
79   grpc_channel_args** target_result_ = nullptr;
80   // if true, return failure
81   bool return_failure_ = false;
82 };
83 
FakeResolver(const ResolverArgs & args)84 FakeResolver::FakeResolver(const ResolverArgs& args) : Resolver(args.combiner) {
85   channel_args_ = grpc_channel_args_copy(args.args);
86   FakeResolverResponseGenerator* response_generator =
87       FakeResolverResponseGenerator::GetFromArgs(args.args);
88   if (response_generator != nullptr) response_generator->resolver_ = this;
89 }
90 
~FakeResolver()91 FakeResolver::~FakeResolver() {
92   grpc_channel_args_destroy(next_results_);
93   grpc_channel_args_destroy(reresolution_results_);
94   grpc_channel_args_destroy(channel_args_);
95 }
96 
NextLocked(grpc_channel_args ** target_result,grpc_closure * on_complete)97 void FakeResolver::NextLocked(grpc_channel_args** target_result,
98                               grpc_closure* on_complete) {
99   GPR_ASSERT(next_completion_ == nullptr);
100   next_completion_ = on_complete;
101   target_result_ = target_result;
102   MaybeFinishNextLocked();
103 }
104 
RequestReresolutionLocked()105 void FakeResolver::RequestReresolutionLocked() {
106   if (reresolution_results_ != nullptr) {
107     grpc_channel_args_destroy(next_results_);
108     next_results_ = grpc_channel_args_copy(reresolution_results_);
109     MaybeFinishNextLocked();
110   }
111 }
112 
MaybeFinishNextLocked()113 void FakeResolver::MaybeFinishNextLocked() {
114   if (next_completion_ != nullptr &&
115       (next_results_ != nullptr || return_failure_)) {
116     *target_result_ =
117         return_failure_ ? nullptr
118                         : grpc_channel_args_union(next_results_, channel_args_);
119     grpc_channel_args_destroy(next_results_);
120     next_results_ = nullptr;
121     GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_NONE);
122     next_completion_ = nullptr;
123     return_failure_ = false;
124   }
125 }
126 
ShutdownLocked()127 void FakeResolver::ShutdownLocked() {
128   if (next_completion_ != nullptr) {
129     *target_result_ = nullptr;
130     GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
131                                              "Resolver Shutdown"));
132     next_completion_ = nullptr;
133   }
134 }
135 
136 //
137 // FakeResolverResponseGenerator
138 //
139 
140 struct SetResponseClosureArg {
141   grpc_closure set_response_closure;
142   FakeResolverResponseGenerator* generator;
143   grpc_channel_args* response;
144 };
145 
SetResponseLocked(void * arg,grpc_error * error)146 void FakeResolverResponseGenerator::SetResponseLocked(void* arg,
147                                                       grpc_error* error) {
148   SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
149   FakeResolver* resolver = closure_arg->generator->resolver_;
150   grpc_channel_args_destroy(resolver->next_results_);
151   resolver->next_results_ = closure_arg->response;
152   resolver->MaybeFinishNextLocked();
153   Delete(closure_arg);
154 }
155 
SetResponse(grpc_channel_args * response)156 void FakeResolverResponseGenerator::SetResponse(grpc_channel_args* response) {
157   GPR_ASSERT(response != nullptr);
158   GPR_ASSERT(resolver_ != nullptr);
159   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
160   closure_arg->generator = this;
161   closure_arg->response = grpc_channel_args_copy(response);
162   GRPC_CLOSURE_SCHED(
163       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetResponseLocked,
164                         closure_arg,
165                         grpc_combiner_scheduler(resolver_->combiner())),
166       GRPC_ERROR_NONE);
167 }
168 
SetReresolutionResponseLocked(void * arg,grpc_error * error)169 void FakeResolverResponseGenerator::SetReresolutionResponseLocked(
170     void* arg, grpc_error* error) {
171   SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
172   FakeResolver* resolver = closure_arg->generator->resolver_;
173   grpc_channel_args_destroy(resolver->reresolution_results_);
174   resolver->reresolution_results_ = closure_arg->response;
175   Delete(closure_arg);
176 }
177 
SetReresolutionResponse(grpc_channel_args * response)178 void FakeResolverResponseGenerator::SetReresolutionResponse(
179     grpc_channel_args* response) {
180   GPR_ASSERT(resolver_ != nullptr);
181   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
182   closure_arg->generator = this;
183   closure_arg->response =
184       response != nullptr ? grpc_channel_args_copy(response) : nullptr;
185   GRPC_CLOSURE_SCHED(
186       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
187                         SetReresolutionResponseLocked, closure_arg,
188                         grpc_combiner_scheduler(resolver_->combiner())),
189       GRPC_ERROR_NONE);
190 }
191 
SetFailureLocked(void * arg,grpc_error * error)192 void FakeResolverResponseGenerator::SetFailureLocked(void* arg,
193                                                      grpc_error* error) {
194   SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
195   FakeResolver* resolver = closure_arg->generator->resolver_;
196   resolver->return_failure_ = true;
197   resolver->MaybeFinishNextLocked();
198   Delete(closure_arg);
199 }
200 
SetFailure()201 void FakeResolverResponseGenerator::SetFailure() {
202   GPR_ASSERT(resolver_ != nullptr);
203   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
204   closure_arg->generator = this;
205   GRPC_CLOSURE_SCHED(
206       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
207                         closure_arg,
208                         grpc_combiner_scheduler(resolver_->combiner())),
209       GRPC_ERROR_NONE);
210 }
211 
212 namespace {
213 
response_generator_arg_copy(void * p)214 static void* response_generator_arg_copy(void* p) {
215   FakeResolverResponseGenerator* generator =
216       static_cast<FakeResolverResponseGenerator*>(p);
217   // TODO(roth): We currently deal with this ref manually.  Once the
218   // new channel args code is converted to C++, find a way to track this ref
219   // in a cleaner way.
220   RefCountedPtr<FakeResolverResponseGenerator> copy = generator->Ref();
221   copy.release();
222   return p;
223 }
224 
response_generator_arg_destroy(void * p)225 static void response_generator_arg_destroy(void* p) {
226   FakeResolverResponseGenerator* generator =
227       static_cast<FakeResolverResponseGenerator*>(p);
228   generator->Unref();
229 }
230 
response_generator_cmp(void * a,void * b)231 static int response_generator_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
232 
233 static const grpc_arg_pointer_vtable response_generator_arg_vtable = {
234     response_generator_arg_copy, response_generator_arg_destroy,
235     response_generator_cmp};
236 
237 }  // namespace
238 
MakeChannelArg(FakeResolverResponseGenerator * generator)239 grpc_arg FakeResolverResponseGenerator::MakeChannelArg(
240     FakeResolverResponseGenerator* generator) {
241   grpc_arg arg;
242   arg.type = GRPC_ARG_POINTER;
243   arg.key = (char*)GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR;
244   arg.value.pointer.p = generator;
245   arg.value.pointer.vtable = &response_generator_arg_vtable;
246   return arg;
247 }
248 
GetFromArgs(const grpc_channel_args * args)249 FakeResolverResponseGenerator* FakeResolverResponseGenerator::GetFromArgs(
250     const grpc_channel_args* args) {
251   const grpc_arg* arg =
252       grpc_channel_args_find(args, GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR);
253   if (arg == nullptr || arg->type != GRPC_ARG_POINTER) return nullptr;
254   return static_cast<FakeResolverResponseGenerator*>(arg->value.pointer.p);
255 }
256 
257 //
258 // Factory
259 //
260 
261 namespace {
262 
263 class FakeResolverFactory : public ResolverFactory {
264  public:
CreateResolver(const ResolverArgs & args) const265   OrphanablePtr<Resolver> CreateResolver(
266       const ResolverArgs& args) const override {
267     return OrphanablePtr<Resolver>(New<FakeResolver>(args));
268   }
269 
scheme() const270   const char* scheme() const override { return "fake"; }
271 };
272 
273 }  // namespace
274 
275 }  // namespace grpc_core
276 
grpc_resolver_fake_init()277 void grpc_resolver_fake_init() {
278   grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
279       grpc_core::UniquePtr<grpc_core::ResolverFactory>(
280           grpc_core::New<grpc_core::FakeResolverFactory>()));
281 }
282 
grpc_resolver_fake_shutdown()283 void grpc_resolver_fake_shutdown() {}
284