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(ResolverArgs args);
55 void StartLocked() override;
57 void RequestReresolutionLocked() override;
60 friend class FakeResolverResponseGenerator;
62 virtual ~FakeResolver();
64 void ShutdownLocked() override { active_ = false; }
66 void MaybeSendResultLocked();
68 static void ReturnReresolutionResult(void* arg, grpc_error* error);
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
74 bool has_next_result_ = false;
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().
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;
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;
105 FakeResolver::~FakeResolver() { grpc_channel_args_destroy(channel_args_); }
107 void FakeResolver::StartLocked() {
109 MaybeSendResultLocked();
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
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);
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_) {
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;
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();
160 // FakeResolverResponseGenerator
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;
171 void FakeResolverResponseGenerator::SetResponseLocked(void* arg,
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();
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);
189 GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetResponseLocked,
191 grpc_combiner_scheduler(resolver_->combiner())),
194 GPR_ASSERT(!has_result_);
196 result_ = std::move(result);
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;
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;
217 GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
218 SetReresolutionResponseLocked, closure_arg,
219 grpc_combiner_scheduler(resolver_->combiner())),
223 void FakeResolverResponseGenerator::UnsetReresolutionResponse() {
224 GPR_ASSERT(resolver_ != nullptr);
225 SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
226 closure_arg->generator = this;
228 GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
229 SetReresolutionResponseLocked, closure_arg,
230 grpc_combiner_scheduler(resolver_->combiner())),
234 void FakeResolverResponseGenerator::SetFailureLocked(void* arg,
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();
243 void FakeResolverResponseGenerator::SetFailure() {
244 GPR_ASSERT(resolver_ != nullptr);
245 SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
246 closure_arg->generator = this;
248 GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
250 grpc_combiner_scheduler(resolver_->combiner())),
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;
260 GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
262 grpc_combiner_scheduler(resolver_->combiner())),
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
274 RefCountedPtr<FakeResolverResponseGenerator> copy = generator->Ref();
279 static void response_generator_arg_destroy(void* p) {
280 FakeResolverResponseGenerator* generator =
281 static_cast<FakeResolverResponseGenerator*>(p);
285 static int response_generator_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
287 static const grpc_arg_pointer_vtable response_generator_arg_vtable = {
288 response_generator_arg_copy, response_generator_arg_destroy,
289 response_generator_cmp};
293 grpc_arg FakeResolverResponseGenerator::MakeChannelArg(
294 FakeResolverResponseGenerator* generator) {
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;
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);
317 class FakeResolverFactory : public ResolverFactory {
319 OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
320 return OrphanablePtr<Resolver>(New<FakeResolver>(std::move(args)));
323 const char* scheme() const override { return "fake"; }
328 } // namespace grpc_core
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>()));
336 void grpc_resolver_fake_shutdown() {}