blob: d089cd4399e8fc933abf63b2d0dd25d5e4b1439c [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 Tiller9533d042016-03-25 17:11:06 -070044#include "src/core/lib/channel/channel_args.h"
Craig Tiller9533d042016-03-25 17:11:06 -070045#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 Tillere0d6c572016-05-13 07:23:36 -070057#define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 1
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;
Craig Tiller2595ab72015-06-25 15:26:00 -0700138};
139
Craig Tillera82950e2015-09-22 12:33:20 -0700140struct grpc_subchannel_call {
Craig Tillerb5585d42015-11-17 07:18:31 -0800141 grpc_connected_subchannel *connection;
Craig Tiller2595ab72015-06-25 15:26:00 -0700142};
143
Craig Tiller04c5d4b2015-06-26 17:21:41 -0700144#define SUBCHANNEL_CALL_TO_CALL_STACK(call) ((grpc_call_stack *)((call) + 1))
Craig Tiller906e3bc2015-11-24 07:31:31 -0800145#define CHANNEL_STACK_FROM_CONNECTION(con) ((grpc_channel_stack *)(con))
Craig Tiller577c9b22015-11-02 14:11:15 -0800146#define CALLSTACK_TO_SUBCHANNEL_CALL(callstack) \
147 (((grpc_subchannel_call *)(callstack)) - 1)
Craig Tiller2595ab72015-06-25 15:26:00 -0700148
Craig Tillera82950e2015-09-22 12:33:20 -0700149static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *subchannel,
Craig Tiller804ff712016-05-05 16:25:40 -0700150 grpc_error *error);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700151
Craig Tiller577c9b22015-11-02 14:11:15 -0800152#ifdef GRPC_STREAM_REFCOUNT_DEBUG
Craig Tiller906e3bc2015-11-24 07:31:31 -0800153#define REF_REASON reason
Craig Tiller079a11b2015-06-30 10:07:15 -0700154#define REF_LOG(name, p) \
155 gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "%s: %p ref %d -> %d %s", \
Craig Tillerab33b482015-11-21 08:11:04 -0800156 (name), (p), (p)->refs.count, (p)->refs.count + 1, reason)
Craig Tiller079a11b2015-06-30 10:07:15 -0700157#define UNREF_LOG(name, p) \
158 gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "%s: %p unref %d -> %d %s", \
Craig Tillerab33b482015-11-21 08:11:04 -0800159 (name), (p), (p)->refs.count, (p)->refs.count - 1, reason)
Craig Tiller1d881fb2015-12-01 07:39:04 -0800160#define REF_MUTATE_EXTRA_ARGS \
161 GRPC_SUBCHANNEL_REF_EXTRA_ARGS, const char *purpose
Craig Tiller12ad5d62015-11-27 12:17:30 -0800162#define REF_MUTATE_PURPOSE(x) , file, line, reason, x
Craig Tillerc3967532015-06-29 14:59:38 -0700163#else
Craig Tiller906e3bc2015-11-24 07:31:31 -0800164#define REF_REASON ""
Craig Tiller11bf14e2015-06-29 16:35:41 -0700165#define REF_LOG(name, p) \
166 do { \
167 } while (0)
168#define UNREF_LOG(name, p) \
169 do { \
170 } while (0)
Craig Tiller12ad5d62015-11-27 12:17:30 -0800171#define REF_MUTATE_EXTRA_ARGS
172#define REF_MUTATE_PURPOSE(x)
Craig Tillerc3967532015-06-29 14:59:38 -0700173#endif
174
Craig Tiller2595ab72015-06-25 15:26:00 -0700175/*
Craig Tillerca3e9d32015-06-27 18:37:27 -0700176 * connection implementation
177 */
178
Craig Tillerab33b482015-11-21 08:11:04 -0800179static void connection_destroy(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -0700180 grpc_error *error) {
Craig Tillerb5585d42015-11-17 07:18:31 -0800181 grpc_connected_subchannel *c = arg;
Craig Tillera82950e2015-09-22 12:33:20 -0700182 grpc_channel_stack_destroy(exec_ctx, CHANNEL_STACK_FROM_CONNECTION(c));
183 gpr_free(c);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700184}
185
Craig Tillerf40df232016-03-25 13:38:14 -0700186void grpc_connected_subchannel_ref(
187 grpc_connected_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller906e3bc2015-11-24 07:31:31 -0800188 GRPC_CHANNEL_STACK_REF(CHANNEL_STACK_FROM_CONNECTION(c), REF_REASON);
Craig Tillerd7b68e72015-06-28 11:41:09 -0700189}
190
Craig Tillerab33b482015-11-21 08:11:04 -0800191void grpc_connected_subchannel_unref(grpc_exec_ctx *exec_ctx,
192 grpc_connected_subchannel *c
193 GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller7b435612015-11-24 08:15:05 -0800194 GRPC_CHANNEL_STACK_UNREF(exec_ctx, CHANNEL_STACK_FROM_CONNECTION(c),
195 REF_REASON);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700196}
197
198/*
Craig Tiller2595ab72015-06-25 15:26:00 -0700199 * grpc_subchannel implementation
200 */
201
Craig Tillerab33b482015-11-21 08:11:04 -0800202static void subchannel_destroy(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -0700203 grpc_error *error) {
Craig Tillerb5585d42015-11-17 07:18:31 -0800204 grpc_subchannel *c = arg;
Craig Tiller565b18b2015-09-23 10:09:42 -0700205 gpr_free((void *)c->filters);
Craig Tillera82950e2015-09-22 12:33:20 -0700206 grpc_channel_args_destroy(c->args);
207 gpr_free(c->addr);
yang-ga6124122015-11-05 22:36:20 -0800208 gpr_slice_unref(c->initial_connect_string);
Craig Tillera82950e2015-09-22 12:33:20 -0700209 grpc_connectivity_state_destroy(exec_ctx, &c->state_tracker);
210 grpc_connector_unref(exec_ctx, c->connector);
Craig Tiller69b093b2016-02-25 19:04:07 -0800211 grpc_pollset_set_destroy(c->pollset_set);
Craig Tiller19482442016-01-25 09:59:20 -0800212 grpc_subchannel_key_destroy(exec_ctx, c->key);
Craig Tillera82950e2015-09-22 12:33:20 -0700213 gpr_free(c);
Craig Tiller2595ab72015-06-25 15:26:00 -0700214}
215
Craig Tiller1d881fb2015-12-01 07:39:04 -0800216static gpr_atm ref_mutate(grpc_subchannel *c, gpr_atm delta,
217 int barrier REF_MUTATE_EXTRA_ARGS) {
218 gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta)
219 : gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta);
Craig Tiller12ad5d62015-11-27 12:17:30 -0800220#ifdef GRPC_STREAM_REFCOUNT_DEBUG
Craig Tiller1d881fb2015-12-01 07:39:04 -0800221 gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
222 "SUBCHANNEL: %p % 12s 0x%08x -> 0x%08x [%s]", c, purpose, old_val,
223 old_val + delta, reason);
Craig Tiller12ad5d62015-11-27 12:17:30 -0800224#endif
225 return old_val;
226}
227
Craig Tillerf40df232016-03-25 13:38:14 -0700228grpc_subchannel *grpc_subchannel_ref(
229 grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller12ad5d62015-11-27 12:17:30 -0800230 gpr_atm old_refs;
Craig Tiller1d881fb2015-12-01 07:39:04 -0800231 old_refs = ref_mutate(c, (1 << INTERNAL_REF_BITS),
232 0 REF_MUTATE_PURPOSE("STRONG_REF"));
Craig Tiller12ad5d62015-11-27 12:17:30 -0800233 GPR_ASSERT((old_refs & STRONG_REF_MASK) != 0);
Craig Tiller19482442016-01-25 09:59:20 -0800234 return c;
Craig Tiller12ad5d62015-11-27 12:17:30 -0800235}
236
Craig Tillerf40df232016-03-25 13:38:14 -0700237grpc_subchannel *grpc_subchannel_weak_ref(
238 grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller12ad5d62015-11-27 12:17:30 -0800239 gpr_atm old_refs;
240 old_refs = ref_mutate(c, 1, 0 REF_MUTATE_PURPOSE("WEAK_REF"));
241 GPR_ASSERT(old_refs != 0);
Craig Tiller19482442016-01-25 09:59:20 -0800242 return c;
Craig Tiller12ad5d62015-11-27 12:17:30 -0800243}
244
Craig Tiller5de79ee2016-01-25 08:16:02 -0800245grpc_subchannel *grpc_subchannel_ref_from_weak_ref(
246 grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller8cdba662016-01-22 20:01:55 -0800247 if (!c) return NULL;
248 for (;;) {
249 gpr_atm old_refs = gpr_atm_acq_load(&c->ref_pair);
250 if (old_refs >= (1 << INTERNAL_REF_BITS)) {
251 gpr_atm new_refs = old_refs + (1 << INTERNAL_REF_BITS);
252 if (gpr_atm_rel_cas(&c->ref_pair, old_refs, new_refs)) {
253 return c;
254 }
255 } else {
256 return NULL;
257 }
258 }
259}
260
Craig Tiller12ad5d62015-11-27 12:17:30 -0800261static void disconnect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
262 grpc_connected_subchannel *con;
Craig Tiller7391f132016-01-22 06:39:54 -0800263 grpc_subchannel_index_unregister(exec_ctx, c->key, c);
Craig Tiller12ad5d62015-11-27 12:17:30 -0800264 gpr_mu_lock(&c->mu);
265 GPR_ASSERT(!c->disconnected);
266 c->disconnected = 1;
Craig Tillercaa4e702015-12-01 06:55:25 -0800267 grpc_connector_shutdown(exec_ctx, c->connector);
Craig Tiller12ad5d62015-11-27 12:17:30 -0800268 con = GET_CONNECTED_SUBCHANNEL(c, no_barrier);
269 if (con != NULL) {
270 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, con, "connection");
Yuchen Zeng615da642016-04-29 18:14:05 -0700271 gpr_atm_no_barrier_store(&c->connected_subchannel, (gpr_atm)0xdeadbeef);
Craig Tiller12ad5d62015-11-27 12:17:30 -0800272 }
273 gpr_mu_unlock(&c->mu);
Craig Tillerb5585d42015-11-17 07:18:31 -0800274}
275
276void grpc_subchannel_unref(grpc_exec_ctx *exec_ctx,
277 grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller12ad5d62015-11-27 12:17:30 -0800278 gpr_atm old_refs;
Craig Tiller1d881fb2015-12-01 07:39:04 -0800279 old_refs = ref_mutate(c, (gpr_atm)1 - (gpr_atm)(1 << INTERNAL_REF_BITS),
280 1 REF_MUTATE_PURPOSE("STRONG_UNREF"));
Craig Tiller50ec2672015-11-27 21:45:11 -0800281 if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) {
Craig Tiller12ad5d62015-11-27 12:17:30 -0800282 disconnect(exec_ctx, c);
283 }
284 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "strong-unref");
285}
286
287void grpc_subchannel_weak_unref(grpc_exec_ctx *exec_ctx,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800288 grpc_subchannel *c
289 GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller12ad5d62015-11-27 12:17:30 -0800290 gpr_atm old_refs;
291 old_refs = ref_mutate(c, -(gpr_atm)1, 1 REF_MUTATE_PURPOSE("WEAK_UNREF"));
Craig Tillerf036a642015-12-01 17:00:40 -0800292 if (old_refs == 1) {
Craig Tiller332f1b32016-05-24 13:21:21 -0700293 grpc_exec_ctx_sched(exec_ctx, grpc_closure_create(subchannel_destroy, c),
Craig Tiller77c983d2016-05-24 13:23:14 -0700294 GRPC_ERROR_NONE, NULL);
Craig Tillerb5585d42015-11-17 07:18:31 -0800295 }
296}
297
Craig Tiller7391f132016-01-22 06:39:54 -0800298grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
299 grpc_connector *connector,
Craig Tillera82950e2015-09-22 12:33:20 -0700300 grpc_subchannel_args *args) {
Craig Tiller7391f132016-01-22 06:39:54 -0800301 grpc_subchannel_key *key = grpc_subchannel_key_create(connector, args);
302 grpc_subchannel *c = grpc_subchannel_index_find(exec_ctx, key);
303 if (c) {
Craig Tiller19482442016-01-25 09:59:20 -0800304 grpc_subchannel_key_destroy(exec_ctx, key);
Craig Tiller7391f132016-01-22 06:39:54 -0800305 return c;
306 }
307
308 c = gpr_malloc(sizeof(*c));
Craig Tillera82950e2015-09-22 12:33:20 -0700309 memset(c, 0, sizeof(*c));
Craig Tiller7391f132016-01-22 06:39:54 -0800310 c->key = key;
Craig Tiller12ad5d62015-11-27 12:17:30 -0800311 gpr_atm_no_barrier_store(&c->ref_pair, 1 << INTERNAL_REF_BITS);
Craig Tillerf7afa1f2015-06-26 09:02:20 -0700312 c->connector = connector;
Craig Tillera82950e2015-09-22 12:33:20 -0700313 grpc_connector_ref(c->connector);
Craig Tiller5945ee12015-06-27 10:36:09 -0700314 c->num_filters = args->filter_count;
Craig Tillerb9c55052016-01-27 15:22:48 -0800315 if (c->num_filters > 0) {
316 c->filters = gpr_malloc(sizeof(grpc_channel_filter *) * c->num_filters);
317 memcpy((void *)c->filters, args->filters,
318 sizeof(grpc_channel_filter *) * c->num_filters);
319 } else {
320 c->filters = NULL;
321 }
Craig Tillera82950e2015-09-22 12:33:20 -0700322 c->addr = gpr_malloc(args->addr_len);
Craig Tiller68897992016-05-03 23:10:07 -0700323 if (args->addr_len) memcpy(c->addr, args->addr, args->addr_len);
Craig Tiller69b093b2016-02-25 19:04:07 -0800324 c->pollset_set = grpc_pollset_set_create();
Craig Tillerf7afa1f2015-06-26 09:02:20 -0700325 c->addr_len = args->addr_len;
yang-ga6124122015-11-05 22:36:20 -0800326 grpc_set_initial_connect_string(&c->addr, &c->addr_len,
327 &c->initial_connect_string);
Craig Tillera82950e2015-09-22 12:33:20 -0700328 c->args = grpc_channel_args_copy(args->args);
Craig Tiller1d881fb2015-12-01 07:39:04 -0800329 c->root_external_state_watcher.next = c->root_external_state_watcher.prev =
330 &c->root_external_state_watcher;
Craig Tillera82950e2015-09-22 12:33:20 -0700331 grpc_closure_init(&c->connected, subchannel_connected, c);
332 grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE,
333 "subchannel");
Craig Tiller536fc532016-03-11 12:36:56 -0800334 gpr_backoff_init(&c->backoff_state,
335 GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER,
336 GRPC_SUBCHANNEL_RECONNECT_JITTER,
337 GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000,
338 GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS * 1000);
339 if (c->args) {
340 for (size_t i = 0; i < c->args->num_args; i++) {
341 if (0 == strcmp(c->args->args[i].key,
342 "grpc.testing.fixed_reconnect_backoff")) {
343 GPR_ASSERT(c->args->args[i].type == GRPC_ARG_INTEGER);
344 gpr_backoff_init(&c->backoff_state, 1.0, 0.0,
345 c->args->args[i].value.integer,
346 c->args->args[i].value.integer);
347 }
Craig Tiller076c2b82016-03-30 17:12:29 -0700348 if (0 ==
349 strcmp(c->args->args[i].key, GRPC_ARG_MAX_RECONNECT_BACKOFF_MS)) {
350 if (c->args->args[i].type == GRPC_ARG_INTEGER) {
351 if (c->args->args[i].value.integer >= 0) {
352 gpr_backoff_init(
353 &c->backoff_state, GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER,
354 GRPC_SUBCHANNEL_RECONNECT_JITTER,
355 GPR_MIN(c->args->args[i].value.integer,
356 GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000),
357 c->args->args[i].value.integer);
358 } else {
359 gpr_log(GPR_ERROR, GRPC_ARG_MAX_RECONNECT_BACKOFF_MS
360 " : must be non-negative");
361 }
362 } else {
363 gpr_log(GPR_ERROR,
364 GRPC_ARG_MAX_RECONNECT_BACKOFF_MS " : must be an integer");
365 }
366 }
Craig Tiller536fc532016-03-11 12:36:56 -0800367 }
368 }
Craig Tillera82950e2015-09-22 12:33:20 -0700369 gpr_mu_init(&c->mu);
Craig Tiller7391f132016-01-22 06:39:54 -0800370
371 return grpc_subchannel_index_register(exec_ctx, key, c);
Craig Tillerf7afa1f2015-06-26 09:02:20 -0700372}
373
Craig Tillera82950e2015-09-22 12:33:20 -0700374static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
Craig Tiller4ab82d22015-06-29 09:40:33 -0700375 grpc_connect_in_args args;
Craig Tiller04c5d4b2015-06-26 17:21:41 -0700376
Craig Tiller69b093b2016-02-25 19:04:07 -0800377 args.interested_parties = c->pollset_set;
Craig Tiller4ab82d22015-06-29 09:40:33 -0700378 args.addr = c->addr;
379 args.addr_len = c->addr_len;
Craig Tiller536fc532016-03-11 12:36:56 -0800380 args.deadline = c->next_attempt;
Craig Tiller4ab82d22015-06-29 09:40:33 -0700381 args.channel_args = c->args;
yang-ga6124122015-11-05 22:36:20 -0800382 args.initial_connect_string = c->initial_connect_string;
Craig Tiller04c5d4b2015-06-26 17:21:41 -0700383
Craig Tillerab33b482015-11-21 08:11:04 -0800384 grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
Craig Tiller804ff712016-05-05 16:25:40 -0700385 GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE,
386 "state_change");
Craig Tillera82950e2015-09-22 12:33:20 -0700387 grpc_connector_connect(exec_ctx, c->connector, &args, &c->connecting_result,
388 &c->connected);
Craig Tiller04c5d4b2015-06-26 17:21:41 -0700389}
390
Craig Tillera82950e2015-09-22 12:33:20 -0700391static void start_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
Craig Tillera82950e2015-09-22 12:33:20 -0700392 c->next_attempt =
Craig Tiller536fc532016-03-11 12:36:56 -0800393 gpr_backoff_begin(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
Craig Tillera82950e2015-09-22 12:33:20 -0700394 continue_connect(exec_ctx, c);
Craig Tillerff3ae682015-06-29 17:44:04 -0700395}
396
Craig Tiller804ff712016-05-05 16:25:40 -0700397grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel *c,
398 grpc_error **error) {
Craig Tiller5f84c842015-06-26 16:08:21 -0700399 grpc_connectivity_state state;
Craig Tillera82950e2015-09-22 12:33:20 -0700400 gpr_mu_lock(&c->mu);
Craig Tiller804ff712016-05-05 16:25:40 -0700401 state = grpc_connectivity_state_check(&c->state_tracker, error);
Craig Tillera82950e2015-09-22 12:33:20 -0700402 gpr_mu_unlock(&c->mu);
Craig Tiller5f84c842015-06-26 16:08:21 -0700403 return state;
404}
405
Craig Tiller1d881fb2015-12-01 07:39:04 -0800406static void on_external_state_watcher_done(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -0700407 grpc_error *error) {
Craig Tiller86c99582015-11-25 15:22:26 -0800408 external_state_watcher *w = arg;
409 grpc_closure *follow_up = w->notify;
Craig Tiller48613042015-11-29 14:45:11 -0800410 if (w->pollset_set != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800411 grpc_pollset_set_del_pollset_set(exec_ctx, w->subchannel->pollset_set,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800412 w->pollset_set);
Craig Tiller48613042015-11-29 14:45:11 -0800413 }
414 gpr_mu_lock(&w->subchannel->mu);
415 w->next->prev = w->prev;
416 w->prev->next = w->next;
417 gpr_mu_unlock(&w->subchannel->mu);
Craig Tiller12ad5d62015-11-27 12:17:30 -0800418 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, w->subchannel, "external_state_watcher");
Craig Tiller86c99582015-11-25 15:22:26 -0800419 gpr_free(w);
Craig Tiller804ff712016-05-05 16:25:40 -0700420 follow_up->cb(exec_ctx, follow_up->cb_arg, error);
Craig Tiller86c99582015-11-25 15:22:26 -0800421}
422
Craig Tiller1d881fb2015-12-01 07:39:04 -0800423void grpc_subchannel_notify_on_state_change(
424 grpc_exec_ctx *exec_ctx, grpc_subchannel *c,
425 grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
426 grpc_closure *notify) {
Craig Tiller48613042015-11-29 14:45:11 -0800427 external_state_watcher *w;
428
429 if (state == NULL) {
430 gpr_mu_lock(&c->mu);
Craig Tiller1d881fb2015-12-01 07:39:04 -0800431 for (w = c->root_external_state_watcher.next;
432 w != &c->root_external_state_watcher; w = w->next) {
Craig Tiller48613042015-11-29 14:45:11 -0800433 if (w->notify == notify) {
Craig Tiller1d881fb2015-12-01 07:39:04 -0800434 grpc_connectivity_state_notify_on_state_change(
435 exec_ctx, &c->state_tracker, NULL, &w->closure);
Craig Tiller48613042015-11-29 14:45:11 -0800436 }
437 }
438 gpr_mu_unlock(&c->mu);
439 } else {
440 w = gpr_malloc(sizeof(*w));
441 w->subchannel = c;
442 w->pollset_set = interested_parties;
443 w->notify = notify;
444 grpc_closure_init(&w->closure, on_external_state_watcher_done, w);
445 if (interested_parties != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800446 grpc_pollset_set_add_pollset_set(exec_ctx, c->pollset_set,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800447 interested_parties);
Craig Tiller48613042015-11-29 14:45:11 -0800448 }
449 GRPC_SUBCHANNEL_WEAK_REF(c, "external_state_watcher");
450 gpr_mu_lock(&c->mu);
451 w->next = &c->root_external_state_watcher;
452 w->prev = w->next->prev;
453 w->next->prev = w->prev->next = w;
454 if (grpc_connectivity_state_notify_on_state_change(
455 exec_ctx, &c->state_tracker, state, &w->closure)) {
Craig Tiller48613042015-11-29 14:45:11 -0800456 c->connecting = 1;
457 /* released by connection */
458 GRPC_SUBCHANNEL_WEAK_REF(c, "connecting");
Craig Tiller8e19f612016-03-01 21:41:13 -0800459 start_connect(exec_ctx, c);
Craig Tiller48613042015-11-29 14:45:11 -0800460 }
461 gpr_mu_unlock(&c->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700462 }
Craig Tiller5f84c842015-06-26 16:08:21 -0700463}
464
Craig Tillerab33b482015-11-21 08:11:04 -0800465void grpc_connected_subchannel_process_transport_op(
466 grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
467 grpc_transport_op *op) {
Craig Tillerb5585d42015-11-17 07:18:31 -0800468 grpc_channel_stack *channel_stack = CHANNEL_STACK_FROM_CONNECTION(con);
Craig Tillerab33b482015-11-21 08:11:04 -0800469 grpc_channel_element *top_elem = grpc_channel_stack_element(channel_stack, 0);
Craig Tillerb5585d42015-11-17 07:18:31 -0800470 top_elem->filter->start_transport_op(exec_ctx, top_elem, op);
471}
472
473static void subchannel_on_child_state_changed(grpc_exec_ctx *exec_ctx, void *p,
Craig Tiller804ff712016-05-05 16:25:40 -0700474 grpc_error *error) {
Craig Tillerdf91ba52015-06-29 10:55:46 -0700475 state_watcher *sw = p;
Craig Tiller48613042015-11-29 14:45:11 -0800476 grpc_subchannel *c = sw->subchannel;
Craig Tillerdf91ba52015-06-29 10:55:46 -0700477 gpr_mu *mu = &c->mu;
Craig Tillerdf91ba52015-06-29 10:55:46 -0700478
Craig Tillera82950e2015-09-22 12:33:20 -0700479 gpr_mu_lock(mu);
Craig Tillerdf91ba52015-06-29 10:55:46 -0700480
Craig Tillerb5585d42015-11-17 07:18:31 -0800481 /* if we failed just leave this closure */
Craig Tiller804ff712016-05-05 16:25:40 -0700482 if (sw->connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
483 /* any errors on a subchannel ==> we're done, create a new one */
Craig Tillerd925c932016-06-06 08:38:50 -0700484 sw->connectivity_state = GRPC_CHANNEL_SHUTDOWN;
Craig Tiller804ff712016-05-05 16:25:40 -0700485 }
486 grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
Craig Tiller94f84532016-05-06 21:03:29 -0700487 sw->connectivity_state, GRPC_ERROR_REF(error),
488 "reflect_child");
Craig Tillerd925c932016-06-06 08:38:50 -0700489 if (sw->connectivity_state != GRPC_CHANNEL_SHUTDOWN) {
Craig Tiller804ff712016-05-05 16:25:40 -0700490 grpc_connected_subchannel_notify_on_state_change(
491 exec_ctx, GET_CONNECTED_SUBCHANNEL(c, no_barrier), NULL,
492 &sw->connectivity_state, &sw->closure);
493 GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
494 sw = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700495 }
Craig Tillerdf91ba52015-06-29 10:55:46 -0700496
Craig Tillera82950e2015-09-22 12:33:20 -0700497 gpr_mu_unlock(mu);
Craig Tiller12ad5d62015-11-27 12:17:30 -0800498 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "state_watcher");
Craig Tillerb5585d42015-11-17 07:18:31 -0800499 gpr_free(sw);
500}
501
Craig Tillerab33b482015-11-21 08:11:04 -0800502static void connected_subchannel_state_op(grpc_exec_ctx *exec_ctx,
503 grpc_connected_subchannel *con,
Craig Tillerf036a642015-12-01 17:00:40 -0800504 grpc_pollset_set *interested_parties,
Craig Tillerab33b482015-11-21 08:11:04 -0800505 grpc_connectivity_state *state,
506 grpc_closure *closure) {
Craig Tillerb5585d42015-11-17 07:18:31 -0800507 grpc_transport_op op;
508 grpc_channel_element *elem;
509 memset(&op, 0, sizeof(op));
510 op.connectivity_state = state;
511 op.on_connectivity_state_change = closure;
Craig Tillerf036a642015-12-01 17:00:40 -0800512 op.bind_pollset_set = interested_parties;
Craig Tillerb5585d42015-11-17 07:18:31 -0800513 elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0);
514 elem->filter->start_transport_op(exec_ctx, elem, &op);
515}
516
Craig Tillerab33b482015-11-21 08:11:04 -0800517void grpc_connected_subchannel_notify_on_state_change(
518 grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
Craig Tillera6bebf42015-12-01 17:02:35 -0800519 grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
520 grpc_closure *closure) {
521 connected_subchannel_state_op(exec_ctx, con, interested_parties, state,
522 closure);
Craig Tillerb5585d42015-11-17 07:18:31 -0800523}
524
Craig Tillere2c62372015-12-07 16:11:03 -0800525void grpc_connected_subchannel_ping(grpc_exec_ctx *exec_ctx,
526 grpc_connected_subchannel *con,
527 grpc_closure *closure) {
Craig Tiller28bf8912015-12-07 16:07:04 -0800528 grpc_transport_op op;
529 grpc_channel_element *elem;
530 memset(&op, 0, sizeof(op));
531 op.send_ping = closure;
532 elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0);
533 elem->filter->start_transport_op(exec_ctx, elem, &op);
534}
535
Craig Tiller35914822016-03-11 19:29:23 -0800536static void publish_transport_locked(grpc_exec_ctx *exec_ctx,
537 grpc_subchannel *c) {
Craig Tillerb5585d42015-11-17 07:18:31 -0800538 grpc_connected_subchannel *con;
Craig Tiller4ab82d22015-06-29 09:40:33 -0700539 grpc_channel_stack *stk;
Craig Tillerb5585d42015-11-17 07:18:31 -0800540 state_watcher *sw_subchannel;
Craig Tiller5945ee12015-06-27 10:36:09 -0700541
Craig Tillerdf91ba52015-06-29 10:55:46 -0700542 /* construct channel stack */
Craig Tiller839bebe2016-04-06 08:07:11 -0700543 grpc_channel_stack_builder *builder = grpc_channel_stack_builder_create();
544 grpc_channel_stack_builder_set_channel_arguments(
545 builder, c->connecting_result.channel_args);
546 grpc_channel_stack_builder_set_transport(builder,
547 c->connecting_result.transport);
548
549 if (grpc_channel_init_create_stack(exec_ctx, builder,
550 GRPC_CLIENT_SUBCHANNEL)) {
551 con = grpc_channel_stack_builder_finish(exec_ctx, builder, 0, 1,
552 connection_destroy, NULL);
553 } else {
554 grpc_channel_stack_builder_destroy(builder);
555 abort(); /* TODO(ctiller): what to do here (previously we just crashed) */
556 }
Craig Tiller906e3bc2015-11-24 07:31:31 -0800557 stk = CHANNEL_STACK_FROM_CONNECTION(con);
Craig Tillera82950e2015-09-22 12:33:20 -0700558 memset(&c->connecting_result, 0, sizeof(c->connecting_result));
Craig Tillerff54c922015-06-26 16:57:20 -0700559
Craig Tillerdf91ba52015-06-29 10:55:46 -0700560 /* initialize state watcher */
Craig Tillerb5585d42015-11-17 07:18:31 -0800561 sw_subchannel = gpr_malloc(sizeof(*sw_subchannel));
Craig Tiller48613042015-11-29 14:45:11 -0800562 sw_subchannel->subchannel = c;
Craig Tillerb5585d42015-11-17 07:18:31 -0800563 sw_subchannel->connectivity_state = GRPC_CHANNEL_READY;
Craig Tillerab33b482015-11-21 08:11:04 -0800564 grpc_closure_init(&sw_subchannel->closure, subchannel_on_child_state_changed,
565 sw_subchannel);
Craig Tillerdf91ba52015-06-29 10:55:46 -0700566
Craig Tillera82950e2015-09-22 12:33:20 -0700567 if (c->disconnected) {
Craig Tillerb5585d42015-11-17 07:18:31 -0800568 gpr_free(sw_subchannel);
Craig Tillera82950e2015-09-22 12:33:20 -0700569 grpc_channel_stack_destroy(exec_ctx, stk);
Craig Tiller50ec2672015-11-27 21:45:11 -0800570 gpr_free(con);
571 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
Craig Tillera82950e2015-09-22 12:33:20 -0700572 return;
573 }
Craig Tillerb6fbf1d2015-06-29 15:25:49 -0700574
Craig Tillerdf91ba52015-06-29 10:55:46 -0700575 /* publish */
Craig Tiller493c1512016-01-27 11:55:44 -0800576 /* TODO(ctiller): this full barrier seems to clear up a TSAN failure.
577 I'd have expected the rel_cas below to be enough, but
578 seemingly it's not.
579 Re-evaluate if we really need this. */
Craig Tiller9ebc87a2016-01-26 15:10:09 +0000580 gpr_atm_full_barrier();
Craig Tillerd9d474a2016-01-26 06:50:51 -0800581 GPR_ASSERT(gpr_atm_rel_cas(&c->connected_subchannel, 0, (gpr_atm)con));
Craig Tiller4ab82d22015-06-29 09:40:33 -0700582 c->connecting = 0;
Craig Tillerdf91ba52015-06-29 10:55:46 -0700583
Craig Tiller839bebe2016-04-06 08:07:11 -0700584 /* setup subchannel watching connected subchannel for changes; subchannel
585 ref
Craig Tillerab33b482015-11-21 08:11:04 -0800586 for connecting is donated
Craig Tillerdf91ba52015-06-29 10:55:46 -0700587 to the state watcher */
Craig Tiller12ad5d62015-11-27 12:17:30 -0800588 GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
Craig Tiller50ec2672015-11-27 21:45:11 -0800589 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
Craig Tillerab33b482015-11-21 08:11:04 -0800590 grpc_connected_subchannel_notify_on_state_change(
Craig Tiller69b093b2016-02-25 19:04:07 -0800591 exec_ctx, con, c->pollset_set, &sw_subchannel->connectivity_state,
Craig Tillerab33b482015-11-21 08:11:04 -0800592 &sw_subchannel->closure);
Craig Tillerdf91ba52015-06-29 10:55:46 -0700593
594 /* signal completion */
Craig Tillerab33b482015-11-21 08:11:04 -0800595 grpc_connectivity_state_set(exec_ctx, &c->state_tracker, GRPC_CHANNEL_READY,
Craig Tiller804ff712016-05-05 16:25:40 -0700596 GRPC_ERROR_NONE, "connected");
Craig Tiller4ab82d22015-06-29 09:40:33 -0700597}
Craig Tillerff54c922015-06-26 16:57:20 -0700598
Craig Tiller804ff712016-05-05 16:25:40 -0700599static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
Craig Tillerff3ae682015-06-29 17:44:04 -0700600 grpc_subchannel *c = arg;
Craig Tillera82950e2015-09-22 12:33:20 -0700601 gpr_mu_lock(&c->mu);
Craig Tillerff3ae682015-06-29 17:44:04 -0700602 c->have_alarm = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700603 if (c->disconnected) {
Craig Tiller804ff712016-05-05 16:25:40 -0700604 error = GRPC_ERROR_CREATE_REFERENCING("Disconnected", &error, 1);
605 } else {
Craig Tillerf707d622016-05-06 14:26:12 -0700606 GRPC_ERROR_REF(error);
Craig Tillera82950e2015-09-22 12:33:20 -0700607 }
Craig Tillercfc8ae12016-05-10 20:49:54 -0700608 if (error == GRPC_ERROR_NONE) {
Craig Tillere0d6c572016-05-13 07:23:36 -0700609 gpr_log(GPR_INFO, "Failed to connect to channel, retrying");
Craig Tiller2b59dbc2016-05-13 15:59:09 -0700610 c->next_attempt =
611 gpr_backoff_step(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
Craig Tillera82950e2015-09-22 12:33:20 -0700612 continue_connect(exec_ctx, c);
Craig Tiller8e19f612016-03-01 21:41:13 -0800613 gpr_mu_unlock(&c->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700614 } else {
Craig Tiller8e19f612016-03-01 21:41:13 -0800615 gpr_mu_unlock(&c->mu);
Craig Tiller50ec2672015-11-27 21:45:11 -0800616 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
Craig Tillera82950e2015-09-22 12:33:20 -0700617 }
Craig Tiller82c63eb2016-05-10 15:28:01 -0700618 GRPC_ERROR_UNREF(error);
Craig Tiller45724b32015-09-22 10:42:19 -0700619}
620
Craig Tillera82950e2015-09-22 12:33:20 -0700621static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -0700622 grpc_error *error) {
Craig Tiller45724b32015-09-22 10:42:19 -0700623 grpc_subchannel *c = arg;
Craig Tiller99b642a2016-06-01 17:20:34 -0700624 grpc_channel_args *delete_channel_args = c->connecting_result.channel_args;
Craig Tiller50ec2672015-11-27 21:45:11 -0800625
Craig Tiller2ba41332016-03-11 17:09:12 -0800626 GRPC_SUBCHANNEL_WEAK_REF(c, "connected");
627 gpr_mu_lock(&c->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700628 if (c->connecting_result.transport != NULL) {
Craig Tiller35914822016-03-11 19:29:23 -0800629 publish_transport_locked(exec_ctx, c);
Craig Tillerb5585d42015-11-17 07:18:31 -0800630 } else if (c->disconnected) {
Craig Tiller50ec2672015-11-27 21:45:11 -0800631 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
Craig Tillera82950e2015-09-22 12:33:20 -0700632 } else {
633 gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
Craig Tillera82950e2015-09-22 12:33:20 -0700634 GPR_ASSERT(!c->have_alarm);
635 c->have_alarm = 1;
Craig Tiller804ff712016-05-05 16:25:40 -0700636 grpc_connectivity_state_set(
637 exec_ctx, &c->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
638 GRPC_ERROR_CREATE_REFERENCING("Connect Failed", &error, 1),
639 "connect_failed");
Craig Tillere0d6c572016-05-13 07:23:36 -0700640 gpr_timespec time_til_next = gpr_time_sub(c->next_attempt, now);
Craig Tillercfc8ae12016-05-10 20:49:54 -0700641 const char *errmsg = grpc_error_string(error);
Craig Tiller2ec184b2016-06-01 13:03:17 -0700642 gpr_log(GPR_INFO, "Connect failed: %s", errmsg);
Craig Tillerdf30bc52016-06-01 14:08:50 -0700643 if (gpr_time_cmp(time_til_next, gpr_time_0(time_til_next.clock_type)) <=
644 0) {
Craig Tiller2ec184b2016-06-01 13:03:17 -0700645 gpr_log(GPR_INFO, "Retry immediately");
646 } else {
Craig Tiller7dce0922016-06-15 10:11:11 -0700647 gpr_log(GPR_INFO, "Retry in %" PRId64 ".%09d seconds",
648 time_til_next.tv_sec, time_til_next.tv_nsec);
Craig Tiller2ec184b2016-06-01 13:03:17 -0700649 }
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700650 grpc_timer_init(exec_ctx, &c->alarm, c->next_attempt, on_alarm, c, now);
Craig Tiller2ec184b2016-06-01 13:03:17 -0700651 grpc_error_free_string(errmsg);
Craig Tillera82950e2015-09-22 12:33:20 -0700652 }
Craig Tiller2ba41332016-03-11 17:09:12 -0800653 gpr_mu_unlock(&c->mu);
654 GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
Craig Tiller99b642a2016-06-01 17:20:34 -0700655 grpc_channel_args_destroy(delete_channel_args);
Craig Tiller45724b32015-09-22 10:42:19 -0700656}
657
Craig Tiller2595ab72015-06-25 15:26:00 -0700658/*
659 * grpc_subchannel_call implementation
660 */
661
Craig Tiller577c9b22015-11-02 14:11:15 -0800662static void subchannel_call_destroy(grpc_exec_ctx *exec_ctx, void *call,
Craig Tiller804ff712016-05-05 16:25:40 -0700663 grpc_error *error) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800664 grpc_subchannel_call *c = call;
Craig Tiller577c9b22015-11-02 14:11:15 -0800665 GPR_TIMER_BEGIN("grpc_subchannel_call_unref.destroy", 0);
Craig Tiller2c8063c2016-03-22 22:12:15 -0700666 grpc_connected_subchannel *connection = c->connection;
David Garcia Quintas580987a2016-04-29 17:26:33 -0700667 grpc_call_stack_destroy(exec_ctx, SUBCHANNEL_CALL_TO_CALL_STACK(c), NULL, c);
Craig Tiller2c8063c2016-03-22 22:12:15 -0700668 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, connection, "subchannel_call");
Craig Tiller577c9b22015-11-02 14:11:15 -0800669 GPR_TIMER_END("grpc_subchannel_call_unref.destroy", 0);
670}
671
Craig Tillerf40df232016-03-25 13:38:14 -0700672void grpc_subchannel_call_ref(
673 grpc_subchannel_call *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller906e3bc2015-11-24 07:31:31 -0800674 GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON);
Craig Tillerc3967532015-06-29 14:59:38 -0700675}
Craig Tiller2595ab72015-06-25 15:26:00 -0700676
Craig Tillera82950e2015-09-22 12:33:20 -0700677void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx,
678 grpc_subchannel_call *c
679 GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
Craig Tiller906e3bc2015-11-24 07:31:31 -0800680 GRPC_CALL_STACK_UNREF(exec_ctx, SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON);
Craig Tiller2595ab72015-06-25 15:26:00 -0700681}
682
Craig Tillera82950e2015-09-22 12:33:20 -0700683char *grpc_subchannel_call_get_peer(grpc_exec_ctx *exec_ctx,
684 grpc_subchannel_call *call) {
685 grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);
686 grpc_call_element *top_elem = grpc_call_stack_element(call_stack, 0);
687 return top_elem->filter->get_peer(exec_ctx, top_elem);
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700688}
689
Craig Tillera82950e2015-09-22 12:33:20 -0700690void grpc_subchannel_call_process_op(grpc_exec_ctx *exec_ctx,
691 grpc_subchannel_call *call,
692 grpc_transport_stream_op *op) {
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700693 GPR_TIMER_BEGIN("grpc_subchannel_call_process_op", 0);
Craig Tillera82950e2015-09-22 12:33:20 -0700694 grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);
695 grpc_call_element *top_elem = grpc_call_stack_element(call_stack, 0);
696 top_elem->filter->start_transport_stream_op(exec_ctx, top_elem, op);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700697 GPR_TIMER_END("grpc_subchannel_call_process_op", 0);
Craig Tiller2595ab72015-06-25 15:26:00 -0700698}
Craig Tillereb3b12e2015-06-26 14:42:49 -0700699
Craig Tillerab33b482015-11-21 08:11:04 -0800700grpc_connected_subchannel *grpc_subchannel_get_connected_subchannel(
701 grpc_subchannel *c) {
Craig Tillerb5585d42015-11-17 07:18:31 -0800702 return GET_CONNECTED_SUBCHANNEL(c, acq);
703}
704
Craig Tillerab33b482015-11-21 08:11:04 -0800705grpc_subchannel_call *grpc_connected_subchannel_create_call(
706 grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700707 grpc_polling_entity *pollent) {
Craig Tillera82950e2015-09-22 12:33:20 -0700708 grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con);
709 grpc_subchannel_call *call =
710 gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
711 grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(call);
Craig Tiller04c5d4b2015-06-26 17:21:41 -0700712 call->connection = con;
Craig Tiller53ee0402015-11-25 09:07:09 -0800713 GRPC_CONNECTED_SUBCHANNEL_REF(con, "subchannel_call");
Craig Tiller577c9b22015-11-02 14:11:15 -0800714 grpc_call_stack_init(exec_ctx, chanstk, 1, subchannel_call_destroy, call,
715 NULL, NULL, callstk);
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700716 grpc_call_stack_set_pollset_or_pollset_set(exec_ctx, callstk, pollent);
Craig Tiller04c5d4b2015-06-26 17:21:41 -0700717 return call;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700718}
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700719
Craig Tiller577c9b22015-11-02 14:11:15 -0800720grpc_call_stack *grpc_subchannel_call_get_call_stack(
721 grpc_subchannel_call *subchannel_call) {
722 return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call);
723}