blob: 125a291f211f4d11c95499cc5e02cc818260203e [file] [log] [blame]
Craig Tilleraf691802015-06-23 14:57:07 -07001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, 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
Craig Tillerd4c98332016-03-31 13:45:47 -070034#include "src/core/ext/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 Tillerd4c98332016-03-31 13:45:47 -070041#include "src/core/ext/client_config/client_channel.h"
Craig Tillerd4c98332016-03-31 13:45:47 -070042#include "src/core/ext/client_config/initial_connect_string.h"
43#include "src/core/ext/client_config/subchannel_index.h"
Craig Tiller4a6dad32016-04-01 13:51:14 -070044#include "src/core/lib/channel/channel_args.h"
45#include "src/core/lib/channel/connected_channel.h"
Craig Tiller9533d042016-03-25 17:11:06 -070046#include "src/core/lib/iomgr/timer.h"
47#include "src/core/lib/profiling/timers.h"
48#include "src/core/lib/support/backoff.h"
49#include "src/core/lib/surface/channel.h"
50#include "src/core/lib/surface/channel_init.h"
51#include "src/core/lib/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
Craig Tillera95f1b52016-03-31 16:58:19 -070057#define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 2
yang-gb4e262c2015-07-21 16:11:55 -070058#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 }
Craig Tiller076c2b82016-03-30 17:12:29 -0700355 if (0 ==
356 strcmp(c->args->args[i].key, GRPC_ARG_MAX_RECONNECT_BACKOFF_MS)) {
357 if (c->args->args[i].type == GRPC_ARG_INTEGER) {
358 if (c->args->args[i].value.integer >= 0) {
359 gpr_backoff_init(
360 &c->backoff_state, GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER,
361 GRPC_SUBCHANNEL_RECONNECT_JITTER,
362 GPR_MIN(c->args->args[i].value.integer,
363 GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000),
364 c->args->args[i].value.integer);
365 } else {
366 gpr_log(GPR_ERROR, GRPC_ARG_MAX_RECONNECT_BACKOFF_MS
367 " : must be non-negative");
368 }
369 } else {
370 gpr_log(GPR_ERROR,
371 GRPC_ARG_MAX_RECONNECT_BACKOFF_MS " : must be an integer");
372 }
373 }
Craig Tiller536fc532016-03-11 12:36:56 -0800374 }
375 }
Craig Tillera82950e2015-09-22 12:33:20 -0700376 gpr_mu_init(&c->mu);
Craig Tiller7391f132016-01-22 06:39:54 -0800377
378 return grpc_subchannel_index_register(exec_ctx, key, c);
Craig Tillerf7afa1f2015-06-26 09:02:20 -0700379}
380
Craig Tillera82950e2015-09-22 12:33:20 -0700381static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
Craig Tiller4ab82d22015-06-29 09:40:33 -0700382 grpc_connect_in_args args;
Craig Tiller04c5d4b2015-06-26 17:21:41 -0700383
Craig Tiller69b093b2016-02-25 19:04:07 -0800384 args.interested_parties = c->pollset_set;
Craig Tiller4ab82d22015-06-29 09:40:33 -0700385 args.addr = c->addr;
386 args.addr_len = c->addr_len;
Craig Tiller536fc532016-03-11 12:36:56 -0800387 args.deadline = c->next_attempt;
Craig Tiller4ab82d22015-06-29 09:40:33 -0700388 args.channel_args = c->args;
yang-ga6124122015-11-05 22:36:20 -0800389 args.initial_connect_string = c->initial_connect_string;
Craig Tiller04c5d4b2015-06-26 17:21:41 -0700390
Craig Tillerab33b482015-11-21 08:11:04 -0800391 grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
392 GRPC_CHANNEL_CONNECTING, "state_change");
Craig Tillera82950e2015-09-22 12:33:20 -0700393 grpc_connector_connect(exec_ctx, c->connector, &args, &c->connecting_result,
394 &c->connected);
Craig Tiller04c5d4b2015-06-26 17:21:41 -0700395}
396
Craig Tillera82950e2015-09-22 12:33:20 -0700397static void start_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
Craig Tillera82950e2015-09-22 12:33:20 -0700398 c->next_attempt =
Craig Tiller536fc532016-03-11 12:36:56 -0800399 gpr_backoff_begin(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
Craig Tillera82950e2015-09-22 12:33:20 -0700400 continue_connect(exec_ctx, c);
Craig Tillerff3ae682015-06-29 17:44:04 -0700401}
402
Craig Tillera82950e2015-09-22 12:33:20 -0700403grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel *c) {
Craig Tiller5f84c842015-06-26 16:08:21 -0700404 grpc_connectivity_state state;
Craig Tillera82950e2015-09-22 12:33:20 -0700405 gpr_mu_lock(&c->mu);
406 state = grpc_connectivity_state_check(&c->state_tracker);
407 gpr_mu_unlock(&c->mu);
Craig Tiller5f84c842015-06-26 16:08:21 -0700408 return state;
409}
410
Craig Tiller1d881fb2015-12-01 07:39:04 -0800411static void on_external_state_watcher_done(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller6c396862016-01-28 13:53:40 -0800412 bool success) {
Craig Tiller86c99582015-11-25 15:22:26 -0800413 external_state_watcher *w = arg;
414 grpc_closure *follow_up = w->notify;
Craig Tiller48613042015-11-29 14:45:11 -0800415 if (w->pollset_set != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800416 grpc_pollset_set_del_pollset_set(exec_ctx, w->subchannel->pollset_set,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800417 w->pollset_set);
Craig Tiller48613042015-11-29 14:45:11 -0800418 }
419 gpr_mu_lock(&w->subchannel->mu);
420 w->next->prev = w->prev;
421 w->prev->next = w->next;
422 gpr_mu_unlock(&w->subchannel->mu);
Craig Tiller12ad5d62015-11-27 12:17:30 -0800423 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, w->subchannel, "external_state_watcher");
Craig Tiller86c99582015-11-25 15:22:26 -0800424 gpr_free(w);
425 follow_up->cb(exec_ctx, follow_up->cb_arg, success);
426}
427
Craig Tiller1d881fb2015-12-01 07:39:04 -0800428void grpc_subchannel_notify_on_state_change(
429 grpc_exec_ctx *exec_ctx, grpc_subchannel *c,
430 grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
431 grpc_closure *notify) {
Craig Tiller48613042015-11-29 14:45:11 -0800432 external_state_watcher *w;
433
434 if (state == NULL) {
435 gpr_mu_lock(&c->mu);
Craig Tiller1d881fb2015-12-01 07:39:04 -0800436 for (w = c->root_external_state_watcher.next;
437 w != &c->root_external_state_watcher; w = w->next) {
Craig Tiller48613042015-11-29 14:45:11 -0800438 if (w->notify == notify) {
Craig Tiller1d881fb2015-12-01 07:39:04 -0800439 grpc_connectivity_state_notify_on_state_change(
440 exec_ctx, &c->state_tracker, NULL, &w->closure);
Craig Tiller48613042015-11-29 14:45:11 -0800441 }
442 }
443 gpr_mu_unlock(&c->mu);
444 } else {
445 w = gpr_malloc(sizeof(*w));
446 w->subchannel = c;
447 w->pollset_set = interested_parties;
448 w->notify = notify;
449 grpc_closure_init(&w->closure, on_external_state_watcher_done, w);
450 if (interested_parties != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800451 grpc_pollset_set_add_pollset_set(exec_ctx, c->pollset_set,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800452 interested_parties);
Craig Tiller48613042015-11-29 14:45:11 -0800453 }
454 GRPC_SUBCHANNEL_WEAK_REF(c, "external_state_watcher");
455 gpr_mu_lock(&c->mu);
456 w->next = &c->root_external_state_watcher;
457 w->prev = w->next->prev;
458 w->next->prev = w->prev->next = w;
459 if (grpc_connectivity_state_notify_on_state_change(
460 exec_ctx, &c->state_tracker, state, &w->closure)) {
Craig Tiller48613042015-11-29 14:45:11 -0800461 c->connecting = 1;
462 /* released by connection */
463 GRPC_SUBCHANNEL_WEAK_REF(c, "connecting");
Craig Tiller8e19f612016-03-01 21:41:13 -0800464 start_connect(exec_ctx, c);
Craig Tiller48613042015-11-29 14:45:11 -0800465 }
466 gpr_mu_unlock(&c->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700467 }
Craig Tiller5f84c842015-06-26 16:08:21 -0700468}
469
Craig Tillerab33b482015-11-21 08:11:04 -0800470void grpc_connected_subchannel_process_transport_op(
471 grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
472 grpc_transport_op *op) {
Craig Tillerb5585d42015-11-17 07:18:31 -0800473 grpc_channel_stack *channel_stack = CHANNEL_STACK_FROM_CONNECTION(con);
Craig Tillerab33b482015-11-21 08:11:04 -0800474 grpc_channel_element *top_elem = grpc_channel_stack_element(channel_stack, 0);
Craig Tillerb5585d42015-11-17 07:18:31 -0800475 top_elem->filter->start_transport_op(exec_ctx, top_elem, op);
476}
477
478static void subchannel_on_child_state_changed(grpc_exec_ctx *exec_ctx, void *p,
Craig Tiller6c396862016-01-28 13:53:40 -0800479 bool iomgr_success) {
Craig Tillerdf91ba52015-06-29 10:55:46 -0700480 state_watcher *sw = p;
Craig Tiller48613042015-11-29 14:45:11 -0800481 grpc_subchannel *c = sw->subchannel;
Craig Tillerdf91ba52015-06-29 10:55:46 -0700482 gpr_mu *mu = &c->mu;
Craig Tillerdf91ba52015-06-29 10:55:46 -0700483
Craig Tillera82950e2015-09-22 12:33:20 -0700484 gpr_mu_lock(mu);
Craig Tillerdf91ba52015-06-29 10:55:46 -0700485
Craig Tillerb5585d42015-11-17 07:18:31 -0800486 /* if we failed just leave this closure */
487 if (iomgr_success) {
Craig Tiller2c174942015-11-24 16:51:23 -0800488 if (sw->connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
489 /* any errors on a subchannel ==> we're done, create a new one */
490 sw->connectivity_state = GRPC_CHANNEL_FATAL_FAILURE;
491 }
Craig Tillerab33b482015-11-21 08:11:04 -0800492 grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
493 sw->connectivity_state, "reflect_child");
Craig Tillerb5585d42015-11-17 07:18:31 -0800494 if (sw->connectivity_state != GRPC_CHANNEL_FATAL_FAILURE) {
Craig Tillerab33b482015-11-21 08:11:04 -0800495 grpc_connected_subchannel_notify_on_state_change(
Craig Tillerf036a642015-12-01 17:00:40 -0800496 exec_ctx, GET_CONNECTED_SUBCHANNEL(c, no_barrier), NULL,
Craig Tillerab33b482015-11-21 08:11:04 -0800497 &sw->connectivity_state, &sw->closure);
Craig Tiller12ad5d62015-11-27 12:17:30 -0800498 GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
Craig Tillerb5585d42015-11-17 07:18:31 -0800499 sw = NULL;
500 }
Craig Tillera82950e2015-09-22 12:33:20 -0700501 }
Craig Tillerdf91ba52015-06-29 10:55:46 -0700502
Craig Tillera82950e2015-09-22 12:33:20 -0700503 gpr_mu_unlock(mu);
Craig Tiller12ad5d62015-11-27 12:17:30 -0800504 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "state_watcher");
Craig Tillerb5585d42015-11-17 07:18:31 -0800505 gpr_free(sw);
506}
507
Craig Tillerab33b482015-11-21 08:11:04 -0800508static void connected_subchannel_state_op(grpc_exec_ctx *exec_ctx,
509 grpc_connected_subchannel *con,
Craig Tillerf036a642015-12-01 17:00:40 -0800510 grpc_pollset_set *interested_parties,
Craig Tillerab33b482015-11-21 08:11:04 -0800511 grpc_connectivity_state *state,
512 grpc_closure *closure) {
Craig Tillerb5585d42015-11-17 07:18:31 -0800513 grpc_transport_op op;
514 grpc_channel_element *elem;
515 memset(&op, 0, sizeof(op));
516 op.connectivity_state = state;
517 op.on_connectivity_state_change = closure;
Craig Tillerf036a642015-12-01 17:00:40 -0800518 op.bind_pollset_set = interested_parties;
Craig Tillerb5585d42015-11-17 07:18:31 -0800519 elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0);
520 elem->filter->start_transport_op(exec_ctx, elem, &op);
521}
522
Craig Tillerab33b482015-11-21 08:11:04 -0800523void grpc_connected_subchannel_notify_on_state_change(
524 grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
Craig Tillera6bebf42015-12-01 17:02:35 -0800525 grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
526 grpc_closure *closure) {
527 connected_subchannel_state_op(exec_ctx, con, interested_parties, state,
528 closure);
Craig Tillerb5585d42015-11-17 07:18:31 -0800529}
530
Craig Tillere2c62372015-12-07 16:11:03 -0800531void grpc_connected_subchannel_ping(grpc_exec_ctx *exec_ctx,
532 grpc_connected_subchannel *con,
533 grpc_closure *closure) {
Craig Tiller28bf8912015-12-07 16:07:04 -0800534 grpc_transport_op op;
535 grpc_channel_element *elem;
536 memset(&op, 0, sizeof(op));
537 op.send_ping = closure;
538 elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0);
539 elem->filter->start_transport_op(exec_ctx, elem, &op);
540}
541
Craig Tiller35914822016-03-11 19:29:23 -0800542static void publish_transport_locked(grpc_exec_ctx *exec_ctx,
543 grpc_subchannel *c) {
Craig Tillerb5585d42015-11-17 07:18:31 -0800544 grpc_connected_subchannel *con;
Craig Tiller4ab82d22015-06-29 09:40:33 -0700545 grpc_channel_stack *stk;
Craig Tillerb5585d42015-11-17 07:18:31 -0800546 state_watcher *sw_subchannel;
Craig Tiller5945ee12015-06-27 10:36:09 -0700547
Craig Tillerdf91ba52015-06-29 10:55:46 -0700548 /* construct channel stack */
Craig Tiller839bebe2016-04-06 08:07:11 -0700549 grpc_channel_stack_builder *builder = grpc_channel_stack_builder_create();
550 grpc_channel_stack_builder_set_channel_arguments(
551 builder, c->connecting_result.channel_args);
552 grpc_channel_stack_builder_set_transport(builder,
553 c->connecting_result.transport);
554
555 if (grpc_channel_init_create_stack(exec_ctx, builder,
556 GRPC_CLIENT_SUBCHANNEL)) {
557 con = grpc_channel_stack_builder_finish(exec_ctx, builder, 0, 1,
558 connection_destroy, NULL);
559 } else {
560 grpc_channel_stack_builder_destroy(builder);
561 abort(); /* TODO(ctiller): what to do here (previously we just crashed) */
562 }
Craig Tiller906e3bc2015-11-24 07:31:31 -0800563 stk = CHANNEL_STACK_FROM_CONNECTION(con);
Craig Tillera82950e2015-09-22 12:33:20 -0700564 memset(&c->connecting_result, 0, sizeof(c->connecting_result));
Craig Tillerff54c922015-06-26 16:57:20 -0700565
Craig Tillerdf91ba52015-06-29 10:55:46 -0700566 /* initialize state watcher */
Craig Tillerb5585d42015-11-17 07:18:31 -0800567 sw_subchannel = gpr_malloc(sizeof(*sw_subchannel));
Craig Tiller48613042015-11-29 14:45:11 -0800568 sw_subchannel->subchannel = c;
Craig Tillerb5585d42015-11-17 07:18:31 -0800569 sw_subchannel->connectivity_state = GRPC_CHANNEL_READY;
Craig Tillerab33b482015-11-21 08:11:04 -0800570 grpc_closure_init(&sw_subchannel->closure, subchannel_on_child_state_changed,
571 sw_subchannel);
Craig Tillerdf91ba52015-06-29 10:55:46 -0700572
Craig Tillera82950e2015-09-22 12:33:20 -0700573 if (c->disconnected) {
Craig Tillerb5585d42015-11-17 07:18:31 -0800574 gpr_free(sw_subchannel);
Craig Tillera82950e2015-09-22 12:33:20 -0700575 grpc_channel_stack_destroy(exec_ctx, stk);
Craig Tiller50ec2672015-11-27 21:45:11 -0800576 gpr_free(con);
577 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
Craig Tillera82950e2015-09-22 12:33:20 -0700578 return;
579 }
Craig Tillerb6fbf1d2015-06-29 15:25:49 -0700580
Craig Tillerdf91ba52015-06-29 10:55:46 -0700581 /* publish */
Craig Tiller493c1512016-01-27 11:55:44 -0800582 /* TODO(ctiller): this full barrier seems to clear up a TSAN failure.
583 I'd have expected the rel_cas below to be enough, but
584 seemingly it's not.
585 Re-evaluate if we really need this. */
Craig Tiller9ebc87a2016-01-26 15:10:09 +0000586 gpr_atm_full_barrier();
Craig Tillerd9d474a2016-01-26 06:50:51 -0800587 GPR_ASSERT(gpr_atm_rel_cas(&c->connected_subchannel, 0, (gpr_atm)con));
Craig Tiller4ab82d22015-06-29 09:40:33 -0700588 c->connecting = 0;
Craig Tillerdf91ba52015-06-29 10:55:46 -0700589
Craig Tiller839bebe2016-04-06 08:07:11 -0700590 /* setup subchannel watching connected subchannel for changes; subchannel
591 ref
Craig Tillerab33b482015-11-21 08:11:04 -0800592 for connecting is donated
Craig Tillerdf91ba52015-06-29 10:55:46 -0700593 to the state watcher */
Craig Tiller12ad5d62015-11-27 12:17:30 -0800594 GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
Craig Tiller50ec2672015-11-27 21:45:11 -0800595 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
Craig Tillerab33b482015-11-21 08:11:04 -0800596 grpc_connected_subchannel_notify_on_state_change(
Craig Tiller69b093b2016-02-25 19:04:07 -0800597 exec_ctx, con, c->pollset_set, &sw_subchannel->connectivity_state,
Craig Tillerab33b482015-11-21 08:11:04 -0800598 &sw_subchannel->closure);
Craig Tillerdf91ba52015-06-29 10:55:46 -0700599
600 /* signal completion */
Craig Tillerab33b482015-11-21 08:11:04 -0800601 grpc_connectivity_state_set(exec_ctx, &c->state_tracker, GRPC_CHANNEL_READY,
602 "connected");
Craig Tiller4ab82d22015-06-29 09:40:33 -0700603}
Craig Tillerff54c922015-06-26 16:57:20 -0700604
Craig Tiller6c396862016-01-28 13:53:40 -0800605static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, bool iomgr_success) {
Craig Tillerff3ae682015-06-29 17:44:04 -0700606 grpc_subchannel *c = arg;
Craig Tillera82950e2015-09-22 12:33:20 -0700607 gpr_mu_lock(&c->mu);
Craig Tillerff3ae682015-06-29 17:44:04 -0700608 c->have_alarm = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700609 if (c->disconnected) {
610 iomgr_success = 0;
611 }
Craig Tillera82950e2015-09-22 12:33:20 -0700612 if (iomgr_success) {
Craig Tiller536fc532016-03-11 12:36:56 -0800613 c->next_attempt =
614 gpr_backoff_step(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
Craig Tillera82950e2015-09-22 12:33:20 -0700615 continue_connect(exec_ctx, c);
Craig Tiller8e19f612016-03-01 21:41:13 -0800616 gpr_mu_unlock(&c->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700617 } else {
Craig Tiller8e19f612016-03-01 21:41:13 -0800618 gpr_mu_unlock(&c->mu);
Craig Tiller50ec2672015-11-27 21:45:11 -0800619 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
Craig Tillera82950e2015-09-22 12:33:20 -0700620 }
Craig Tiller45724b32015-09-22 10:42:19 -0700621}
622
Craig Tillera82950e2015-09-22 12:33:20 -0700623static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller6c396862016-01-28 13:53:40 -0800624 bool iomgr_success) {
Craig Tiller45724b32015-09-22 10:42:19 -0700625 grpc_subchannel *c = arg;
Craig Tiller50ec2672015-11-27 21:45:11 -0800626
Craig Tiller2ba41332016-03-11 17:09:12 -0800627 GRPC_SUBCHANNEL_WEAK_REF(c, "connected");
628 gpr_mu_lock(&c->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700629 if (c->connecting_result.transport != NULL) {
Craig Tiller35914822016-03-11 19:29:23 -0800630 publish_transport_locked(exec_ctx, c);
Craig Tillerb5585d42015-11-17 07:18:31 -0800631 } else if (c->disconnected) {
Craig Tiller50ec2672015-11-27 21:45:11 -0800632 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
Craig Tillera82950e2015-09-22 12:33:20 -0700633 } else {
634 gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
Craig Tillera82950e2015-09-22 12:33:20 -0700635 GPR_ASSERT(!c->have_alarm);
636 c->have_alarm = 1;
Craig Tillerab33b482015-11-21 08:11:04 -0800637 grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
638 GRPC_CHANNEL_TRANSIENT_FAILURE,
639 "connect_failed");
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700640 grpc_timer_init(exec_ctx, &c->alarm, c->next_attempt, on_alarm, c, now);
Craig Tillera82950e2015-09-22 12:33:20 -0700641 }
Craig Tiller2ba41332016-03-11 17:09:12 -0800642 gpr_mu_unlock(&c->mu);
643 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
Craig Tiller45724b32015-09-22 10:42:19 -0700644}
645
Craig Tiller2595ab72015-06-25 15:26:00 -0700646/*
647 * grpc_subchannel_call implementation
648 */
649
Craig Tiller577c9b22015-11-02 14:11:15 -0800650static void subchannel_call_destroy(grpc_exec_ctx *exec_ctx, void *call,
Craig Tiller6c396862016-01-28 13:53:40 -0800651 bool success) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800652 grpc_subchannel_call *c = call;
Craig Tiller577c9b22015-11-02 14:11:15 -0800653 GPR_TIMER_BEGIN("grpc_subchannel_call_unref.destroy", 0);
654 grpc_call_stack_destroy(exec_ctx, SUBCHANNEL_CALL_TO_CALL_STACK(c));
Craig Tiller53ee0402015-11-25 09:07:09 -0800655 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, c->connection, "subchannel_call");
Craig Tiller577c9b22015-11-02 14:11:15 -0800656 gpr_free(c);
Craig Tiller577c9b22015-11-02 14:11:15 -0800657 GPR_TIMER_END("grpc_subchannel_call_unref.destroy", 0);
658}
659
Craig Tillerf40df232016-03-25 13:38:14 -0700660void grpc_subchannel_call_ref(
661 grpc_subchannel_call *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller906e3bc2015-11-24 07:31:31 -0800662 GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON);
Craig Tillerc3967532015-06-29 14:59:38 -0700663}
Craig Tiller2595ab72015-06-25 15:26:00 -0700664
Craig Tillera82950e2015-09-22 12:33:20 -0700665void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx,
666 grpc_subchannel_call *c
667 GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller906e3bc2015-11-24 07:31:31 -0800668 GRPC_CALL_STACK_UNREF(exec_ctx, SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON);
Craig Tiller2595ab72015-06-25 15:26:00 -0700669}
670
Craig Tillera82950e2015-09-22 12:33:20 -0700671char *grpc_subchannel_call_get_peer(grpc_exec_ctx *exec_ctx,
672 grpc_subchannel_call *call) {
673 grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);
674 grpc_call_element *top_elem = grpc_call_stack_element(call_stack, 0);
675 return top_elem->filter->get_peer(exec_ctx, top_elem);
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700676}
677
Craig Tillera82950e2015-09-22 12:33:20 -0700678void grpc_subchannel_call_process_op(grpc_exec_ctx *exec_ctx,
679 grpc_subchannel_call *call,
680 grpc_transport_stream_op *op) {
681 grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);
682 grpc_call_element *top_elem = grpc_call_stack_element(call_stack, 0);
683 top_elem->filter->start_transport_stream_op(exec_ctx, top_elem, op);
Craig Tiller2595ab72015-06-25 15:26:00 -0700684}
Craig Tillereb3b12e2015-06-26 14:42:49 -0700685
Craig Tillerab33b482015-11-21 08:11:04 -0800686grpc_connected_subchannel *grpc_subchannel_get_connected_subchannel(
687 grpc_subchannel *c) {
Craig Tillerb5585d42015-11-17 07:18:31 -0800688 return GET_CONNECTED_SUBCHANNEL(c, acq);
689}
690
Craig Tillerab33b482015-11-21 08:11:04 -0800691grpc_subchannel_call *grpc_connected_subchannel_create_call(
692 grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
693 grpc_pollset *pollset) {
Craig Tillera82950e2015-09-22 12:33:20 -0700694 grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con);
695 grpc_subchannel_call *call =
696 gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
697 grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(call);
Craig Tiller04c5d4b2015-06-26 17:21:41 -0700698 call->connection = con;
Craig Tiller53ee0402015-11-25 09:07:09 -0800699 GRPC_CONNECTED_SUBCHANNEL_REF(con, "subchannel_call");
Craig Tiller577c9b22015-11-02 14:11:15 -0800700 grpc_call_stack_init(exec_ctx, chanstk, 1, subchannel_call_destroy, call,
701 NULL, NULL, callstk);
702 grpc_call_stack_set_pollset(exec_ctx, callstk, pollset);
Craig Tiller04c5d4b2015-06-26 17:21:41 -0700703 return call;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700704}
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700705
Craig Tiller577c9b22015-11-02 14:11:15 -0800706grpc_call_stack *grpc_subchannel_call_get_call_stack(
707 grpc_subchannel_call *subchannel_call) {
708 return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call);
709}