blob: 1a0bf305d656d59c1c75e955f357192d4149787f [file] [log] [blame]
Craig Tillercd29c582015-06-24 09:15:15 -07001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
Craig Tillercd29c582015-06-24 09:15:15 -07004 * 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
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070034#include <string.h>
35
36#include <grpc/support/alloc.h>
Craig Tiller6b9f5c62015-07-29 18:47:35 -070037#include <grpc/support/host_port.h>
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070038#include <grpc/support/string_util.h>
39
Craig Tiller9533d042016-03-25 17:11:06 -070040#include "src/core/lib/client_config/lb_policy_registry.h"
Craig Tiller65938df2016-03-31 13:08:49 -070041#include "src/core/lib/client_config/resolver_registry.h"
Craig Tiller9533d042016-03-25 17:11:06 -070042#include "src/core/lib/iomgr/resolve_address.h"
43#include "src/core/lib/iomgr/timer.h"
44#include "src/core/lib/support/backoff.h"
45#include "src/core/lib/support/string.h"
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070046
Craig Tiller476bb3b2016-03-11 12:54:40 -080047#define BACKOFF_MULTIPLIER 1.6
48#define BACKOFF_JITTER 0.2
49#define BACKOFF_MIN_SECONDS 1
50#define BACKOFF_MAX_SECONDS 120
51
Craig Tillera82950e2015-09-22 12:33:20 -070052typedef struct {
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070053 /** base class: must be first */
54 grpc_resolver base;
55 /** refcount */
56 gpr_refcount refs;
57 /** name to resolve */
58 char *name;
59 /** default port to use */
60 char *default_port;
61 /** subchannel factory */
David Garcia Quintasfcf7ad62016-03-29 21:55:34 -070062 grpc_client_channel_factory *client_channel_factory;
David Garcia Quintas5c4543d2015-09-03 15:49:56 -070063 /** load balancing policy name */
64 char *lb_policy_name;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070065
66 /** mutex guarding the rest of the state */
67 gpr_mu mu;
68 /** are we currently resolving? */
69 int resolving;
70 /** which version of resolved_config have we published? */
71 int published_version;
72 /** which version of resolved_config is current? */
73 int resolved_version;
74 /** pending next completion, or NULL */
Craig Tiller33825112015-09-18 07:44:19 -070075 grpc_closure *next_completion;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070076 /** target config address for next completion */
77 grpc_client_config **target_config;
78 /** current (fully resolved) config */
79 grpc_client_config *resolved_config;
Craig Tiller1e55bd42016-03-11 09:47:43 -080080 /** retry timer */
81 bool have_retry_timer;
82 grpc_timer retry_timer;
Craig Tiller476bb3b2016-03-11 12:54:40 -080083 /** retry backoff state */
84 gpr_backoff backoff_state;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070085} dns_resolver;
86
Craig Tillera82950e2015-09-22 12:33:20 -070087static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070088
Craig Tillera82950e2015-09-22 12:33:20 -070089static void dns_start_resolving_locked(dns_resolver *r);
90static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
91 dns_resolver *r);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070092
Craig Tillera82950e2015-09-22 12:33:20 -070093static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
Craig Tillercb2609f2015-11-24 17:19:19 -080094static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
Craig Tillera82950e2015-09-22 12:33:20 -070095static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
96 grpc_client_config **target_config,
97 grpc_closure *on_complete);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070098
99static const grpc_resolver_vtable dns_resolver_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700100 dns_destroy, dns_shutdown, dns_channel_saw_error, dns_next};
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700101
Craig Tillera82950e2015-09-22 12:33:20 -0700102static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
103 dns_resolver *r = (dns_resolver *)resolver;
104 gpr_mu_lock(&r->mu);
Craig Tillere2327db2016-03-11 09:52:42 -0800105 if (r->have_retry_timer) {
106 grpc_timer_cancel(exec_ctx, &r->retry_timer);
107 }
Craig Tillera82950e2015-09-22 12:33:20 -0700108 if (r->next_completion != NULL) {
109 *r->target_config = NULL;
Craig Tiller6c396862016-01-28 13:53:40 -0800110 grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700111 r->next_completion = NULL;
112 }
113 gpr_mu_unlock(&r->mu);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700114}
115
Craig Tillera82950e2015-09-22 12:33:20 -0700116static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx,
Craig Tillercb2609f2015-11-24 17:19:19 -0800117 grpc_resolver *resolver) {
Craig Tillera82950e2015-09-22 12:33:20 -0700118 dns_resolver *r = (dns_resolver *)resolver;
119 gpr_mu_lock(&r->mu);
120 if (!r->resolving) {
Craig Tiller476bb3b2016-03-11 12:54:40 -0800121 gpr_backoff_reset(&r->backoff_state);
Craig Tillera82950e2015-09-22 12:33:20 -0700122 dns_start_resolving_locked(r);
123 }
124 gpr_mu_unlock(&r->mu);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700125}
126
Craig Tillera82950e2015-09-22 12:33:20 -0700127static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
128 grpc_client_config **target_config,
129 grpc_closure *on_complete) {
130 dns_resolver *r = (dns_resolver *)resolver;
131 gpr_mu_lock(&r->mu);
132 GPR_ASSERT(!r->next_completion);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700133 r->next_completion = on_complete;
134 r->target_config = target_config;
Craig Tillera82950e2015-09-22 12:33:20 -0700135 if (r->resolved_version == 0 && !r->resolving) {
Craig Tiller476bb3b2016-03-11 12:54:40 -0800136 gpr_backoff_reset(&r->backoff_state);
Craig Tillera82950e2015-09-22 12:33:20 -0700137 dns_start_resolving_locked(r);
138 } else {
139 dns_maybe_finish_next_locked(exec_ctx, r);
140 }
141 gpr_mu_unlock(&r->mu);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700142}
143
Craig Tiller1e55bd42016-03-11 09:47:43 -0800144static void dns_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
145 bool success) {
146 dns_resolver *r = arg;
147
Craig Tillere2327db2016-03-11 09:52:42 -0800148 gpr_mu_lock(&r->mu);
149 r->have_retry_timer = false;
Craig Tiller1e55bd42016-03-11 09:47:43 -0800150 if (success) {
Craig Tiller1e55bd42016-03-11 09:47:43 -0800151 if (!r->resolving) {
152 dns_start_resolving_locked(r);
153 }
Craig Tiller1e55bd42016-03-11 09:47:43 -0800154 }
Craig Tillere2327db2016-03-11 09:52:42 -0800155 gpr_mu_unlock(&r->mu);
Craig Tiller1e55bd42016-03-11 09:47:43 -0800156
157 GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "retry-timer");
158}
159
Craig Tillera82950e2015-09-22 12:33:20 -0700160static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
161 grpc_resolved_addresses *addresses) {
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700162 dns_resolver *r = arg;
163 grpc_client_config *config = NULL;
Craig Tillerd7b68e72015-06-28 11:41:09 -0700164 grpc_lb_policy *lb_policy;
Craig Tiller1e55bd42016-03-11 09:47:43 -0800165 gpr_mu_lock(&r->mu);
166 GPR_ASSERT(r->resolving);
167 r->resolving = 0;
168 if (addresses != NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -0700169 grpc_lb_policy_args lb_policy_args;
170 config = grpc_client_config_create();
Craig Tillera82950e2015-09-22 12:33:20 -0700171 memset(&lb_policy_args, 0, sizeof(lb_policy_args));
David Garcia Quintas67c0d042016-03-25 01:37:53 -0700172 lb_policy_args.addresses = addresses;
David Garcia Quintas86fcfcc2016-03-31 23:22:28 -0700173 lb_policy_args.client_channel_factory = r->client_channel_factory;
David Garcia Quintas67c0d042016-03-25 01:37:53 -0700174 lb_policy =
175 grpc_lb_policy_create(exec_ctx, r->lb_policy_name, &lb_policy_args);
Craig Tiller1e55bd42016-03-11 09:47:43 -0800176 if (lb_policy != NULL) {
177 grpc_client_config_set_lb_policy(config, lb_policy);
178 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
179 }
Craig Tillera82950e2015-09-22 12:33:20 -0700180 grpc_resolved_addresses_destroy(addresses);
Craig Tiller1e55bd42016-03-11 09:47:43 -0800181 } else {
Craig Tiller476bb3b2016-03-11 12:54:40 -0800182 gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
183 gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now);
184 gpr_timespec timeout = gpr_time_sub(next_try, now);
185 gpr_log(GPR_DEBUG, "dns resolution failed: retrying in %d.%09d seconds",
186 timeout.tv_sec, timeout.tv_nsec);
Craig Tiller1e55bd42016-03-11 09:47:43 -0800187 GPR_ASSERT(!r->have_retry_timer);
188 r->have_retry_timer = true;
Craig Tiller1e55bd42016-03-11 09:47:43 -0800189 GRPC_RESOLVER_REF(&r->base, "retry-timer");
Craig Tiller476bb3b2016-03-11 12:54:40 -0800190 grpc_timer_init(exec_ctx, &r->retry_timer, next_try, dns_on_retry_timer, r,
191 now);
Craig Tillera82950e2015-09-22 12:33:20 -0700192 }
Craig Tillera82950e2015-09-22 12:33:20 -0700193 if (r->resolved_config) {
194 grpc_client_config_unref(exec_ctx, r->resolved_config);
195 }
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700196 r->resolved_config = config;
197 r->resolved_version++;
Craig Tillera82950e2015-09-22 12:33:20 -0700198 dns_maybe_finish_next_locked(exec_ctx, r);
199 gpr_mu_unlock(&r->mu);
Craig Tillerd7b68e72015-06-28 11:41:09 -0700200
Craig Tillera82950e2015-09-22 12:33:20 -0700201 GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving");
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700202}
203
Craig Tillera82950e2015-09-22 12:33:20 -0700204static void dns_start_resolving_locked(dns_resolver *r) {
205 GRPC_RESOLVER_REF(&r->base, "dns-resolving");
206 GPR_ASSERT(!r->resolving);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700207 r->resolving = 1;
Craig Tillera82950e2015-09-22 12:33:20 -0700208 grpc_resolve_address(r->name, r->default_port, dns_on_resolved, r);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700209}
210
Craig Tillera82950e2015-09-22 12:33:20 -0700211static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
212 dns_resolver *r) {
213 if (r->next_completion != NULL &&
214 r->resolved_version != r->published_version) {
215 *r->target_config = r->resolved_config;
216 if (r->resolved_config) {
217 grpc_client_config_ref(r->resolved_config);
Craig Tillerabf36382015-06-29 16:13:27 -0700218 }
Craig Tiller6c396862016-01-28 13:53:40 -0800219 grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700220 r->next_completion = NULL;
221 r->published_version = r->resolved_version;
222 }
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700223}
224
Craig Tillera82950e2015-09-22 12:33:20 -0700225static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
226 dns_resolver *r = (dns_resolver *)gr;
227 gpr_mu_destroy(&r->mu);
228 if (r->resolved_config) {
229 grpc_client_config_unref(exec_ctx, r->resolved_config);
230 }
David Garcia Quintasfcf7ad62016-03-29 21:55:34 -0700231 grpc_client_channel_factory_unref(exec_ctx, r->client_channel_factory);
Craig Tillera82950e2015-09-22 12:33:20 -0700232 gpr_free(r->name);
233 gpr_free(r->default_port);
234 gpr_free(r->lb_policy_name);
235 gpr_free(r);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700236}
237
Craig Tillera82950e2015-09-22 12:33:20 -0700238static grpc_resolver *dns_create(grpc_resolver_args *args,
239 const char *default_port,
240 const char *lb_policy_name) {
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700241 dns_resolver *r;
Craig Tiller06a43f52015-09-15 07:41:28 -0700242 const char *path = args->uri->path;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700243
Craig Tillera82950e2015-09-22 12:33:20 -0700244 if (0 != strcmp(args->uri->authority, "")) {
245 gpr_log(GPR_ERROR, "authority based dns uri's not supported");
246 return NULL;
247 }
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700248
Craig Tillera82950e2015-09-22 12:33:20 -0700249 if (path[0] == '/') ++path;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700250
Craig Tillera82950e2015-09-22 12:33:20 -0700251 r = gpr_malloc(sizeof(dns_resolver));
252 memset(r, 0, sizeof(*r));
253 gpr_ref_init(&r->refs, 1);
254 gpr_mu_init(&r->mu);
255 grpc_resolver_init(&r->base, &dns_resolver_vtable);
256 r->name = gpr_strdup(path);
257 r->default_port = gpr_strdup(default_port);
David Garcia Quintasfcf7ad62016-03-29 21:55:34 -0700258 r->client_channel_factory = args->client_channel_factory;
Craig Tiller476bb3b2016-03-11 12:54:40 -0800259 gpr_backoff_init(&r->backoff_state, BACKOFF_MULTIPLIER, BACKOFF_JITTER,
260 BACKOFF_MIN_SECONDS * 1000, BACKOFF_MAX_SECONDS * 1000);
David Garcia Quintasfcf7ad62016-03-29 21:55:34 -0700261 grpc_client_channel_factory_ref(r->client_channel_factory);
Craig Tillera82950e2015-09-22 12:33:20 -0700262 r->lb_policy_name = gpr_strdup(lb_policy_name);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700263 return &r->base;
264}
265
266/*
267 * FACTORY
268 */
269
Craig Tillera82950e2015-09-22 12:33:20 -0700270static void dns_factory_ref(grpc_resolver_factory *factory) {}
271
272static void dns_factory_unref(grpc_resolver_factory *factory) {}
273
274static grpc_resolver *dns_factory_create_resolver(
275 grpc_resolver_factory *factory, grpc_resolver_args *args) {
276 return dns_create(args, "https", "pick_first");
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700277}
278
Craig Tiller65938df2016-03-31 13:08:49 -0700279static char *dns_factory_get_default_host_name(grpc_resolver_factory *factory,
280 grpc_uri *uri) {
Craig Tillerbc85be12015-08-24 10:36:39 -0700281 const char *path = uri->path;
Craig Tillera82950e2015-09-22 12:33:20 -0700282 if (path[0] == '/') ++path;
283 return gpr_strdup(path);
Craig Tillerbc85be12015-08-24 10:36:39 -0700284}
285
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700286static const grpc_resolver_factory_vtable dns_factory_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700287 dns_factory_ref, dns_factory_unref, dns_factory_create_resolver,
288 dns_factory_get_default_host_name, "dns"};
289static grpc_resolver_factory dns_resolver_factory = {&dns_factory_vtable};
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700290
Craig Tiller65938df2016-03-31 13:08:49 -0700291static grpc_resolver_factory *dns_resolver_factory_create() {
Craig Tillereb3b12e2015-06-26 14:42:49 -0700292 return &dns_resolver_factory;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700293}
Craig Tiller65938df2016-03-31 13:08:49 -0700294
295void grpc_resolver_dns_native_init(void) {
296 grpc_register_resolver_type(dns_resolver_factory_create());
297}
298
299void grpc_resolver_dns_native_shutdown(void) {}