LCOV - code coverage report
Current view: top level - src/core/client_config/resolvers - dns_resolver.c (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 101 111 91.0 %
Date: 2015-10-10 Functions: 12 13 92.3 %

          Line data    Source code
       1             : /*
       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             : 
      36             : #include <string.h>
      37             : 
      38             : #include <grpc/support/alloc.h>
      39             : #include <grpc/support/host_port.h>
      40             : #include <grpc/support/string_util.h>
      41             : 
      42             : #include "src/core/client_config/lb_policy_registry.h"
      43             : #include "src/core/client_config/subchannel_factory_decorators/add_channel_arg.h"
      44             : #include "src/core/iomgr/resolve_address.h"
      45             : #include "src/core/support/string.h"
      46             : 
      47             : typedef 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 name */
      59             :   char *lb_policy_name;
      60             : 
      61             :   /** mutex guarding the rest of the state */
      62             :   gpr_mu mu;
      63             :   /** are we currently resolving? */
      64             :   int resolving;
      65             :   /** which version of resolved_config have we published? */
      66             :   int published_version;
      67             :   /** which version of resolved_config is current? */
      68             :   int resolved_version;
      69             :   /** pending next completion, or NULL */
      70             :   grpc_closure *next_completion;
      71             :   /** target config address for next completion */
      72             :   grpc_client_config **target_config;
      73             :   /** current (fully resolved) config */
      74             :   grpc_client_config *resolved_config;
      75             : } dns_resolver;
      76             : 
      77             : static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
      78             : 
      79             : static void dns_start_resolving_locked(dns_resolver *r);
      80             : static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
      81             :                                          dns_resolver *r);
      82             : 
      83             : static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
      84             : static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
      85             :                                   struct sockaddr *failing_address,
      86             :                                   int failing_address_len);
      87             : static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
      88             :                      grpc_client_config **target_config,
      89             :                      grpc_closure *on_complete);
      90             : 
      91             : static const grpc_resolver_vtable dns_resolver_vtable = {
      92             :     dns_destroy, dns_shutdown, dns_channel_saw_error, dns_next};
      93             : 
      94        1418 : static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
      95        1418 :   dns_resolver *r = (dns_resolver *)resolver;
      96        1418 :   gpr_mu_lock(&r->mu);
      97        1418 :   if (r->next_completion != NULL) {
      98        1167 :     *r->target_config = NULL;
      99        1167 :     grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, 1);
     100        1167 :     r->next_completion = NULL;
     101             :   }
     102        1418 :   gpr_mu_unlock(&r->mu);
     103        1418 : }
     104             : 
     105           0 : static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx,
     106             :                                   grpc_resolver *resolver, struct sockaddr *sa,
     107             :                                   int len) {
     108           0 :   dns_resolver *r = (dns_resolver *)resolver;
     109           0 :   gpr_mu_lock(&r->mu);
     110           0 :   if (!r->resolving) {
     111           0 :     dns_start_resolving_locked(r);
     112             :   }
     113           0 :   gpr_mu_unlock(&r->mu);
     114           0 : }
     115             : 
     116        2275 : static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
     117             :                      grpc_client_config **target_config,
     118             :                      grpc_closure *on_complete) {
     119        2275 :   dns_resolver *r = (dns_resolver *)resolver;
     120        2275 :   gpr_mu_lock(&r->mu);
     121        2275 :   GPR_ASSERT(!r->next_completion);
     122        2275 :   r->next_completion = on_complete;
     123        2275 :   r->target_config = target_config;
     124        2275 :   if (r->resolved_version == 0 && !r->resolving) {
     125        1167 :     dns_start_resolving_locked(r);
     126             :   } else {
     127        1108 :     dns_maybe_finish_next_locked(exec_ctx, r);
     128             :   }
     129        2275 :   gpr_mu_unlock(&r->mu);
     130        2275 : }
     131             : 
     132        1167 : static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
     133             :                             grpc_resolved_addresses *addresses) {
     134        1167 :   dns_resolver *r = arg;
     135        1167 :   grpc_client_config *config = NULL;
     136             :   grpc_subchannel **subchannels;
     137             :   grpc_subchannel_args args;
     138             :   grpc_lb_policy *lb_policy;
     139             :   size_t i;
     140        1167 :   if (addresses) {
     141             :     grpc_lb_policy_args lb_policy_args;
     142        1166 :     config = grpc_client_config_create();
     143        1166 :     subchannels = gpr_malloc(sizeof(grpc_subchannel *) * addresses->naddrs);
     144        2336 :     for (i = 0; i < addresses->naddrs; i++) {
     145        1170 :       memset(&args, 0, sizeof(args));
     146        1170 :       args.addr = (struct sockaddr *)(addresses->addrs[i].addr);
     147        1170 :       args.addr_len = (size_t)addresses->addrs[i].len;
     148        1170 :       subchannels[i] = grpc_subchannel_factory_create_subchannel(
     149             :           exec_ctx, r->subchannel_factory, &args);
     150             :     }
     151        1166 :     memset(&lb_policy_args, 0, sizeof(lb_policy_args));
     152        1166 :     lb_policy_args.subchannels = subchannels;
     153        1166 :     lb_policy_args.num_subchannels = addresses->naddrs;
     154        1166 :     lb_policy = grpc_lb_policy_create(r->lb_policy_name, &lb_policy_args);
     155        1166 :     grpc_client_config_set_lb_policy(config, lb_policy);
     156        1166 :     GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
     157        1166 :     grpc_resolved_addresses_destroy(addresses);
     158        1166 :     gpr_free(subchannels);
     159             :   }
     160        1167 :   gpr_mu_lock(&r->mu);
     161        1167 :   GPR_ASSERT(r->resolving);
     162        1167 :   r->resolving = 0;
     163        1167 :   if (r->resolved_config) {
     164           0 :     grpc_client_config_unref(exec_ctx, r->resolved_config);
     165             :   }
     166        1167 :   r->resolved_config = config;
     167        1167 :   r->resolved_version++;
     168        1167 :   dns_maybe_finish_next_locked(exec_ctx, r);
     169        1167 :   gpr_mu_unlock(&r->mu);
     170             : 
     171        1167 :   GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving");
     172        1167 : }
     173             : 
     174        1167 : static void dns_start_resolving_locked(dns_resolver *r) {
     175        1167 :   GRPC_RESOLVER_REF(&r->base, "dns-resolving");
     176        1167 :   GPR_ASSERT(!r->resolving);
     177        1167 :   r->resolving = 1;
     178        1167 :   grpc_resolve_address(r->name, r->default_port, dns_on_resolved, r);
     179        1167 : }
     180             : 
     181        2275 : static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
     182             :                                          dns_resolver *r) {
     183        4491 :   if (r->next_completion != NULL &&
     184        2216 :       r->resolved_version != r->published_version) {
     185        1108 :     *r->target_config = r->resolved_config;
     186        1108 :     if (r->resolved_config) {
     187        1107 :       grpc_client_config_ref(r->resolved_config);
     188             :     }
     189        1108 :     grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, 1);
     190        1108 :     r->next_completion = NULL;
     191        1108 :     r->published_version = r->resolved_version;
     192             :   }
     193        2275 : }
     194             : 
     195        1418 : static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
     196        1418 :   dns_resolver *r = (dns_resolver *)gr;
     197        1418 :   gpr_mu_destroy(&r->mu);
     198        1418 :   if (r->resolved_config) {
     199        1166 :     grpc_client_config_unref(exec_ctx, r->resolved_config);
     200             :   }
     201        1418 :   grpc_subchannel_factory_unref(exec_ctx, r->subchannel_factory);
     202        1418 :   gpr_free(r->name);
     203        1418 :   gpr_free(r->default_port);
     204        1418 :   gpr_free(r->lb_policy_name);
     205        1418 :   gpr_free(r);
     206        1418 : }
     207             : 
     208        1418 : static grpc_resolver *dns_create(grpc_resolver_args *args,
     209             :                                  const char *default_port,
     210             :                                  const char *lb_policy_name) {
     211             :   dns_resolver *r;
     212        1418 :   const char *path = args->uri->path;
     213             : 
     214        1418 :   if (0 != strcmp(args->uri->authority, "")) {
     215           0 :     gpr_log(GPR_ERROR, "authority based dns uri's not supported");
     216           0 :     return NULL;
     217             :   }
     218             : 
     219        1418 :   if (path[0] == '/') ++path;
     220             : 
     221        1418 :   r = gpr_malloc(sizeof(dns_resolver));
     222        1418 :   memset(r, 0, sizeof(*r));
     223        1418 :   gpr_ref_init(&r->refs, 1);
     224        1418 :   gpr_mu_init(&r->mu);
     225        1418 :   grpc_resolver_init(&r->base, &dns_resolver_vtable);
     226        1418 :   r->name = gpr_strdup(path);
     227        1418 :   r->default_port = gpr_strdup(default_port);
     228        1418 :   r->subchannel_factory = args->subchannel_factory;
     229        1418 :   grpc_subchannel_factory_ref(r->subchannel_factory);
     230        1418 :   r->lb_policy_name = gpr_strdup(lb_policy_name);
     231        1418 :   return &r->base;
     232             : }
     233             : 
     234             : /*
     235             :  * FACTORY
     236             :  */
     237             : 
     238        2501 : static void dns_factory_ref(grpc_resolver_factory *factory) {}
     239             : 
     240        2501 : static void dns_factory_unref(grpc_resolver_factory *factory) {}
     241             : 
     242        1418 : static grpc_resolver *dns_factory_create_resolver(
     243             :     grpc_resolver_factory *factory, grpc_resolver_args *args) {
     244        1418 :   return dns_create(args, "https", "pick_first");
     245             : }
     246             : 
     247        1429 : char *dns_factory_get_default_host_name(grpc_resolver_factory *factory,
     248             :                                         grpc_uri *uri) {
     249        1429 :   const char *path = uri->path;
     250        1429 :   if (path[0] == '/') ++path;
     251        1429 :   return gpr_strdup(path);
     252             : }
     253             : 
     254             : static const grpc_resolver_factory_vtable dns_factory_vtable = {
     255             :     dns_factory_ref, dns_factory_unref, dns_factory_create_resolver,
     256             :     dns_factory_get_default_host_name, "dns"};
     257             : static grpc_resolver_factory dns_resolver_factory = {&dns_factory_vtable};
     258             : 
     259        2501 : grpc_resolver_factory *grpc_dns_resolver_factory_create() {
     260        2501 :   return &dns_resolver_factory;
     261             : }

Generated by: LCOV version 1.10