LCOV - code coverage report
Current view: top level - core/surface - channel.c (source / functions) Hit Total Coverage
Test: tmp.CaZ6RjdVn2 Lines: 121 121 100.0 %
Date: 2015-12-10 22:15:08 Functions: 13 13 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             : #include "src/core/transport/static_metadata.h"
      50             : 
      51             : /** Cache grpc-status: X mdelems for X = 0..NUM_CACHED_STATUS_ELEMS.
      52             :  *  Avoids needing to take a metadata context lock for sending status
      53             :  *  if the status code is <= NUM_CACHED_STATUS_ELEMS.
      54             :  *  Sized to allow the most commonly used codes to fit in
      55             :  *  (OK, Cancelled, Unknown). */
      56             : #define NUM_CACHED_STATUS_ELEMS 3
      57             : 
      58             : typedef struct registered_call {
      59             :   grpc_mdelem *path;
      60             :   grpc_mdelem *authority;
      61             :   struct registered_call *next;
      62             : } registered_call;
      63             : 
      64             : struct grpc_channel {
      65             :   int is_client;
      66             :   gpr_refcount refs;
      67             :   gpr_uint32 max_message_length;
      68             :   grpc_mdelem *default_authority;
      69             : 
      70             :   gpr_mu registered_call_mu;
      71             :   registered_call *registered_calls;
      72             :   char *target;
      73             : };
      74             : 
      75             : #define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c) + 1))
      76             : #define CHANNEL_FROM_CHANNEL_STACK(channel_stack) \
      77             :   (((grpc_channel *)(channel_stack)) - 1)
      78             : #define CHANNEL_FROM_TOP_ELEM(top_elem) \
      79             :   CHANNEL_FROM_CHANNEL_STACK(grpc_channel_stack_from_top_element(top_elem))
      80             : 
      81             : /* the protobuf library will (by default) start warning at 100megs */
      82             : #define DEFAULT_MAX_MESSAGE_LENGTH (100 * 1024 * 1024)
      83             : 
      84        6731 : grpc_channel *grpc_channel_create_from_filters(
      85             :     grpc_exec_ctx *exec_ctx, const char *target,
      86             :     const grpc_channel_filter **filters, size_t num_filters,
      87             :     const grpc_channel_args *args, int is_client) {
      88             :   size_t i;
      89        6731 :   size_t size =
      90        6731 :       sizeof(grpc_channel) + grpc_channel_stack_size(filters, num_filters);
      91        6731 :   grpc_channel *channel = gpr_malloc(size);
      92        6731 :   memset(channel, 0, sizeof(*channel));
      93        6731 :   channel->target = gpr_strdup(target);
      94        6731 :   GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
      95        6731 :   channel->is_client = is_client;
      96             :   /* decremented by grpc_channel_destroy */
      97        6731 :   gpr_ref_init(&channel->refs, 1);
      98        6731 :   gpr_mu_init(&channel->registered_call_mu);
      99        6731 :   channel->registered_calls = NULL;
     100             : 
     101        6731 :   channel->max_message_length = DEFAULT_MAX_MESSAGE_LENGTH;
     102        6731 :   if (args) {
     103       10627 :     for (i = 0; i < args->num_args; i++) {
     104        5828 :       if (0 == strcmp(args->args[i].key, GRPC_ARG_MAX_MESSAGE_LENGTH)) {
     105         101 :         if (args->args[i].type != GRPC_ARG_INTEGER) {
     106           1 :           gpr_log(GPR_ERROR, "%s ignored: it must be an integer",
     107             :                   GRPC_ARG_MAX_MESSAGE_LENGTH);
     108         100 :         } else if (args->args[i].value.integer < 0) {
     109           1 :           gpr_log(GPR_ERROR, "%s ignored: it must be >= 0",
     110             :                   GRPC_ARG_MAX_MESSAGE_LENGTH);
     111             :         } else {
     112          99 :           channel->max_message_length = (gpr_uint32)args->args[i].value.integer;
     113             :         }
     114        5727 :       } else if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) {
     115          23 :         if (args->args[i].type != GRPC_ARG_STRING) {
     116           1 :           gpr_log(GPR_ERROR, "%s ignored: it must be a string",
     117             :                   GRPC_ARG_DEFAULT_AUTHORITY);
     118             :         } else {
     119          22 :           if (channel->default_authority) {
     120             :             /* setting this takes precedence over anything else */
     121          21 :             GRPC_MDELEM_UNREF(channel->default_authority);
     122             :           }
     123          22 :           channel->default_authority = grpc_mdelem_from_strings(
     124          22 :               ":authority", args->args[i].value.string);
     125             :         }
     126        5704 :       } else if (0 ==
     127        5704 :                  strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) {
     128         590 :         if (args->args[i].type != GRPC_ARG_STRING) {
     129           1 :           gpr_log(GPR_ERROR, "%s ignored: it must be a string",
     130             :                   GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
     131             :         } else {
     132         589 :           if (channel->default_authority) {
     133             :             /* other ways of setting this (notably ssl) take precedence */
     134           1 :             gpr_log(GPR_ERROR,
     135             :                     "%s ignored: default host already set some other way",
     136             :                     GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
     137             :           } else {
     138         588 :             channel->default_authority = grpc_mdelem_from_strings(
     139         588 :                 ":authority", args->args[i].value.string);
     140             :           }
     141             :         }
     142             :       }
     143             :     }
     144             :   }
     145             : 
     146        6731 :   if (channel->is_client && channel->default_authority == NULL &&
     147             :       target != NULL) {
     148        3086 :     char *default_authority = grpc_get_default_authority(target);
     149        3086 :     if (default_authority) {
     150        3085 :       channel->default_authority =
     151        3085 :           grpc_mdelem_from_strings(":authority", default_authority);
     152             :     }
     153        3086 :     gpr_free(default_authority);
     154             :   }
     155             : 
     156        6731 :   grpc_channel_stack_init(exec_ctx, filters, num_filters, channel, args,
     157             :                           CHANNEL_STACK_FROM_CHANNEL(channel));
     158             : 
     159        6731 :   return channel;
     160             : }
     161             : 
     162         633 : char *grpc_channel_get_target(grpc_channel *channel) {
     163         633 :   GRPC_API_TRACE("grpc_channel_get_target(channel=%p)", 1, (channel));
     164         633 :   return gpr_strdup(channel->target);
     165             : }
     166             : 
     167     2272331 : static grpc_call *grpc_channel_create_call_internal(
     168             :     grpc_channel *channel, grpc_call *parent_call, gpr_uint32 propagation_mask,
     169             :     grpc_completion_queue *cq, grpc_mdelem *path_mdelem,
     170             :     grpc_mdelem *authority_mdelem, gpr_timespec deadline) {
     171             :   grpc_mdelem *send_metadata[2];
     172     2272220 :   size_t num_metadata = 0;
     173             : 
     174     2272331 :   GPR_ASSERT(channel->is_client);
     175             : 
     176     2272331 :   send_metadata[num_metadata++] = path_mdelem;
     177     2272331 :   if (authority_mdelem != NULL) {
     178      673261 :     send_metadata[num_metadata++] = authority_mdelem;
     179     1599070 :   } else if (channel->default_authority != NULL) {
     180     1599371 :     send_metadata[num_metadata++] = GRPC_MDELEM_REF(channel->default_authority);
     181             :   }
     182             : 
     183     2272353 :   return grpc_call_create(channel, parent_call, propagation_mask, cq, NULL,
     184             :                           send_metadata, num_metadata, deadline);
     185             : }
     186             : 
     187      625792 : grpc_call *grpc_channel_create_call(grpc_channel *channel,
     188             :                                     grpc_call *parent_call,
     189             :                                     gpr_uint32 propagation_mask,
     190             :                                     grpc_completion_queue *cq,
     191             :                                     const char *method, const char *host,
     192             :                                     gpr_timespec deadline, void *reserved) {
     193      625792 :   GRPC_API_TRACE(
     194             :       "grpc_channel_create_call("
     195             :       "channel=%p, parent_call=%p, propagation_mask=%x, cq=%p, method=%s, "
     196             :       "host=%s, "
     197             :       "deadline=gpr_timespec { tv_sec: %ld, tv_nsec: %d, clock_type: %d }, "
     198             :       "reserved=%p)",
     199             :       10, (channel, parent_call, (unsigned)propagation_mask, cq, method, host,
     200             :            (long)deadline.tv_sec, deadline.tv_nsec, (int)deadline.clock_type,
     201             :            reserved));
     202      625792 :   GPR_ASSERT(!reserved);
     203     1251382 :   return grpc_channel_create_call_internal(
     204             :       channel, parent_call, propagation_mask, cq,
     205             :       grpc_mdelem_from_metadata_strings(GRPC_MDSTR_PATH,
     206             :                                         grpc_mdstr_from_string(method)),
     207      625590 :       host ? grpc_mdelem_from_metadata_strings(GRPC_MDSTR_AUTHORITY,
     208             :                                                grpc_mdstr_from_string(host))
     209             :            : NULL,
     210             :       deadline);
     211             : }
     212             : 
     213         818 : void *grpc_channel_register_call(grpc_channel *channel, const char *method,
     214             :                                  const char *host, void *reserved) {
     215         818 :   registered_call *rc = gpr_malloc(sizeof(registered_call));
     216         818 :   GRPC_API_TRACE(
     217             :       "grpc_channel_register_call(channel=%p, method=%s, host=%s, reserved=%p)",
     218             :       4, (channel, method, host, reserved));
     219         818 :   GPR_ASSERT(!reserved);
     220         818 :   rc->path = grpc_mdelem_from_metadata_strings(GRPC_MDSTR_PATH,
     221             :                                                grpc_mdstr_from_string(method));
     222        1095 :   rc->authority = host ? grpc_mdelem_from_metadata_strings(
     223             :                              GRPC_MDSTR_AUTHORITY, grpc_mdstr_from_string(host))
     224        1095 :                        : NULL;
     225         818 :   gpr_mu_lock(&channel->registered_call_mu);
     226         818 :   rc->next = channel->registered_calls;
     227         818 :   channel->registered_calls = rc;
     228         818 :   gpr_mu_unlock(&channel->registered_call_mu);
     229         818 :   return rc;
     230             : }
     231             : 
     232     1645696 : grpc_call *grpc_channel_create_registered_call(
     233             :     grpc_channel *channel, grpc_call *parent_call, gpr_uint32 propagation_mask,
     234             :     grpc_completion_queue *completion_queue, void *registered_call_handle,
     235             :     gpr_timespec deadline, void *reserved) {
     236     1645696 :   registered_call *rc = registered_call_handle;
     237     1645696 :   GRPC_API_TRACE(
     238             :       "grpc_channel_create_registered_call("
     239             :       "channel=%p, parent_call=%p, propagation_mask=%x, completion_queue=%p, "
     240             :       "registered_call_handle=%p, "
     241             :       "deadline=gpr_timespec { tv_sec: %ld, tv_nsec: %d, clock_type: %d }, "
     242             :       "reserved=%p)",
     243             :       9, (channel, parent_call, (unsigned)propagation_mask, completion_queue,
     244             :           registered_call_handle, (long)deadline.tv_sec, deadline.tv_nsec,
     245             :           (int)deadline.clock_type, reserved));
     246     1646873 :   GPR_ASSERT(!reserved);
     247     1694544 :   return grpc_channel_create_call_internal(
     248             :       channel, parent_call, propagation_mask, completion_queue,
     249             :       GRPC_MDELEM_REF(rc->path),
     250     1694544 :       rc->authority ? GRPC_MDELEM_REF(rc->authority) : NULL, deadline);
     251             : }
     252             : 
     253             : #ifdef GRPC_CHANNEL_REF_COUNT_DEBUG
     254             : void grpc_channel_internal_ref(grpc_channel *c, const char *reason) {
     255             :   gpr_log(GPR_DEBUG, "CHANNEL:   ref %p %d -> %d [%s]", c, c->refs.count,
     256             :           c->refs.count + 1, reason);
     257             : #else
     258     4466577 : void grpc_channel_internal_ref(grpc_channel *c) {
     259             : #endif
     260     4466577 :   gpr_ref(&c->refs);
     261     4468156 : }
     262             : 
     263        6639 : static void destroy_channel(grpc_exec_ctx *exec_ctx, grpc_channel *channel) {
     264        6639 :   grpc_channel_stack_destroy(exec_ctx, CHANNEL_STACK_FROM_CHANNEL(channel));
     265       14096 :   while (channel->registered_calls) {
     266         818 :     registered_call *rc = channel->registered_calls;
     267         818 :     channel->registered_calls = rc->next;
     268         818 :     GRPC_MDELEM_UNREF(rc->path);
     269         818 :     if (rc->authority) {
     270         277 :       GRPC_MDELEM_UNREF(rc->authority);
     271             :     }
     272         818 :     gpr_free(rc);
     273             :   }
     274        6639 :   if (channel->default_authority != NULL) {
     275        3614 :     GRPC_MDELEM_UNREF(channel->default_authority);
     276             :   }
     277        6639 :   gpr_mu_destroy(&channel->registered_call_mu);
     278        6639 :   gpr_free(channel->target);
     279        6639 :   gpr_free(channel);
     280        6639 : }
     281             : 
     282             : #ifdef GRPC_CHANNEL_REF_COUNT_DEBUG
     283             : void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx, grpc_channel *channel,
     284             :                                  const char *reason) {
     285             :   gpr_log(GPR_DEBUG, "CHANNEL: unref %p %d -> %d [%s]", channel,
     286             :           channel->refs.count, channel->refs.count - 1, reason);
     287             : #else
     288     4468959 : void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx,
     289             :                                  grpc_channel *channel) {
     290             : #endif
     291     4468959 :   if (gpr_unref(&channel->refs)) {
     292        6639 :     destroy_channel(exec_ctx, channel);
     293             :   }
     294     4473322 : }
     295             : 
     296        3631 : void grpc_channel_destroy(grpc_channel *channel) {
     297             :   grpc_transport_op op;
     298             :   grpc_channel_element *elem;
     299        3631 :   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
     300        3631 :   GRPC_API_TRACE("grpc_channel_destroy(channel=%p)", 1, (channel));
     301        3631 :   memset(&op, 0, sizeof(op));
     302        3631 :   op.disconnect = 1;
     303        3631 :   elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0);
     304        3631 :   elem->filter->start_transport_op(&exec_ctx, elem, &op);
     305             : 
     306        3631 :   GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, channel, "channel");
     307             : 
     308        3631 :   grpc_exec_ctx_finish(&exec_ctx);
     309        3631 : }
     310             : 
     311     4461030 : grpc_channel_stack *grpc_channel_get_channel_stack(grpc_channel *channel) {
     312     4461030 :   return CHANNEL_STACK_FROM_CHANNEL(channel);
     313             : }
     314             : 
     315     2169400 : grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_channel *channel, int i) {
     316             :   char tmp[GPR_LTOA_MIN_BUFSIZE];
     317     2169400 :   switch (i) {
     318             :     case 0:
     319     1646035 :       return GRPC_MDELEM_GRPC_STATUS_0;
     320             :     case 1:
     321          30 :       return GRPC_MDELEM_GRPC_STATUS_1;
     322             :     case 2:
     323          18 :       return GRPC_MDELEM_GRPC_STATUS_2;
     324             :   }
     325      523262 :   gpr_ltoa(i, tmp);
     326      523262 :   return grpc_mdelem_from_metadata_strings(GRPC_MDSTR_GRPC_STATUS,
     327             :                                            grpc_mdstr_from_string(tmp));
     328             : }
     329             : 
     330     3962414 : gpr_uint32 grpc_channel_get_max_message_length(grpc_channel *channel) {
     331     3962414 :   return channel->max_message_length;
     332             : }

Generated by: LCOV version 1.11