Imported Upstream version 1.22.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(ResolverArgs args);
54
55   void StartLocked() override;
56
57   void RequestReresolutionLocked() override;
58
59  private:
60   friend class FakeResolverResponseGenerator;
61
62   virtual ~FakeResolver();
63
64   void ShutdownLocked() override { active_ = false; }
65
66   void MaybeSendResultLocked();
67
68   static void ReturnReresolutionResult(void* arg, grpc_error* error);
69
70   // passed-in parameters
71   grpc_channel_args* channel_args_ = nullptr;
72   // If has_next_result_ is true, next_result_ is the next resolution result
73   // to be returned.
74   bool has_next_result_ = false;
75   Result next_result_;
76   // Result to use for the pretended re-resolution in
77   // RequestReresolutionLocked().
78   bool has_reresolution_result_ = false;
79   Result reresolution_result_;
80   // True between the calls to StartLocked() ShutdownLocked().
81   bool active_ = false;
82   // if true, return failure
83   bool return_failure_ = false;
84   // pending re-resolution
85   grpc_closure reresolution_closure_;
86   bool reresolution_closure_pending_ = false;
87 };
88
89 FakeResolver::FakeResolver(ResolverArgs args)
90     : Resolver(args.combiner, std::move(args.result_handler)) {
91   GRPC_CLOSURE_INIT(&reresolution_closure_, ReturnReresolutionResult, this,
92                     grpc_combiner_scheduler(combiner()));
93   channel_args_ = grpc_channel_args_copy(args.args);
94   FakeResolverResponseGenerator* response_generator =
95       FakeResolverResponseGenerator::GetFromArgs(args.args);
96   if (response_generator != nullptr) {
97     response_generator->resolver_ = this;
98     if (response_generator->has_result_) {
99       response_generator->SetResponse(std::move(response_generator->result_));
100       response_generator->has_result_ = false;
101     }
102   }
103 }
104
105 FakeResolver::~FakeResolver() { grpc_channel_args_destroy(channel_args_); }
106
107 void FakeResolver::StartLocked() {
108   active_ = true;
109   MaybeSendResultLocked();
110 }
111
112 void FakeResolver::RequestReresolutionLocked() {
113   if (has_reresolution_result_ || return_failure_) {
114     next_result_ = reresolution_result_;
115     has_next_result_ = true;
116     // Return the result in a different closure, so that we don't call
117     // back into the LB policy while it's still processing the previous
118     // update.
119     if (!reresolution_closure_pending_) {
120       reresolution_closure_pending_ = true;
121       Ref().release();  // ref held by closure
122       GRPC_CLOSURE_SCHED(&reresolution_closure_, GRPC_ERROR_NONE);
123     }
124   }
125 }
126
127 void FakeResolver::MaybeSendResultLocked() {
128   if (!active_) return;
129   if (return_failure_) {
130     // TODO(roth): Change resolver result generator to be able to inject
131     // the error to be returned.
132     result_handler()->ReturnError(grpc_error_set_int(
133         GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resolver transient failure"),
134         GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
135     return_failure_ = false;
136   } else if (has_next_result_) {
137     Result result;
138     result.addresses = std::move(next_result_.addresses);
139     result.service_config = std::move(next_result_.service_config);
140     // TODO(roth): Use std::move() once grpc_error is converted to C++.
141     result.service_config_error = next_result_.service_config_error;
142     next_result_.service_config_error = GRPC_ERROR_NONE;
143     // When both next_results_ and channel_args_ contain an arg with the same
144     // name, only the one in next_results_ will be kept since next_results_ is
145     // before channel_args_.
146     result.args = grpc_channel_args_union(next_result_.args, channel_args_);
147     result_handler()->ReturnResult(std::move(result));
148     has_next_result_ = false;
149   }
150 }
151
152 void FakeResolver::ReturnReresolutionResult(void* arg, grpc_error* error) {
153   FakeResolver* self = static_cast<FakeResolver*>(arg);
154   self->reresolution_closure_pending_ = false;
155   self->MaybeSendResultLocked();
156   self->Unref();
157 }
158
159 //
160 // FakeResolverResponseGenerator
161 //
162
163 struct SetResponseClosureArg {
164   grpc_closure set_response_closure;
165   FakeResolverResponseGenerator* generator;
166   Resolver::Result result;
167   bool has_result = false;
168   bool immediate = true;
169 };
170
171 void FakeResolverResponseGenerator::SetResponseLocked(void* arg,
172                                                       grpc_error* error) {
173   SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
174   FakeResolver* resolver = closure_arg->generator->resolver_;
175   resolver->next_result_ = std::move(closure_arg->result);
176   resolver->has_next_result_ = true;
177   resolver->MaybeSendResultLocked();
178   closure_arg->generator->Unref();
179   Delete(closure_arg);
180 }
181
182 void FakeResolverResponseGenerator::SetResponse(Resolver::Result result) {
183   if (resolver_ != nullptr) {
184     Ref().release();  // ref to be held by closure
185     SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
186     closure_arg->generator = this;
187     closure_arg->result = std::move(result);
188     GRPC_CLOSURE_SCHED(
189         GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetResponseLocked,
190                           closure_arg,
191                           grpc_combiner_scheduler(resolver_->combiner())),
192         GRPC_ERROR_NONE);
193   } else {
194     GPR_ASSERT(!has_result_);
195     has_result_ = true;
196     result_ = std::move(result);
197   }
198 }
199
200 void FakeResolverResponseGenerator::SetReresolutionResponseLocked(
201     void* arg, grpc_error* error) {
202   SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
203   FakeResolver* resolver = closure_arg->generator->resolver_;
204   resolver->reresolution_result_ = std::move(closure_arg->result);
205   resolver->has_reresolution_result_ = closure_arg->has_result;
206   Delete(closure_arg);
207 }
208
209 void FakeResolverResponseGenerator::SetReresolutionResponse(
210     Resolver::Result result) {
211   GPR_ASSERT(resolver_ != nullptr);
212   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
213   closure_arg->generator = this;
214   closure_arg->result = std::move(result);
215   closure_arg->has_result = true;
216   GRPC_CLOSURE_SCHED(
217       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
218                         SetReresolutionResponseLocked, closure_arg,
219                         grpc_combiner_scheduler(resolver_->combiner())),
220       GRPC_ERROR_NONE);
221 }
222
223 void FakeResolverResponseGenerator::UnsetReresolutionResponse() {
224   GPR_ASSERT(resolver_ != nullptr);
225   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
226   closure_arg->generator = this;
227   GRPC_CLOSURE_SCHED(
228       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
229                         SetReresolutionResponseLocked, closure_arg,
230                         grpc_combiner_scheduler(resolver_->combiner())),
231       GRPC_ERROR_NONE);
232 }
233
234 void FakeResolverResponseGenerator::SetFailureLocked(void* arg,
235                                                      grpc_error* error) {
236   SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
237   FakeResolver* resolver = closure_arg->generator->resolver_;
238   resolver->return_failure_ = true;
239   if (closure_arg->immediate) resolver->MaybeSendResultLocked();
240   Delete(closure_arg);
241 }
242
243 void FakeResolverResponseGenerator::SetFailure() {
244   GPR_ASSERT(resolver_ != nullptr);
245   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
246   closure_arg->generator = this;
247   GRPC_CLOSURE_SCHED(
248       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
249                         closure_arg,
250                         grpc_combiner_scheduler(resolver_->combiner())),
251       GRPC_ERROR_NONE);
252 }
253
254 void FakeResolverResponseGenerator::SetFailureOnReresolution() {
255   GPR_ASSERT(resolver_ != nullptr);
256   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
257   closure_arg->generator = this;
258   closure_arg->immediate = false;
259   GRPC_CLOSURE_SCHED(
260       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
261                         closure_arg,
262                         grpc_combiner_scheduler(resolver_->combiner())),
263       GRPC_ERROR_NONE);
264 }
265
266 namespace {
267
268 static void* response_generator_arg_copy(void* p) {
269   FakeResolverResponseGenerator* generator =
270       static_cast<FakeResolverResponseGenerator*>(p);
271   // TODO(roth): We currently deal with this ref manually.  Once the
272   // new channel args code is converted to C++, find a way to track this ref
273   // in a cleaner way.
274   RefCountedPtr<FakeResolverResponseGenerator> copy = generator->Ref();
275   copy.release();
276   return p;
277 }
278
279 static void response_generator_arg_destroy(void* p) {
280   FakeResolverResponseGenerator* generator =
281       static_cast<FakeResolverResponseGenerator*>(p);
282   generator->Unref();
283 }
284
285 static int response_generator_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
286
287 static const grpc_arg_pointer_vtable response_generator_arg_vtable = {
288     response_generator_arg_copy, response_generator_arg_destroy,
289     response_generator_cmp};
290
291 }  // namespace
292
293 grpc_arg FakeResolverResponseGenerator::MakeChannelArg(
294     FakeResolverResponseGenerator* generator) {
295   grpc_arg arg;
296   arg.type = GRPC_ARG_POINTER;
297   arg.key = (char*)GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR;
298   arg.value.pointer.p = generator;
299   arg.value.pointer.vtable = &response_generator_arg_vtable;
300   return arg;
301 }
302
303 FakeResolverResponseGenerator* FakeResolverResponseGenerator::GetFromArgs(
304     const grpc_channel_args* args) {
305   const grpc_arg* arg =
306       grpc_channel_args_find(args, GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR);
307   if (arg == nullptr || arg->type != GRPC_ARG_POINTER) return nullptr;
308   return static_cast<FakeResolverResponseGenerator*>(arg->value.pointer.p);
309 }
310
311 //
312 // Factory
313 //
314
315 namespace {
316
317 class FakeResolverFactory : public ResolverFactory {
318  public:
319   OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
320     return OrphanablePtr<Resolver>(New<FakeResolver>(std::move(args)));
321   }
322
323   const char* scheme() const override { return "fake"; }
324 };
325
326 }  // namespace
327
328 }  // namespace grpc_core
329
330 void grpc_resolver_fake_init() {
331   grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
332       grpc_core::UniquePtr<grpc_core::ResolverFactory>(
333           grpc_core::New<grpc_core::FakeResolverFactory>()));
334 }
335
336 void grpc_resolver_fake_shutdown() {}