1 /* 2 * 3 * Copyright 2015-2016 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 #include <grpc/support/port_platform.h> 20 21 #include <stdbool.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 26 #include <grpc/support/alloc.h> 27 #include <grpc/support/string_util.h> 28 29 #include "src/core/ext/filters/client_channel/lb_policy_factory.h" 30 #include "src/core/ext/filters/client_channel/parse_address.h" 31 #include "src/core/ext/filters/client_channel/resolver_registry.h" 32 #include "src/core/lib/channel/channel_args.h" 33 #include "src/core/lib/gpr/host_port.h" 34 #include "src/core/lib/gpr/string.h" 35 #include "src/core/lib/iomgr/combiner.h" 36 #include "src/core/lib/iomgr/resolve_address.h" 37 #include "src/core/lib/iomgr/unix_sockets_posix.h" 38 #include "src/core/lib/slice/slice_internal.h" 39 #include "src/core/lib/slice/slice_string_helpers.h" 40 41 namespace grpc_core { 42 43 namespace { 44 45 class SockaddrResolver : public Resolver { 46 public: 47 /// Takes ownership of \a addresses. 48 SockaddrResolver(const ResolverArgs& args, grpc_lb_addresses* addresses); 49 50 void NextLocked(grpc_channel_args** result, 51 grpc_closure* on_complete) override; 52 53 void ShutdownLocked() override; 54 55 private: 56 virtual ~SockaddrResolver(); 57 58 void MaybeFinishNextLocked(); 59 60 /// the addresses that we've "resolved" 61 grpc_lb_addresses* addresses_ = nullptr; 62 /// channel args 63 grpc_channel_args* channel_args_ = nullptr; 64 /// have we published? 65 bool published_ = false; 66 /// pending next completion, or NULL 67 grpc_closure* next_completion_ = nullptr; 68 /// target result address for next completion 69 grpc_channel_args** target_result_ = nullptr; 70 }; 71 72 SockaddrResolver::SockaddrResolver(const ResolverArgs& args, 73 grpc_lb_addresses* addresses) 74 : Resolver(args.combiner), 75 addresses_(addresses), 76 channel_args_(grpc_channel_args_copy(args.args)) {} 77 78 SockaddrResolver::~SockaddrResolver() { 79 grpc_lb_addresses_destroy(addresses_); 80 grpc_channel_args_destroy(channel_args_); 81 } 82 83 void SockaddrResolver::NextLocked(grpc_channel_args** target_result, 84 grpc_closure* on_complete) { 85 GPR_ASSERT(!next_completion_); 86 next_completion_ = on_complete; 87 target_result_ = target_result; 88 MaybeFinishNextLocked(); 89 } 90 91 void SockaddrResolver::ShutdownLocked() { 92 if (next_completion_ != nullptr) { 93 *target_result_ = nullptr; 94 GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_CREATE_FROM_STATIC_STRING( 95 "Resolver Shutdown")); 96 next_completion_ = nullptr; 97 } 98 } 99 100 void SockaddrResolver::MaybeFinishNextLocked() { 101 if (next_completion_ != nullptr && !published_) { 102 published_ = true; 103 grpc_arg arg = grpc_lb_addresses_create_channel_arg(addresses_); 104 *target_result_ = grpc_channel_args_copy_and_add(channel_args_, &arg, 1); 105 GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_NONE); 106 next_completion_ = nullptr; 107 } 108 } 109 110 // 111 // Factory 112 // 113 114 void DoNothing(void* ignored) {} 115 116 OrphanablePtr<Resolver> CreateSockaddrResolver( 117 const ResolverArgs& args, 118 bool parse(const grpc_uri* uri, grpc_resolved_address* dst)) { 119 if (0 != strcmp(args.uri->authority, "")) { 120 gpr_log(GPR_ERROR, "authority-based URIs not supported by the %s scheme", 121 args.uri->scheme); 122 return OrphanablePtr<Resolver>(nullptr); 123 } 124 // Construct addresses. 125 grpc_slice path_slice = 126 grpc_slice_new(args.uri->path, strlen(args.uri->path), DoNothing); 127 grpc_slice_buffer path_parts; 128 grpc_slice_buffer_init(&path_parts); 129 grpc_slice_split(path_slice, ",", &path_parts); 130 grpc_lb_addresses* addresses = grpc_lb_addresses_create( 131 path_parts.count, nullptr /* user_data_vtable */); 132 bool errors_found = false; 133 for (size_t i = 0; i < addresses->num_addresses; i++) { 134 grpc_uri ith_uri = *args.uri; 135 char* part_str = grpc_slice_to_c_string(path_parts.slices[i]); 136 ith_uri.path = part_str; 137 if (!parse(&ith_uri, &addresses->addresses[i].address)) { 138 errors_found = true; /* GPR_TRUE */ 139 } 140 gpr_free(part_str); 141 if (errors_found) break; 142 } 143 grpc_slice_buffer_destroy_internal(&path_parts); 144 grpc_slice_unref_internal(path_slice); 145 if (errors_found) { 146 grpc_lb_addresses_destroy(addresses); 147 return OrphanablePtr<Resolver>(nullptr); 148 } 149 // Instantiate resolver. 150 return OrphanablePtr<Resolver>(New<SockaddrResolver>(args, addresses)); 151 } 152 153 class IPv4ResolverFactory : public ResolverFactory { 154 public: 155 OrphanablePtr<Resolver> CreateResolver( 156 const ResolverArgs& args) const override { 157 return CreateSockaddrResolver(args, grpc_parse_ipv4); 158 } 159 160 const char* scheme() const override { return "ipv4"; } 161 }; 162 163 class IPv6ResolverFactory : public ResolverFactory { 164 public: 165 OrphanablePtr<Resolver> CreateResolver( 166 const ResolverArgs& args) const override { 167 return CreateSockaddrResolver(args, grpc_parse_ipv6); 168 } 169 170 const char* scheme() const override { return "ipv6"; } 171 }; 172 173 #ifdef GRPC_HAVE_UNIX_SOCKET 174 class UnixResolverFactory : public ResolverFactory { 175 public: 176 OrphanablePtr<Resolver> CreateResolver( 177 const ResolverArgs& args) const override { 178 return CreateSockaddrResolver(args, grpc_parse_unix); 179 } 180 181 UniquePtr<char> GetDefaultAuthority(grpc_uri* uri) const override { 182 return UniquePtr<char>(gpr_strdup("localhost")); 183 } 184 185 const char* scheme() const override { return "unix"; } 186 }; 187 #endif // GRPC_HAVE_UNIX_SOCKET 188 189 } // namespace 190 191 } // namespace grpc_core 192 193 void grpc_resolver_sockaddr_init() { 194 grpc_core::ResolverRegistry::Builder::RegisterResolverFactory( 195 grpc_core::UniquePtr<grpc_core::ResolverFactory>( 196 grpc_core::New<grpc_core::IPv4ResolverFactory>())); 197 grpc_core::ResolverRegistry::Builder::RegisterResolverFactory( 198 grpc_core::UniquePtr<grpc_core::ResolverFactory>( 199 grpc_core::New<grpc_core::IPv6ResolverFactory>())); 200 #ifdef GRPC_HAVE_UNIX_SOCKET 201 grpc_core::ResolverRegistry::Builder::RegisterResolverFactory( 202 grpc_core::UniquePtr<grpc_core::ResolverFactory>( 203 grpc_core::New<grpc_core::UnixResolverFactory>())); 204 #endif 205 } 206 207 void grpc_resolver_sockaddr_shutdown() {} 208