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 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 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 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 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 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 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 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 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 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 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 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 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 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 225 static void response_generator_arg_destroy(void* p) { 226 FakeResolverResponseGenerator* generator = 227 static_cast<FakeResolverResponseGenerator*>(p); 228 generator->Unref(); 229 } 230 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 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 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: 265 OrphanablePtr<Resolver> CreateResolver( 266 const ResolverArgs& args) const override { 267 return OrphanablePtr<Resolver>(New<FakeResolver>(args)); 268 } 269 270 const char* scheme() const override { return "fake"; } 271 }; 272 273 } // namespace 274 275 } // namespace grpc_core 276 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 283 void grpc_resolver_fake_shutdown() {} 284