LCOV - code coverage report
Current view: top level - src/core/surface - secure_channel_create.c (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 136 148 91.9 %
Date: 2015-10-10 Functions: 10 10 100.0 %

          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 <grpc/grpc.h>
      35             : 
      36             : #include <stdlib.h>
      37             : #include <string.h>
      38             : 
      39             : #include <grpc/support/alloc.h>
      40             : 
      41             : #include "src/core/census/grpc_filter.h"
      42             : #include "src/core/channel/channel_args.h"
      43             : #include "src/core/channel/client_channel.h"
      44             : #include "src/core/channel/compress_filter.h"
      45             : #include "src/core/channel/http_client_filter.h"
      46             : #include "src/core/client_config/resolver_registry.h"
      47             : #include "src/core/iomgr/tcp_client.h"
      48             : #include "src/core/security/auth_filters.h"
      49             : #include "src/core/security/credentials.h"
      50             : #include "src/core/surface/api_trace.h"
      51             : #include "src/core/surface/channel.h"
      52             : #include "src/core/transport/chttp2_transport.h"
      53             : #include "src/core/tsi/transport_security_interface.h"
      54             : 
      55             : typedef struct {
      56             :   grpc_connector base;
      57             :   gpr_refcount refs;
      58             : 
      59             :   grpc_channel_security_connector *security_connector;
      60             : 
      61             :   grpc_closure *notify;
      62             :   grpc_connect_in_args args;
      63             :   grpc_connect_out_args *result;
      64             : 
      65             :   gpr_mu mu;
      66             :   grpc_endpoint *connecting_endpoint;
      67             :   grpc_endpoint *newly_connecting_endpoint;
      68             : 
      69             :   grpc_closure connected_closure;
      70             : 
      71             :   grpc_mdctx *mdctx;
      72             : } connector;
      73             : 
      74         419 : static void connector_ref(grpc_connector *con) {
      75         419 :   connector *c = (connector *)con;
      76         419 :   gpr_ref(&c->refs);
      77         419 : }
      78             : 
      79         838 : static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
      80         838 :   connector *c = (connector *)con;
      81         838 :   if (gpr_unref(&c->refs)) {
      82         419 :     grpc_mdctx_unref(c->mdctx);
      83         419 :     gpr_free(c);
      84             :   }
      85         838 : }
      86             : 
      87         446 : static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
      88             :                                      grpc_security_status status,
      89             :                                      grpc_endpoint *wrapped_endpoint,
      90             :                                      grpc_endpoint *secure_endpoint) {
      91         446 :   connector *c = arg;
      92             :   grpc_closure *notify;
      93         446 :   gpr_mu_lock(&c->mu);
      94         446 :   if (c->connecting_endpoint == NULL) {
      95           8 :     memset(c->result, 0, sizeof(*c->result));
      96           8 :     gpr_mu_unlock(&c->mu);
      97         438 :   } else if (status != GRPC_SECURITY_OK) {
      98           0 :     GPR_ASSERT(c->connecting_endpoint == wrapped_endpoint);
      99           0 :     gpr_log(GPR_ERROR, "Secure handshake failed with error %d.", status);
     100           0 :     memset(c->result, 0, sizeof(*c->result));
     101           0 :     c->connecting_endpoint = NULL;
     102           0 :     gpr_mu_unlock(&c->mu);
     103             :   } else {
     104         438 :     GPR_ASSERT(c->connecting_endpoint == wrapped_endpoint);
     105         438 :     c->connecting_endpoint = NULL;
     106         438 :     gpr_mu_unlock(&c->mu);
     107         438 :     c->result->transport = grpc_create_chttp2_transport(
     108             :         exec_ctx, c->args.channel_args, secure_endpoint, c->mdctx, 1);
     109         438 :     grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL,
     110             :                                         0);
     111         438 :     c->result->filters = gpr_malloc(sizeof(grpc_channel_filter *) * 2);
     112         438 :     c->result->filters[0] = &grpc_http_client_filter;
     113         438 :     c->result->filters[1] = &grpc_client_auth_filter;
     114         438 :     c->result->num_filters = 2;
     115             :   }
     116         446 :   notify = c->notify;
     117         446 :   c->notify = NULL;
     118         446 :   notify->cb(exec_ctx, notify->cb_arg, 1);
     119         446 : }
     120             : 
     121         531 : static void connected(grpc_exec_ctx *exec_ctx, void *arg, int success) {
     122         531 :   connector *c = arg;
     123             :   grpc_closure *notify;
     124         531 :   grpc_endpoint *tcp = c->newly_connecting_endpoint;
     125         531 :   if (tcp != NULL) {
     126         446 :     gpr_mu_lock(&c->mu);
     127         446 :     GPR_ASSERT(c->connecting_endpoint == NULL);
     128         446 :     c->connecting_endpoint = tcp;
     129         446 :     gpr_mu_unlock(&c->mu);
     130         446 :     grpc_security_connector_do_handshake(exec_ctx, &c->security_connector->base,
     131             :                                          tcp, on_secure_handshake_done, c);
     132             :   } else {
     133          85 :     memset(c->result, 0, sizeof(*c->result));
     134          85 :     notify = c->notify;
     135          85 :     c->notify = NULL;
     136          85 :     notify->cb(exec_ctx, notify->cb_arg, 1);
     137             :   }
     138         531 : }
     139             : 
     140         399 : static void connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
     141         399 :   connector *c = (connector *)con;
     142             :   grpc_endpoint *ep;
     143         399 :   gpr_mu_lock(&c->mu);
     144         399 :   ep = c->connecting_endpoint;
     145         399 :   c->connecting_endpoint = NULL;
     146         399 :   gpr_mu_unlock(&c->mu);
     147         399 :   if (ep) {
     148           8 :     grpc_endpoint_shutdown(exec_ctx, ep);
     149             :   }
     150         399 : }
     151             : 
     152         531 : static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con,
     153             :                               const grpc_connect_in_args *args,
     154             :                               grpc_connect_out_args *result,
     155             :                               grpc_closure *notify) {
     156         531 :   connector *c = (connector *)con;
     157         531 :   GPR_ASSERT(c->notify == NULL);
     158         531 :   GPR_ASSERT(notify->cb);
     159         531 :   c->notify = notify;
     160         531 :   c->args = *args;
     161         531 :   c->result = result;
     162         531 :   gpr_mu_lock(&c->mu);
     163         531 :   GPR_ASSERT(c->connecting_endpoint == NULL);
     164         531 :   gpr_mu_unlock(&c->mu);
     165         531 :   grpc_closure_init(&c->connected_closure, connected, c);
     166         531 :   grpc_tcp_client_connect(
     167             :       exec_ctx, &c->connected_closure, &c->newly_connecting_endpoint,
     168             :       args->interested_parties, args->addr, args->addr_len, args->deadline);
     169         531 : }
     170             : 
     171             : static const grpc_connector_vtable connector_vtable = {
     172             :     connector_ref, connector_unref, connector_shutdown, connector_connect};
     173             : 
     174             : typedef struct {
     175             :   grpc_subchannel_factory base;
     176             :   gpr_refcount refs;
     177             :   grpc_mdctx *mdctx;
     178             :   grpc_channel_args *merge_args;
     179             :   grpc_channel_security_connector *security_connector;
     180             :   grpc_channel *master;
     181             : } subchannel_factory;
     182             : 
     183         518 : static void subchannel_factory_ref(grpc_subchannel_factory *scf) {
     184         518 :   subchannel_factory *f = (subchannel_factory *)scf;
     185         518 :   gpr_ref(&f->refs);
     186         518 : }
     187             : 
     188        1036 : static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
     189             :                                      grpc_subchannel_factory *scf) {
     190        1036 :   subchannel_factory *f = (subchannel_factory *)scf;
     191        1036 :   if (gpr_unref(&f->refs)) {
     192         518 :     GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
     193             :                                   "subchannel_factory");
     194         518 :     GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master, "subchannel_factory");
     195         518 :     grpc_channel_args_destroy(f->merge_args);
     196         518 :     grpc_mdctx_unref(f->mdctx);
     197         518 :     gpr_free(f);
     198             :   }
     199        1036 : }
     200             : 
     201         419 : static grpc_subchannel *subchannel_factory_create_subchannel(
     202             :     grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *scf,
     203             :     grpc_subchannel_args *args) {
     204         419 :   subchannel_factory *f = (subchannel_factory *)scf;
     205         419 :   connector *c = gpr_malloc(sizeof(*c));
     206         419 :   grpc_channel_args *final_args =
     207         419 :       grpc_channel_args_merge(args->args, f->merge_args);
     208             :   grpc_subchannel *s;
     209         419 :   memset(c, 0, sizeof(*c));
     210         419 :   c->base.vtable = &connector_vtable;
     211         419 :   c->security_connector = f->security_connector;
     212         419 :   c->mdctx = f->mdctx;
     213         419 :   gpr_mu_init(&c->mu);
     214         419 :   grpc_mdctx_ref(c->mdctx);
     215         419 :   gpr_ref_init(&c->refs, 1);
     216         419 :   args->args = final_args;
     217         419 :   args->master = f->master;
     218         419 :   args->mdctx = f->mdctx;
     219         419 :   s = grpc_subchannel_create(&c->base, args);
     220         419 :   grpc_connector_unref(exec_ctx, &c->base);
     221         419 :   grpc_channel_args_destroy(final_args);
     222         419 :   return s;
     223             : }
     224             : 
     225             : static const grpc_subchannel_factory_vtable subchannel_factory_vtable = {
     226             :     subchannel_factory_ref, subchannel_factory_unref,
     227             :     subchannel_factory_create_subchannel};
     228             : 
     229             : /* Create a secure client channel:
     230             :    Asynchronously: - resolve target
     231             :                    - connect to it (trying alternatives as presented)
     232             :                    - perform handshakes */
     233         518 : grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
     234             :                                          const char *target,
     235             :                                          const grpc_channel_args *args,
     236             :                                          void *reserved) {
     237             :   grpc_channel *channel;
     238             :   grpc_arg connector_arg;
     239             :   grpc_channel_args *args_copy;
     240             :   grpc_channel_args *new_args_from_connector;
     241             :   grpc_channel_security_connector *security_connector;
     242             :   grpc_mdctx *mdctx;
     243             :   grpc_resolver *resolver;
     244             :   subchannel_factory *f;
     245             : #define MAX_FILTERS 3
     246             :   const grpc_channel_filter *filters[MAX_FILTERS];
     247         518 :   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
     248         518 :   size_t n = 0;
     249             : 
     250         518 :   GRPC_API_TRACE(
     251             :       "grpc_secure_channel_create(creds=%p, target=%s, args=%p, "
     252             :       "reserved=%p)",
     253             :       4, (creds, target, args, reserved));
     254         518 :   GPR_ASSERT(reserved == NULL);
     255             : 
     256         518 :   if (grpc_find_security_connector_in_args(args) != NULL) {
     257           0 :     gpr_log(GPR_ERROR, "Cannot set security context in channel args.");
     258           0 :     grpc_exec_ctx_finish(&exec_ctx);
     259           0 :     return grpc_lame_client_channel_create(
     260             :         target, GRPC_STATUS_INVALID_ARGUMENT,
     261             :         "Security connector exists in channel args.");
     262             :   }
     263             : 
     264         518 :   if (grpc_credentials_create_security_connector(
     265             :           creds, target, args, NULL, &security_connector,
     266             :           &new_args_from_connector) != GRPC_SECURITY_OK) {
     267           0 :     grpc_exec_ctx_finish(&exec_ctx);
     268           0 :     return grpc_lame_client_channel_create(
     269             :         target, GRPC_STATUS_INVALID_ARGUMENT,
     270             :         "Failed to create security connector.");
     271             :   }
     272         518 :   mdctx = grpc_mdctx_create();
     273             : 
     274         518 :   connector_arg = grpc_security_connector_to_arg(&security_connector->base);
     275         518 :   args_copy = grpc_channel_args_copy_and_add(
     276         518 :       new_args_from_connector != NULL ? new_args_from_connector : args,
     277             :       &connector_arg, 1);
     278         518 :   if (grpc_channel_args_is_census_enabled(args)) {
     279           5 :     filters[n++] = &grpc_client_census_filter;
     280             :   }
     281         518 :   filters[n++] = &grpc_compress_filter;
     282         518 :   filters[n++] = &grpc_client_channel_filter;
     283         518 :   GPR_ASSERT(n <= MAX_FILTERS);
     284             : 
     285         518 :   channel = grpc_channel_create_from_filters(&exec_ctx, target, filters, n,
     286             :                                              args_copy, mdctx, 1);
     287             : 
     288         518 :   f = gpr_malloc(sizeof(*f));
     289         518 :   f->base.vtable = &subchannel_factory_vtable;
     290         518 :   gpr_ref_init(&f->refs, 1);
     291         518 :   grpc_mdctx_ref(mdctx);
     292         518 :   f->mdctx = mdctx;
     293         518 :   GRPC_SECURITY_CONNECTOR_REF(&security_connector->base, "subchannel_factory");
     294         518 :   f->security_connector = security_connector;
     295         518 :   f->merge_args = grpc_channel_args_copy(args_copy);
     296         518 :   f->master = channel;
     297         518 :   GRPC_CHANNEL_INTERNAL_REF(channel, "subchannel_factory");
     298         518 :   resolver = grpc_resolver_create(target, &f->base);
     299         518 :   if (!resolver) {
     300           0 :     grpc_exec_ctx_finish(&exec_ctx);
     301           0 :     return NULL;
     302             :   }
     303             : 
     304         518 :   grpc_client_channel_set_resolver(
     305             :       &exec_ctx, grpc_channel_get_channel_stack(channel), resolver);
     306         518 :   GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "create");
     307         518 :   grpc_subchannel_factory_unref(&exec_ctx, &f->base);
     308         518 :   GRPC_SECURITY_CONNECTOR_UNREF(&security_connector->base, "channel_create");
     309             : 
     310         518 :   grpc_channel_args_destroy(args_copy);
     311         518 :   if (new_args_from_connector != NULL) {
     312         434 :     grpc_channel_args_destroy(new_args_from_connector);
     313             :   }
     314             : 
     315         518 :   grpc_exec_ctx_finish(&exec_ctx);
     316             : 
     317         518 :   return channel;
     318             : }

Generated by: LCOV version 1.10