blob: c5cd5049297fc5bcdecae77d217f495016c88d4a [file] [log] [blame]
Craig Tilleraf691802015-06-23 14:57:07 -07001/*
2 *
Craig Tiller19482442016-01-25 09:59:20 -08003 * Copyright 2015-2016, Google Inc.
Craig Tilleraf691802015-06-23 14:57:07 -07004 * 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,
Craig Tiller892f2d32015-11-08 13:53:04 +000025 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Craig Tilleraf691802015-06-23 14:57:07 -070026 * 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/client_config/subchannel.h"
Craig Tiller2595ab72015-06-25 15:26:00 -070035
Craig Tillerf7afa1f2015-06-26 09:02:20 -070036#include <string.h>
37
Craig Tiller2595ab72015-06-25 15:26:00 -070038#include <grpc/support/alloc.h>
Craig Tiller694cf8b2016-01-15 21:13:25 -080039#include <grpc/support/avl.h>
Craig Tiller2595ab72015-06-25 15:26:00 -070040
Craig Tillereb3b12e2015-06-26 14:42:49 -070041#include "src/core/channel/channel_args.h"
Craig Tiller1ada6ad2015-07-16 16:19:14 -070042#include "src/core/channel/client_channel.h"
Craig Tillerff54c922015-06-26 16:57:20 -070043#include "src/core/channel/connected_channel.h"
yang-ga6124122015-11-05 22:36:20 -080044#include "src/core/client_config/initial_connect_string.h"
Craig Tiller7391f132016-01-22 06:39:54 -080045#include "src/core/client_config/subchannel_index.h"
David Garcia Quintasf747bbc2015-10-04 23:09:47 -070046#include "src/core/iomgr/timer.h"
Craig Tiller577c9b22015-11-02 14:11:15 -080047#include "src/core/profiling/timers.h"
Craig Tiller536fc532016-03-11 12:36:56 -080048#include "src/core/support/backoff.h"
Craig Tiller1ada6ad2015-07-16 16:19:14 -070049#include "src/core/surface/channel.h"
Craig Tiller121e7a92016-03-16 07:50:18 -070050#include "src/core/surface/channel_init.h"
Craig Tiller577c9b22015-11-02 14:11:15 -080051#include "src/core/transport/connectivity_state.h"
Craig Tillereb3b12e2015-06-26 14:42:49 -070052
Craig Tiller12ad5d62015-11-27 12:17:30 -080053#define INTERNAL_REF_BITS 16
54#define STRONG_REF_MASK (~(gpr_atm)((1 << INTERNAL_REF_BITS) - 1))
55
yang-gb4e262c2015-07-21 16:11:55 -070056#define GRPC_SUBCHANNEL_MIN_CONNECT_TIMEOUT_SECONDS 20
57#define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 1
58#define GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER 1.6
59#define GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS 120
60#define GRPC_SUBCHANNEL_RECONNECT_JITTER 0.2
61
Craig Tillerab33b482015-11-21 08:11:04 -080062#define GET_CONNECTED_SUBCHANNEL(subchannel, barrier) \
63 ((grpc_connected_subchannel *)(gpr_atm_##barrier##_load( \
64 &(subchannel)->connected_subchannel)))
Craig Tillerb5585d42015-11-17 07:18:31 -080065
Craig Tillera82950e2015-09-22 12:33:20 -070066typedef struct {
Craig Tiller33825112015-09-18 07:44:19 -070067 grpc_closure closure;
Craig Tiller48613042015-11-29 14:45:11 -080068 grpc_subchannel *subchannel;
Craig Tillerdf91ba52015-06-29 10:55:46 -070069 grpc_connectivity_state connectivity_state;
70} state_watcher;
71
Craig Tiller48613042015-11-29 14:45:11 -080072typedef struct external_state_watcher {
73 grpc_subchannel *subchannel;
74 grpc_pollset_set *pollset_set;
75 grpc_closure *notify;
76 grpc_closure closure;
77 struct external_state_watcher *next;
78 struct external_state_watcher *prev;
79} external_state_watcher;
80
Craig Tillera82950e2015-09-22 12:33:20 -070081struct grpc_subchannel {
Craig Tiller91624662015-06-25 16:31:02 -070082 grpc_connector *connector;
Craig Tillerf7afa1f2015-06-26 09:02:20 -070083
Craig Tiller1d881fb2015-12-01 07:39:04 -080084 /** refcount
85 - lower INTERNAL_REF_BITS bits are for internal references:
86 these do not keep the subchannel open.
Craig Tiller12ad5d62015-11-27 12:17:30 -080087 - upper remaining bits are for public references: these do
88 keep the subchannel open */
89 gpr_atm ref_pair;
Craig Tillerb5585d42015-11-17 07:18:31 -080090
Craig Tillerf7afa1f2015-06-26 09:02:20 -070091 /** non-transport related channel filters */
92 const grpc_channel_filter **filters;
Craig Tiller5945ee12015-06-27 10:36:09 -070093 size_t num_filters;
Craig Tillerf7afa1f2015-06-26 09:02:20 -070094 /** channel arguments */
95 grpc_channel_args *args;
96 /** address to connect to */
97 struct sockaddr *addr;
98 size_t addr_len;
Craig Tillereb3b12e2015-06-26 14:42:49 -070099
Craig Tiller7391f132016-01-22 06:39:54 -0800100 grpc_subchannel_key *key;
101
yang-ga6124122015-11-05 22:36:20 -0800102 /** initial string to send to peer */
103 gpr_slice initial_connect_string;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700104
105 /** set during connection */
Craig Tiller04c5d4b2015-06-26 17:21:41 -0700106 grpc_connect_out_args connecting_result;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700107
108 /** callback for connection finishing */
Craig Tiller33825112015-09-18 07:44:19 -0700109 grpc_closure connected;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700110
Craig Tiller5f84c842015-06-26 16:08:21 -0700111 /** pollset_set tracking who's interested in a connection
Craig Tiller906e3bc2015-11-24 07:31:31 -0800112 being setup */
Craig Tiller69b093b2016-02-25 19:04:07 -0800113 grpc_pollset_set *pollset_set;
Craig Tiller5f84c842015-06-26 16:08:21 -0700114
Craig Tillerb5585d42015-11-17 07:18:31 -0800115 /** active connection, or null; of type grpc_connected_subchannel */
116 gpr_atm connected_subchannel;
117
Craig Tillereb3b12e2015-06-26 14:42:49 -0700118 /** mutex protecting remaining elements */
119 gpr_mu mu;
120
Craig Tillerb5585d42015-11-17 07:18:31 -0800121 /** have we seen a disconnection? */
122 int disconnected;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700123 /** are we connecting */
124 int connecting;
Craig Tillerc7b5f762015-06-27 11:48:42 -0700125 /** connectivity state tracking */
126 grpc_connectivity_state_tracker state_tracker;
Craig Tillerff3ae682015-06-29 17:44:04 -0700127
Craig Tiller48613042015-11-29 14:45:11 -0800128 external_state_watcher root_external_state_watcher;
129
Craig Tillerff3ae682015-06-29 17:44:04 -0700130 /** next connect attempt time */
131 gpr_timespec next_attempt;
Craig Tiller536fc532016-03-11 12:36:56 -0800132 /** backoff state */
133 gpr_backoff backoff_state;
Craig Tillerff3ae682015-06-29 17:44:04 -0700134 /** do we have an active alarm? */
135 int have_alarm;
136 /** our alarm */
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700137 grpc_timer alarm;
yang-gb4e262c2015-07-21 16:11:55 -0700138 /** current random value */
Craig Tiller7536af02015-12-22 13:49:30 -0800139 uint32_t random;
Craig Tiller2595ab72015-06-25 15:26:00 -0700140};
141
Craig Tillera82950e2015-09-22 12:33:20 -0700142struct grpc_subchannel_call {
Craig Tillerb5585d42015-11-17 07:18:31 -0800143 grpc_connected_subchannel *connection;
Craig Tiller2595ab72015-06-25 15:26:00 -0700144};
145
Craig Tiller04c5d4b2015-06-26 17:21:41 -0700146#define SUBCHANNEL_CALL_TO_CALL_STACK(call) ((grpc_call_stack *)((call) + 1))
Craig Tiller906e3bc2015-11-24 07:31:31 -0800147#define CHANNEL_STACK_FROM_CONNECTION(con) ((grpc_channel_stack *)(con))
Craig Tiller577c9b22015-11-02 14:11:15 -0800148#define CALLSTACK_TO_SUBCHANNEL_CALL(callstack) \
149 (((grpc_subchannel_call *)(callstack)) - 1)
Craig Tiller2595ab72015-06-25 15:26:00 -0700150
Craig Tillera82950e2015-09-22 12:33:20 -0700151static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *subchannel,
Craig Tiller6c396862016-01-28 13:53:40 -0800152 bool iomgr_success);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700153
Craig Tiller577c9b22015-11-02 14:11:15 -0800154#ifdef GRPC_STREAM_REFCOUNT_DEBUG
Craig Tiller906e3bc2015-11-24 07:31:31 -0800155#define REF_REASON reason
Craig Tiller079a11b2015-06-30 10:07:15 -0700156#define REF_LOG(name, p) \
157 gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "%s: %p ref %d -> %d %s", \
Craig Tillerab33b482015-11-21 08:11:04 -0800158 (name), (p), (p)->refs.count, (p)->refs.count + 1, reason)
Craig Tiller079a11b2015-06-30 10:07:15 -0700159#define UNREF_LOG(name, p) \
160 gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "%s: %p unref %d -> %d %s", \
Craig Tillerab33b482015-11-21 08:11:04 -0800161 (name), (p), (p)->refs.count, (p)->refs.count - 1, reason)
Craig Tiller1d881fb2015-12-01 07:39:04 -0800162#define REF_MUTATE_EXTRA_ARGS \
163 GRPC_SUBCHANNEL_REF_EXTRA_ARGS, const char *purpose
Craig Tiller12ad5d62015-11-27 12:17:30 -0800164#define REF_MUTATE_PURPOSE(x) , file, line, reason, x
Craig Tillerc3967532015-06-29 14:59:38 -0700165#else
Craig Tiller906e3bc2015-11-24 07:31:31 -0800166#define REF_REASON ""
Craig Tiller11bf14e2015-06-29 16:35:41 -0700167#define REF_LOG(name, p) \
168 do { \
169 } while (0)
170#define UNREF_LOG(name, p) \
171 do { \
172 } while (0)
Craig Tiller12ad5d62015-11-27 12:17:30 -0800173#define REF_MUTATE_EXTRA_ARGS
174#define REF_MUTATE_PURPOSE(x)
Craig Tillerc3967532015-06-29 14:59:38 -0700175#endif
176
Craig Tiller2595ab72015-06-25 15:26:00 -0700177/*
Craig Tillerca3e9d32015-06-27 18:37:27 -0700178 * connection implementation
179 */
180
Craig Tillerab33b482015-11-21 08:11:04 -0800181static void connection_destroy(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller6c396862016-01-28 13:53:40 -0800182 bool success) {
Craig Tillerb5585d42015-11-17 07:18:31 -0800183 grpc_connected_subchannel *c = arg;
Craig Tillera82950e2015-09-22 12:33:20 -0700184 grpc_channel_stack_destroy(exec_ctx, CHANNEL_STACK_FROM_CONNECTION(c));
185 gpr_free(c);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700186}
187
Craig Tillerf40df232016-03-25 13:38:14 -0700188void grpc_connected_subchannel_ref(
189 grpc_connected_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller906e3bc2015-11-24 07:31:31 -0800190 GRPC_CHANNEL_STACK_REF(CHANNEL_STACK_FROM_CONNECTION(c), REF_REASON);
Craig Tillerd7b68e72015-06-28 11:41:09 -0700191}
192
Craig Tillerab33b482015-11-21 08:11:04 -0800193void grpc_connected_subchannel_unref(grpc_exec_ctx *exec_ctx,
194 grpc_connected_subchannel *c
195 GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller7b435612015-11-24 08:15:05 -0800196 GRPC_CHANNEL_STACK_UNREF(exec_ctx, CHANNEL_STACK_FROM_CONNECTION(c),
197 REF_REASON);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700198}
199
200/*
Craig Tiller2595ab72015-06-25 15:26:00 -0700201 * grpc_subchannel implementation
202 */
203
Craig Tillerab33b482015-11-21 08:11:04 -0800204static void subchannel_destroy(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller6c396862016-01-28 13:53:40 -0800205 bool success) {
Craig Tillerb5585d42015-11-17 07:18:31 -0800206 grpc_subchannel *c = arg;
Craig Tiller565b18b2015-09-23 10:09:42 -0700207 gpr_free((void *)c->filters);
Craig Tillera82950e2015-09-22 12:33:20 -0700208 grpc_channel_args_destroy(c->args);
209 gpr_free(c->addr);
yang-ga6124122015-11-05 22:36:20 -0800210 gpr_slice_unref(c->initial_connect_string);
Craig Tillera82950e2015-09-22 12:33:20 -0700211 grpc_connectivity_state_destroy(exec_ctx, &c->state_tracker);
212 grpc_connector_unref(exec_ctx, c->connector);
Craig Tiller69b093b2016-02-25 19:04:07 -0800213 grpc_pollset_set_destroy(c->pollset_set);
Craig Tiller19482442016-01-25 09:59:20 -0800214 grpc_subchannel_key_destroy(exec_ctx, c->key);
Craig Tillera82950e2015-09-22 12:33:20 -0700215 gpr_free(c);
Craig Tiller2595ab72015-06-25 15:26:00 -0700216}
217
Craig Tiller1d881fb2015-12-01 07:39:04 -0800218static gpr_atm ref_mutate(grpc_subchannel *c, gpr_atm delta,
219 int barrier REF_MUTATE_EXTRA_ARGS) {
220 gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta)
221 : gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta);
Craig Tiller12ad5d62015-11-27 12:17:30 -0800222#ifdef GRPC_STREAM_REFCOUNT_DEBUG
Craig Tiller1d881fb2015-12-01 07:39:04 -0800223 gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
224 "SUBCHANNEL: %p % 12s 0x%08x -> 0x%08x [%s]", c, purpose, old_val,
225 old_val + delta, reason);
Craig Tiller12ad5d62015-11-27 12:17:30 -0800226#endif
227 return old_val;
228}
229
Craig Tillerf40df232016-03-25 13:38:14 -0700230grpc_subchannel *grpc_subchannel_ref(
231 grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller12ad5d62015-11-27 12:17:30 -0800232 gpr_atm old_refs;
Craig Tiller1d881fb2015-12-01 07:39:04 -0800233 old_refs = ref_mutate(c, (1 << INTERNAL_REF_BITS),
234 0 REF_MUTATE_PURPOSE("STRONG_REF"));
Craig Tiller12ad5d62015-11-27 12:17:30 -0800235 GPR_ASSERT((old_refs & STRONG_REF_MASK) != 0);
Craig Tiller19482442016-01-25 09:59:20 -0800236 return c;
Craig Tiller12ad5d62015-11-27 12:17:30 -0800237}
238
Craig Tillerf40df232016-03-25 13:38:14 -0700239grpc_subchannel *grpc_subchannel_weak_ref(
240 grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller12ad5d62015-11-27 12:17:30 -0800241 gpr_atm old_refs;
242 old_refs = ref_mutate(c, 1, 0 REF_MUTATE_PURPOSE("WEAK_REF"));
243 GPR_ASSERT(old_refs != 0);
Craig Tiller19482442016-01-25 09:59:20 -0800244 return c;
Craig Tiller12ad5d62015-11-27 12:17:30 -0800245}
246
Craig Tiller5de79ee2016-01-25 08:16:02 -0800247grpc_subchannel *grpc_subchannel_ref_from_weak_ref(
248 grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller8cdba662016-01-22 20:01:55 -0800249 if (!c) return NULL;
250 for (;;) {
251 gpr_atm old_refs = gpr_atm_acq_load(&c->ref_pair);
252 if (old_refs >= (1 << INTERNAL_REF_BITS)) {
253 gpr_atm new_refs = old_refs + (1 << INTERNAL_REF_BITS);
254 if (gpr_atm_rel_cas(&c->ref_pair, old_refs, new_refs)) {
255 return c;
256 }
257 } else {
258 return NULL;
259 }
260 }
261}
262
Craig Tiller12ad5d62015-11-27 12:17:30 -0800263static void disconnect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
264 grpc_connected_subchannel *con;
Craig Tiller7391f132016-01-22 06:39:54 -0800265 grpc_subchannel_index_unregister(exec_ctx, c->key, c);
Craig Tiller12ad5d62015-11-27 12:17:30 -0800266 gpr_mu_lock(&c->mu);
267 GPR_ASSERT(!c->disconnected);
268 c->disconnected = 1;
Craig Tillercaa4e702015-12-01 06:55:25 -0800269 grpc_connector_shutdown(exec_ctx, c->connector);
Craig Tiller12ad5d62015-11-27 12:17:30 -0800270 con = GET_CONNECTED_SUBCHANNEL(c, no_barrier);
271 if (con != NULL) {
272 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, con, "connection");
273 gpr_atm_no_barrier_store(&c->connected_subchannel, 0xdeadbeef);
274 }
275 gpr_mu_unlock(&c->mu);
Craig Tillerb5585d42015-11-17 07:18:31 -0800276}
277
278void grpc_subchannel_unref(grpc_exec_ctx *exec_ctx,
279 grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller12ad5d62015-11-27 12:17:30 -0800280 gpr_atm old_refs;
Craig Tiller1d881fb2015-12-01 07:39:04 -0800281 old_refs = ref_mutate(c, (gpr_atm)1 - (gpr_atm)(1 << INTERNAL_REF_BITS),
282 1 REF_MUTATE_PURPOSE("STRONG_UNREF"));
Craig Tiller50ec2672015-11-27 21:45:11 -0800283 if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) {
Craig Tiller12ad5d62015-11-27 12:17:30 -0800284 disconnect(exec_ctx, c);
285 }
286 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "strong-unref");
287}
288
289void grpc_subchannel_weak_unref(grpc_exec_ctx *exec_ctx,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800290 grpc_subchannel *c
291 GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller12ad5d62015-11-27 12:17:30 -0800292 gpr_atm old_refs;
293 old_refs = ref_mutate(c, -(gpr_atm)1, 1 REF_MUTATE_PURPOSE("WEAK_UNREF"));
Craig Tillerf036a642015-12-01 17:00:40 -0800294 if (old_refs == 1) {
Craig Tillerab33b482015-11-21 08:11:04 -0800295 grpc_exec_ctx_enqueue(exec_ctx, grpc_closure_create(subchannel_destroy, c),
Craig Tiller6c396862016-01-28 13:53:40 -0800296 true, NULL);
Craig Tillerb5585d42015-11-17 07:18:31 -0800297 }
298}
299
Craig Tiller7536af02015-12-22 13:49:30 -0800300static uint32_t random_seed() {
301 return (uint32_t)(gpr_time_to_millis(gpr_now(GPR_CLOCK_MONOTONIC)));
yang-gb4e262c2015-07-21 16:11:55 -0700302}
303
Craig Tiller7391f132016-01-22 06:39:54 -0800304grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
305 grpc_connector *connector,
Craig Tillera82950e2015-09-22 12:33:20 -0700306 grpc_subchannel_args *args) {
Craig Tiller7391f132016-01-22 06:39:54 -0800307 grpc_subchannel_key *key = grpc_subchannel_key_create(connector, args);
308 grpc_subchannel *c = grpc_subchannel_index_find(exec_ctx, key);
309 if (c) {
Craig Tiller19482442016-01-25 09:59:20 -0800310 grpc_subchannel_key_destroy(exec_ctx, key);
Craig Tiller7391f132016-01-22 06:39:54 -0800311 return c;
312 }
313
314 c = gpr_malloc(sizeof(*c));
Craig Tillera82950e2015-09-22 12:33:20 -0700315 memset(c, 0, sizeof(*c));
Craig Tiller7391f132016-01-22 06:39:54 -0800316 c->key = key;
Craig Tiller12ad5d62015-11-27 12:17:30 -0800317 gpr_atm_no_barrier_store(&c->ref_pair, 1 << INTERNAL_REF_BITS);
Craig Tillerf7afa1f2015-06-26 09:02:20 -0700318 c->connector = connector;
Craig Tillera82950e2015-09-22 12:33:20 -0700319 grpc_connector_ref(c->connector);
Craig Tiller5945ee12015-06-27 10:36:09 -0700320 c->num_filters = args->filter_count;
Craig Tillerb9c55052016-01-27 15:22:48 -0800321 if (c->num_filters > 0) {
322 c->filters = gpr_malloc(sizeof(grpc_channel_filter *) * c->num_filters);
323 memcpy((void *)c->filters, args->filters,
324 sizeof(grpc_channel_filter *) * c->num_filters);
325 } else {
326 c->filters = NULL;
327 }
Craig Tillera82950e2015-09-22 12:33:20 -0700328 c->addr = gpr_malloc(args->addr_len);
329 memcpy(c->addr, args->addr, args->addr_len);
Craig Tiller69b093b2016-02-25 19:04:07 -0800330 c->pollset_set = grpc_pollset_set_create();
Craig Tillerf7afa1f2015-06-26 09:02:20 -0700331 c->addr_len = args->addr_len;
yang-ga6124122015-11-05 22:36:20 -0800332 grpc_set_initial_connect_string(&c->addr, &c->addr_len,
333 &c->initial_connect_string);
Craig Tillera82950e2015-09-22 12:33:20 -0700334 c->args = grpc_channel_args_copy(args->args);
Craig Tillera82950e2015-09-22 12:33:20 -0700335 c->random = random_seed();
Craig Tiller1d881fb2015-12-01 07:39:04 -0800336 c->root_external_state_watcher.next = c->root_external_state_watcher.prev =
337 &c->root_external_state_watcher;
Craig Tillera82950e2015-09-22 12:33:20 -0700338 grpc_closure_init(&c->connected, subchannel_connected, c);
339 grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE,
340 "subchannel");
Craig Tiller536fc532016-03-11 12:36:56 -0800341 gpr_backoff_init(&c->backoff_state,
342 GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER,
343 GRPC_SUBCHANNEL_RECONNECT_JITTER,
344 GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000,
345 GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS * 1000);
346 if (c->args) {
347 for (size_t i = 0; i < c->args->num_args; i++) {
348 if (0 == strcmp(c->args->args[i].key,
349 "grpc.testing.fixed_reconnect_backoff")) {
350 GPR_ASSERT(c->args->args[i].type == GRPC_ARG_INTEGER);
351 gpr_backoff_init(&c->backoff_state, 1.0, 0.0,
352 c->args->args[i].value.integer,
353 c->args->args[i].value.integer);
354 }
355 }
356 }
Craig Tillera82950e2015-09-22 12:33:20 -0700357 gpr_mu_init(&c->mu);
Craig Tiller7391f132016-01-22 06:39:54 -0800358
359 return grpc_subchannel_index_register(exec_ctx, key, c);
Craig Tillerf7afa1f2015-06-26 09:02:20 -0700360}
361
Craig Tillera82950e2015-09-22 12:33:20 -0700362static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
Craig Tiller4ab82d22015-06-29 09:40:33 -0700363 grpc_connect_in_args args;
Craig Tiller04c5d4b2015-06-26 17:21:41 -0700364
Craig Tiller69b093b2016-02-25 19:04:07 -0800365 args.interested_parties = c->pollset_set;
Craig Tiller4ab82d22015-06-29 09:40:33 -0700366 args.addr = c->addr;
367 args.addr_len = c->addr_len;
Craig Tiller536fc532016-03-11 12:36:56 -0800368 args.deadline = c->next_attempt;
Craig Tiller4ab82d22015-06-29 09:40:33 -0700369 args.channel_args = c->args;
yang-ga6124122015-11-05 22:36:20 -0800370 args.initial_connect_string = c->initial_connect_string;
Craig Tiller04c5d4b2015-06-26 17:21:41 -0700371
Craig Tillerab33b482015-11-21 08:11:04 -0800372 grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
373 GRPC_CHANNEL_CONNECTING, "state_change");
Craig Tillera82950e2015-09-22 12:33:20 -0700374 grpc_connector_connect(exec_ctx, c->connector, &args, &c->connecting_result,
375 &c->connected);
Craig Tiller04c5d4b2015-06-26 17:21:41 -0700376}
377
Craig Tillera82950e2015-09-22 12:33:20 -0700378static void start_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
Craig Tillera82950e2015-09-22 12:33:20 -0700379 c->next_attempt =
Craig Tiller536fc532016-03-11 12:36:56 -0800380 gpr_backoff_begin(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
Craig Tillera82950e2015-09-22 12:33:20 -0700381 continue_connect(exec_ctx, c);
Craig Tillerff3ae682015-06-29 17:44:04 -0700382}
383
Craig Tillera82950e2015-09-22 12:33:20 -0700384grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel *c) {
Craig Tiller5f84c842015-06-26 16:08:21 -0700385 grpc_connectivity_state state;
Craig Tillera82950e2015-09-22 12:33:20 -0700386 gpr_mu_lock(&c->mu);
387 state = grpc_connectivity_state_check(&c->state_tracker);
388 gpr_mu_unlock(&c->mu);
Craig Tiller5f84c842015-06-26 16:08:21 -0700389 return state;
390}
391
Craig Tiller1d881fb2015-12-01 07:39:04 -0800392static void on_external_state_watcher_done(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller6c396862016-01-28 13:53:40 -0800393 bool success) {
Craig Tiller86c99582015-11-25 15:22:26 -0800394 external_state_watcher *w = arg;
395 grpc_closure *follow_up = w->notify;
Craig Tiller48613042015-11-29 14:45:11 -0800396 if (w->pollset_set != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800397 grpc_pollset_set_del_pollset_set(exec_ctx, w->subchannel->pollset_set,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800398 w->pollset_set);
Craig Tiller48613042015-11-29 14:45:11 -0800399 }
400 gpr_mu_lock(&w->subchannel->mu);
401 w->next->prev = w->prev;
402 w->prev->next = w->next;
403 gpr_mu_unlock(&w->subchannel->mu);
Craig Tiller12ad5d62015-11-27 12:17:30 -0800404 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, w->subchannel, "external_state_watcher");
Craig Tiller86c99582015-11-25 15:22:26 -0800405 gpr_free(w);
406 follow_up->cb(exec_ctx, follow_up->cb_arg, success);
407}
408
Craig Tiller1d881fb2015-12-01 07:39:04 -0800409void grpc_subchannel_notify_on_state_change(
410 grpc_exec_ctx *exec_ctx, grpc_subchannel *c,
411 grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
412 grpc_closure *notify) {
Craig Tiller48613042015-11-29 14:45:11 -0800413 external_state_watcher *w;
414
415 if (state == NULL) {
416 gpr_mu_lock(&c->mu);
Craig Tiller1d881fb2015-12-01 07:39:04 -0800417 for (w = c->root_external_state_watcher.next;
418 w != &c->root_external_state_watcher; w = w->next) {
Craig Tiller48613042015-11-29 14:45:11 -0800419 if (w->notify == notify) {
Craig Tiller1d881fb2015-12-01 07:39:04 -0800420 grpc_connectivity_state_notify_on_state_change(
421 exec_ctx, &c->state_tracker, NULL, &w->closure);
Craig Tiller48613042015-11-29 14:45:11 -0800422 }
423 }
424 gpr_mu_unlock(&c->mu);
425 } else {
426 w = gpr_malloc(sizeof(*w));
427 w->subchannel = c;
428 w->pollset_set = interested_parties;
429 w->notify = notify;
430 grpc_closure_init(&w->closure, on_external_state_watcher_done, w);
431 if (interested_parties != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800432 grpc_pollset_set_add_pollset_set(exec_ctx, c->pollset_set,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800433 interested_parties);
Craig Tiller48613042015-11-29 14:45:11 -0800434 }
435 GRPC_SUBCHANNEL_WEAK_REF(c, "external_state_watcher");
436 gpr_mu_lock(&c->mu);
437 w->next = &c->root_external_state_watcher;
438 w->prev = w->next->prev;
439 w->next->prev = w->prev->next = w;
440 if (grpc_connectivity_state_notify_on_state_change(
441 exec_ctx, &c->state_tracker, state, &w->closure)) {
Craig Tiller48613042015-11-29 14:45:11 -0800442 c->connecting = 1;
443 /* released by connection */
444 GRPC_SUBCHANNEL_WEAK_REF(c, "connecting");
Craig Tiller8e19f612016-03-01 21:41:13 -0800445 start_connect(exec_ctx, c);
Craig Tiller48613042015-11-29 14:45:11 -0800446 }
447 gpr_mu_unlock(&c->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700448 }
Craig Tiller5f84c842015-06-26 16:08:21 -0700449}
450
Craig Tillerab33b482015-11-21 08:11:04 -0800451void grpc_connected_subchannel_process_transport_op(
452 grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
453 grpc_transport_op *op) {
Craig Tillerb5585d42015-11-17 07:18:31 -0800454 grpc_channel_stack *channel_stack = CHANNEL_STACK_FROM_CONNECTION(con);
Craig Tillerab33b482015-11-21 08:11:04 -0800455 grpc_channel_element *top_elem = grpc_channel_stack_element(channel_stack, 0);
Craig Tillerb5585d42015-11-17 07:18:31 -0800456 top_elem->filter->start_transport_op(exec_ctx, top_elem, op);
457}
458
459static void subchannel_on_child_state_changed(grpc_exec_ctx *exec_ctx, void *p,
Craig Tiller6c396862016-01-28 13:53:40 -0800460 bool iomgr_success) {
Craig Tillerdf91ba52015-06-29 10:55:46 -0700461 state_watcher *sw = p;
Craig Tiller48613042015-11-29 14:45:11 -0800462 grpc_subchannel *c = sw->subchannel;
Craig Tillerdf91ba52015-06-29 10:55:46 -0700463 gpr_mu *mu = &c->mu;
Craig Tillerdf91ba52015-06-29 10:55:46 -0700464
Craig Tillera82950e2015-09-22 12:33:20 -0700465 gpr_mu_lock(mu);
Craig Tillerdf91ba52015-06-29 10:55:46 -0700466
Craig Tillerb5585d42015-11-17 07:18:31 -0800467 /* if we failed just leave this closure */
468 if (iomgr_success) {
Craig Tiller2c174942015-11-24 16:51:23 -0800469 if (sw->connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
470 /* any errors on a subchannel ==> we're done, create a new one */
471 sw->connectivity_state = GRPC_CHANNEL_FATAL_FAILURE;
472 }
Craig Tillerab33b482015-11-21 08:11:04 -0800473 grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
474 sw->connectivity_state, "reflect_child");
Craig Tillerb5585d42015-11-17 07:18:31 -0800475 if (sw->connectivity_state != GRPC_CHANNEL_FATAL_FAILURE) {
Craig Tillerab33b482015-11-21 08:11:04 -0800476 grpc_connected_subchannel_notify_on_state_change(
Craig Tillerf036a642015-12-01 17:00:40 -0800477 exec_ctx, GET_CONNECTED_SUBCHANNEL(c, no_barrier), NULL,
Craig Tillerab33b482015-11-21 08:11:04 -0800478 &sw->connectivity_state, &sw->closure);
Craig Tiller12ad5d62015-11-27 12:17:30 -0800479 GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
Craig Tillerb5585d42015-11-17 07:18:31 -0800480 sw = NULL;
481 }
Craig Tillera82950e2015-09-22 12:33:20 -0700482 }
Craig Tillerdf91ba52015-06-29 10:55:46 -0700483
Craig Tillera82950e2015-09-22 12:33:20 -0700484 gpr_mu_unlock(mu);
Craig Tiller12ad5d62015-11-27 12:17:30 -0800485 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "state_watcher");
Craig Tillerb5585d42015-11-17 07:18:31 -0800486 gpr_free(sw);
487}
488
Craig Tillerab33b482015-11-21 08:11:04 -0800489static void connected_subchannel_state_op(grpc_exec_ctx *exec_ctx,
490 grpc_connected_subchannel *con,
Craig Tillerf036a642015-12-01 17:00:40 -0800491 grpc_pollset_set *interested_parties,
Craig Tillerab33b482015-11-21 08:11:04 -0800492 grpc_connectivity_state *state,
493 grpc_closure *closure) {
Craig Tillerb5585d42015-11-17 07:18:31 -0800494 grpc_transport_op op;
495 grpc_channel_element *elem;
496 memset(&op, 0, sizeof(op));
497 op.connectivity_state = state;
498 op.on_connectivity_state_change = closure;
Craig Tillerf036a642015-12-01 17:00:40 -0800499 op.bind_pollset_set = interested_parties;
Craig Tillerb5585d42015-11-17 07:18:31 -0800500 elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0);
501 elem->filter->start_transport_op(exec_ctx, elem, &op);
502}
503
Craig Tillerab33b482015-11-21 08:11:04 -0800504void grpc_connected_subchannel_notify_on_state_change(
505 grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
Craig Tillera6bebf42015-12-01 17:02:35 -0800506 grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
507 grpc_closure *closure) {
508 connected_subchannel_state_op(exec_ctx, con, interested_parties, state,
509 closure);
Craig Tillerb5585d42015-11-17 07:18:31 -0800510}
511
Craig Tillere2c62372015-12-07 16:11:03 -0800512void grpc_connected_subchannel_ping(grpc_exec_ctx *exec_ctx,
513 grpc_connected_subchannel *con,
514 grpc_closure *closure) {
Craig Tiller28bf8912015-12-07 16:07:04 -0800515 grpc_transport_op op;
516 grpc_channel_element *elem;
517 memset(&op, 0, sizeof(op));
518 op.send_ping = closure;
519 elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0);
520 elem->filter->start_transport_op(exec_ctx, elem, &op);
521}
522
Craig Tiller35914822016-03-11 19:29:23 -0800523static void publish_transport_locked(grpc_exec_ctx *exec_ctx,
524 grpc_subchannel *c) {
Craig Tillerb5585d42015-11-17 07:18:31 -0800525 grpc_connected_subchannel *con;
Craig Tiller4ab82d22015-06-29 09:40:33 -0700526 grpc_channel_stack *stk;
Craig Tillerb5585d42015-11-17 07:18:31 -0800527 state_watcher *sw_subchannel;
Craig Tiller5945ee12015-06-27 10:36:09 -0700528
Craig Tillerdf91ba52015-06-29 10:55:46 -0700529 /* construct channel stack */
Craig Tiller178edfa2016-02-17 20:54:46 -0800530 con = grpc_channel_init_create_stack(
531 exec_ctx, GRPC_CLIENT_SUBCHANNEL, 0, c->connecting_result.channel_args, 1,
532 connection_destroy, NULL, c->connecting_result.transport);
Craig Tiller906e3bc2015-11-24 07:31:31 -0800533 stk = CHANNEL_STACK_FROM_CONNECTION(con);
Craig Tillera82950e2015-09-22 12:33:20 -0700534 memset(&c->connecting_result, 0, sizeof(c->connecting_result));
Craig Tillerff54c922015-06-26 16:57:20 -0700535
Craig Tillerdf91ba52015-06-29 10:55:46 -0700536 /* initialize state watcher */
Craig Tillerb5585d42015-11-17 07:18:31 -0800537 sw_subchannel = gpr_malloc(sizeof(*sw_subchannel));
Craig Tiller48613042015-11-29 14:45:11 -0800538 sw_subchannel->subchannel = c;
Craig Tillerb5585d42015-11-17 07:18:31 -0800539 sw_subchannel->connectivity_state = GRPC_CHANNEL_READY;
Craig Tillerab33b482015-11-21 08:11:04 -0800540 grpc_closure_init(&sw_subchannel->closure, subchannel_on_child_state_changed,
541 sw_subchannel);
Craig Tillerdf91ba52015-06-29 10:55:46 -0700542
Craig Tillera82950e2015-09-22 12:33:20 -0700543 if (c->disconnected) {
Craig Tillerb5585d42015-11-17 07:18:31 -0800544 gpr_free(sw_subchannel);
Craig Tillera82950e2015-09-22 12:33:20 -0700545 grpc_channel_stack_destroy(exec_ctx, stk);
Craig Tiller50ec2672015-11-27 21:45:11 -0800546 gpr_free(con);
547 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
Craig Tillera82950e2015-09-22 12:33:20 -0700548 return;
549 }
Craig Tillerb6fbf1d2015-06-29 15:25:49 -0700550
Craig Tillerdf91ba52015-06-29 10:55:46 -0700551 /* publish */
Craig Tiller493c1512016-01-27 11:55:44 -0800552 /* TODO(ctiller): this full barrier seems to clear up a TSAN failure.
553 I'd have expected the rel_cas below to be enough, but
554 seemingly it's not.
555 Re-evaluate if we really need this. */
Craig Tiller9ebc87a2016-01-26 15:10:09 +0000556 gpr_atm_full_barrier();
Craig Tillerd9d474a2016-01-26 06:50:51 -0800557 GPR_ASSERT(gpr_atm_rel_cas(&c->connected_subchannel, 0, (gpr_atm)con));
Craig Tiller4ab82d22015-06-29 09:40:33 -0700558 c->connecting = 0;
Craig Tillerdf91ba52015-06-29 10:55:46 -0700559
Craig Tillerab33b482015-11-21 08:11:04 -0800560 /* setup subchannel watching connected subchannel for changes; subchannel ref
561 for connecting is donated
Craig Tillerdf91ba52015-06-29 10:55:46 -0700562 to the state watcher */
Craig Tiller12ad5d62015-11-27 12:17:30 -0800563 GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
Craig Tiller50ec2672015-11-27 21:45:11 -0800564 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
Craig Tillerab33b482015-11-21 08:11:04 -0800565 grpc_connected_subchannel_notify_on_state_change(
Craig Tiller69b093b2016-02-25 19:04:07 -0800566 exec_ctx, con, c->pollset_set, &sw_subchannel->connectivity_state,
Craig Tillerab33b482015-11-21 08:11:04 -0800567 &sw_subchannel->closure);
Craig Tillerdf91ba52015-06-29 10:55:46 -0700568
569 /* signal completion */
Craig Tillerab33b482015-11-21 08:11:04 -0800570 grpc_connectivity_state_set(exec_ctx, &c->state_tracker, GRPC_CHANNEL_READY,
571 "connected");
Craig Tiller4ab82d22015-06-29 09:40:33 -0700572}
Craig Tillerff54c922015-06-26 16:57:20 -0700573
Craig Tiller6c396862016-01-28 13:53:40 -0800574static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, bool iomgr_success) {
Craig Tillerff3ae682015-06-29 17:44:04 -0700575 grpc_subchannel *c = arg;
Craig Tillera82950e2015-09-22 12:33:20 -0700576 gpr_mu_lock(&c->mu);
Craig Tillerff3ae682015-06-29 17:44:04 -0700577 c->have_alarm = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700578 if (c->disconnected) {
579 iomgr_success = 0;
580 }
Craig Tillera82950e2015-09-22 12:33:20 -0700581 if (iomgr_success) {
Craig Tiller536fc532016-03-11 12:36:56 -0800582 c->next_attempt =
583 gpr_backoff_step(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
Craig Tillera82950e2015-09-22 12:33:20 -0700584 continue_connect(exec_ctx, c);
Craig Tiller8e19f612016-03-01 21:41:13 -0800585 gpr_mu_unlock(&c->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700586 } else {
Craig Tiller8e19f612016-03-01 21:41:13 -0800587 gpr_mu_unlock(&c->mu);
Craig Tiller50ec2672015-11-27 21:45:11 -0800588 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
Craig Tillera82950e2015-09-22 12:33:20 -0700589 }
Craig Tiller45724b32015-09-22 10:42:19 -0700590}
591
Craig Tillera82950e2015-09-22 12:33:20 -0700592static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller6c396862016-01-28 13:53:40 -0800593 bool iomgr_success) {
Craig Tiller45724b32015-09-22 10:42:19 -0700594 grpc_subchannel *c = arg;
Craig Tiller50ec2672015-11-27 21:45:11 -0800595
Craig Tiller2ba41332016-03-11 17:09:12 -0800596 GRPC_SUBCHANNEL_WEAK_REF(c, "connected");
597 gpr_mu_lock(&c->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700598 if (c->connecting_result.transport != NULL) {
Craig Tiller35914822016-03-11 19:29:23 -0800599 publish_transport_locked(exec_ctx, c);
Craig Tillerb5585d42015-11-17 07:18:31 -0800600 } else if (c->disconnected) {
Craig Tiller50ec2672015-11-27 21:45:11 -0800601 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
Craig Tillera82950e2015-09-22 12:33:20 -0700602 } else {
603 gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
Craig Tillera82950e2015-09-22 12:33:20 -0700604 GPR_ASSERT(!c->have_alarm);
605 c->have_alarm = 1;
Craig Tillerab33b482015-11-21 08:11:04 -0800606 grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
607 GRPC_CHANNEL_TRANSIENT_FAILURE,
608 "connect_failed");
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700609 grpc_timer_init(exec_ctx, &c->alarm, c->next_attempt, on_alarm, c, now);
Craig Tillera82950e2015-09-22 12:33:20 -0700610 }
Craig Tiller2ba41332016-03-11 17:09:12 -0800611 gpr_mu_unlock(&c->mu);
612 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
Craig Tiller45724b32015-09-22 10:42:19 -0700613}
614
Craig Tiller2595ab72015-06-25 15:26:00 -0700615/*
616 * grpc_subchannel_call implementation
617 */
618
Craig Tiller577c9b22015-11-02 14:11:15 -0800619static void subchannel_call_destroy(grpc_exec_ctx *exec_ctx, void *call,
Craig Tiller6c396862016-01-28 13:53:40 -0800620 bool success) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800621 grpc_subchannel_call *c = call;
Craig Tiller577c9b22015-11-02 14:11:15 -0800622 GPR_TIMER_BEGIN("grpc_subchannel_call_unref.destroy", 0);
623 grpc_call_stack_destroy(exec_ctx, SUBCHANNEL_CALL_TO_CALL_STACK(c));
Craig Tiller53ee0402015-11-25 09:07:09 -0800624 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, c->connection, "subchannel_call");
Craig Tiller577c9b22015-11-02 14:11:15 -0800625 gpr_free(c);
Craig Tiller577c9b22015-11-02 14:11:15 -0800626 GPR_TIMER_END("grpc_subchannel_call_unref.destroy", 0);
627}
628
Craig Tillerf40df232016-03-25 13:38:14 -0700629void grpc_subchannel_call_ref(
630 grpc_subchannel_call *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller906e3bc2015-11-24 07:31:31 -0800631 GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON);
Craig Tillerc3967532015-06-29 14:59:38 -0700632}
Craig Tiller2595ab72015-06-25 15:26:00 -0700633
Craig Tillera82950e2015-09-22 12:33:20 -0700634void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx,
635 grpc_subchannel_call *c
636 GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller906e3bc2015-11-24 07:31:31 -0800637 GRPC_CALL_STACK_UNREF(exec_ctx, SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON);
Craig Tiller2595ab72015-06-25 15:26:00 -0700638}
639
Craig Tillera82950e2015-09-22 12:33:20 -0700640char *grpc_subchannel_call_get_peer(grpc_exec_ctx *exec_ctx,
641 grpc_subchannel_call *call) {
642 grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);
643 grpc_call_element *top_elem = grpc_call_stack_element(call_stack, 0);
644 return top_elem->filter->get_peer(exec_ctx, top_elem);
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700645}
646
Craig Tillera82950e2015-09-22 12:33:20 -0700647void grpc_subchannel_call_process_op(grpc_exec_ctx *exec_ctx,
648 grpc_subchannel_call *call,
649 grpc_transport_stream_op *op) {
650 grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);
651 grpc_call_element *top_elem = grpc_call_stack_element(call_stack, 0);
652 top_elem->filter->start_transport_stream_op(exec_ctx, top_elem, op);
Craig Tiller2595ab72015-06-25 15:26:00 -0700653}
Craig Tillereb3b12e2015-06-26 14:42:49 -0700654
Craig Tillerab33b482015-11-21 08:11:04 -0800655grpc_connected_subchannel *grpc_subchannel_get_connected_subchannel(
656 grpc_subchannel *c) {
Craig Tillerb5585d42015-11-17 07:18:31 -0800657 return GET_CONNECTED_SUBCHANNEL(c, acq);
658}
659
Craig Tillerab33b482015-11-21 08:11:04 -0800660grpc_subchannel_call *grpc_connected_subchannel_create_call(
661 grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
662 grpc_pollset *pollset) {
Craig Tillera82950e2015-09-22 12:33:20 -0700663 grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con);
664 grpc_subchannel_call *call =
665 gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
666 grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(call);
Craig Tiller04c5d4b2015-06-26 17:21:41 -0700667 call->connection = con;
Craig Tiller53ee0402015-11-25 09:07:09 -0800668 GRPC_CONNECTED_SUBCHANNEL_REF(con, "subchannel_call");
Craig Tiller577c9b22015-11-02 14:11:15 -0800669 grpc_call_stack_init(exec_ctx, chanstk, 1, subchannel_call_destroy, call,
670 NULL, NULL, callstk);
671 grpc_call_stack_set_pollset(exec_ctx, callstk, pollset);
Craig Tiller04c5d4b2015-06-26 17:21:41 -0700672 return call;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700673}
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700674
Craig Tiller577c9b22015-11-02 14:11:15 -0800675grpc_call_stack *grpc_subchannel_call_get_call_stack(
676 grpc_subchannel_call *subchannel_call) {
677 return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call);
678}