blob: 830f3f52868f5d6c37e1becc0f242c9b3d2506e6 [file] [log] [blame]
Craig Tillercd29c582015-06-24 09:15:15 -07001/*
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 "src/core/client_config/resolvers/dns_resolver.h"
35
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070036#include <string.h>
37
38#include <grpc/support/alloc.h>
Craig Tiller6b9f5c62015-07-29 18:47:35 -070039#include <grpc/support/host_port.h>
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070040#include <grpc/support/string_util.h>
41
David Garcia Quintas5c4543d2015-09-03 15:49:56 -070042#include "src/core/client_config/lb_policy_registry.h"
Craig Tiller6b9f5c62015-07-29 18:47:35 -070043#include "src/core/client_config/subchannel_factory_decorators/add_channel_arg.h"
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070044#include "src/core/iomgr/resolve_address.h"
45#include "src/core/support/string.h"
46
47typedef struct {
48 /** base class: must be first */
49 grpc_resolver base;
50 /** refcount */
51 gpr_refcount refs;
52 /** name to resolve */
53 char *name;
54 /** default port to use */
55 char *default_port;
56 /** subchannel factory */
57 grpc_subchannel_factory *subchannel_factory;
David Garcia Quintas5c4543d2015-09-03 15:49:56 -070058 /** load balancing policy name */
59 char *lb_policy_name;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070060
61 /** mutex guarding the rest of the state */
62 gpr_mu mu;
63 /** are we currently resolving? */
64 int resolving;
65 /** which version of resolved_config have we published? */
66 int published_version;
67 /** which version of resolved_config is current? */
68 int resolved_version;
69 /** pending next completion, or NULL */
70 grpc_iomgr_closure *next_completion;
71 /** target config address for next completion */
72 grpc_client_config **target_config;
73 /** current (fully resolved) config */
74 grpc_client_config *resolved_config;
75} dns_resolver;
76
Craig Tiller98465032015-06-29 14:36:42 -070077static void dns_destroy(grpc_resolver *r);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070078
79static void dns_start_resolving_locked(dns_resolver *r);
80static void dns_maybe_finish_next_locked(dns_resolver *r);
81
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070082static void dns_shutdown(grpc_resolver *r);
83static void dns_channel_saw_error(grpc_resolver *r,
84 struct sockaddr *failing_address,
85 int failing_address_len);
86static void dns_next(grpc_resolver *r, grpc_client_config **target_config,
87 grpc_iomgr_closure *on_complete);
88
89static const grpc_resolver_vtable dns_resolver_vtable = {
Craig Tiller98465032015-06-29 14:36:42 -070090 dns_destroy, dns_shutdown, dns_channel_saw_error, dns_next};
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070091
92static void dns_shutdown(grpc_resolver *resolver) {
93 dns_resolver *r = (dns_resolver *)resolver;
94 gpr_mu_lock(&r->mu);
95 if (r->next_completion != NULL) {
96 *r->target_config = NULL;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070097 grpc_iomgr_add_callback(r->next_completion);
98 r->next_completion = NULL;
99 }
100 gpr_mu_unlock(&r->mu);
101}
102
103static void dns_channel_saw_error(grpc_resolver *resolver, struct sockaddr *sa,
104 int len) {
105 dns_resolver *r = (dns_resolver *)resolver;
106 gpr_mu_lock(&r->mu);
107 if (!r->resolving) {
108 dns_start_resolving_locked(r);
109 }
110 gpr_mu_unlock(&r->mu);
111}
112
113static void dns_next(grpc_resolver *resolver,
114 grpc_client_config **target_config,
115 grpc_iomgr_closure *on_complete) {
116 dns_resolver *r = (dns_resolver *)resolver;
117 gpr_mu_lock(&r->mu);
118 GPR_ASSERT(!r->next_completion);
119 r->next_completion = on_complete;
120 r->target_config = target_config;
121 if (r->resolved_version == 0 && !r->resolving) {
122 dns_start_resolving_locked(r);
123 } else {
124 dns_maybe_finish_next_locked(r);
125 }
126 gpr_mu_unlock(&r->mu);
127}
128
129static void dns_on_resolved(void *arg, grpc_resolved_addresses *addresses) {
130 dns_resolver *r = arg;
131 grpc_client_config *config = NULL;
132 grpc_subchannel **subchannels;
133 grpc_subchannel_args args;
Craig Tillerd7b68e72015-06-28 11:41:09 -0700134 grpc_lb_policy *lb_policy;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700135 size_t i;
136 if (addresses) {
137 config = grpc_client_config_create();
138 subchannels = gpr_malloc(sizeof(grpc_subchannel *) * addresses->naddrs);
139 for (i = 0; i < addresses->naddrs; i++) {
140 memset(&args, 0, sizeof(args));
141 args.addr = (struct sockaddr *)(addresses->addrs[i].addr);
142 args.addr_len = addresses->addrs[i].len;
143 subchannels[i] = grpc_subchannel_factory_create_subchannel(
144 r->subchannel_factory, &args);
145 }
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700146 lb_policy = grpc_lb_policy_create(r->lb_policy_name, subchannels,
147 addresses->naddrs);
Craig Tillerd7b68e72015-06-28 11:41:09 -0700148 grpc_client_config_set_lb_policy(config, lb_policy);
149 GRPC_LB_POLICY_UNREF(lb_policy, "construction");
Craig Tiller98465032015-06-29 14:36:42 -0700150 grpc_resolved_addresses_destroy(addresses);
151 gpr_free(subchannels);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700152 }
153 gpr_mu_lock(&r->mu);
Craig Tiller98465032015-06-29 14:36:42 -0700154 GPR_ASSERT(r->resolving);
155 r->resolving = 0;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700156 if (r->resolved_config) {
157 grpc_client_config_unref(r->resolved_config);
158 }
159 r->resolved_config = config;
160 r->resolved_version++;
161 dns_maybe_finish_next_locked(r);
162 gpr_mu_unlock(&r->mu);
Craig Tillerd7b68e72015-06-28 11:41:09 -0700163
Craig Tiller98465032015-06-29 14:36:42 -0700164 GRPC_RESOLVER_UNREF(&r->base, "dns-resolving");
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700165}
166
167static void dns_start_resolving_locked(dns_resolver *r) {
Craig Tiller98465032015-06-29 14:36:42 -0700168 GRPC_RESOLVER_REF(&r->base, "dns-resolving");
169 GPR_ASSERT(!r->resolving);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700170 r->resolving = 1;
171 grpc_resolve_address(r->name, r->default_port, dns_on_resolved, r);
172}
173
174static void dns_maybe_finish_next_locked(dns_resolver *r) {
175 if (r->next_completion != NULL &&
176 r->resolved_version != r->published_version) {
Craig Tillereb3b12e2015-06-26 14:42:49 -0700177 *r->target_config = r->resolved_config;
Craig Tillerabf36382015-06-29 16:13:27 -0700178 if (r->resolved_config) {
179 grpc_client_config_ref(r->resolved_config);
180 }
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700181 grpc_iomgr_add_callback(r->next_completion);
182 r->next_completion = NULL;
183 r->published_version = r->resolved_version;
184 }
185}
186
Craig Tiller98465032015-06-29 14:36:42 -0700187static void dns_destroy(grpc_resolver *gr) {
188 dns_resolver *r = (dns_resolver *)gr;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700189 gpr_mu_destroy(&r->mu);
Craig Tillerd7b68e72015-06-28 11:41:09 -0700190 if (r->resolved_config) {
191 grpc_client_config_unref(r->resolved_config);
192 }
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700193 grpc_subchannel_factory_unref(r->subchannel_factory);
194 gpr_free(r->name);
195 gpr_free(r->default_port);
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700196 gpr_free(r->lb_policy_name);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700197 gpr_free(r);
198}
199
Craig Tillereb3b12e2015-06-26 14:42:49 -0700200static grpc_resolver *dns_create(
201 grpc_uri *uri, const char *default_port,
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700202 const char* lb_policy_name,
Craig Tillereb3b12e2015-06-26 14:42:49 -0700203 grpc_subchannel_factory *subchannel_factory) {
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700204 dns_resolver *r;
205 const char *path = uri->path;
206
207 if (0 != strcmp(uri->authority, "")) {
208 gpr_log(GPR_ERROR, "authority based uri's not supported");
209 return NULL;
210 }
211
212 if (path[0] == '/') ++path;
213
214 r = gpr_malloc(sizeof(dns_resolver));
215 memset(r, 0, sizeof(*r));
216 gpr_ref_init(&r->refs, 1);
217 gpr_mu_init(&r->mu);
Craig Tiller98465032015-06-29 14:36:42 -0700218 grpc_resolver_init(&r->base, &dns_resolver_vtable);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700219 r->name = gpr_strdup(path);
220 r->default_port = gpr_strdup(default_port);
221 r->subchannel_factory = subchannel_factory;
Craig Tillerbc85be12015-08-24 10:36:39 -0700222 grpc_subchannel_factory_ref(subchannel_factory);
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700223 r->lb_policy_name = gpr_strdup(lb_policy_name);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700224 return &r->base;
225}
226
227/*
228 * FACTORY
229 */
230
Craig Tillereb3b12e2015-06-26 14:42:49 -0700231static void dns_factory_ref(grpc_resolver_factory *factory) {}
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700232
Craig Tillereb3b12e2015-06-26 14:42:49 -0700233static void dns_factory_unref(grpc_resolver_factory *factory) {}
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700234
235static grpc_resolver *dns_factory_create_resolver(
236 grpc_resolver_factory *factory, grpc_uri *uri,
237 grpc_subchannel_factory *subchannel_factory) {
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700238 return dns_create(uri, "https", "pick_first", subchannel_factory);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700239}
240
Craig Tillerbc85be12015-08-24 10:36:39 -0700241char *dns_factory_get_default_host_name(grpc_resolver_factory *factory,
242 grpc_uri *uri) {
243 const char *path = uri->path;
244 if (path[0] == '/') ++path;
245 return gpr_strdup(path);
246}
247
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700248static const grpc_resolver_factory_vtable dns_factory_vtable = {
Craig Tillerbc85be12015-08-24 10:36:39 -0700249 dns_factory_ref, dns_factory_unref, dns_factory_create_resolver,
250 dns_factory_get_default_host_name, "dns"};
Craig Tillereb3b12e2015-06-26 14:42:49 -0700251static grpc_resolver_factory dns_resolver_factory = {&dns_factory_vtable};
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700252
Craig Tillereb3b12e2015-06-26 14:42:49 -0700253grpc_resolver_factory *grpc_dns_resolver_factory_create() {
254 return &dns_resolver_factory;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700255}