Line data Source code
1 : /*
2 : *
3 : * Copyright 2015, Google Inc.
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions are
8 : * met:
9 : *
10 : * * Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * * Redistributions in binary form must reproduce the above
13 : * copyright notice, this list of conditions and the following disclaimer
14 : * in the documentation and/or other materials provided with the
15 : * distribution.
16 : * * Neither the name of Google Inc. nor the names of its
17 : * contributors may be used to endorse or promote products derived from
18 : * this software without specific prior written permission.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 : * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 : * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 : * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 : *
32 : */
33 :
34 : #include <grpc/support/port_platform.h>
35 :
36 : #include "src/core/client_config/resolvers/sockaddr_resolver.h"
37 :
38 : #include <stdio.h>
39 : #include <string.h>
40 : #ifdef GPR_POSIX_SOCKET
41 : #include <sys/un.h>
42 : #endif
43 :
44 : #include <grpc/support/alloc.h>
45 : #include <grpc/support/host_port.h>
46 : #include <grpc/support/string_util.h>
47 :
48 : #include "src/core/client_config/lb_policy_registry.h"
49 : #include "src/core/iomgr/resolve_address.h"
50 : #include "src/core/support/string.h"
51 :
52 : typedef struct {
53 : /** base class: must be first */
54 : grpc_resolver base;
55 : /** refcount */
56 : gpr_refcount refs;
57 : /** subchannel factory */
58 : grpc_subchannel_factory *subchannel_factory;
59 : /** load balancing policy name */
60 : char *lb_policy_name;
61 :
62 : /** the addresses that we've 'resolved' */
63 : struct sockaddr_storage *addrs;
64 : /** the corresponding length of the addresses */
65 : size_t *addrs_len;
66 : /** how many elements in \a addrs */
67 : size_t num_addrs;
68 :
69 : /** mutex guarding the rest of the state */
70 : gpr_mu mu;
71 : /** have we published? */
72 : int published;
73 : /** pending next completion, or NULL */
74 : grpc_closure *next_completion;
75 : /** target config address for next completion */
76 : grpc_client_config **target_config;
77 : } sockaddr_resolver;
78 :
79 : static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
80 :
81 : static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
82 : sockaddr_resolver *r);
83 :
84 : static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
85 : static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
86 : grpc_resolver *r,
87 : struct sockaddr *failing_address,
88 : int failing_address_len);
89 : static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
90 : grpc_client_config **target_config,
91 : grpc_closure *on_complete);
92 :
93 : static const grpc_resolver_vtable sockaddr_resolver_vtable = {
94 : sockaddr_destroy, sockaddr_shutdown, sockaddr_channel_saw_error,
95 : sockaddr_next};
96 :
97 343 : static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx,
98 : grpc_resolver *resolver) {
99 343 : sockaddr_resolver *r = (sockaddr_resolver *)resolver;
100 343 : gpr_mu_lock(&r->mu);
101 343 : if (r->next_completion != NULL) {
102 279 : *r->target_config = NULL;
103 279 : grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, 1);
104 279 : r->next_completion = NULL;
105 : }
106 343 : gpr_mu_unlock(&r->mu);
107 343 : }
108 :
109 0 : static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
110 : grpc_resolver *resolver,
111 0 : struct sockaddr *sa, int len) {}
112 :
113 558 : static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
114 : grpc_client_config **target_config,
115 : grpc_closure *on_complete) {
116 558 : sockaddr_resolver *r = (sockaddr_resolver *)resolver;
117 558 : gpr_mu_lock(&r->mu);
118 558 : GPR_ASSERT(!r->next_completion);
119 558 : r->next_completion = on_complete;
120 558 : r->target_config = target_config;
121 558 : sockaddr_maybe_finish_next_locked(exec_ctx, r);
122 558 : gpr_mu_unlock(&r->mu);
123 558 : }
124 :
125 558 : static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
126 : sockaddr_resolver *r) {
127 : grpc_client_config *cfg;
128 : grpc_lb_policy *lb_policy;
129 : grpc_lb_policy_args lb_policy_args;
130 : grpc_subchannel **subchannels;
131 : grpc_subchannel_args args;
132 :
133 558 : if (r->next_completion != NULL && !r->published) {
134 : size_t i;
135 279 : cfg = grpc_client_config_create();
136 279 : subchannels = gpr_malloc(sizeof(grpc_subchannel *) * r->num_addrs);
137 579 : for (i = 0; i < r->num_addrs; i++) {
138 300 : memset(&args, 0, sizeof(args));
139 300 : args.addr = (struct sockaddr *)&r->addrs[i];
140 300 : args.addr_len = r->addrs_len[i];
141 300 : subchannels[i] = grpc_subchannel_factory_create_subchannel(
142 : exec_ctx, r->subchannel_factory, &args);
143 : }
144 279 : memset(&lb_policy_args, 0, sizeof(lb_policy_args));
145 279 : lb_policy_args.subchannels = subchannels;
146 279 : lb_policy_args.num_subchannels = r->num_addrs;
147 279 : lb_policy = grpc_lb_policy_create(r->lb_policy_name, &lb_policy_args);
148 279 : gpr_free(subchannels);
149 279 : grpc_client_config_set_lb_policy(cfg, lb_policy);
150 279 : GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "sockaddr");
151 279 : r->published = 1;
152 279 : *r->target_config = cfg;
153 279 : grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, 1);
154 279 : r->next_completion = NULL;
155 : }
156 558 : }
157 :
158 343 : static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
159 343 : sockaddr_resolver *r = (sockaddr_resolver *)gr;
160 343 : gpr_mu_destroy(&r->mu);
161 343 : grpc_subchannel_factory_unref(exec_ctx, r->subchannel_factory);
162 343 : gpr_free(r->addrs);
163 343 : gpr_free(r->addrs_len);
164 343 : gpr_free(r->lb_policy_name);
165 343 : gpr_free(r);
166 343 : }
167 :
168 : #ifdef GPR_POSIX_SOCKET
169 316 : static int parse_unix(grpc_uri *uri, struct sockaddr_storage *addr,
170 : size_t *len) {
171 316 : struct sockaddr_un *un = (struct sockaddr_un *)addr;
172 :
173 316 : un->sun_family = AF_UNIX;
174 316 : strcpy(un->sun_path, uri->path);
175 316 : *len = strlen(un->sun_path) + sizeof(un->sun_family) + 1;
176 :
177 316 : return 1;
178 : }
179 :
180 316 : static char *unix_get_default_authority(grpc_resolver_factory *factory,
181 : grpc_uri *uri) {
182 316 : return gpr_strdup("localhost");
183 : }
184 : #endif
185 :
186 27 : static char *ip_get_default_authority(grpc_uri *uri) {
187 27 : const char *path = uri->path;
188 27 : if (path[0] == '/') ++path;
189 27 : return gpr_strdup(path);
190 : }
191 :
192 15 : static char *ipv4_get_default_authority(grpc_resolver_factory *factory,
193 : grpc_uri *uri) {
194 15 : return ip_get_default_authority(uri);
195 : }
196 :
197 12 : static char *ipv6_get_default_authority(grpc_resolver_factory *factory,
198 : grpc_uri *uri) {
199 12 : return ip_get_default_authority(uri);
200 : }
201 :
202 34 : static int parse_ipv4(grpc_uri *uri, struct sockaddr_storage *addr,
203 : size_t *len) {
204 34 : const char *host_port = uri->path;
205 : char *host;
206 : char *port;
207 : int port_num;
208 34 : int result = 0;
209 34 : struct sockaddr_in *in = (struct sockaddr_in *)addr;
210 :
211 34 : if (*host_port == '/') ++host_port;
212 34 : if (!gpr_split_host_port(host_port, &host, &port)) {
213 0 : return 0;
214 : }
215 :
216 34 : memset(in, 0, sizeof(*in));
217 34 : *len = sizeof(*in);
218 34 : in->sin_family = AF_INET;
219 34 : if (inet_pton(AF_INET, host, &in->sin_addr) == 0) {
220 0 : gpr_log(GPR_ERROR, "invalid ipv4 address: '%s'", host);
221 0 : goto done;
222 : }
223 :
224 34 : if (port != NULL) {
225 68 : if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 ||
226 34 : port_num > 65535) {
227 0 : gpr_log(GPR_ERROR, "invalid ipv4 port: '%s'", port);
228 0 : goto done;
229 : }
230 34 : in->sin_port = htons((gpr_uint16)port_num);
231 : } else {
232 0 : gpr_log(GPR_ERROR, "no port given for ipv4 scheme");
233 0 : goto done;
234 : }
235 :
236 34 : result = 1;
237 : done:
238 34 : gpr_free(host);
239 34 : gpr_free(port);
240 34 : return result;
241 : }
242 :
243 14 : static int parse_ipv6(grpc_uri *uri, struct sockaddr_storage *addr,
244 : size_t *len) {
245 14 : const char *host_port = uri->path;
246 : char *host;
247 : char *port;
248 : int port_num;
249 14 : int result = 0;
250 14 : struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr;
251 :
252 14 : if (*host_port == '/') ++host_port;
253 14 : if (!gpr_split_host_port(host_port, &host, &port)) {
254 0 : return 0;
255 : }
256 :
257 14 : memset(in6, 0, sizeof(*in6));
258 14 : *len = sizeof(*in6);
259 14 : in6->sin6_family = AF_INET6;
260 14 : if (inet_pton(AF_INET6, host, &in6->sin6_addr) == 0) {
261 0 : gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host);
262 0 : goto done;
263 : }
264 :
265 14 : if (port != NULL) {
266 28 : if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 ||
267 14 : port_num > 65535) {
268 0 : gpr_log(GPR_ERROR, "invalid ipv6 port: '%s'", port);
269 0 : goto done;
270 : }
271 14 : in6->sin6_port = htons((gpr_uint16)port_num);
272 : } else {
273 0 : gpr_log(GPR_ERROR, "no port given for ipv6 scheme");
274 0 : goto done;
275 : }
276 :
277 14 : result = 1;
278 : done:
279 14 : gpr_free(host);
280 14 : gpr_free(port);
281 14 : return result;
282 : }
283 :
284 348 : static void do_nothing(void *ignored) {}
285 :
286 343 : static grpc_resolver *sockaddr_create(
287 : grpc_resolver_args *args, const char *default_lb_policy_name,
288 : int parse(grpc_uri *uri, struct sockaddr_storage *dst, size_t *len)) {
289 : size_t i;
290 343 : int errors_found = 0; /* GPR_FALSE */
291 : sockaddr_resolver *r;
292 : gpr_slice path_slice;
293 : gpr_slice_buffer path_parts;
294 :
295 343 : if (0 != strcmp(args->uri->authority, "")) {
296 0 : gpr_log(GPR_ERROR, "authority based uri's not supported by the %s scheme",
297 0 : args->uri->scheme);
298 0 : return NULL;
299 : }
300 :
301 343 : r = gpr_malloc(sizeof(sockaddr_resolver));
302 343 : memset(r, 0, sizeof(*r));
303 :
304 343 : r->lb_policy_name = NULL;
305 343 : if (0 != strcmp(args->uri->query, "")) {
306 : gpr_slice query_slice;
307 : gpr_slice_buffer query_parts;
308 :
309 5 : query_slice =
310 5 : gpr_slice_new(args->uri->query, strlen(args->uri->query), do_nothing);
311 5 : gpr_slice_buffer_init(&query_parts);
312 5 : gpr_slice_split(query_slice, "=", &query_parts);
313 5 : GPR_ASSERT(query_parts.count == 2);
314 5 : if (0 == gpr_slice_str_cmp(query_parts.slices[0], "lb_policy")) {
315 5 : r->lb_policy_name = gpr_dump_slice(query_parts.slices[1], GPR_DUMP_ASCII);
316 : }
317 5 : gpr_slice_buffer_destroy(&query_parts);
318 5 : gpr_slice_unref(query_slice);
319 : }
320 343 : if (r->lb_policy_name == NULL) {
321 338 : r->lb_policy_name = gpr_strdup(default_lb_policy_name);
322 : }
323 :
324 343 : path_slice =
325 343 : gpr_slice_new(args->uri->path, strlen(args->uri->path), do_nothing);
326 343 : gpr_slice_buffer_init(&path_parts);
327 :
328 343 : gpr_slice_split(path_slice, ",", &path_parts);
329 343 : r->num_addrs = path_parts.count;
330 343 : r->addrs = gpr_malloc(sizeof(struct sockaddr_storage) * r->num_addrs);
331 343 : r->addrs_len = gpr_malloc(sizeof(*r->addrs_len) * r->num_addrs);
332 :
333 707 : for (i = 0; i < r->num_addrs; i++) {
334 364 : grpc_uri ith_uri = *args->uri;
335 364 : char *part_str = gpr_dump_slice(path_parts.slices[i], GPR_DUMP_ASCII);
336 364 : ith_uri.path = part_str;
337 364 : if (!parse(&ith_uri, &r->addrs[i], &r->addrs_len[i])) {
338 0 : errors_found = 1; /* GPR_TRUE */
339 : }
340 364 : gpr_free(part_str);
341 364 : if (errors_found) break;
342 : }
343 :
344 343 : gpr_slice_buffer_destroy(&path_parts);
345 343 : gpr_slice_unref(path_slice);
346 343 : if (errors_found) {
347 0 : gpr_free(r);
348 0 : return NULL;
349 : }
350 :
351 343 : gpr_ref_init(&r->refs, 1);
352 343 : gpr_mu_init(&r->mu);
353 343 : grpc_resolver_init(&r->base, &sockaddr_resolver_vtable);
354 343 : r->subchannel_factory = args->subchannel_factory;
355 343 : grpc_subchannel_factory_ref(r->subchannel_factory);
356 :
357 343 : return &r->base;
358 : }
359 :
360 : /*
361 : * FACTORY
362 : */
363 :
364 7503 : static void sockaddr_factory_ref(grpc_resolver_factory *factory) {}
365 :
366 7503 : static void sockaddr_factory_unref(grpc_resolver_factory *factory) {}
367 :
368 : #define DECL_FACTORY(name) \
369 : static grpc_resolver *name##_factory_create_resolver( \
370 : grpc_resolver_factory *factory, grpc_resolver_args *args) { \
371 : return sockaddr_create(args, "pick_first", parse_##name); \
372 : } \
373 : static const grpc_resolver_factory_vtable name##_factory_vtable = { \
374 : sockaddr_factory_ref, sockaddr_factory_unref, \
375 : name##_factory_create_resolver, name##_get_default_authority, #name}; \
376 : static grpc_resolver_factory name##_resolver_factory = { \
377 : &name##_factory_vtable}; \
378 : grpc_resolver_factory *grpc_##name##_resolver_factory_create() { \
379 : return &name##_resolver_factory; \
380 : }
381 :
382 : #ifdef GPR_POSIX_SOCKET
383 2817 : DECL_FACTORY(unix)
384 : #endif
385 5029 : DECL_FACTORY(ipv4) DECL_FACTORY(ipv6)
|