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/resolver_registry.h"
32 #include "src/core/ext/filters/client_channel/server_address.h"
33 #include "src/core/lib/channel/channel_args.h"
34 #include "src/core/lib/gpr/string.h"
35 #include "src/core/lib/gpr/useful.h"
36 #include "src/core/lib/iomgr/closure.h"
37 #include "src/core/lib/iomgr/parse_address.h"
38 #include "src/core/lib/iomgr/resolve_address.h"
39 #include "src/core/lib/iomgr/unix_sockets_posix.h"
40 #include "src/core/lib/iomgr/work_serializer.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(ResolverArgs args);
53
54 void StartLocked() override;
55
56 void RequestReresolutionLocked() override;
57
58 private:
59 friend class FakeResolverResponseGenerator;
60 friend class FakeResolverResponseSetter;
61
62 ~FakeResolver() override;
63
64 void ShutdownLocked() override;
65
66 void MaybeSendResultLocked();
67
68 void ReturnReresolutionResult();
69
70 // passed-in parameters
71 grpc_channel_args* channel_args_ = nullptr;
72 std::shared_ptr<WorkSerializer> work_serializer_;
73 std::unique_ptr<ResultHandler> result_handler_;
74 RefCountedPtr<FakeResolverResponseGenerator> response_generator_;
75 // If has_next_result_ is true, next_result_ is the next resolution result
76 // to be returned.
77 bool has_next_result_ = false;
78 Result next_result_;
79 // Result to use for the pretended re-resolution in
80 // RequestReresolutionLocked().
81 bool has_reresolution_result_ = false;
82 Result reresolution_result_;
83 // True after the call to StartLocked().
84 bool started_ = false;
85 // True after the call to ShutdownLocked().
86 bool shutdown_ = false;
87 // if true, return failure
88 bool return_failure_ = false;
89 // pending re-resolution
90 bool reresolution_closure_pending_ = false;
91 };
92
FakeResolver(ResolverArgs args)93 FakeResolver::FakeResolver(ResolverArgs args)
94 : work_serializer_(std::move(args.work_serializer)),
95 result_handler_(std::move(args.result_handler)),
96 response_generator_(
97 FakeResolverResponseGenerator::GetFromArgs(args.args)) {
98 // Channels sharing the same subchannels may have different resolver response
99 // generators. If we don't remove this arg, subchannel pool will create new
100 // subchannels for the same address instead of reusing existing ones because
101 // of different values of this channel arg.
102 const char* args_to_remove[] = {GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR};
103 channel_args_ = grpc_channel_args_copy_and_remove(
104 args.args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove));
105 if (response_generator_ != nullptr) {
106 response_generator_->SetFakeResolver(Ref());
107 }
108 }
109
~FakeResolver()110 FakeResolver::~FakeResolver() { grpc_channel_args_destroy(channel_args_); }
111
StartLocked()112 void FakeResolver::StartLocked() {
113 started_ = true;
114 MaybeSendResultLocked();
115 }
116
RequestReresolutionLocked()117 void FakeResolver::RequestReresolutionLocked() {
118 if (has_reresolution_result_ || return_failure_) {
119 next_result_ = reresolution_result_;
120 has_next_result_ = true;
121 // Return the result in a different closure, so that we don't call
122 // back into the LB policy while it's still processing the previous
123 // update.
124 if (!reresolution_closure_pending_) {
125 reresolution_closure_pending_ = true;
126 Ref().release(); // ref held by closure
127 work_serializer_->Run([this]() { ReturnReresolutionResult(); },
128 DEBUG_LOCATION);
129 }
130 }
131 }
132
ShutdownLocked()133 void FakeResolver::ShutdownLocked() {
134 shutdown_ = true;
135 if (response_generator_ != nullptr) {
136 response_generator_->SetFakeResolver(nullptr);
137 response_generator_.reset();
138 }
139 }
140
MaybeSendResultLocked()141 void FakeResolver::MaybeSendResultLocked() {
142 if (!started_ || shutdown_) return;
143 if (return_failure_) {
144 // TODO(roth): Change resolver result generator to be able to inject
145 // the error to be returned.
146 result_handler_->ReturnError(grpc_error_set_int(
147 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resolver transient failure"),
148 GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
149 return_failure_ = false;
150 } else if (has_next_result_) {
151 Result result;
152 result.addresses = std::move(next_result_.addresses);
153 result.service_config = std::move(next_result_.service_config);
154 // TODO(roth): Use std::move() once grpc_error is converted to C++.
155 result.service_config_error = next_result_.service_config_error;
156 next_result_.service_config_error = GRPC_ERROR_NONE;
157 // When both next_results_ and channel_args_ contain an arg with the same
158 // name, only the one in next_results_ will be kept since next_results_ is
159 // before channel_args_.
160 result.args = grpc_channel_args_union(next_result_.args, channel_args_);
161 result_handler_->ReturnResult(std::move(result));
162 has_next_result_ = false;
163 }
164 }
165
ReturnReresolutionResult()166 void FakeResolver::ReturnReresolutionResult() {
167 reresolution_closure_pending_ = false;
168 MaybeSendResultLocked();
169 Unref();
170 }
171
172 class FakeResolverResponseSetter {
173 public:
FakeResolverResponseSetter(RefCountedPtr<FakeResolver> resolver,Resolver::Result result,bool has_result=false,bool immediate=true)174 explicit FakeResolverResponseSetter(RefCountedPtr<FakeResolver> resolver,
175 Resolver::Result result,
176 bool has_result = false,
177 bool immediate = true)
178 : resolver_(std::move(resolver)),
179 result_(std::move(result)),
180 has_result_(has_result),
181 immediate_(immediate) {}
182 void SetResponseLocked();
183 void SetReresolutionResponseLocked();
184 void SetFailureLocked();
185
186 private:
187 RefCountedPtr<FakeResolver> resolver_;
188 Resolver::Result result_;
189 bool has_result_;
190 bool immediate_;
191 };
192
193 // Deletes object when done
SetReresolutionResponseLocked()194 void FakeResolverResponseSetter::SetReresolutionResponseLocked() {
195 if (!resolver_->shutdown_) {
196 resolver_->reresolution_result_ = std::move(result_);
197 resolver_->has_reresolution_result_ = has_result_;
198 }
199 delete this;
200 }
201
202 // Deletes object when done
SetResponseLocked()203 void FakeResolverResponseSetter::SetResponseLocked() {
204 if (!resolver_->shutdown_) {
205 resolver_->next_result_ = std::move(result_);
206 resolver_->has_next_result_ = true;
207 resolver_->MaybeSendResultLocked();
208 }
209 delete this;
210 }
211
212 // Deletes object when done
SetFailureLocked()213 void FakeResolverResponseSetter::SetFailureLocked() {
214 if (!resolver_->shutdown_) {
215 resolver_->return_failure_ = true;
216 if (immediate_) resolver_->MaybeSendResultLocked();
217 }
218 delete this;
219 }
220
221 //
222 // FakeResolverResponseGenerator
223 //
224
FakeResolverResponseGenerator()225 FakeResolverResponseGenerator::FakeResolverResponseGenerator() {}
226
~FakeResolverResponseGenerator()227 FakeResolverResponseGenerator::~FakeResolverResponseGenerator() {}
228
SetResponse(Resolver::Result result)229 void FakeResolverResponseGenerator::SetResponse(Resolver::Result result) {
230 RefCountedPtr<FakeResolver> resolver;
231 {
232 MutexLock lock(&mu_);
233 if (resolver_ == nullptr) {
234 has_result_ = true;
235 result_ = std::move(result);
236 return;
237 }
238 resolver = resolver_->Ref();
239 }
240 FakeResolverResponseSetter* arg =
241 new FakeResolverResponseSetter(resolver, std::move(result));
242 resolver->work_serializer_->Run([arg]() { arg->SetResponseLocked(); },
243 DEBUG_LOCATION);
244 }
245
SetReresolutionResponse(Resolver::Result result)246 void FakeResolverResponseGenerator::SetReresolutionResponse(
247 Resolver::Result result) {
248 RefCountedPtr<FakeResolver> resolver;
249 {
250 MutexLock lock(&mu_);
251 GPR_ASSERT(resolver_ != nullptr);
252 resolver = resolver_->Ref();
253 }
254 FakeResolverResponseSetter* arg = new FakeResolverResponseSetter(
255 resolver, std::move(result), true /* has_result */);
256 resolver->work_serializer_->Run(
257 [arg]() { arg->SetReresolutionResponseLocked(); }, DEBUG_LOCATION);
258 }
259
UnsetReresolutionResponse()260 void FakeResolverResponseGenerator::UnsetReresolutionResponse() {
261 RefCountedPtr<FakeResolver> resolver;
262 {
263 MutexLock lock(&mu_);
264 GPR_ASSERT(resolver_ != nullptr);
265 resolver = resolver_->Ref();
266 }
267 FakeResolverResponseSetter* arg =
268 new FakeResolverResponseSetter(resolver, Resolver::Result());
269 resolver->work_serializer_->Run(
270 [arg]() { arg->SetReresolutionResponseLocked(); }, DEBUG_LOCATION);
271 }
272
SetFailure()273 void FakeResolverResponseGenerator::SetFailure() {
274 RefCountedPtr<FakeResolver> resolver;
275 {
276 MutexLock lock(&mu_);
277 GPR_ASSERT(resolver_ != nullptr);
278 resolver = resolver_->Ref();
279 }
280 FakeResolverResponseSetter* arg =
281 new FakeResolverResponseSetter(resolver, Resolver::Result());
282 resolver->work_serializer_->Run([arg]() { arg->SetFailureLocked(); },
283 DEBUG_LOCATION);
284 }
285
SetFailureOnReresolution()286 void FakeResolverResponseGenerator::SetFailureOnReresolution() {
287 RefCountedPtr<FakeResolver> resolver;
288 {
289 MutexLock lock(&mu_);
290 GPR_ASSERT(resolver_ != nullptr);
291 resolver = resolver_->Ref();
292 }
293 FakeResolverResponseSetter* arg = new FakeResolverResponseSetter(
294 resolver, Resolver::Result(), false /* has_result */,
295 false /* immediate */);
296 resolver->work_serializer_->Run([arg]() { arg->SetFailureLocked(); },
297 DEBUG_LOCATION);
298 }
299
SetFakeResolver(RefCountedPtr<FakeResolver> resolver)300 void FakeResolverResponseGenerator::SetFakeResolver(
301 RefCountedPtr<FakeResolver> resolver) {
302 MutexLock lock(&mu_);
303 resolver_ = std::move(resolver);
304 if (resolver_ == nullptr) return;
305 if (has_result_) {
306 FakeResolverResponseSetter* arg =
307 new FakeResolverResponseSetter(resolver_, std::move(result_));
308 resolver_->work_serializer_->Run([arg]() { arg->SetResponseLocked(); },
309 DEBUG_LOCATION);
310 has_result_ = false;
311 }
312 }
313
314 namespace {
315
response_generator_arg_copy(void * p)316 static void* response_generator_arg_copy(void* p) {
317 FakeResolverResponseGenerator* generator =
318 static_cast<FakeResolverResponseGenerator*>(p);
319 // TODO(roth): We currently deal with this ref manually. Once the
320 // new channel args code is converted to C++, find a way to track this ref
321 // in a cleaner way.
322 RefCountedPtr<FakeResolverResponseGenerator> copy = generator->Ref();
323 copy.release();
324 return p;
325 }
326
response_generator_arg_destroy(void * p)327 static void response_generator_arg_destroy(void* p) {
328 FakeResolverResponseGenerator* generator =
329 static_cast<FakeResolverResponseGenerator*>(p);
330 generator->Unref();
331 }
332
response_generator_cmp(void * a,void * b)333 static int response_generator_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
334
335 static const grpc_arg_pointer_vtable response_generator_arg_vtable = {
336 response_generator_arg_copy, response_generator_arg_destroy,
337 response_generator_cmp};
338
339 } // namespace
340
MakeChannelArg(FakeResolverResponseGenerator * generator)341 grpc_arg FakeResolverResponseGenerator::MakeChannelArg(
342 FakeResolverResponseGenerator* generator) {
343 grpc_arg arg;
344 arg.type = GRPC_ARG_POINTER;
345 arg.key = const_cast<char*>(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR);
346 arg.value.pointer.p = generator;
347 arg.value.pointer.vtable = &response_generator_arg_vtable;
348 return arg;
349 }
350
351 RefCountedPtr<FakeResolverResponseGenerator>
GetFromArgs(const grpc_channel_args * args)352 FakeResolverResponseGenerator::GetFromArgs(const grpc_channel_args* args) {
353 const grpc_arg* arg =
354 grpc_channel_args_find(args, GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR);
355 if (arg == nullptr || arg->type != GRPC_ARG_POINTER) return nullptr;
356 return static_cast<FakeResolverResponseGenerator*>(arg->value.pointer.p)
357 ->Ref();
358 }
359
360 //
361 // Factory
362 //
363
364 namespace {
365
366 class FakeResolverFactory : public ResolverFactory {
367 public:
IsValidUri(const URI &) const368 bool IsValidUri(const URI& /*uri*/) const override { return true; }
369
CreateResolver(ResolverArgs args) const370 OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
371 return MakeOrphanable<FakeResolver>(std::move(args));
372 }
373
scheme() const374 const char* scheme() const override { return "fake"; }
375 };
376
377 } // namespace
378
379 } // namespace grpc_core
380
grpc_resolver_fake_init()381 void grpc_resolver_fake_init() {
382 grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
383 absl::make_unique<grpc_core::FakeResolverFactory>());
384 }
385
grpc_resolver_fake_shutdown()386 void grpc_resolver_fake_shutdown() {}
387