Imported Upstream version 1.20.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   Delete(closure_arg);
179 }
180
181 void FakeResolverResponseGenerator::SetResponse(Resolver::Result result) {
182   if (resolver_ != nullptr) {
183     SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
184     closure_arg->generator = this;
185     closure_arg->result = std::move(result);
186     GRPC_CLOSURE_SCHED(
187         GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetResponseLocked,
188                           closure_arg,
189                           grpc_combiner_scheduler(resolver_->combiner())),
190         GRPC_ERROR_NONE);
191   } else {
192     GPR_ASSERT(!has_result_);
193     has_result_ = true;
194     result_ = std::move(result);
195   }
196 }
197
198 void FakeResolverResponseGenerator::SetReresolutionResponseLocked(
199     void* arg, grpc_error* error) {
200   SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
201   FakeResolver* resolver = closure_arg->generator->resolver_;
202   resolver->reresolution_result_ = std::move(closure_arg->result);
203   resolver->has_reresolution_result_ = closure_arg->has_result;
204   Delete(closure_arg);
205 }
206
207 void FakeResolverResponseGenerator::SetReresolutionResponse(
208     Resolver::Result result) {
209   GPR_ASSERT(resolver_ != nullptr);
210   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
211   closure_arg->generator = this;
212   closure_arg->result = std::move(result);
213   closure_arg->has_result = true;
214   GRPC_CLOSURE_SCHED(
215       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
216                         SetReresolutionResponseLocked, closure_arg,
217                         grpc_combiner_scheduler(resolver_->combiner())),
218       GRPC_ERROR_NONE);
219 }
220
221 void FakeResolverResponseGenerator::UnsetReresolutionResponse() {
222   GPR_ASSERT(resolver_ != nullptr);
223   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
224   closure_arg->generator = this;
225   GRPC_CLOSURE_SCHED(
226       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
227                         SetReresolutionResponseLocked, closure_arg,
228                         grpc_combiner_scheduler(resolver_->combiner())),
229       GRPC_ERROR_NONE);
230 }
231
232 void FakeResolverResponseGenerator::SetFailureLocked(void* arg,
233                                                      grpc_error* error) {
234   SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
235   FakeResolver* resolver = closure_arg->generator->resolver_;
236   resolver->return_failure_ = true;
237   if (closure_arg->immediate) resolver->MaybeSendResultLocked();
238   Delete(closure_arg);
239 }
240
241 void FakeResolverResponseGenerator::SetFailure() {
242   GPR_ASSERT(resolver_ != nullptr);
243   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
244   closure_arg->generator = this;
245   GRPC_CLOSURE_SCHED(
246       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
247                         closure_arg,
248                         grpc_combiner_scheduler(resolver_->combiner())),
249       GRPC_ERROR_NONE);
250 }
251
252 void FakeResolverResponseGenerator::SetFailureOnReresolution() {
253   GPR_ASSERT(resolver_ != nullptr);
254   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
255   closure_arg->generator = this;
256   closure_arg->immediate = false;
257   GRPC_CLOSURE_SCHED(
258       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
259                         closure_arg,
260                         grpc_combiner_scheduler(resolver_->combiner())),
261       GRPC_ERROR_NONE);
262 }
263
264 namespace {
265
266 static void* response_generator_arg_copy(void* p) {
267   FakeResolverResponseGenerator* generator =
268       static_cast<FakeResolverResponseGenerator*>(p);
269   // TODO(roth): We currently deal with this ref manually.  Once the
270   // new channel args code is converted to C++, find a way to track this ref
271   // in a cleaner way.
272   RefCountedPtr<FakeResolverResponseGenerator> copy = generator->Ref();
273   copy.release();
274   return p;
275 }
276
277 static void response_generator_arg_destroy(void* p) {
278   FakeResolverResponseGenerator* generator =
279       static_cast<FakeResolverResponseGenerator*>(p);
280   generator->Unref();
281 }
282
283 static int response_generator_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
284
285 static const grpc_arg_pointer_vtable response_generator_arg_vtable = {
286     response_generator_arg_copy, response_generator_arg_destroy,
287     response_generator_cmp};
288
289 }  // namespace
290
291 grpc_arg FakeResolverResponseGenerator::MakeChannelArg(
292     FakeResolverResponseGenerator* generator) {
293   grpc_arg arg;
294   arg.type = GRPC_ARG_POINTER;
295   arg.key = (char*)GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR;
296   arg.value.pointer.p = generator;
297   arg.value.pointer.vtable = &response_generator_arg_vtable;
298   return arg;
299 }
300
301 FakeResolverResponseGenerator* FakeResolverResponseGenerator::GetFromArgs(
302     const grpc_channel_args* args) {
303   const grpc_arg* arg =
304       grpc_channel_args_find(args, GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR);
305   if (arg == nullptr || arg->type != GRPC_ARG_POINTER) return nullptr;
306   return static_cast<FakeResolverResponseGenerator*>(arg->value.pointer.p);
307 }
308
309 //
310 // Factory
311 //
312
313 namespace {
314
315 class FakeResolverFactory : public ResolverFactory {
316  public:
317   OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
318     return OrphanablePtr<Resolver>(New<FakeResolver>(std::move(args)));
319   }
320
321   const char* scheme() const override { return "fake"; }
322 };
323
324 }  // namespace
325
326 }  // namespace grpc_core
327
328 void grpc_resolver_fake_init() {
329   grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
330       grpc_core::UniquePtr<grpc_core::ResolverFactory>(
331           grpc_core::New<grpc_core::FakeResolverFactory>()));
332 }
333
334 void grpc_resolver_fake_shutdown() {}