blob: 84643c464a971bdd3ee1309c66380ab60dd6a076 [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
Craig Tillereb3b12e2015-06-26 14:42:49 -070042#include "src/core/client_config/lb_policies/pick_first.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;
58 /** load balancing policy factory */
59 grpc_lb_policy *(*lb_policy_factory)(grpc_subchannel **subchannels,
60 size_t num_subchannels);
61
62 /** mutex guarding the rest of the state */
63 gpr_mu mu;
64 /** are we currently resolving? */
65 int resolving;
66 /** which version of resolved_config have we published? */
67 int published_version;
68 /** which version of resolved_config is current? */
69 int resolved_version;
70 /** pending next completion, or NULL */
71 grpc_iomgr_closure *next_completion;
72 /** target config address for next completion */
73 grpc_client_config **target_config;
74 /** current (fully resolved) config */
75 grpc_client_config *resolved_config;
76} dns_resolver;
77
Craig Tiller98465032015-06-29 14:36:42 -070078static void dns_destroy(grpc_resolver *r);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070079
80static void dns_start_resolving_locked(dns_resolver *r);
81static void dns_maybe_finish_next_locked(dns_resolver *r);
82
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070083static void dns_shutdown(grpc_resolver *r);
84static void dns_channel_saw_error(grpc_resolver *r,
85 struct sockaddr *failing_address,
86 int failing_address_len);
87static void dns_next(grpc_resolver *r, grpc_client_config **target_config,
88 grpc_iomgr_closure *on_complete);
89
90static const grpc_resolver_vtable dns_resolver_vtable = {
Craig Tiller98465032015-06-29 14:36:42 -070091 dns_destroy, dns_shutdown, dns_channel_saw_error, dns_next};
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070092
93static void dns_shutdown(grpc_resolver *resolver) {
94 dns_resolver *r = (dns_resolver *)resolver;
95 gpr_mu_lock(&r->mu);
96 if (r->next_completion != NULL) {
97 *r->target_config = NULL;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070098 grpc_iomgr_add_callback(r->next_completion);
99 r->next_completion = NULL;
100 }
101 gpr_mu_unlock(&r->mu);
102}
103
104static void dns_channel_saw_error(grpc_resolver *resolver, struct sockaddr *sa,
105 int len) {
106 dns_resolver *r = (dns_resolver *)resolver;
107 gpr_mu_lock(&r->mu);
108 if (!r->resolving) {
109 dns_start_resolving_locked(r);
110 }
111 gpr_mu_unlock(&r->mu);
112}
113
114static void dns_next(grpc_resolver *resolver,
115 grpc_client_config **target_config,
116 grpc_iomgr_closure *on_complete) {
117 dns_resolver *r = (dns_resolver *)resolver;
118 gpr_mu_lock(&r->mu);
119 GPR_ASSERT(!r->next_completion);
120 r->next_completion = on_complete;
121 r->target_config = target_config;
122 if (r->resolved_version == 0 && !r->resolving) {
123 dns_start_resolving_locked(r);
124 } else {
125 dns_maybe_finish_next_locked(r);
126 }
127 gpr_mu_unlock(&r->mu);
128}
129
130static void dns_on_resolved(void *arg, grpc_resolved_addresses *addresses) {
131 dns_resolver *r = arg;
132 grpc_client_config *config = NULL;
133 grpc_subchannel **subchannels;
134 grpc_subchannel_args args;
Craig Tillerd7b68e72015-06-28 11:41:09 -0700135 grpc_lb_policy *lb_policy;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700136 size_t i;
137 if (addresses) {
138 config = grpc_client_config_create();
139 subchannels = gpr_malloc(sizeof(grpc_subchannel *) * addresses->naddrs);
140 for (i = 0; i < addresses->naddrs; i++) {
141 memset(&args, 0, sizeof(args));
142 args.addr = (struct sockaddr *)(addresses->addrs[i].addr);
143 args.addr_len = addresses->addrs[i].len;
144 subchannels[i] = grpc_subchannel_factory_create_subchannel(
145 r->subchannel_factory, &args);
146 }
Craig Tillerd7b68e72015-06-28 11:41:09 -0700147 lb_policy = r->lb_policy_factory(subchannels, addresses->naddrs);
148 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);
196 gpr_free(r);
197}
198
Craig Tillereb3b12e2015-06-26 14:42:49 -0700199static grpc_resolver *dns_create(
200 grpc_uri *uri, const char *default_port,
201 grpc_lb_policy *(*lb_policy_factory)(grpc_subchannel **subchannels,
202 size_t num_subchannels),
203 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);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700223 r->lb_policy_factory = lb_policy_factory;
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) {
Craig Tillereb3b12e2015-06-26 14:42:49 -0700238 return dns_create(uri, "https", grpc_create_pick_first_lb_policy,
239 subchannel_factory);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700240}
241
Craig Tillerbc85be12015-08-24 10:36:39 -0700242char *dns_factory_get_default_host_name(grpc_resolver_factory *factory,
243 grpc_uri *uri) {
244 const char *path = uri->path;
245 if (path[0] == '/') ++path;
246 return gpr_strdup(path);
247}
248
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700249static const grpc_resolver_factory_vtable dns_factory_vtable = {
Craig Tillerbc85be12015-08-24 10:36:39 -0700250 dns_factory_ref, dns_factory_unref, dns_factory_create_resolver,
251 dns_factory_get_default_host_name, "dns"};
Craig Tillereb3b12e2015-06-26 14:42:49 -0700252static grpc_resolver_factory dns_resolver_factory = {&dns_factory_vtable};
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700253
Craig Tillereb3b12e2015-06-26 14:42:49 -0700254grpc_resolver_factory *grpc_dns_resolver_factory_create() {
255 return &dns_resolver_factory;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700256}