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

Generated by: LCOV version 1.11