blob: 964ab344316206e25f5f0d6aa8bb70c335e4b5e7 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tillera93a25f2016-01-28 13:55:49 -08003 * Copyright 2015-2016, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * 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
Craig Tiller1b22b9d2015-07-20 13:42:22 -070039#include <grpc/support/alloc.h>
40#include <grpc/support/log.h>
41#include <grpc/support/string_util.h>
42
Craig Tiller178edfa2016-02-17 20:54:46 -080043#include "src/core/surface/channel_init.h"
Craig Tillerbc85be12015-08-24 10:36:39 -070044#include "src/core/client_config/resolver_registry.h"
Craig Tiller7bd5ab12015-02-17 22:29:04 -080045#include "src/core/iomgr/iomgr.h"
Craig Tiller3fc8e822015-06-08 16:31:28 -070046#include "src/core/support/string.h"
Masood Malekghassemi76c3d742015-08-19 18:22:53 -070047#include "src/core/surface/api_trace.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080048#include "src/core/surface/call.h"
Craig Tiller60fd3612015-03-05 16:24:22 -080049#include "src/core/surface/init.h"
Craig Tillerebdef9d2015-11-19 17:09:49 -080050#include "src/core/transport/static_metadata.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080051
Craig Tiller5d5bd222015-06-08 17:01:49 -070052/** Cache grpc-status: X mdelems for X = 0..NUM_CACHED_STATUS_ELEMS.
53 * Avoids needing to take a metadata context lock for sending status
54 * if the status code is <= NUM_CACHED_STATUS_ELEMS.
55 * Sized to allow the most commonly used codes to fit in
56 * (OK, Cancelled, Unknown). */
Craig Tiller3fc8e822015-06-08 16:31:28 -070057#define NUM_CACHED_STATUS_ELEMS 3
58
Craig Tillera82950e2015-09-22 12:33:20 -070059typedef struct registered_call {
Craig Tiller08453372015-04-10 16:05:38 -070060 grpc_mdelem *path;
61 grpc_mdelem *authority;
62 struct registered_call *next;
63} registered_call;
64
Craig Tillera82950e2015-09-22 12:33:20 -070065struct grpc_channel {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080066 int is_client;
Craig Tiller7536af02015-12-22 13:49:30 -080067 uint32_t max_message_length;
Craig Tillerbc85be12015-08-24 10:36:39 -070068 grpc_mdelem *default_authority;
Craig Tiller08453372015-04-10 16:05:38 -070069
70 gpr_mu registered_call_mu;
71 registered_call *registered_calls;
Craig Tiller1b22b9d2015-07-20 13:42:22 -070072 char *target;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080073};
74
Craig Tiller6902ad22015-04-16 08:01:49 -070075#define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c) + 1))
Craig Tillerb20111c2015-04-10 23:27:11 +000076#define CHANNEL_FROM_CHANNEL_STACK(channel_stack) \
77 (((grpc_channel *)(channel_stack)) - 1)
Craig Tillerda669372015-02-05 10:10:15 -080078#define CHANNEL_FROM_TOP_ELEM(top_elem) \
79 CHANNEL_FROM_CHANNEL_STACK(grpc_channel_stack_from_top_element(top_elem))
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080080
Craig Tiller629b0ed2015-04-22 11:14:26 -070081/* the protobuf library will (by default) start warning at 100megs */
82#define DEFAULT_MAX_MESSAGE_LENGTH (100 * 1024 * 1024)
83
Craig Tiller6c396862016-01-28 13:53:40 -080084static void destroy_channel(grpc_exec_ctx *exec_ctx, void *arg, bool success);
Craig Tiller7b435612015-11-24 08:15:05 -080085
Craig Tiller178edfa2016-02-17 20:54:46 -080086grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,
87 const grpc_channel_args *args,
88 grpc_channel_stack_type channel_stack_type,
89 grpc_transport *optional_transport) {
90 bool is_client = grpc_channel_stack_type_is_client(channel_stack_type);
91
92 grpc_channel *channel = grpc_channel_init_create_stack(
93 exec_ctx, channel_stack_type, sizeof(grpc_channel), args, 1,
94 destroy_channel, NULL, optional_transport);
95
Craig Tillera82950e2015-09-22 12:33:20 -070096 memset(channel, 0, sizeof(*channel));
97 channel->target = gpr_strdup(target);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080098 channel->is_client = is_client;
Craig Tillera82950e2015-09-22 12:33:20 -070099 gpr_mu_init(&channel->registered_call_mu);
Craig Tiller08453372015-04-10 16:05:38 -0700100 channel->registered_calls = NULL;
Craig Tiller629b0ed2015-04-22 11:14:26 -0700101
102 channel->max_message_length = DEFAULT_MAX_MESSAGE_LENGTH;
Craig Tillera82950e2015-09-22 12:33:20 -0700103 if (args) {
Craig Tiller178edfa2016-02-17 20:54:46 -0800104 for (size_t i = 0; i < args->num_args; i++) {
Craig Tillera82950e2015-09-22 12:33:20 -0700105 if (0 == strcmp(args->args[i].key, GRPC_ARG_MAX_MESSAGE_LENGTH)) {
106 if (args->args[i].type != GRPC_ARG_INTEGER) {
107 gpr_log(GPR_ERROR, "%s ignored: it must be an integer",
108 GRPC_ARG_MAX_MESSAGE_LENGTH);
109 } else if (args->args[i].value.integer < 0) {
110 gpr_log(GPR_ERROR, "%s ignored: it must be >= 0",
111 GRPC_ARG_MAX_MESSAGE_LENGTH);
112 } else {
Craig Tiller7536af02015-12-22 13:49:30 -0800113 channel->max_message_length = (uint32_t)args->args[i].value.integer;
Craig Tillera82950e2015-09-22 12:33:20 -0700114 }
115 } else if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) {
116 if (args->args[i].type != GRPC_ARG_STRING) {
yang-gc1aefa72015-12-07 15:30:01 -0800117 gpr_log(GPR_ERROR, "%s ignored: it must be a string",
Craig Tillera82950e2015-09-22 12:33:20 -0700118 GRPC_ARG_DEFAULT_AUTHORITY);
119 } else {
120 if (channel->default_authority) {
121 /* setting this takes precedence over anything else */
122 GRPC_MDELEM_UNREF(channel->default_authority);
123 }
124 channel->default_authority = grpc_mdelem_from_strings(
Craig Tillerb2b42612015-11-20 12:02:17 -0800125 ":authority", args->args[i].value.string);
Craig Tillera82950e2015-09-22 12:33:20 -0700126 }
127 } else if (0 ==
128 strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) {
129 if (args->args[i].type != GRPC_ARG_STRING) {
yang-gc1aefa72015-12-07 15:30:01 -0800130 gpr_log(GPR_ERROR, "%s ignored: it must be a string",
Craig Tillera82950e2015-09-22 12:33:20 -0700131 GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
132 } else {
133 if (channel->default_authority) {
134 /* other ways of setting this (notably ssl) take precedence */
yang-g3c504c82015-12-07 15:31:16 -0800135 gpr_log(GPR_ERROR,
136 "%s ignored: default host already set some other way",
yang-g325f2a32015-12-07 15:43:44 -0800137 GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
Craig Tillera82950e2015-09-22 12:33:20 -0700138 } else {
139 channel->default_authority = grpc_mdelem_from_strings(
Craig Tillerb2b42612015-11-20 12:02:17 -0800140 ":authority", args->args[i].value.string);
Craig Tillera82950e2015-09-22 12:33:20 -0700141 }
142 }
143 }
Craig Tiller629b0ed2015-04-22 11:14:26 -0700144 }
Craig Tillera82950e2015-09-22 12:33:20 -0700145 }
Craig Tiller629b0ed2015-04-22 11:14:26 -0700146
Craig Tillera82950e2015-09-22 12:33:20 -0700147 if (channel->is_client && channel->default_authority == NULL &&
148 target != NULL) {
149 char *default_authority = grpc_get_default_authority(target);
150 if (default_authority) {
Craig Tillerb2b42612015-11-20 12:02:17 -0800151 channel->default_authority =
152 grpc_mdelem_from_strings(":authority", default_authority);
Craig Tillerbc85be12015-08-24 10:36:39 -0700153 }
Craig Tillera82950e2015-09-22 12:33:20 -0700154 gpr_free(default_authority);
155 }
Craig Tillerbc85be12015-08-24 10:36:39 -0700156
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800157 return channel;
158}
159
Craig Tillera82950e2015-09-22 12:33:20 -0700160char *grpc_channel_get_target(grpc_channel *channel) {
Masood Malekghassemi76c3d742015-08-19 18:22:53 -0700161 GRPC_API_TRACE("grpc_channel_get_target(channel=%p)", 1, (channel));
Craig Tillera82950e2015-09-22 12:33:20 -0700162 return gpr_strdup(channel->target);
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700163}
164
Craig Tillera82950e2015-09-22 12:33:20 -0700165static grpc_call *grpc_channel_create_call_internal(
Craig Tiller7536af02015-12-22 13:49:30 -0800166 grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask,
Craig Tillera82950e2015-09-22 12:33:20 -0700167 grpc_completion_queue *cq, grpc_mdelem *path_mdelem,
168 grpc_mdelem *authority_mdelem, gpr_timespec deadline) {
Craig Tiller6902ad22015-04-16 08:01:49 -0700169 grpc_mdelem *send_metadata[2];
Craig Tiller32ca48c2015-09-10 11:47:15 -0700170 size_t num_metadata = 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800171
Craig Tillera82950e2015-09-22 12:33:20 -0700172 GPR_ASSERT(channel->is_client);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800173
Craig Tillerc4b56b62015-07-23 17:44:11 -0700174 send_metadata[num_metadata++] = path_mdelem;
Craig Tillera82950e2015-09-22 12:33:20 -0700175 if (authority_mdelem != NULL) {
176 send_metadata[num_metadata++] = authority_mdelem;
177 } else if (channel->default_authority != NULL) {
178 send_metadata[num_metadata++] = GRPC_MDELEM_REF(channel->default_authority);
179 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800180
Craig Tillera82950e2015-09-22 12:33:20 -0700181 return grpc_call_create(channel, parent_call, propagation_mask, cq, NULL,
182 send_metadata, num_metadata, deadline);
Craig Tiller6902ad22015-04-16 08:01:49 -0700183}
klempnerc463f742014-12-19 13:03:35 -0800184
Craig Tillera82950e2015-09-22 12:33:20 -0700185grpc_call *grpc_channel_create_call(grpc_channel *channel,
186 grpc_call *parent_call,
Craig Tiller7536af02015-12-22 13:49:30 -0800187 uint32_t propagation_mask,
Craig Tillera82950e2015-09-22 12:33:20 -0700188 grpc_completion_queue *cq,
189 const char *method, const char *host,
190 gpr_timespec deadline, void *reserved) {
Masood Malekghassemi76c3d742015-08-19 18:22:53 -0700191 GRPC_API_TRACE(
192 "grpc_channel_create_call("
Craig Tiller4de3e4f2015-10-05 08:55:50 -0700193 "channel=%p, parent_call=%p, propagation_mask=%x, cq=%p, method=%s, "
194 "host=%s, "
Jan Tattermusch88086372015-12-10 10:54:12 -0800195 "deadline=gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, "
Craig Tiller4de3e4f2015-10-05 08:55:50 -0700196 "reserved=%p)",
197 10, (channel, parent_call, (unsigned)propagation_mask, cq, method, host,
Craig Tiller620e9652015-12-14 12:02:50 -0800198 (long long)deadline.tv_sec, (int)deadline.tv_nsec,
199 (int)deadline.clock_type, reserved));
Craig Tillera82950e2015-09-22 12:33:20 -0700200 GPR_ASSERT(!reserved);
201 return grpc_channel_create_call_internal(
202 channel, parent_call, propagation_mask, cq,
Craig Tillerb2b42612015-11-20 12:02:17 -0800203 grpc_mdelem_from_metadata_strings(GRPC_MDSTR_PATH,
204 grpc_mdstr_from_string(method)),
205 host ? grpc_mdelem_from_metadata_strings(GRPC_MDSTR_AUTHORITY,
206 grpc_mdstr_from_string(host))
Craig Tillera82950e2015-09-22 12:33:20 -0700207 : NULL,
208 deadline);
Craig Tiller08453372015-04-10 16:05:38 -0700209}
210
Craig Tillera82950e2015-09-22 12:33:20 -0700211void *grpc_channel_register_call(grpc_channel *channel, const char *method,
212 const char *host, void *reserved) {
213 registered_call *rc = gpr_malloc(sizeof(registered_call));
Masood Malekghassemi76c3d742015-08-19 18:22:53 -0700214 GRPC_API_TRACE(
215 "grpc_channel_register_call(channel=%p, method=%s, host=%s, reserved=%p)",
216 4, (channel, method, host, reserved));
Craig Tillera82950e2015-09-22 12:33:20 -0700217 GPR_ASSERT(!reserved);
Craig Tillerb2b42612015-11-20 12:02:17 -0800218 rc->path = grpc_mdelem_from_metadata_strings(GRPC_MDSTR_PATH,
219 grpc_mdstr_from_string(method));
220 rc->authority = host ? grpc_mdelem_from_metadata_strings(
221 GRPC_MDSTR_AUTHORITY, grpc_mdstr_from_string(host))
222 : NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700223 gpr_mu_lock(&channel->registered_call_mu);
Craig Tiller08453372015-04-10 16:05:38 -0700224 rc->next = channel->registered_calls;
225 channel->registered_calls = rc;
Craig Tillera82950e2015-09-22 12:33:20 -0700226 gpr_mu_unlock(&channel->registered_call_mu);
Craig Tiller08453372015-04-10 16:05:38 -0700227 return rc;
228}
229
Craig Tillera82950e2015-09-22 12:33:20 -0700230grpc_call *grpc_channel_create_registered_call(
Craig Tiller7536af02015-12-22 13:49:30 -0800231 grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask,
Craig Tillera82950e2015-09-22 12:33:20 -0700232 grpc_completion_queue *completion_queue, void *registered_call_handle,
233 gpr_timespec deadline, void *reserved) {
Craig Tiller08453372015-04-10 16:05:38 -0700234 registered_call *rc = registered_call_handle;
Masood Malekghassemi76c3d742015-08-19 18:22:53 -0700235 GRPC_API_TRACE(
236 "grpc_channel_create_registered_call("
Craig Tiller4de3e4f2015-10-05 08:55:50 -0700237 "channel=%p, parent_call=%p, propagation_mask=%x, completion_queue=%p, "
238 "registered_call_handle=%p, "
Jan Tattermusch88086372015-12-10 10:54:12 -0800239 "deadline=gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, "
Craig Tiller4de3e4f2015-10-05 08:55:50 -0700240 "reserved=%p)",
Masood Malekghassemi76c3d742015-08-19 18:22:53 -0700241 9, (channel, parent_call, (unsigned)propagation_mask, completion_queue,
Craig Tiller620e9652015-12-14 12:02:50 -0800242 registered_call_handle, (long long)deadline.tv_sec,
243 (int)deadline.tv_nsec, (int)deadline.clock_type, reserved));
Craig Tillera82950e2015-09-22 12:33:20 -0700244 GPR_ASSERT(!reserved);
245 return grpc_channel_create_call_internal(
246 channel, parent_call, propagation_mask, completion_queue,
247 GRPC_MDELEM_REF(rc->path),
248 rc->authority ? GRPC_MDELEM_REF(rc->authority) : NULL, deadline);
Craig Tiller08453372015-04-10 16:05:38 -0700249}
250
Craig Tiller7b435612015-11-24 08:15:05 -0800251#ifdef GRPC_STREAM_REFCOUNT_DEBUG
252#define REF_REASON reason
253#define REF_ARG , const char *reason
Craig Tiller9ec2a522015-05-29 22:46:54 -0700254#else
Craig Tiller7b435612015-11-24 08:15:05 -0800255#define REF_REASON ""
256#define REF_ARG
Craig Tiller9ec2a522015-05-29 22:46:54 -0700257#endif
Craig Tiller7b435612015-11-24 08:15:05 -0800258void grpc_channel_internal_ref(grpc_channel *c REF_ARG) {
259 GRPC_CHANNEL_STACK_REF(CHANNEL_STACK_FROM_CHANNEL(c), REF_REASON);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800260}
261
Craig Tiller7b435612015-11-24 08:15:05 -0800262void grpc_channel_internal_unref(grpc_exec_ctx *exec_ctx,
263 grpc_channel *c REF_ARG) {
264 GRPC_CHANNEL_STACK_UNREF(exec_ctx, CHANNEL_STACK_FROM_CHANNEL(c), REF_REASON);
265}
266
267static void destroy_channel(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller6c396862016-01-28 13:53:40 -0800268 bool iomgr_success) {
Craig Tiller7b435612015-11-24 08:15:05 -0800269 grpc_channel *channel = arg;
Craig Tillera82950e2015-09-22 12:33:20 -0700270 grpc_channel_stack_destroy(exec_ctx, CHANNEL_STACK_FROM_CHANNEL(channel));
Craig Tillera82950e2015-09-22 12:33:20 -0700271 while (channel->registered_calls) {
272 registered_call *rc = channel->registered_calls;
273 channel->registered_calls = rc->next;
274 GRPC_MDELEM_UNREF(rc->path);
275 if (rc->authority) {
276 GRPC_MDELEM_UNREF(rc->authority);
yang-g2f04c6e2015-07-31 22:02:22 -0700277 }
Craig Tillera82950e2015-09-22 12:33:20 -0700278 gpr_free(rc);
279 }
280 if (channel->default_authority != NULL) {
281 GRPC_MDELEM_UNREF(channel->default_authority);
282 }
Craig Tillera82950e2015-09-22 12:33:20 -0700283 gpr_mu_destroy(&channel->registered_call_mu);
284 gpr_free(channel->target);
285 gpr_free(channel);
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800286}
287
Craig Tillera82950e2015-09-22 12:33:20 -0700288void grpc_channel_destroy(grpc_channel *channel) {
Craig Tiller98465032015-06-29 14:36:42 -0700289 grpc_transport_op op;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800290 grpc_channel_element *elem;
Craig Tillerf5768a62015-09-22 10:54:34 -0700291 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Masood Malekghassemi76c3d742015-08-19 18:22:53 -0700292 GRPC_API_TRACE("grpc_channel_destroy(channel=%p)", 1, (channel));
Craig Tillera82950e2015-09-22 12:33:20 -0700293 memset(&op, 0, sizeof(op));
Craig Tiller98465032015-06-29 14:36:42 -0700294 op.disconnect = 1;
Craig Tillera82950e2015-09-22 12:33:20 -0700295 elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0);
296 elem->filter->start_transport_op(&exec_ctx, elem, &op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800297
Craig Tillera82950e2015-09-22 12:33:20 -0700298 GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, channel, "channel");
Craig Tillerdfff1b82015-09-21 14:39:57 -0700299
Craig Tillera82950e2015-09-22 12:33:20 -0700300 grpc_exec_ctx_finish(&exec_ctx);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800301}
302
Craig Tillera82950e2015-09-22 12:33:20 -0700303grpc_channel_stack *grpc_channel_get_channel_stack(grpc_channel *channel) {
304 return CHANNEL_STACK_FROM_CHANNEL(channel);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800305}
306
Craig Tillera82950e2015-09-22 12:33:20 -0700307grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_channel *channel, int i) {
Craig Tillerebdef9d2015-11-19 17:09:49 -0800308 char tmp[GPR_LTOA_MIN_BUFSIZE];
309 switch (i) {
310 case 0:
311 return GRPC_MDELEM_GRPC_STATUS_0;
312 case 1:
313 return GRPC_MDELEM_GRPC_STATUS_1;
314 case 2:
315 return GRPC_MDELEM_GRPC_STATUS_2;
Craig Tillera82950e2015-09-22 12:33:20 -0700316 }
Craig Tillerebdef9d2015-11-19 17:09:49 -0800317 gpr_ltoa(i, tmp);
Craig Tillerb2b42612015-11-20 12:02:17 -0800318 return grpc_mdelem_from_metadata_strings(GRPC_MDSTR_GRPC_STATUS,
319 grpc_mdstr_from_string(tmp));
Craig Tiller190d3602015-02-18 09:23:38 -0800320}
Craig Tillerfbf5be22015-04-22 16:17:09 -0700321
Craig Tiller7536af02015-12-22 13:49:30 -0800322uint32_t grpc_channel_get_max_message_length(grpc_channel *channel) {
Craig Tillerfbf5be22015-04-22 16:17:09 -0700323 return channel->max_message_length;
Craig Tiller09b49d72015-04-22 16:40:23 -0700324}