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/string.h"
36 #include "src/core/lib/gpr/useful.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"
44 #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
48 // This cannot be in an anonymous namespace, because it is a friend of
49 // FakeResolverResponseGenerator.
50 class FakeResolver : public Resolver {
52 explicit FakeResolver(ResolverArgs args);
54 void StartLocked() override;
56 void RequestReresolutionLocked() override;
59 friend class FakeResolverResponseGenerator;
61 virtual ~FakeResolver();
63 void ShutdownLocked() override {
65 if (response_generator_ != nullptr) {
66 response_generator_->SetFakeResolver(nullptr);
67 response_generator_.reset();
71 void MaybeSendResultLocked();
73 static void ReturnReresolutionResult(void* arg, grpc_error* error);
75 // passed-in parameters
76 grpc_channel_args* channel_args_ = nullptr;
77 RefCountedPtr<FakeResolverResponseGenerator> response_generator_;
78 // If has_next_result_ is true, next_result_ is the next resolution result
80 bool has_next_result_ = false;
82 // Result to use for the pretended re-resolution in
83 // RequestReresolutionLocked().
84 bool has_reresolution_result_ = false;
85 Result reresolution_result_;
86 // True after the call to StartLocked().
87 bool started_ = false;
88 // True after the call to ShutdownLocked().
89 bool shutdown_ = false;
90 // if true, return failure
91 bool return_failure_ = false;
92 // pending re-resolution
93 grpc_closure reresolution_closure_;
94 bool reresolution_closure_pending_ = false;
97 FakeResolver::FakeResolver(ResolverArgs args)
98 : Resolver(args.combiner, std::move(args.result_handler)),
100 FakeResolverResponseGenerator::GetFromArgs(args.args)) {
101 // Channels sharing the same subchannels may have different resolver response
102 // generators. If we don't remove this arg, subchannel pool will create new
103 // subchannels for the same address instead of reusing existing ones because
104 // of different values of this channel arg.
105 const char* args_to_remove[] = {GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR};
106 channel_args_ = grpc_channel_args_copy_and_remove(
107 args.args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove));
108 if (response_generator_ != nullptr) {
109 response_generator_->SetFakeResolver(Ref());
113 FakeResolver::~FakeResolver() { grpc_channel_args_destroy(channel_args_); }
115 void FakeResolver::StartLocked() {
117 MaybeSendResultLocked();
120 void FakeResolver::RequestReresolutionLocked() {
121 if (has_reresolution_result_ || return_failure_) {
122 next_result_ = reresolution_result_;
123 has_next_result_ = true;
124 // Return the result in a different closure, so that we don't call
125 // back into the LB policy while it's still processing the previous
127 if (!reresolution_closure_pending_) {
128 reresolution_closure_pending_ = true;
129 Ref().release(); // ref held by closure
130 GRPC_CLOSURE_INIT(&reresolution_closure_, ReturnReresolutionResult, this,
132 combiner()->Run(&reresolution_closure_, GRPC_ERROR_NONE);
137 void FakeResolver::MaybeSendResultLocked() {
138 if (!started_ || shutdown_) return;
139 if (return_failure_) {
140 // TODO(roth): Change resolver result generator to be able to inject
141 // the error to be returned.
142 result_handler()->ReturnError(grpc_error_set_int(
143 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resolver transient failure"),
144 GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
145 return_failure_ = false;
146 } else if (has_next_result_) {
148 result.addresses = std::move(next_result_.addresses);
149 result.service_config = std::move(next_result_.service_config);
150 // TODO(roth): Use std::move() once grpc_error is converted to C++.
151 result.service_config_error = next_result_.service_config_error;
152 next_result_.service_config_error = GRPC_ERROR_NONE;
153 // When both next_results_ and channel_args_ contain an arg with the same
154 // name, only the one in next_results_ will be kept since next_results_ is
155 // before channel_args_.
156 result.args = grpc_channel_args_union(next_result_.args, channel_args_);
157 result_handler()->ReturnResult(std::move(result));
158 has_next_result_ = false;
162 void FakeResolver::ReturnReresolutionResult(void* arg, grpc_error* /*error*/) {
163 FakeResolver* self = static_cast<FakeResolver*>(arg);
164 self->reresolution_closure_pending_ = false;
165 self->MaybeSendResultLocked();
170 // FakeResolverResponseGenerator
173 FakeResolverResponseGenerator::FakeResolverResponseGenerator() {}
175 FakeResolverResponseGenerator::~FakeResolverResponseGenerator() {}
177 struct SetResponseClosureArg {
178 grpc_closure set_response_closure;
179 RefCountedPtr<FakeResolver> resolver;
180 Resolver::Result result;
181 bool has_result = false;
182 bool immediate = true;
185 void FakeResolverResponseGenerator::SetResponseLocked(void* arg,
186 grpc_error* /*error*/) {
187 SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
188 auto& resolver = closure_arg->resolver;
189 if (!resolver->shutdown_) {
190 resolver->next_result_ = std::move(closure_arg->result);
191 resolver->has_next_result_ = true;
192 resolver->MaybeSendResultLocked();
197 void FakeResolverResponseGenerator::SetResponse(Resolver::Result result) {
198 RefCountedPtr<FakeResolver> resolver;
200 MutexLock lock(&mu_);
201 if (resolver_ == nullptr) {
203 result_ = std::move(result);
206 resolver = resolver_->Ref();
208 SetResponseClosureArg* closure_arg = new SetResponseClosureArg();
209 closure_arg->resolver = std::move(resolver);
210 closure_arg->result = std::move(result);
211 closure_arg->resolver->combiner()->Run(
212 GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetResponseLocked,
213 closure_arg, nullptr),
217 void FakeResolverResponseGenerator::SetReresolutionResponseLocked(
218 void* arg, grpc_error* /*error*/) {
219 SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
220 auto& resolver = closure_arg->resolver;
221 if (!resolver->shutdown_) {
222 resolver->reresolution_result_ = std::move(closure_arg->result);
223 resolver->has_reresolution_result_ = closure_arg->has_result;
228 void FakeResolverResponseGenerator::SetReresolutionResponse(
229 Resolver::Result result) {
230 RefCountedPtr<FakeResolver> resolver;
232 MutexLock lock(&mu_);
233 GPR_ASSERT(resolver_ != nullptr);
234 resolver = resolver_->Ref();
236 SetResponseClosureArg* closure_arg = new SetResponseClosureArg();
237 closure_arg->resolver = std::move(resolver);
238 closure_arg->result = std::move(result);
239 closure_arg->has_result = true;
240 closure_arg->resolver->combiner()->Run(
241 GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
242 SetReresolutionResponseLocked, closure_arg, nullptr),
246 void FakeResolverResponseGenerator::UnsetReresolutionResponse() {
247 RefCountedPtr<FakeResolver> resolver;
249 MutexLock lock(&mu_);
250 GPR_ASSERT(resolver_ != nullptr);
251 resolver = resolver_->Ref();
253 SetResponseClosureArg* closure_arg = new SetResponseClosureArg();
254 closure_arg->resolver = std::move(resolver);
255 closure_arg->resolver->combiner()->Run(
256 GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
257 SetReresolutionResponseLocked, closure_arg, nullptr),
261 void FakeResolverResponseGenerator::SetFailureLocked(void* arg,
262 grpc_error* /*error*/) {
263 SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
264 auto& resolver = closure_arg->resolver;
265 if (!resolver->shutdown_) {
266 resolver->return_failure_ = true;
267 if (closure_arg->immediate) resolver->MaybeSendResultLocked();
272 void FakeResolverResponseGenerator::SetFailure() {
273 RefCountedPtr<FakeResolver> resolver;
275 MutexLock lock(&mu_);
276 GPR_ASSERT(resolver_ != nullptr);
277 resolver = resolver_->Ref();
279 SetResponseClosureArg* closure_arg = new SetResponseClosureArg();
280 closure_arg->resolver = std::move(resolver);
281 closure_arg->resolver->combiner()->Run(
282 GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
283 closure_arg, nullptr),
287 void FakeResolverResponseGenerator::SetFailureOnReresolution() {
288 RefCountedPtr<FakeResolver> resolver;
290 MutexLock lock(&mu_);
291 GPR_ASSERT(resolver_ != nullptr);
292 resolver = resolver_->Ref();
294 SetResponseClosureArg* closure_arg = new SetResponseClosureArg();
295 closure_arg->resolver = std::move(resolver);
296 closure_arg->immediate = false;
297 closure_arg->resolver->combiner()->Run(
298 GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
299 closure_arg, nullptr),
303 void FakeResolverResponseGenerator::SetFakeResolver(
304 RefCountedPtr<FakeResolver> resolver) {
305 MutexLock lock(&mu_);
306 resolver_ = std::move(resolver);
307 if (resolver_ == nullptr) return;
309 SetResponseClosureArg* closure_arg = new SetResponseClosureArg();
310 closure_arg->resolver = resolver_->Ref();
311 closure_arg->result = std::move(result_);
312 resolver_->combiner()->Run(
313 GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetResponseLocked,
314 closure_arg, nullptr),
322 static void* response_generator_arg_copy(void* p) {
323 FakeResolverResponseGenerator* generator =
324 static_cast<FakeResolverResponseGenerator*>(p);
325 // TODO(roth): We currently deal with this ref manually. Once the
326 // new channel args code is converted to C++, find a way to track this ref
328 RefCountedPtr<FakeResolverResponseGenerator> copy = generator->Ref();
333 static void response_generator_arg_destroy(void* p) {
334 FakeResolverResponseGenerator* generator =
335 static_cast<FakeResolverResponseGenerator*>(p);
339 static int response_generator_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
341 static const grpc_arg_pointer_vtable response_generator_arg_vtable = {
342 response_generator_arg_copy, response_generator_arg_destroy,
343 response_generator_cmp};
347 grpc_arg FakeResolverResponseGenerator::MakeChannelArg(
348 FakeResolverResponseGenerator* generator) {
350 arg.type = GRPC_ARG_POINTER;
351 arg.key = (char*)GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR;
352 arg.value.pointer.p = generator;
353 arg.value.pointer.vtable = &response_generator_arg_vtable;
357 RefCountedPtr<FakeResolverResponseGenerator>
358 FakeResolverResponseGenerator::GetFromArgs(const grpc_channel_args* args) {
359 const grpc_arg* arg =
360 grpc_channel_args_find(args, GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR);
361 if (arg == nullptr || arg->type != GRPC_ARG_POINTER) return nullptr;
362 return static_cast<FakeResolverResponseGenerator*>(arg->value.pointer.p)
372 class FakeResolverFactory : public ResolverFactory {
374 bool IsValidUri(const grpc_uri* /*uri*/) const override { return true; }
376 OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
377 return MakeOrphanable<FakeResolver>(std::move(args));
380 const char* scheme() const override { return "fake"; }
385 } // namespace grpc_core
387 void grpc_resolver_fake_init() {
388 grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
389 grpc_core::MakeUnique<grpc_core::FakeResolverFactory>());
392 void grpc_resolver_fake_shutdown() {}