blob: 66430c43cbdd9bd8a21067ad5e2132e5f522a798 [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
Craig Tiller45724b32015-09-22 10:42:19 -070047typedef struct
48{
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070049 /** base class: must be first */
50 grpc_resolver base;
51 /** refcount */
52 gpr_refcount refs;
53 /** name to resolve */
54 char *name;
55 /** default port to use */
56 char *default_port;
57 /** subchannel factory */
58 grpc_subchannel_factory *subchannel_factory;
David Garcia Quintas5c4543d2015-09-03 15:49:56 -070059 /** load balancing policy name */
60 char *lb_policy_name;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070061
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 */
Craig Tiller33825112015-09-18 07:44:19 -070071 grpc_closure *next_completion;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070072 /** 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 Tiller1be70cc2015-09-22 10:45:28 -070078static void dns_destroy (grpc_exec_ctx * exec_ctx, grpc_resolver * r);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070079
Craig Tiller45724b32015-09-22 10:42:19 -070080static void dns_start_resolving_locked (dns_resolver * r);
Craig Tiller1be70cc2015-09-22 10:45:28 -070081static void dns_maybe_finish_next_locked (grpc_exec_ctx * exec_ctx, dns_resolver * r);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070082
Craig Tiller1be70cc2015-09-22 10:45:28 -070083static void dns_shutdown (grpc_exec_ctx * exec_ctx, grpc_resolver * r);
84static void dns_channel_saw_error (grpc_exec_ctx * exec_ctx, grpc_resolver * r, struct sockaddr *failing_address, int failing_address_len);
85static void dns_next (grpc_exec_ctx * exec_ctx, grpc_resolver * r, grpc_client_config ** target_config, grpc_closure * on_complete);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070086
87static const grpc_resolver_vtable dns_resolver_vtable = {
Craig Tiller45724b32015-09-22 10:42:19 -070088 dns_destroy, dns_shutdown, dns_channel_saw_error, dns_next
89};
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070090
Craig Tiller45724b32015-09-22 10:42:19 -070091static void
Craig Tiller1be70cc2015-09-22 10:45:28 -070092dns_shutdown (grpc_exec_ctx * exec_ctx, grpc_resolver * resolver)
Craig Tiller45724b32015-09-22 10:42:19 -070093{
94 dns_resolver *r = (dns_resolver *) resolver;
95 gpr_mu_lock (&r->mu);
96 if (r->next_completion != NULL)
97 {
98 *r->target_config = NULL;
99 grpc_closure_list_add (closure_list, r->next_completion, 1);
100 r->next_completion = NULL;
101 }
102 gpr_mu_unlock (&r->mu);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700103}
104
Craig Tiller45724b32015-09-22 10:42:19 -0700105static void
Craig Tiller1be70cc2015-09-22 10:45:28 -0700106dns_channel_saw_error (grpc_exec_ctx * exec_ctx, grpc_resolver * resolver, struct sockaddr *sa, int len)
Craig Tiller45724b32015-09-22 10:42:19 -0700107{
108 dns_resolver *r = (dns_resolver *) resolver;
109 gpr_mu_lock (&r->mu);
110 if (!r->resolving)
111 {
112 dns_start_resolving_locked (r);
113 }
114 gpr_mu_unlock (&r->mu);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700115}
116
Craig Tiller45724b32015-09-22 10:42:19 -0700117static void
Craig Tiller1be70cc2015-09-22 10:45:28 -0700118dns_next (grpc_exec_ctx * exec_ctx, grpc_resolver * resolver, grpc_client_config ** target_config, grpc_closure * on_complete)
Craig Tiller45724b32015-09-22 10:42:19 -0700119{
120 dns_resolver *r = (dns_resolver *) resolver;
121 gpr_mu_lock (&r->mu);
122 GPR_ASSERT (!r->next_completion);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700123 r->next_completion = on_complete;
124 r->target_config = target_config;
Craig Tiller45724b32015-09-22 10:42:19 -0700125 if (r->resolved_version == 0 && !r->resolving)
126 {
127 dns_start_resolving_locked (r);
128 }
129 else
130 {
131 dns_maybe_finish_next_locked (r, closure_list);
132 }
133 gpr_mu_unlock (&r->mu);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700134}
135
Craig Tiller45724b32015-09-22 10:42:19 -0700136static void
Craig Tiller1be70cc2015-09-22 10:45:28 -0700137dns_on_resolved (grpc_exec_ctx * exec_ctx, void *arg, grpc_resolved_addresses * addresses)
Craig Tiller45724b32015-09-22 10:42:19 -0700138{
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700139 dns_resolver *r = arg;
140 grpc_client_config *config = NULL;
141 grpc_subchannel **subchannels;
142 grpc_subchannel_args args;
Craig Tillerd7b68e72015-06-28 11:41:09 -0700143 grpc_lb_policy *lb_policy;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700144 size_t i;
Craig Tiller45724b32015-09-22 10:42:19 -0700145 if (addresses)
146 {
147 grpc_lb_policy_args lb_policy_args;
148 config = grpc_client_config_create ();
149 subchannels = gpr_malloc (sizeof (grpc_subchannel *) * addresses->naddrs);
150 for (i = 0; i < addresses->naddrs; i++)
151 {
152 memset (&args, 0, sizeof (args));
153 args.addr = (struct sockaddr *) (addresses->addrs[i].addr);
154 args.addr_len = (size_t) addresses->addrs[i].len;
155 subchannels[i] = grpc_subchannel_factory_create_subchannel (r->subchannel_factory, &args, closure_list);
156 }
157 memset (&lb_policy_args, 0, sizeof (lb_policy_args));
158 lb_policy_args.subchannels = subchannels;
159 lb_policy_args.num_subchannels = addresses->naddrs;
160 lb_policy = grpc_lb_policy_create (r->lb_policy_name, &lb_policy_args);
161 grpc_client_config_set_lb_policy (config, lb_policy);
162 GRPC_LB_POLICY_UNREF (lb_policy, "construction", closure_list);
163 grpc_resolved_addresses_destroy (addresses);
164 gpr_free (subchannels);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700165 }
Craig Tiller45724b32015-09-22 10:42:19 -0700166 gpr_mu_lock (&r->mu);
167 GPR_ASSERT (r->resolving);
Craig Tiller98465032015-06-29 14:36:42 -0700168 r->resolving = 0;
Craig Tiller45724b32015-09-22 10:42:19 -0700169 if (r->resolved_config)
170 {
171 grpc_client_config_unref (r->resolved_config, closure_list);
172 }
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700173 r->resolved_config = config;
174 r->resolved_version++;
Craig Tiller45724b32015-09-22 10:42:19 -0700175 dns_maybe_finish_next_locked (r, closure_list);
176 gpr_mu_unlock (&r->mu);
Craig Tillerd7b68e72015-06-28 11:41:09 -0700177
Craig Tiller45724b32015-09-22 10:42:19 -0700178 GRPC_RESOLVER_UNREF (&r->base, "dns-resolving", closure_list);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700179}
180
Craig Tiller45724b32015-09-22 10:42:19 -0700181static void
182dns_start_resolving_locked (dns_resolver * r)
183{
184 GRPC_RESOLVER_REF (&r->base, "dns-resolving");
185 GPR_ASSERT (!r->resolving);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700186 r->resolving = 1;
Craig Tiller45724b32015-09-22 10:42:19 -0700187 grpc_resolve_address (r->name, r->default_port, dns_on_resolved, r);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700188}
189
Craig Tiller45724b32015-09-22 10:42:19 -0700190static void
Craig Tiller1be70cc2015-09-22 10:45:28 -0700191dns_maybe_finish_next_locked (grpc_exec_ctx * exec_ctx, dns_resolver * r)
Craig Tiller45724b32015-09-22 10:42:19 -0700192{
193 if (r->next_completion != NULL && r->resolved_version != r->published_version)
194 {
195 *r->target_config = r->resolved_config;
196 if (r->resolved_config)
197 {
198 grpc_client_config_ref (r->resolved_config);
199 }
200 grpc_closure_list_add (closure_list, r->next_completion, 1);
201 r->next_completion = NULL;
202 r->published_version = r->resolved_version;
Craig Tillerabf36382015-06-29 16:13:27 -0700203 }
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700204}
205
Craig Tiller45724b32015-09-22 10:42:19 -0700206static void
Craig Tiller1be70cc2015-09-22 10:45:28 -0700207dns_destroy (grpc_exec_ctx * exec_ctx, grpc_resolver * gr)
Craig Tiller45724b32015-09-22 10:42:19 -0700208{
209 dns_resolver *r = (dns_resolver *) gr;
210 gpr_mu_destroy (&r->mu);
211 if (r->resolved_config)
212 {
213 grpc_client_config_unref (r->resolved_config, closure_list);
214 }
215 grpc_subchannel_factory_unref (r->subchannel_factory, closure_list);
216 gpr_free (r->name);
217 gpr_free (r->default_port);
218 gpr_free (r->lb_policy_name);
219 gpr_free (r);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700220}
221
Craig Tiller45724b32015-09-22 10:42:19 -0700222static grpc_resolver *
223dns_create (grpc_resolver_args * args, const char *default_port, const char *lb_policy_name)
224{
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700225 dns_resolver *r;
Craig Tiller06a43f52015-09-15 07:41:28 -0700226 const char *path = args->uri->path;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700227
Craig Tiller45724b32015-09-22 10:42:19 -0700228 if (0 != strcmp (args->uri->authority, ""))
229 {
230 gpr_log (GPR_ERROR, "authority based dns uri's not supported");
231 return NULL;
232 }
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700233
Craig Tiller45724b32015-09-22 10:42:19 -0700234 if (path[0] == '/')
235 ++path;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700236
Craig Tiller45724b32015-09-22 10:42:19 -0700237 r = gpr_malloc (sizeof (dns_resolver));
238 memset (r, 0, sizeof (*r));
239 gpr_ref_init (&r->refs, 1);
240 gpr_mu_init (&r->mu);
241 grpc_resolver_init (&r->base, &dns_resolver_vtable);
242 r->name = gpr_strdup (path);
243 r->default_port = gpr_strdup (default_port);
Craig Tiller06a43f52015-09-15 07:41:28 -0700244 r->subchannel_factory = args->subchannel_factory;
Craig Tiller45724b32015-09-22 10:42:19 -0700245 grpc_subchannel_factory_ref (r->subchannel_factory);
246 r->lb_policy_name = gpr_strdup (lb_policy_name);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700247 return &r->base;
248}
249
250/*
251 * FACTORY
252 */
253
Craig Tiller45724b32015-09-22 10:42:19 -0700254static void
255dns_factory_ref (grpc_resolver_factory * factory)
256{
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700257}
258
Craig Tiller45724b32015-09-22 10:42:19 -0700259static void
260dns_factory_unref (grpc_resolver_factory * factory)
261{
262}
263
264static grpc_resolver *
265dns_factory_create_resolver (grpc_resolver_factory * factory, grpc_resolver_args * args)
266{
267 return dns_create (args, "https", "pick_first");
268}
269
270char *
271dns_factory_get_default_host_name (grpc_resolver_factory * factory, grpc_uri * uri)
272{
Craig Tillerbc85be12015-08-24 10:36:39 -0700273 const char *path = uri->path;
Craig Tiller45724b32015-09-22 10:42:19 -0700274 if (path[0] == '/')
275 ++path;
276 return gpr_strdup (path);
Craig Tillerbc85be12015-08-24 10:36:39 -0700277}
278
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700279static const grpc_resolver_factory_vtable dns_factory_vtable = {
Craig Tiller45724b32015-09-22 10:42:19 -0700280 dns_factory_ref, dns_factory_unref, dns_factory_create_resolver,
281 dns_factory_get_default_host_name, "dns"
282};
283static grpc_resolver_factory dns_resolver_factory = { &dns_factory_vtable };
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700284
Craig Tiller45724b32015-09-22 10:42:19 -0700285grpc_resolver_factory *
286grpc_dns_resolver_factory_create ()
287{
Craig Tillereb3b12e2015-06-26 14:42:49 -0700288 return &dns_resolver_factory;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700289}