blob: 620ba4e2aa076fdaa1da7741300892ac6f7588fc [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 Tillerd4c98332016-03-31 13:45:47 -070040#include "src/core/ext/client_config/lb_policy_registry.h"
41#include "src/core/ext/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 Tiller24d687e2016-04-13 19:47:27 -070089static void dns_start_resolving_locked(grpc_exec_ctx *exec_ctx,
90 dns_resolver *r);
Craig Tillera82950e2015-09-22 12:33:20 -070091static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
92 dns_resolver *r);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070093
Craig Tillera82950e2015-09-22 12:33:20 -070094static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
Craig Tillercb2609f2015-11-24 17:19:19 -080095static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
Craig Tillera82950e2015-09-22 12:33:20 -070096static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
97 grpc_client_config **target_config,
98 grpc_closure *on_complete);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070099
100static const grpc_resolver_vtable dns_resolver_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700101 dns_destroy, dns_shutdown, dns_channel_saw_error, dns_next};
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700102
Craig Tillera82950e2015-09-22 12:33:20 -0700103static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
104 dns_resolver *r = (dns_resolver *)resolver;
105 gpr_mu_lock(&r->mu);
Craig Tillere2327db2016-03-11 09:52:42 -0800106 if (r->have_retry_timer) {
107 grpc_timer_cancel(exec_ctx, &r->retry_timer);
108 }
Craig Tillera82950e2015-09-22 12:33:20 -0700109 if (r->next_completion != NULL) {
110 *r->target_config = NULL;
Craig Tiller6c396862016-01-28 13:53:40 -0800111 grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700112 r->next_completion = NULL;
113 }
114 gpr_mu_unlock(&r->mu);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700115}
116
Craig Tillera82950e2015-09-22 12:33:20 -0700117static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx,
Craig Tillercb2609f2015-11-24 17:19:19 -0800118 grpc_resolver *resolver) {
Craig Tillera82950e2015-09-22 12:33:20 -0700119 dns_resolver *r = (dns_resolver *)resolver;
120 gpr_mu_lock(&r->mu);
121 if (!r->resolving) {
Craig Tiller476bb3b2016-03-11 12:54:40 -0800122 gpr_backoff_reset(&r->backoff_state);
Craig Tiller24d687e2016-04-13 19:47:27 -0700123 dns_start_resolving_locked(exec_ctx, r);
Craig Tillera82950e2015-09-22 12:33:20 -0700124 }
125 gpr_mu_unlock(&r->mu);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700126}
127
Craig Tillera82950e2015-09-22 12:33:20 -0700128static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
129 grpc_client_config **target_config,
130 grpc_closure *on_complete) {
131 dns_resolver *r = (dns_resolver *)resolver;
132 gpr_mu_lock(&r->mu);
133 GPR_ASSERT(!r->next_completion);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700134 r->next_completion = on_complete;
135 r->target_config = target_config;
Craig Tillera82950e2015-09-22 12:33:20 -0700136 if (r->resolved_version == 0 && !r->resolving) {
Craig Tiller476bb3b2016-03-11 12:54:40 -0800137 gpr_backoff_reset(&r->backoff_state);
Craig Tiller24d687e2016-04-13 19:47:27 -0700138 dns_start_resolving_locked(exec_ctx, r);
Craig Tillera82950e2015-09-22 12:33:20 -0700139 } else {
140 dns_maybe_finish_next_locked(exec_ctx, r);
141 }
142 gpr_mu_unlock(&r->mu);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700143}
144
Craig Tiller1e55bd42016-03-11 09:47:43 -0800145static void dns_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
146 bool success) {
147 dns_resolver *r = arg;
148
Craig Tillere2327db2016-03-11 09:52:42 -0800149 gpr_mu_lock(&r->mu);
150 r->have_retry_timer = false;
Craig Tiller1e55bd42016-03-11 09:47:43 -0800151 if (success) {
Craig Tiller1e55bd42016-03-11 09:47:43 -0800152 if (!r->resolving) {
Craig Tiller24d687e2016-04-13 19:47:27 -0700153 dns_start_resolving_locked(exec_ctx, r);
Craig Tiller1e55bd42016-03-11 09:47:43 -0800154 }
Craig Tiller1e55bd42016-03-11 09:47:43 -0800155 }
Craig Tillere2327db2016-03-11 09:52:42 -0800156 gpr_mu_unlock(&r->mu);
Craig Tiller1e55bd42016-03-11 09:47:43 -0800157
158 GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "retry-timer");
159}
160
Craig Tillera82950e2015-09-22 12:33:20 -0700161static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
162 grpc_resolved_addresses *addresses) {
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700163 dns_resolver *r = arg;
164 grpc_client_config *config = NULL;
Craig Tillerd7b68e72015-06-28 11:41:09 -0700165 grpc_lb_policy *lb_policy;
Craig Tiller1e55bd42016-03-11 09:47:43 -0800166 gpr_mu_lock(&r->mu);
167 GPR_ASSERT(r->resolving);
168 r->resolving = 0;
169 if (addresses != NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -0700170 grpc_lb_policy_args lb_policy_args;
171 config = grpc_client_config_create();
Craig Tillera82950e2015-09-22 12:33:20 -0700172 memset(&lb_policy_args, 0, sizeof(lb_policy_args));
David Garcia Quintas67c0d042016-03-25 01:37:53 -0700173 lb_policy_args.addresses = addresses;
David Garcia Quintas86fcfcc2016-03-31 23:22:28 -0700174 lb_policy_args.client_channel_factory = r->client_channel_factory;
David Garcia Quintas67c0d042016-03-25 01:37:53 -0700175 lb_policy =
176 grpc_lb_policy_create(exec_ctx, r->lb_policy_name, &lb_policy_args);
Craig Tiller1e55bd42016-03-11 09:47:43 -0800177 if (lb_policy != NULL) {
178 grpc_client_config_set_lb_policy(config, lb_policy);
179 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
180 }
Craig Tillera82950e2015-09-22 12:33:20 -0700181 grpc_resolved_addresses_destroy(addresses);
Craig Tiller1e55bd42016-03-11 09:47:43 -0800182 } else {
Craig Tiller476bb3b2016-03-11 12:54:40 -0800183 gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
184 gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now);
185 gpr_timespec timeout = gpr_time_sub(next_try, now);
186 gpr_log(GPR_DEBUG, "dns resolution failed: retrying in %d.%09d seconds",
187 timeout.tv_sec, timeout.tv_nsec);
Craig Tiller1e55bd42016-03-11 09:47:43 -0800188 GPR_ASSERT(!r->have_retry_timer);
189 r->have_retry_timer = true;
Craig Tiller1e55bd42016-03-11 09:47:43 -0800190 GRPC_RESOLVER_REF(&r->base, "retry-timer");
Craig Tiller476bb3b2016-03-11 12:54:40 -0800191 grpc_timer_init(exec_ctx, &r->retry_timer, next_try, dns_on_retry_timer, r,
192 now);
Craig Tillera82950e2015-09-22 12:33:20 -0700193 }
Craig Tillera82950e2015-09-22 12:33:20 -0700194 if (r->resolved_config) {
195 grpc_client_config_unref(exec_ctx, r->resolved_config);
196 }
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700197 r->resolved_config = config;
198 r->resolved_version++;
Craig Tillera82950e2015-09-22 12:33:20 -0700199 dns_maybe_finish_next_locked(exec_ctx, r);
200 gpr_mu_unlock(&r->mu);
Craig Tillerd7b68e72015-06-28 11:41:09 -0700201
Craig Tillera82950e2015-09-22 12:33:20 -0700202 GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving");
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700203}
204
Craig Tiller24d687e2016-04-13 19:47:27 -0700205static void dns_start_resolving_locked(grpc_exec_ctx *exec_ctx,
206 dns_resolver *r) {
Craig Tillera82950e2015-09-22 12:33:20 -0700207 GRPC_RESOLVER_REF(&r->base, "dns-resolving");
208 GPR_ASSERT(!r->resolving);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700209 r->resolving = 1;
Craig Tiller24d687e2016-04-13 19:47:27 -0700210 grpc_resolve_address(exec_ctx, r->name, r->default_port, dns_on_resolved, r);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700211}
212
Craig Tillera82950e2015-09-22 12:33:20 -0700213static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
214 dns_resolver *r) {
215 if (r->next_completion != NULL &&
216 r->resolved_version != r->published_version) {
217 *r->target_config = r->resolved_config;
218 if (r->resolved_config) {
219 grpc_client_config_ref(r->resolved_config);
Craig Tillerabf36382015-06-29 16:13:27 -0700220 }
Craig Tiller6c396862016-01-28 13:53:40 -0800221 grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700222 r->next_completion = NULL;
223 r->published_version = r->resolved_version;
224 }
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700225}
226
Craig Tillera82950e2015-09-22 12:33:20 -0700227static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
228 dns_resolver *r = (dns_resolver *)gr;
229 gpr_mu_destroy(&r->mu);
230 if (r->resolved_config) {
231 grpc_client_config_unref(exec_ctx, r->resolved_config);
232 }
David Garcia Quintasfcf7ad62016-03-29 21:55:34 -0700233 grpc_client_channel_factory_unref(exec_ctx, r->client_channel_factory);
Craig Tillera82950e2015-09-22 12:33:20 -0700234 gpr_free(r->name);
235 gpr_free(r->default_port);
236 gpr_free(r->lb_policy_name);
237 gpr_free(r);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700238}
239
Craig Tillera82950e2015-09-22 12:33:20 -0700240static grpc_resolver *dns_create(grpc_resolver_args *args,
241 const char *default_port,
242 const char *lb_policy_name) {
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700243 dns_resolver *r;
Craig Tiller06a43f52015-09-15 07:41:28 -0700244 const char *path = args->uri->path;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700245
Craig Tillera82950e2015-09-22 12:33:20 -0700246 if (0 != strcmp(args->uri->authority, "")) {
247 gpr_log(GPR_ERROR, "authority based dns uri's not supported");
248 return NULL;
249 }
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700250
Craig Tillera82950e2015-09-22 12:33:20 -0700251 if (path[0] == '/') ++path;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700252
Craig Tillera82950e2015-09-22 12:33:20 -0700253 r = gpr_malloc(sizeof(dns_resolver));
254 memset(r, 0, sizeof(*r));
255 gpr_ref_init(&r->refs, 1);
256 gpr_mu_init(&r->mu);
257 grpc_resolver_init(&r->base, &dns_resolver_vtable);
258 r->name = gpr_strdup(path);
259 r->default_port = gpr_strdup(default_port);
David Garcia Quintasfcf7ad62016-03-29 21:55:34 -0700260 r->client_channel_factory = args->client_channel_factory;
Craig Tiller476bb3b2016-03-11 12:54:40 -0800261 gpr_backoff_init(&r->backoff_state, BACKOFF_MULTIPLIER, BACKOFF_JITTER,
262 BACKOFF_MIN_SECONDS * 1000, BACKOFF_MAX_SECONDS * 1000);
David Garcia Quintasfcf7ad62016-03-29 21:55:34 -0700263 grpc_client_channel_factory_ref(r->client_channel_factory);
Craig Tillera82950e2015-09-22 12:33:20 -0700264 r->lb_policy_name = gpr_strdup(lb_policy_name);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700265 return &r->base;
266}
267
268/*
269 * FACTORY
270 */
271
Craig Tillera82950e2015-09-22 12:33:20 -0700272static void dns_factory_ref(grpc_resolver_factory *factory) {}
273
274static void dns_factory_unref(grpc_resolver_factory *factory) {}
275
276static grpc_resolver *dns_factory_create_resolver(
277 grpc_resolver_factory *factory, grpc_resolver_args *args) {
278 return dns_create(args, "https", "pick_first");
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700279}
280
Craig Tiller65938df2016-03-31 13:08:49 -0700281static char *dns_factory_get_default_host_name(grpc_resolver_factory *factory,
282 grpc_uri *uri) {
Craig Tillerbc85be12015-08-24 10:36:39 -0700283 const char *path = uri->path;
Craig Tillera82950e2015-09-22 12:33:20 -0700284 if (path[0] == '/') ++path;
285 return gpr_strdup(path);
Craig Tillerbc85be12015-08-24 10:36:39 -0700286}
287
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700288static const grpc_resolver_factory_vtable dns_factory_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700289 dns_factory_ref, dns_factory_unref, dns_factory_create_resolver,
290 dns_factory_get_default_host_name, "dns"};
291static grpc_resolver_factory dns_resolver_factory = {&dns_factory_vtable};
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700292
Craig Tiller65938df2016-03-31 13:08:49 -0700293static grpc_resolver_factory *dns_resolver_factory_create() {
Craig Tillereb3b12e2015-06-26 14:42:49 -0700294 return &dns_resolver_factory;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700295}
Craig Tiller65938df2016-03-31 13:08:49 -0700296
297void grpc_resolver_dns_native_init(void) {
298 grpc_register_resolver_type(dns_resolver_factory_create());
299}
300
301void grpc_resolver_dns_native_shutdown(void) {}