2 // Copyright 2016 gRPC authors.
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
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.
20 #include <grpc/support/port_platform.h>
28 #include <grpc/support/alloc.h>
29 #include <grpc/support/string_util.h>
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"
45 #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
49 // This cannot be in an anonymous namespace, because it is a friend of
50 // FakeResolverResponseGenerator.
51 class FakeResolver : public Resolver {
53 explicit FakeResolver(const ResolverArgs& args);
55 void NextLocked(grpc_channel_args** result,
56 grpc_closure* on_complete) override;
58 void RequestReresolutionLocked() override;
61 friend class FakeResolverResponseGenerator;
63 virtual ~FakeResolver();
65 void MaybeFinishNextLocked();
67 void ShutdownLocked() override;
69 // passed-in parameters
70 grpc_channel_args* channel_args_ = nullptr;
71 // If not NULL, the next set of resolution results to be returned to
72 // NextLocked()'s closure.
73 grpc_channel_args* next_results_ = nullptr;
74 // Results to use for the pretended re-resolution in
75 // RequestReresolutionLocked().
76 grpc_channel_args* reresolution_results_ = nullptr;
77 // pending next completion, or NULL
78 grpc_closure* next_completion_ = nullptr;
79 // target result address for next completion
80 grpc_channel_args** target_result_ = nullptr;
81 // if true, return failure
82 bool return_failure_ = false;
85 FakeResolver::FakeResolver(const ResolverArgs& args) : Resolver(args.combiner) {
86 channel_args_ = grpc_channel_args_copy(args.args);
87 FakeResolverResponseGenerator* response_generator =
88 FakeResolverResponseGenerator::GetFromArgs(args.args);
89 if (response_generator != nullptr) response_generator->resolver_ = this;
92 FakeResolver::~FakeResolver() {
93 grpc_channel_args_destroy(next_results_);
94 grpc_channel_args_destroy(reresolution_results_);
95 grpc_channel_args_destroy(channel_args_);
98 void FakeResolver::NextLocked(grpc_channel_args** target_result,
99 grpc_closure* on_complete) {
100 GPR_ASSERT(next_completion_ == nullptr);
101 next_completion_ = on_complete;
102 target_result_ = target_result;
103 MaybeFinishNextLocked();
106 void FakeResolver::RequestReresolutionLocked() {
107 if (reresolution_results_ != nullptr || return_failure_) {
108 grpc_channel_args_destroy(next_results_);
109 next_results_ = grpc_channel_args_copy(reresolution_results_);
110 MaybeFinishNextLocked();
114 void FakeResolver::MaybeFinishNextLocked() {
115 if (next_completion_ != nullptr &&
116 (next_results_ != nullptr || return_failure_)) {
118 return_failure_ ? nullptr
119 : grpc_channel_args_union(next_results_, channel_args_);
120 grpc_channel_args_destroy(next_results_);
121 next_results_ = nullptr;
122 GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_NONE);
123 next_completion_ = nullptr;
124 return_failure_ = false;
128 void FakeResolver::ShutdownLocked() {
129 if (next_completion_ != nullptr) {
130 *target_result_ = nullptr;
131 GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
132 "Resolver Shutdown"));
133 next_completion_ = nullptr;
138 // FakeResolverResponseGenerator
141 struct SetResponseClosureArg {
142 grpc_closure set_response_closure;
143 FakeResolverResponseGenerator* generator;
144 grpc_channel_args* response;
145 bool immediate = true;
148 void FakeResolverResponseGenerator::SetResponseLocked(void* arg,
150 SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
151 FakeResolver* resolver = closure_arg->generator->resolver_;
152 grpc_channel_args_destroy(resolver->next_results_);
153 resolver->next_results_ = closure_arg->response;
154 resolver->MaybeFinishNextLocked();
158 void FakeResolverResponseGenerator::SetResponse(grpc_channel_args* response) {
159 GPR_ASSERT(response != nullptr);
160 GPR_ASSERT(resolver_ != nullptr);
161 SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
162 closure_arg->generator = this;
163 closure_arg->response = grpc_channel_args_copy(response);
165 GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetResponseLocked,
167 grpc_combiner_scheduler(resolver_->combiner())),
171 void FakeResolverResponseGenerator::SetReresolutionResponseLocked(
172 void* arg, grpc_error* error) {
173 SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
174 FakeResolver* resolver = closure_arg->generator->resolver_;
175 grpc_channel_args_destroy(resolver->reresolution_results_);
176 resolver->reresolution_results_ = closure_arg->response;
180 void FakeResolverResponseGenerator::SetReresolutionResponse(
181 grpc_channel_args* response) {
182 GPR_ASSERT(resolver_ != nullptr);
183 SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
184 closure_arg->generator = this;
185 closure_arg->response =
186 response != nullptr ? grpc_channel_args_copy(response) : nullptr;
188 GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
189 SetReresolutionResponseLocked, closure_arg,
190 grpc_combiner_scheduler(resolver_->combiner())),
194 void FakeResolverResponseGenerator::SetFailureLocked(void* arg,
196 SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
197 FakeResolver* resolver = closure_arg->generator->resolver_;
198 resolver->return_failure_ = true;
199 if (closure_arg->immediate) resolver->MaybeFinishNextLocked();
203 void FakeResolverResponseGenerator::SetFailure() {
204 GPR_ASSERT(resolver_ != nullptr);
205 SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
206 closure_arg->generator = this;
208 GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
210 grpc_combiner_scheduler(resolver_->combiner())),
214 void FakeResolverResponseGenerator::SetFailureOnReresolution() {
215 GPR_ASSERT(resolver_ != nullptr);
216 SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
217 closure_arg->generator = this;
218 closure_arg->immediate = false;
220 GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
222 grpc_combiner_scheduler(resolver_->combiner())),
228 static void* response_generator_arg_copy(void* p) {
229 FakeResolverResponseGenerator* generator =
230 static_cast<FakeResolverResponseGenerator*>(p);
231 // TODO(roth): We currently deal with this ref manually. Once the
232 // new channel args code is converted to C++, find a way to track this ref
234 RefCountedPtr<FakeResolverResponseGenerator> copy = generator->Ref();
239 static void response_generator_arg_destroy(void* p) {
240 FakeResolverResponseGenerator* generator =
241 static_cast<FakeResolverResponseGenerator*>(p);
245 static int response_generator_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
247 static const grpc_arg_pointer_vtable response_generator_arg_vtable = {
248 response_generator_arg_copy, response_generator_arg_destroy,
249 response_generator_cmp};
253 grpc_arg FakeResolverResponseGenerator::MakeChannelArg(
254 FakeResolverResponseGenerator* generator) {
256 arg.type = GRPC_ARG_POINTER;
257 arg.key = (char*)GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR;
258 arg.value.pointer.p = generator;
259 arg.value.pointer.vtable = &response_generator_arg_vtable;
263 FakeResolverResponseGenerator* FakeResolverResponseGenerator::GetFromArgs(
264 const grpc_channel_args* args) {
265 const grpc_arg* arg =
266 grpc_channel_args_find(args, GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR);
267 if (arg == nullptr || arg->type != GRPC_ARG_POINTER) return nullptr;
268 return static_cast<FakeResolverResponseGenerator*>(arg->value.pointer.p);
277 class FakeResolverFactory : public ResolverFactory {
279 OrphanablePtr<Resolver> CreateResolver(
280 const ResolverArgs& args) const override {
281 return OrphanablePtr<Resolver>(New<FakeResolver>(args));
284 const char* scheme() const override { return "fake"; }
289 } // namespace grpc_core
291 void grpc_resolver_fake_init() {
292 grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
293 grpc_core::UniquePtr<grpc_core::ResolverFactory>(
294 grpc_core::New<grpc_core::FakeResolverFactory>()));
297 void grpc_resolver_fake_shutdown() {}