blob: 2b2ee97e12a5f810e2eb502cd008654e2d1372a8 [file] [log] [blame]
Craig Tillercd29c582015-06-24 09:15:15 -07001/*
2 *
Craig Tillera93a25f2016-01-28 13:55:49 -08003 * Copyright 2015-2016, 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
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 Tiller3bc8ebd2015-06-24 15:41:15 -070043#include "src/core/iomgr/resolve_address.h"
Craig Tiller1e55bd42016-03-11 09:47:43 -080044#include "src/core/iomgr/timer.h"
Craig Tiller476bb3b2016-03-11 12:54:40 -080045#include "src/core/support/backoff.h"
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070046#include "src/core/support/string.h"
47
Craig Tiller476bb3b2016-03-11 12:54:40 -080048#define BACKOFF_MULTIPLIER 1.6
49#define BACKOFF_JITTER 0.2
50#define BACKOFF_MIN_SECONDS 1
51#define BACKOFF_MAX_SECONDS 120
52
Craig Tillera82950e2015-09-22 12:33:20 -070053typedef struct {
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070054 /** base class: must be first */
55 grpc_resolver base;
56 /** refcount */
57 gpr_refcount refs;
58 /** name to resolve */
59 char *name;
60 /** default port to use */
61 char *default_port;
62 /** subchannel factory */
63 grpc_subchannel_factory *subchannel_factory;
David Garcia Quintas5c4543d2015-09-03 15:49:56 -070064 /** load balancing policy name */
65 char *lb_policy_name;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070066
67 /** mutex guarding the rest of the state */
68 gpr_mu mu;
69 /** are we currently resolving? */
70 int resolving;
71 /** which version of resolved_config have we published? */
72 int published_version;
73 /** which version of resolved_config is current? */
74 int resolved_version;
75 /** pending next completion, or NULL */
Craig Tiller33825112015-09-18 07:44:19 -070076 grpc_closure *next_completion;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070077 /** target config address for next completion */
78 grpc_client_config **target_config;
79 /** current (fully resolved) config */
80 grpc_client_config *resolved_config;
Craig Tiller1e55bd42016-03-11 09:47:43 -080081 /** retry timer */
82 bool have_retry_timer;
83 grpc_timer retry_timer;
Craig Tiller476bb3b2016-03-11 12:54:40 -080084 /** retry backoff state */
85 gpr_backoff backoff_state;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070086} dns_resolver;
87
Craig Tillera82950e2015-09-22 12:33:20 -070088static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070089
Craig Tillera82950e2015-09-22 12:33:20 -070090static void dns_start_resolving_locked(dns_resolver *r);
91static 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 Tillera82950e2015-09-22 12:33:20 -0700123 dns_start_resolving_locked(r);
124 }
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 Tillera82950e2015-09-22 12:33:20 -0700138 dns_start_resolving_locked(r);
139 } 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) {
153 dns_start_resolving_locked(r);
154 }
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;
165 grpc_subchannel **subchannels;
166 grpc_subchannel_args args;
Craig Tillerd7b68e72015-06-28 11:41:09 -0700167 grpc_lb_policy *lb_policy;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700168 size_t i;
Craig Tiller1e55bd42016-03-11 09:47:43 -0800169 gpr_mu_lock(&r->mu);
170 GPR_ASSERT(r->resolving);
171 r->resolving = 0;
172 if (addresses != NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -0700173 grpc_lb_policy_args lb_policy_args;
174 config = grpc_client_config_create();
175 subchannels = gpr_malloc(sizeof(grpc_subchannel *) * addresses->naddrs);
Craig Tiller1e55bd42016-03-11 09:47:43 -0800176 size_t naddrs = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700177 for (i = 0; i < addresses->naddrs; i++) {
178 memset(&args, 0, sizeof(args));
179 args.addr = (struct sockaddr *)(addresses->addrs[i].addr);
180 args.addr_len = (size_t)addresses->addrs[i].len;
Craig Tiller1e55bd42016-03-11 09:47:43 -0800181 grpc_subchannel *subchannel = grpc_subchannel_factory_create_subchannel(
Craig Tillera82950e2015-09-22 12:33:20 -0700182 exec_ctx, r->subchannel_factory, &args);
Craig Tiller1e55bd42016-03-11 09:47:43 -0800183 if (subchannel != NULL) {
184 subchannels[naddrs++] = subchannel;
185 }
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700186 }
Craig Tillera82950e2015-09-22 12:33:20 -0700187 memset(&lb_policy_args, 0, sizeof(lb_policy_args));
188 lb_policy_args.subchannels = subchannels;
Craig Tiller1e55bd42016-03-11 09:47:43 -0800189 lb_policy_args.num_subchannels = naddrs;
Craig Tillera82950e2015-09-22 12:33:20 -0700190 lb_policy = grpc_lb_policy_create(r->lb_policy_name, &lb_policy_args);
Craig Tiller1e55bd42016-03-11 09:47:43 -0800191 if (lb_policy != NULL) {
192 grpc_client_config_set_lb_policy(config, lb_policy);
193 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
194 }
Craig Tillera82950e2015-09-22 12:33:20 -0700195 grpc_resolved_addresses_destroy(addresses);
196 gpr_free(subchannels);
Craig Tiller1e55bd42016-03-11 09:47:43 -0800197 } else {
Craig Tiller476bb3b2016-03-11 12:54:40 -0800198 gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
199 gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now);
200 gpr_timespec timeout = gpr_time_sub(next_try, now);
201 gpr_log(GPR_DEBUG, "dns resolution failed: retrying in %d.%09d seconds",
202 timeout.tv_sec, timeout.tv_nsec);
Craig Tiller1e55bd42016-03-11 09:47:43 -0800203 GPR_ASSERT(!r->have_retry_timer);
204 r->have_retry_timer = true;
Craig Tiller1e55bd42016-03-11 09:47:43 -0800205 GRPC_RESOLVER_REF(&r->base, "retry-timer");
Craig Tiller476bb3b2016-03-11 12:54:40 -0800206 grpc_timer_init(exec_ctx, &r->retry_timer, next_try, dns_on_retry_timer, r,
207 now);
Craig Tillera82950e2015-09-22 12:33:20 -0700208 }
Craig Tillera82950e2015-09-22 12:33:20 -0700209 if (r->resolved_config) {
210 grpc_client_config_unref(exec_ctx, r->resolved_config);
211 }
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700212 r->resolved_config = config;
213 r->resolved_version++;
Craig Tillera82950e2015-09-22 12:33:20 -0700214 dns_maybe_finish_next_locked(exec_ctx, r);
215 gpr_mu_unlock(&r->mu);
Craig Tillerd7b68e72015-06-28 11:41:09 -0700216
Craig Tillera82950e2015-09-22 12:33:20 -0700217 GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving");
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700218}
219
Craig Tillera82950e2015-09-22 12:33:20 -0700220static void dns_start_resolving_locked(dns_resolver *r) {
221 GRPC_RESOLVER_REF(&r->base, "dns-resolving");
222 GPR_ASSERT(!r->resolving);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700223 r->resolving = 1;
Craig Tillera82950e2015-09-22 12:33:20 -0700224 grpc_resolve_address(r->name, r->default_port, dns_on_resolved, r);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700225}
226
Craig Tillera82950e2015-09-22 12:33:20 -0700227static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
228 dns_resolver *r) {
229 if (r->next_completion != NULL &&
230 r->resolved_version != r->published_version) {
231 *r->target_config = r->resolved_config;
232 if (r->resolved_config) {
233 grpc_client_config_ref(r->resolved_config);
Craig Tillerabf36382015-06-29 16:13:27 -0700234 }
Craig Tiller6c396862016-01-28 13:53:40 -0800235 grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700236 r->next_completion = NULL;
237 r->published_version = r->resolved_version;
238 }
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700239}
240
Craig Tillera82950e2015-09-22 12:33:20 -0700241static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
242 dns_resolver *r = (dns_resolver *)gr;
243 gpr_mu_destroy(&r->mu);
244 if (r->resolved_config) {
245 grpc_client_config_unref(exec_ctx, r->resolved_config);
246 }
247 grpc_subchannel_factory_unref(exec_ctx, r->subchannel_factory);
248 gpr_free(r->name);
249 gpr_free(r->default_port);
250 gpr_free(r->lb_policy_name);
251 gpr_free(r);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700252}
253
Craig Tillera82950e2015-09-22 12:33:20 -0700254static grpc_resolver *dns_create(grpc_resolver_args *args,
255 const char *default_port,
256 const char *lb_policy_name) {
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700257 dns_resolver *r;
Craig Tiller06a43f52015-09-15 07:41:28 -0700258 const char *path = args->uri->path;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700259
Craig Tillera82950e2015-09-22 12:33:20 -0700260 if (0 != strcmp(args->uri->authority, "")) {
261 gpr_log(GPR_ERROR, "authority based dns uri's not supported");
262 return NULL;
263 }
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700264
Craig Tillera82950e2015-09-22 12:33:20 -0700265 if (path[0] == '/') ++path;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700266
Craig Tillera82950e2015-09-22 12:33:20 -0700267 r = gpr_malloc(sizeof(dns_resolver));
268 memset(r, 0, sizeof(*r));
269 gpr_ref_init(&r->refs, 1);
270 gpr_mu_init(&r->mu);
271 grpc_resolver_init(&r->base, &dns_resolver_vtable);
272 r->name = gpr_strdup(path);
273 r->default_port = gpr_strdup(default_port);
Craig Tiller06a43f52015-09-15 07:41:28 -0700274 r->subchannel_factory = args->subchannel_factory;
Craig Tiller476bb3b2016-03-11 12:54:40 -0800275 gpr_backoff_init(&r->backoff_state, BACKOFF_MULTIPLIER, BACKOFF_JITTER,
276 BACKOFF_MIN_SECONDS * 1000, BACKOFF_MAX_SECONDS * 1000);
Craig Tillera82950e2015-09-22 12:33:20 -0700277 grpc_subchannel_factory_ref(r->subchannel_factory);
278 r->lb_policy_name = gpr_strdup(lb_policy_name);
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700279 return &r->base;
280}
281
282/*
283 * FACTORY
284 */
285
Craig Tillera82950e2015-09-22 12:33:20 -0700286static void dns_factory_ref(grpc_resolver_factory *factory) {}
287
288static void dns_factory_unref(grpc_resolver_factory *factory) {}
289
290static grpc_resolver *dns_factory_create_resolver(
291 grpc_resolver_factory *factory, grpc_resolver_args *args) {
292 return dns_create(args, "https", "pick_first");
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700293}
294
Craig Tillera82950e2015-09-22 12:33:20 -0700295char *dns_factory_get_default_host_name(grpc_resolver_factory *factory,
296 grpc_uri *uri) {
Craig Tillerbc85be12015-08-24 10:36:39 -0700297 const char *path = uri->path;
Craig Tillera82950e2015-09-22 12:33:20 -0700298 if (path[0] == '/') ++path;
299 return gpr_strdup(path);
Craig Tillerbc85be12015-08-24 10:36:39 -0700300}
301
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700302static const grpc_resolver_factory_vtable dns_factory_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700303 dns_factory_ref, dns_factory_unref, dns_factory_create_resolver,
304 dns_factory_get_default_host_name, "dns"};
305static grpc_resolver_factory dns_resolver_factory = {&dns_factory_vtable};
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700306
Craig Tillera82950e2015-09-22 12:33:20 -0700307grpc_resolver_factory *grpc_dns_resolver_factory_create() {
Craig Tillereb3b12e2015-06-26 14:42:49 -0700308 return &dns_resolver_factory;
Craig Tiller3bc8ebd2015-06-24 15:41:15 -0700309}