LCOV - code coverage report
Current view: top level - core/client_config/resolvers - dns_resolver.c (source / functions) Hit Total Coverage
Test: tmp.CaZ6RjdVn2 Lines: 101 111 91.0 %
Date: 2015-12-10 22:15:08 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/iomgr/resolve_address.h"
      44             : #include "src/core/support/string.h"
      45             : 
      46             : typedef struct {
      47             :   /** base class: must be first */
      48             :   grpc_resolver base;
      49             :   /** refcount */
      50             :   gpr_refcount refs;
      51             :   /** name to resolve */
      52             :   char *name;
      53             :   /** default port to use */
      54             :   char *default_port;
      55             :   /** subchannel factory */
      56             :   grpc_subchannel_factory *subchannel_factory;
      57             :   /** load balancing policy name */
      58             :   char *lb_policy_name;
      59             : 
      60             :   /** mutex guarding the rest of the state */
      61             :   gpr_mu mu;
      62             :   /** are we currently resolving? */
      63             :   int resolving;
      64             :   /** which version of resolved_config have we published? */
      65             :   int published_version;
      66             :   /** which version of resolved_config is current? */
      67             :   int resolved_version;
      68             :   /** pending next completion, or NULL */
      69             :   grpc_closure *next_completion;
      70             :   /** target config address for next completion */
      71             :   grpc_client_config **target_config;
      72             :   /** current (fully resolved) config */
      73             :   grpc_client_config *resolved_config;
      74             : } dns_resolver;
      75             : 
      76             : static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
      77             : 
      78             : static void dns_start_resolving_locked(dns_resolver *r);
      79             : static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
      80             :                                          dns_resolver *r);
      81             : 
      82             : static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
      83             : static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
      84             :                                   struct sockaddr *failing_address,
      85             :                                   int failing_address_len);
      86             : static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
      87             :                      grpc_client_config **target_config,
      88             :                      grpc_closure *on_complete);
      89             : 
      90             : static const grpc_resolver_vtable dns_resolver_vtable = {
      91             :     dns_destroy, dns_shutdown, dns_channel_saw_error, dns_next};
      92             : 
      93        1983 : static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
      94        1966 :   dns_resolver *r = (dns_resolver *)resolver;
      95        1983 :   gpr_mu_lock(&r->mu);
      96        1983 :   if (r->next_completion != NULL) {
      97        1623 :     *r->target_config = NULL;
      98        1623 :     grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, 1);
      99        1623 :     r->next_completion = NULL;
     100             :   }
     101        1983 :   gpr_mu_unlock(&r->mu);
     102        1983 : }
     103             : 
     104           0 : static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx,
     105             :                                   grpc_resolver *resolver, struct sockaddr *sa,
     106             :                                   int len) {
     107           0 :   dns_resolver *r = (dns_resolver *)resolver;
     108           0 :   gpr_mu_lock(&r->mu);
     109           0 :   if (!r->resolving) {
     110           0 :     dns_start_resolving_locked(r);
     111             :   }
     112           0 :   gpr_mu_unlock(&r->mu);
     113           0 : }
     114             : 
     115        3204 : static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
     116             :                      grpc_client_config **target_config,
     117             :                      grpc_closure *on_complete) {
     118        3114 :   dns_resolver *r = (dns_resolver *)resolver;
     119        3204 :   gpr_mu_lock(&r->mu);
     120        3204 :   GPR_ASSERT(!r->next_completion);
     121        3204 :   r->next_completion = on_complete;
     122        3204 :   r->target_config = target_config;
     123        3204 :   if (r->resolved_version == 0 && !r->resolving) {
     124        1661 :     dns_start_resolving_locked(r);
     125             :   } else {
     126        1543 :     dns_maybe_finish_next_locked(exec_ctx, r);
     127             :   }
     128        3204 :   gpr_mu_unlock(&r->mu);
     129        3204 : }
     130             : 
     131        1661 : static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
     132             :                             grpc_resolved_addresses *addresses) {
     133        1616 :   dns_resolver *r = arg;
     134        1616 :   grpc_client_config *config = NULL;
     135             :   grpc_subchannel **subchannels;
     136             :   grpc_subchannel_args args;
     137             :   grpc_lb_policy *lb_policy;
     138             :   size_t i;
     139        1661 :   if (addresses) {
     140             :     grpc_lb_policy_args lb_policy_args;
     141        1658 :     config = grpc_client_config_create();
     142        1658 :     subchannels = gpr_malloc(sizeof(grpc_subchannel *) * addresses->naddrs);
     143        4841 :     for (i = 0; i < addresses->naddrs; i++) {
     144        3183 :       memset(&args, 0, sizeof(args));
     145        3183 :       args.addr = (struct sockaddr *)(addresses->addrs[i].addr);
     146        3183 :       args.addr_len = (size_t)addresses->addrs[i].len;
     147        3183 :       subchannels[i] = grpc_subchannel_factory_create_subchannel(
     148             :           exec_ctx, r->subchannel_factory, &args);
     149             :     }
     150        1658 :     memset(&lb_policy_args, 0, sizeof(lb_policy_args));
     151        1658 :     lb_policy_args.subchannels = subchannels;
     152        1658 :     lb_policy_args.num_subchannels = addresses->naddrs;
     153        1658 :     lb_policy = grpc_lb_policy_create(r->lb_policy_name, &lb_policy_args);
     154        1658 :     grpc_client_config_set_lb_policy(config, lb_policy);
     155        1658 :     GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
     156        1658 :     grpc_resolved_addresses_destroy(addresses);
     157        1658 :     gpr_free(subchannels);
     158             :   }
     159        1661 :   gpr_mu_lock(&r->mu);
     160        1661 :   GPR_ASSERT(r->resolving);
     161        1661 :   r->resolving = 0;
     162        1661 :   if (r->resolved_config) {
     163           0 :     grpc_client_config_unref(exec_ctx, r->resolved_config);
     164             :   }
     165        1661 :   r->resolved_config = config;
     166        1661 :   r->resolved_version++;
     167        1661 :   dns_maybe_finish_next_locked(exec_ctx, r);
     168        1661 :   gpr_mu_unlock(&r->mu);
     169             : 
     170        1661 :   GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving");
     171        1661 : }
     172             : 
     173        1661 : static void dns_start_resolving_locked(dns_resolver *r) {
     174        1661 :   GRPC_RESOLVER_REF(&r->base, "dns-resolving");
     175        1661 :   GPR_ASSERT(!r->resolving);
     176        1661 :   r->resolving = 1;
     177        1661 :   grpc_resolve_address(r->name, r->default_port, dns_on_resolved, r);
     178        1661 : }
     179             : 
     180        3204 : static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
     181             :                                          dns_resolver *r) {
     182        6290 :   if (r->next_completion != NULL &&
     183        3086 :       r->resolved_version != r->published_version) {
     184        1543 :     *r->target_config = r->resolved_config;
     185        1543 :     if (r->resolved_config) {
     186        1540 :       grpc_client_config_ref(r->resolved_config);
     187             :     }
     188        1543 :     grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, 1);
     189        1543 :     r->next_completion = NULL;
     190        1543 :     r->published_version = r->resolved_version;
     191             :   }
     192        3204 : }
     193             : 
     194        1983 : static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
     195        1966 :   dns_resolver *r = (dns_resolver *)gr;
     196        1983 :   gpr_mu_destroy(&r->mu);
     197        1983 :   if (r->resolved_config) {
     198        1620 :     grpc_client_config_unref(exec_ctx, r->resolved_config);
     199             :   }
     200        1983 :   grpc_subchannel_factory_unref(exec_ctx, r->subchannel_factory);
     201        1983 :   gpr_free(r->name);
     202        1983 :   gpr_free(r->default_port);
     203        1983 :   gpr_free(r->lb_policy_name);
     204        1983 :   gpr_free(r);
     205        1983 : }
     206             : 
     207        2026 : static grpc_resolver *dns_create(grpc_resolver_args *args,
     208             :                                  const char *default_port,
     209             :                                  const char *lb_policy_name) {
     210             :   dns_resolver *r;
     211        2026 :   const char *path = args->uri->path;
     212             : 
     213        2026 :   if (0 != strcmp(args->uri->authority, "")) {
     214           0 :     gpr_log(GPR_ERROR, "authority based dns uri's not supported");
     215           0 :     return NULL;
     216             :   }
     217             : 
     218        2026 :   if (path[0] == '/') ++path;
     219             : 
     220        2026 :   r = gpr_malloc(sizeof(dns_resolver));
     221        2026 :   memset(r, 0, sizeof(*r));
     222        2026 :   gpr_ref_init(&r->refs, 1);
     223        2026 :   gpr_mu_init(&r->mu);
     224        2026 :   grpc_resolver_init(&r->base, &dns_resolver_vtable);
     225        2026 :   r->name = gpr_strdup(path);
     226        2026 :   r->default_port = gpr_strdup(default_port);
     227        2026 :   r->subchannel_factory = args->subchannel_factory;
     228        2026 :   grpc_subchannel_factory_ref(r->subchannel_factory);
     229        2026 :   r->lb_policy_name = gpr_strdup(lb_policy_name);
     230        2026 :   return &r->base;
     231             : }
     232             : 
     233             : /*
     234             :  * FACTORY
     235             :  */
     236             : 
     237        3452 : static void dns_factory_ref(grpc_resolver_factory *factory) {}
     238             : 
     239        3450 : static void dns_factory_unref(grpc_resolver_factory *factory) {}
     240             : 
     241        2026 : static grpc_resolver *dns_factory_create_resolver(
     242             :     grpc_resolver_factory *factory, grpc_resolver_args *args) {
     243        2026 :   return dns_create(args, "https", "pick_first");
     244             : }
     245             : 
     246        2074 : char *dns_factory_get_default_host_name(grpc_resolver_factory *factory,
     247             :                                         grpc_uri *uri) {
     248        2074 :   const char *path = uri->path;
     249        2074 :   if (path[0] == '/') ++path;
     250        2074 :   return gpr_strdup(path);
     251             : }
     252             : 
     253             : static const grpc_resolver_factory_vtable dns_factory_vtable = {
     254             :     dns_factory_ref, dns_factory_unref, dns_factory_create_resolver,
     255             :     dns_factory_get_default_host_name, "dns"};
     256             : static grpc_resolver_factory dns_resolver_factory = {&dns_factory_vtable};
     257             : 
     258        3452 : grpc_resolver_factory *grpc_dns_resolver_factory_create() {
     259        3452 :   return &dns_resolver_factory;
     260             : }

Generated by: LCOV version 1.11