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/lb_policy_factory.h"
32 #include "src/core/ext/filters/client_channel/parse_address.h"
33 #include "src/core/ext/filters/client_channel/resolver_registry.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/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"
43
44 #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
45
46 namespace grpc_core {
47
48 // This cannot be in an anonymous namespace, because it is a friend of
49 // FakeResolverResponseGenerator.
50 class FakeResolver : public Resolver {
51 public:
52 explicit FakeResolver(const ResolverArgs& args);
53
54 void NextLocked(grpc_channel_args** result,
55 grpc_closure* on_complete) override;
56
57 void RequestReresolutionLocked() override;
58
59 private:
60 friend class FakeResolverResponseGenerator;
61
62 virtual ~FakeResolver();
63
64 void MaybeFinishNextLocked();
65
66 void ShutdownLocked() override;
67
68 // passed-in parameters
69 grpc_channel_args* channel_args_ = nullptr;
70 // If not NULL, the next set of resolution results to be returned to
71 // NextLocked()'s closure.
72 grpc_channel_args* next_results_ = nullptr;
73 // Results to use for the pretended re-resolution in
74 // RequestReresolutionLocked().
75 grpc_channel_args* reresolution_results_ = nullptr;
76 // pending next completion, or NULL
77 grpc_closure* next_completion_ = nullptr;
78 // target result address for next completion
79 grpc_channel_args** target_result_ = nullptr;
80 // if true, return failure
81 bool return_failure_ = false;
82 };
83
FakeResolver(const ResolverArgs & args)84 FakeResolver::FakeResolver(const ResolverArgs& args) : Resolver(args.combiner) {
85 channel_args_ = grpc_channel_args_copy(args.args);
86 FakeResolverResponseGenerator* response_generator =
87 FakeResolverResponseGenerator::GetFromArgs(args.args);
88 if (response_generator != nullptr) response_generator->resolver_ = this;
89 }
90
~FakeResolver()91 FakeResolver::~FakeResolver() {
92 grpc_channel_args_destroy(next_results_);
93 grpc_channel_args_destroy(reresolution_results_);
94 grpc_channel_args_destroy(channel_args_);
95 }
96
NextLocked(grpc_channel_args ** target_result,grpc_closure * on_complete)97 void FakeResolver::NextLocked(grpc_channel_args** target_result,
98 grpc_closure* on_complete) {
99 GPR_ASSERT(next_completion_ == nullptr);
100 next_completion_ = on_complete;
101 target_result_ = target_result;
102 MaybeFinishNextLocked();
103 }
104
RequestReresolutionLocked()105 void FakeResolver::RequestReresolutionLocked() {
106 if (reresolution_results_ != nullptr) {
107 grpc_channel_args_destroy(next_results_);
108 next_results_ = grpc_channel_args_copy(reresolution_results_);
109 MaybeFinishNextLocked();
110 }
111 }
112
MaybeFinishNextLocked()113 void FakeResolver::MaybeFinishNextLocked() {
114 if (next_completion_ != nullptr &&
115 (next_results_ != nullptr || return_failure_)) {
116 *target_result_ =
117 return_failure_ ? nullptr
118 : grpc_channel_args_union(next_results_, channel_args_);
119 grpc_channel_args_destroy(next_results_);
120 next_results_ = nullptr;
121 GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_NONE);
122 next_completion_ = nullptr;
123 return_failure_ = false;
124 }
125 }
126
ShutdownLocked()127 void FakeResolver::ShutdownLocked() {
128 if (next_completion_ != nullptr) {
129 *target_result_ = nullptr;
130 GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
131 "Resolver Shutdown"));
132 next_completion_ = nullptr;
133 }
134 }
135
136 //
137 // FakeResolverResponseGenerator
138 //
139
140 struct SetResponseClosureArg {
141 grpc_closure set_response_closure;
142 FakeResolverResponseGenerator* generator;
143 grpc_channel_args* response;
144 };
145
SetResponseLocked(void * arg,grpc_error * error)146 void FakeResolverResponseGenerator::SetResponseLocked(void* arg,
147 grpc_error* error) {
148 SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
149 FakeResolver* resolver = closure_arg->generator->resolver_;
150 grpc_channel_args_destroy(resolver->next_results_);
151 resolver->next_results_ = closure_arg->response;
152 resolver->MaybeFinishNextLocked();
153 Delete(closure_arg);
154 }
155
SetResponse(grpc_channel_args * response)156 void FakeResolverResponseGenerator::SetResponse(grpc_channel_args* response) {
157 GPR_ASSERT(response != nullptr);
158 GPR_ASSERT(resolver_ != nullptr);
159 SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
160 closure_arg->generator = this;
161 closure_arg->response = grpc_channel_args_copy(response);
162 GRPC_CLOSURE_SCHED(
163 GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetResponseLocked,
164 closure_arg,
165 grpc_combiner_scheduler(resolver_->combiner())),
166 GRPC_ERROR_NONE);
167 }
168
SetReresolutionResponseLocked(void * arg,grpc_error * error)169 void FakeResolverResponseGenerator::SetReresolutionResponseLocked(
170 void* arg, grpc_error* error) {
171 SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
172 FakeResolver* resolver = closure_arg->generator->resolver_;
173 grpc_channel_args_destroy(resolver->reresolution_results_);
174 resolver->reresolution_results_ = closure_arg->response;
175 Delete(closure_arg);
176 }
177
SetReresolutionResponse(grpc_channel_args * response)178 void FakeResolverResponseGenerator::SetReresolutionResponse(
179 grpc_channel_args* response) {
180 GPR_ASSERT(resolver_ != nullptr);
181 SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
182 closure_arg->generator = this;
183 closure_arg->response =
184 response != nullptr ? grpc_channel_args_copy(response) : nullptr;
185 GRPC_CLOSURE_SCHED(
186 GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
187 SetReresolutionResponseLocked, closure_arg,
188 grpc_combiner_scheduler(resolver_->combiner())),
189 GRPC_ERROR_NONE);
190 }
191
SetFailureLocked(void * arg,grpc_error * error)192 void FakeResolverResponseGenerator::SetFailureLocked(void* arg,
193 grpc_error* error) {
194 SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
195 FakeResolver* resolver = closure_arg->generator->resolver_;
196 resolver->return_failure_ = true;
197 resolver->MaybeFinishNextLocked();
198 Delete(closure_arg);
199 }
200
SetFailure()201 void FakeResolverResponseGenerator::SetFailure() {
202 GPR_ASSERT(resolver_ != nullptr);
203 SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
204 closure_arg->generator = this;
205 GRPC_CLOSURE_SCHED(
206 GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
207 closure_arg,
208 grpc_combiner_scheduler(resolver_->combiner())),
209 GRPC_ERROR_NONE);
210 }
211
212 namespace {
213
response_generator_arg_copy(void * p)214 static void* response_generator_arg_copy(void* p) {
215 FakeResolverResponseGenerator* generator =
216 static_cast<FakeResolverResponseGenerator*>(p);
217 // TODO(roth): We currently deal with this ref manually. Once the
218 // new channel args code is converted to C++, find a way to track this ref
219 // in a cleaner way.
220 RefCountedPtr<FakeResolverResponseGenerator> copy = generator->Ref();
221 copy.release();
222 return p;
223 }
224
response_generator_arg_destroy(void * p)225 static void response_generator_arg_destroy(void* p) {
226 FakeResolverResponseGenerator* generator =
227 static_cast<FakeResolverResponseGenerator*>(p);
228 generator->Unref();
229 }
230
response_generator_cmp(void * a,void * b)231 static int response_generator_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
232
233 static const grpc_arg_pointer_vtable response_generator_arg_vtable = {
234 response_generator_arg_copy, response_generator_arg_destroy,
235 response_generator_cmp};
236
237 } // namespace
238
MakeChannelArg(FakeResolverResponseGenerator * generator)239 grpc_arg FakeResolverResponseGenerator::MakeChannelArg(
240 FakeResolverResponseGenerator* generator) {
241 grpc_arg arg;
242 arg.type = GRPC_ARG_POINTER;
243 arg.key = (char*)GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR;
244 arg.value.pointer.p = generator;
245 arg.value.pointer.vtable = &response_generator_arg_vtable;
246 return arg;
247 }
248
GetFromArgs(const grpc_channel_args * args)249 FakeResolverResponseGenerator* FakeResolverResponseGenerator::GetFromArgs(
250 const grpc_channel_args* args) {
251 const grpc_arg* arg =
252 grpc_channel_args_find(args, GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR);
253 if (arg == nullptr || arg->type != GRPC_ARG_POINTER) return nullptr;
254 return static_cast<FakeResolverResponseGenerator*>(arg->value.pointer.p);
255 }
256
257 //
258 // Factory
259 //
260
261 namespace {
262
263 class FakeResolverFactory : public ResolverFactory {
264 public:
CreateResolver(const ResolverArgs & args) const265 OrphanablePtr<Resolver> CreateResolver(
266 const ResolverArgs& args) const override {
267 return OrphanablePtr<Resolver>(New<FakeResolver>(args));
268 }
269
scheme() const270 const char* scheme() const override { return "fake"; }
271 };
272
273 } // namespace
274
275 } // namespace grpc_core
276
grpc_resolver_fake_init()277 void grpc_resolver_fake_init() {
278 grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
279 grpc_core::UniquePtr<grpc_core::ResolverFactory>(
280 grpc_core::New<grpc_core::FakeResolverFactory>()));
281 }
282
grpc_resolver_fake_shutdown()283 void grpc_resolver_fake_shutdown() {}
284