LCOV - code coverage report
Current view: top level - src/core/surface - channel.c (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 140 150 93.3 %
Date: 2015-10-10 Functions: 18 18 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 "src/core/surface/channel.h"
      35             : 
      36             : #include <stdlib.h>
      37             : #include <string.h>
      38             : 
      39             : #include <grpc/support/alloc.h>
      40             : #include <grpc/support/log.h>
      41             : #include <grpc/support/string_util.h>
      42             : 
      43             : #include "src/core/client_config/resolver_registry.h"
      44             : #include "src/core/iomgr/iomgr.h"
      45             : #include "src/core/support/string.h"
      46             : #include "src/core/surface/api_trace.h"
      47             : #include "src/core/surface/call.h"
      48             : #include "src/core/surface/init.h"
      49             : 
      50             : /** Cache grpc-status: X mdelems for X = 0..NUM_CACHED_STATUS_ELEMS.
      51             :  *  Avoids needing to take a metadata context lock for sending status
      52             :  *  if the status code is <= NUM_CACHED_STATUS_ELEMS.
      53             :  *  Sized to allow the most commonly used codes to fit in
      54             :  *  (OK, Cancelled, Unknown). */
      55             : #define NUM_CACHED_STATUS_ELEMS 3
      56             : 
      57             : typedef struct registered_call {
      58             :   grpc_mdelem *path;
      59             :   grpc_mdelem *authority;
      60             :   struct registered_call *next;
      61             : } registered_call;
      62             : 
      63             : struct grpc_channel {
      64             :   int is_client;
      65             :   gpr_refcount refs;
      66             :   gpr_uint32 max_message_length;
      67             :   grpc_mdctx *metadata_context;
      68             :   /** mdstr for the grpc-status key */
      69             :   grpc_mdstr *grpc_status_string;
      70             :   grpc_mdstr *grpc_compression_algorithm_string;
      71             :   grpc_mdstr *grpc_encodings_accepted_by_peer_string;
      72             :   grpc_mdstr *grpc_message_string;
      73             :   grpc_mdstr *path_string;
      74             :   grpc_mdstr *authority_string;
      75             :   grpc_mdelem *default_authority;
      76             :   /** mdelem for grpc-status: 0 thru grpc-status: 2 */
      77             :   grpc_mdelem *grpc_status_elem[NUM_CACHED_STATUS_ELEMS];
      78             : 
      79             :   gpr_mu registered_call_mu;
      80             :   registered_call *registered_calls;
      81             :   char *target;
      82             : };
      83             : 
      84             : #define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c) + 1))
      85             : #define CHANNEL_FROM_CHANNEL_STACK(channel_stack) \
      86             :   (((grpc_channel *)(channel_stack)) - 1)
      87             : #define CHANNEL_FROM_TOP_ELEM(top_elem) \
      88             :   CHANNEL_FROM_CHANNEL_STACK(grpc_channel_stack_from_top_element(top_elem))
      89             : 
      90             : /* the protobuf library will (by default) start warning at 100megs */
      91             : #define DEFAULT_MAX_MESSAGE_LENGTH (100 * 1024 * 1024)
      92             : 
      93        4229 : grpc_channel *grpc_channel_create_from_filters(
      94             :     grpc_exec_ctx *exec_ctx, const char *target,
      95             :     const grpc_channel_filter **filters, size_t num_filters,
      96             :     const grpc_channel_args *args, grpc_mdctx *mdctx, int is_client) {
      97             :   size_t i;
      98        4229 :   size_t size =
      99        4229 :       sizeof(grpc_channel) + grpc_channel_stack_size(filters, num_filters);
     100        4229 :   grpc_channel *channel = gpr_malloc(size);
     101        4229 :   memset(channel, 0, sizeof(*channel));
     102        4229 :   channel->target = gpr_strdup(target);
     103        4229 :   GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
     104        4229 :   channel->is_client = is_client;
     105             :   /* decremented by grpc_channel_destroy */
     106        4229 :   gpr_ref_init(&channel->refs, 1);
     107        4229 :   channel->metadata_context = mdctx;
     108        4229 :   channel->grpc_status_string = grpc_mdstr_from_string(mdctx, "grpc-status");
     109        4229 :   channel->grpc_compression_algorithm_string =
     110        4229 :       grpc_mdstr_from_string(mdctx, "grpc-encoding");
     111        4229 :   channel->grpc_encodings_accepted_by_peer_string =
     112        4229 :       grpc_mdstr_from_string(mdctx, "grpc-accept-encoding");
     113        4229 :   channel->grpc_message_string = grpc_mdstr_from_string(mdctx, "grpc-message");
     114       16916 :   for (i = 0; i < NUM_CACHED_STATUS_ELEMS; i++) {
     115             :     char buf[GPR_LTOA_MIN_BUFSIZE];
     116       12687 :     gpr_ltoa((long)i, buf);
     117       12687 :     channel->grpc_status_elem[i] = grpc_mdelem_from_metadata_strings(
     118             :         mdctx, GRPC_MDSTR_REF(channel->grpc_status_string),
     119             :         grpc_mdstr_from_string(mdctx, buf));
     120             :   }
     121        4229 :   channel->path_string = grpc_mdstr_from_string(mdctx, ":path");
     122        4229 :   channel->authority_string = grpc_mdstr_from_string(mdctx, ":authority");
     123        4229 :   gpr_mu_init(&channel->registered_call_mu);
     124        4229 :   channel->registered_calls = NULL;
     125             : 
     126        4229 :   channel->max_message_length = DEFAULT_MAX_MESSAGE_LENGTH;
     127        4229 :   if (args) {
     128        6399 :     for (i = 0; i < args->num_args; i++) {
     129        3440 :       if (0 == strcmp(args->args[i].key, GRPC_ARG_MAX_MESSAGE_LENGTH)) {
     130          97 :         if (args->args[i].type != GRPC_ARG_INTEGER) {
     131           0 :           gpr_log(GPR_ERROR, "%s ignored: it must be an integer",
     132             :                   GRPC_ARG_MAX_MESSAGE_LENGTH);
     133          97 :         } else if (args->args[i].value.integer < 0) {
     134           0 :           gpr_log(GPR_ERROR, "%s ignored: it must be >= 0",
     135             :                   GRPC_ARG_MAX_MESSAGE_LENGTH);
     136             :         } else {
     137          97 :           channel->max_message_length = (gpr_uint32)args->args[i].value.integer;
     138             :         }
     139        3343 :       } else if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) {
     140           0 :         if (args->args[i].type != GRPC_ARG_STRING) {
     141           0 :           gpr_log(GPR_ERROR, "%s: must be an string",
     142             :                   GRPC_ARG_DEFAULT_AUTHORITY);
     143             :         } else {
     144           0 :           if (channel->default_authority) {
     145             :             /* setting this takes precedence over anything else */
     146           0 :             GRPC_MDELEM_UNREF(channel->default_authority);
     147             :           }
     148           0 :           channel->default_authority = grpc_mdelem_from_strings(
     149           0 :               mdctx, ":authority", args->args[i].value.string);
     150             :         }
     151        3343 :       } else if (0 ==
     152        3343 :                  strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) {
     153         434 :         if (args->args[i].type != GRPC_ARG_STRING) {
     154           0 :           gpr_log(GPR_ERROR, "%s: must be an string",
     155             :                   GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
     156             :         } else {
     157         434 :           if (channel->default_authority) {
     158             :             /* other ways of setting this (notably ssl) take precedence */
     159           0 :             gpr_log(GPR_ERROR, "%s: default host already set some other way",
     160             :                     GRPC_ARG_DEFAULT_AUTHORITY);
     161             :           } else {
     162         434 :             channel->default_authority = grpc_mdelem_from_strings(
     163         434 :                 mdctx, ":authority", args->args[i].value.string);
     164             :           }
     165             :         }
     166             :       }
     167             :     }
     168             :   }
     169             : 
     170        4229 :   if (channel->is_client && channel->default_authority == NULL &&
     171             :       target != NULL) {
     172        1772 :     char *default_authority = grpc_get_default_authority(target);
     173        1772 :     if (default_authority) {
     174        1772 :       channel->default_authority = grpc_mdelem_from_strings(
     175             :           channel->metadata_context, ":authority", default_authority);
     176             :     }
     177        1772 :     gpr_free(default_authority);
     178             :   }
     179             : 
     180        4229 :   grpc_channel_stack_init(exec_ctx, filters, num_filters, channel, args,
     181             :                           channel->metadata_context,
     182             :                           CHANNEL_STACK_FROM_CHANNEL(channel));
     183             : 
     184        4229 :   return channel;
     185             : }
     186             : 
     187         340 : char *grpc_channel_get_target(grpc_channel *channel) {
     188         340 :   GRPC_API_TRACE("grpc_channel_get_target(channel=%p)", 1, (channel));
     189         340 :   return gpr_strdup(channel->target);
     190             : }
     191             : 
     192     1403346 : static grpc_call *grpc_channel_create_call_internal(
     193             :     grpc_channel *channel, grpc_call *parent_call, gpr_uint32 propagation_mask,
     194             :     grpc_completion_queue *cq, grpc_mdelem *path_mdelem,
     195             :     grpc_mdelem *authority_mdelem, gpr_timespec deadline) {
     196             :   grpc_mdelem *send_metadata[2];
     197     1403346 :   size_t num_metadata = 0;
     198             : 
     199     1403346 :   GPR_ASSERT(channel->is_client);
     200             : 
     201     1403346 :   send_metadata[num_metadata++] = path_mdelem;
     202     1403346 :   if (authority_mdelem != NULL) {
     203      104401 :     send_metadata[num_metadata++] = authority_mdelem;
     204     1298945 :   } else if (channel->default_authority != NULL) {
     205     1298942 :     send_metadata[num_metadata++] = GRPC_MDELEM_REF(channel->default_authority);
     206             :   }
     207             : 
     208     1403348 :   return grpc_call_create(channel, parent_call, propagation_mask, cq, NULL,
     209             :                           send_metadata, num_metadata, deadline);
     210             : }
     211             : 
     212      103920 : grpc_call *grpc_channel_create_call(grpc_channel *channel,
     213             :                                     grpc_call *parent_call,
     214             :                                     gpr_uint32 propagation_mask,
     215             :                                     grpc_completion_queue *cq,
     216             :                                     const char *method, const char *host,
     217             :                                     gpr_timespec deadline, void *reserved) {
     218      103920 :   GRPC_API_TRACE(
     219             :       "grpc_channel_create_call("
     220             :       "channel=%p, parent_call=%p, propagation_mask=%x, cq=%p, method=%s, "
     221             :       "host=%s, "
     222             :       "deadline=gpr_timespec { tv_sec: %ld, tv_nsec: %d, clock_type: %d }, "
     223             :       "reserved=%p)",
     224             :       10, (channel, parent_call, (unsigned)propagation_mask, cq, method, host,
     225             :            (long)deadline.tv_sec, deadline.tv_nsec, (int)deadline.clock_type,
     226             :            reserved));
     227      103920 :   GPR_ASSERT(!reserved);
     228      207827 :   return grpc_channel_create_call_internal(
     229             :       channel, parent_call, propagation_mask, cq,
     230             :       grpc_mdelem_from_metadata_strings(
     231             :           channel->metadata_context, GRPC_MDSTR_REF(channel->path_string),
     232             :           grpc_mdstr_from_string(channel->metadata_context, method)),
     233      103907 :       host ? grpc_mdelem_from_metadata_strings(
     234             :                  channel->metadata_context,
     235             :                  GRPC_MDSTR_REF(channel->authority_string),
     236             :                  grpc_mdstr_from_string(channel->metadata_context, host))
     237             :            : NULL,
     238             :       deadline);
     239             : }
     240             : 
     241         830 : void *grpc_channel_register_call(grpc_channel *channel, const char *method,
     242             :                                  const char *host, void *reserved) {
     243         830 :   registered_call *rc = gpr_malloc(sizeof(registered_call));
     244         830 :   GRPC_API_TRACE(
     245             :       "grpc_channel_register_call(channel=%p, method=%s, host=%s, reserved=%p)",
     246             :       4, (channel, method, host, reserved));
     247         830 :   GPR_ASSERT(!reserved);
     248         830 :   rc->path = grpc_mdelem_from_metadata_strings(
     249             :       channel->metadata_context, GRPC_MDSTR_REF(channel->path_string),
     250             :       grpc_mdstr_from_string(channel->metadata_context, method));
     251         830 :   rc->authority =
     252         273 :       host ? grpc_mdelem_from_metadata_strings(
     253             :                  channel->metadata_context,
     254             :                  GRPC_MDSTR_REF(channel->authority_string),
     255             :                  grpc_mdstr_from_string(channel->metadata_context, host))
     256        1103 :            : NULL;
     257         830 :   gpr_mu_lock(&channel->registered_call_mu);
     258         830 :   rc->next = channel->registered_calls;
     259         830 :   channel->registered_calls = rc;
     260         830 :   gpr_mu_unlock(&channel->registered_call_mu);
     261         830 :   return rc;
     262             : }
     263             : 
     264     1298874 : grpc_call *grpc_channel_create_registered_call(
     265             :     grpc_channel *channel, grpc_call *parent_call, gpr_uint32 propagation_mask,
     266             :     grpc_completion_queue *completion_queue, void *registered_call_handle,
     267             :     gpr_timespec deadline, void *reserved) {
     268     1298874 :   registered_call *rc = registered_call_handle;
     269     1298874 :   GRPC_API_TRACE(
     270             :       "grpc_channel_create_registered_call("
     271             :       "channel=%p, parent_call=%p, propagation_mask=%x, completion_queue=%p, "
     272             :       "registered_call_handle=%p, "
     273             :       "deadline=gpr_timespec { tv_sec: %ld, tv_nsec: %d, clock_type: %d }, "
     274             :       "reserved=%p)",
     275             :       9, (channel, parent_call, (unsigned)propagation_mask, completion_queue,
     276             :           registered_call_handle, (long)deadline.tv_sec, deadline.tv_nsec,
     277             :           (int)deadline.clock_type, reserved));
     278     1298980 :   GPR_ASSERT(!reserved);
     279     1299474 :   return grpc_channel_create_call_internal(
     280             :       channel, parent_call, propagation_mask, completion_queue,
     281             :       GRPC_MDELEM_REF(rc->path),
     282     1299474 :       rc->authority ? GRPC_MDELEM_REF(rc->authority) : NULL, deadline);
     283             : }
     284             : 
     285             : #ifdef GRPC_CHANNEL_REF_COUNT_DEBUG
     286             : void grpc_channel_internal_ref(grpc_channel *c, const char *reason) {
     287             :   gpr_log(GPR_DEBUG, "CHANNEL:   ref %p %d -> %d [%s]", c, c->refs.count,
     288             :           c->refs.count + 1, reason);
     289             : #else
     290     2720275 : void grpc_channel_internal_ref(grpc_channel *c) {
     291             : #endif
     292     2720275 :   gpr_ref(&c->refs);
     293     2720935 : }
     294             : 
     295        4229 : static void destroy_channel(grpc_exec_ctx *exec_ctx, grpc_channel *channel) {
     296             :   size_t i;
     297        4229 :   grpc_channel_stack_destroy(exec_ctx, CHANNEL_STACK_FROM_CHANNEL(channel));
     298       16916 :   for (i = 0; i < NUM_CACHED_STATUS_ELEMS; i++) {
     299       12687 :     GRPC_MDELEM_UNREF(channel->grpc_status_elem[i]);
     300             :   }
     301        4229 :   GRPC_MDSTR_UNREF(channel->grpc_status_string);
     302        4229 :   GRPC_MDSTR_UNREF(channel->grpc_compression_algorithm_string);
     303        4229 :   GRPC_MDSTR_UNREF(channel->grpc_encodings_accepted_by_peer_string);
     304        4229 :   GRPC_MDSTR_UNREF(channel->grpc_message_string);
     305        4229 :   GRPC_MDSTR_UNREF(channel->path_string);
     306        4229 :   GRPC_MDSTR_UNREF(channel->authority_string);
     307        9288 :   while (channel->registered_calls) {
     308         830 :     registered_call *rc = channel->registered_calls;
     309         830 :     channel->registered_calls = rc->next;
     310         830 :     GRPC_MDELEM_UNREF(rc->path);
     311         830 :     if (rc->authority) {
     312         273 :       GRPC_MDELEM_UNREF(rc->authority);
     313             :     }
     314         830 :     gpr_free(rc);
     315             :   }
     316        4229 :   if (channel->default_authority != NULL) {
     317        2206 :     GRPC_MDELEM_UNREF(channel->default_authority);
     318             :   }
     319        4229 :   grpc_mdctx_unref(channel->metadata_context);
     320        4229 :   gpr_mu_destroy(&channel->registered_call_mu);
     321        4229 :   gpr_free(channel->target);
     322        4229 :   gpr_free(channel);
     323        4229 : }
     324             : 
     325             : #ifdef GRPC_CHANNEL_REF_COUNT_DEBUG
     326             : void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx, grpc_channel *channel,
     327             :                                  const char *reason) {
     328             :   gpr_log(GPR_DEBUG, "CHANNEL: unref %p %d -> %d [%s]", channel,
     329             :           channel->refs.count, channel->refs.count - 1, reason);
     330             : #else
     331     2722994 : void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx,
     332             :                                  grpc_channel *channel) {
     333             : #endif
     334     2722994 :   if (gpr_unref(&channel->refs)) {
     335        4229 :     destroy_channel(exec_ctx, channel);
     336             :   }
     337     2725153 : }
     338             : 
     339        2207 : void grpc_channel_destroy(grpc_channel *channel) {
     340             :   grpc_transport_op op;
     341             :   grpc_channel_element *elem;
     342        2207 :   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
     343        2207 :   GRPC_API_TRACE("grpc_channel_destroy(channel=%p)", 1, (channel));
     344        2207 :   memset(&op, 0, sizeof(op));
     345        2207 :   op.disconnect = 1;
     346        2207 :   elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0);
     347        2207 :   elem->filter->start_transport_op(&exec_ctx, elem, &op);
     348             : 
     349        2207 :   GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, channel, "channel");
     350             : 
     351        2207 :   grpc_exec_ctx_finish(&exec_ctx);
     352        2207 : }
     353             : 
     354     2714092 : grpc_channel_stack *grpc_channel_get_channel_stack(grpc_channel *channel) {
     355     2714092 :   return CHANNEL_STACK_FROM_CHANNEL(channel);
     356             : }
     357             : 
     358     2705045 : grpc_mdctx *grpc_channel_get_metadata_context(grpc_channel *channel) {
     359     2705045 :   return channel->metadata_context;
     360             : }
     361             : 
     362     8212555 : grpc_mdstr *grpc_channel_get_status_string(grpc_channel *channel) {
     363     8212555 :   return channel->grpc_status_string;
     364             : }
     365             : 
     366     6700232 : grpc_mdstr *grpc_channel_get_compression_algorithm_string(
     367             :     grpc_channel *channel) {
     368     6700232 :   return channel->grpc_compression_algorithm_string;
     369             : }
     370             : 
     371     4003836 : grpc_mdstr *grpc_channel_get_encodings_accepted_by_peer_string(
     372             :     grpc_channel *channel) {
     373     4003836 :   return channel->grpc_encodings_accepted_by_peer_string;
     374             : }
     375             : 
     376     1301429 : grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_channel *channel, int i) {
     377     1301429 :   if (i >= 0 && i < NUM_CACHED_STATUS_ELEMS) {
     378     1299652 :     return GRPC_MDELEM_REF(channel->grpc_status_elem[i]);
     379             :   } else {
     380             :     char tmp[GPR_LTOA_MIN_BUFSIZE];
     381        1777 :     gpr_ltoa(i, tmp);
     382        1869 :     return grpc_mdelem_from_metadata_strings(
     383             :         channel->metadata_context, GRPC_MDSTR_REF(channel->grpc_status_string),
     384             :         grpc_mdstr_from_string(channel->metadata_context, tmp));
     385             :   }
     386             : }
     387             : 
     388     6806624 : grpc_mdstr *grpc_channel_get_message_string(grpc_channel *channel) {
     389     6806624 :   return channel->grpc_message_string;
     390             : }
     391             : 
     392     3001410 : gpr_uint32 grpc_channel_get_max_message_length(grpc_channel *channel) {
     393     3001410 :   return channel->max_message_length;
     394             : }

Generated by: LCOV version 1.10