blob: 16d91d427780edc89dd0a84aaffcc24cf9c6b7d9 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller06059952015-02-18 08:34:56 -08003 * Copyright 2015, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#include "src/core/channel/client_channel.h"
35
36#include <stdio.h>
Craig Tillereb3b12e2015-06-26 14:42:49 -070037#include <string.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080038
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080039#include <grpc/support/alloc.h>
40#include <grpc/support/log.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080041#include <grpc/support/sync.h>
42#include <grpc/support/useful.h>
43
Craig Tiller8910ac62015-10-08 16:49:15 -070044#include "src/core/channel/channel_args.h"
45#include "src/core/channel/connected_channel.h"
Craig Tiller577c9b22015-11-02 14:11:15 -080046#include "src/core/channel/subchannel_call_holder.h"
Craig Tiller8910ac62015-10-08 16:49:15 -070047#include "src/core/iomgr/iomgr.h"
48#include "src/core/profiling/timers.h"
49#include "src/core/support/string.h"
50#include "src/core/surface/channel.h"
51#include "src/core/transport/connectivity_state.h"
52
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080053/* Client channel implementation */
54
Craig Tiller577c9b22015-11-02 14:11:15 -080055typedef grpc_subchannel_call_holder call_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080056
Craig Tiller800dacb2015-10-06 09:10:26 -070057typedef struct client_channel_channel_data {
Craig Tillerf5f17122015-06-25 08:47:26 -070058 /** metadata context for this channel */
Craig Tillere70413c2015-04-24 10:12:34 -070059 grpc_mdctx *mdctx;
Craig Tillerf5f17122015-06-25 08:47:26 -070060 /** resolver for this channel */
61 grpc_resolver *resolver;
Craig Tiller20a3c352015-08-05 08:39:50 -070062 /** have we started resolving this channel */
63 int started_resolving;
Craig Tiller50bc6092015-07-01 14:25:19 -070064 /** master channel - the grpc_channel instance that ultimately owns
65 this channel_data via its channel stack.
66 We occasionally use this to bump the refcount on the master channel
67 to keep ourselves alive through an asynchronous operation. */
Craig Tiller98465032015-06-29 14:36:42 -070068 grpc_channel *master;
Craig Tillerf5f17122015-06-25 08:47:26 -070069
Craig Tiller9d94b602015-07-01 14:23:18 -070070 /** mutex protecting client configuration, including all
71 variables below in this data structure */
Craig Tillerf5f17122015-06-25 08:47:26 -070072 gpr_mu mu_config;
Craig Tillerf5f17122015-06-25 08:47:26 -070073 /** currently active load balancer - guarded by mu_config */
74 grpc_lb_policy *lb_policy;
Craig Tillerf5f17122015-06-25 08:47:26 -070075 /** incoming configuration - set by resolver.next
76 guarded by mu_config */
77 grpc_client_config *incoming_configuration;
Craig Tiller3f475422015-06-25 10:43:05 -070078 /** a list of closures that are all waiting for config to come in */
Craig Tillerd9ccbbf2015-09-22 09:30:00 -070079 grpc_closure_list waiting_for_config_closures;
Craig Tiller3f475422015-06-25 10:43:05 -070080 /** resolver callback */
Craig Tiller33825112015-09-18 07:44:19 -070081 grpc_closure on_config_changed;
Craig Tiller3f475422015-06-25 10:43:05 -070082 /** connectivity state being tracked */
Craig Tillerca3e9d32015-06-27 18:37:27 -070083 grpc_connectivity_state_tracker state_tracker;
Craig Tiller48cb07c2015-07-15 16:16:15 -070084 /** when an lb_policy arrives, should we try to exit idle */
85 int exit_idle_when_lb_policy_arrives;
Craig Tiller1ada6ad2015-07-16 16:19:14 -070086 /** pollset_set of interested parties in a new connection */
87 grpc_pollset_set pollset_set;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080088} channel_data;
89
Craig Tillerd6c98df2015-08-18 09:33:44 -070090/** We create one watcher for each new lb_policy that is returned from a
91 resolver,
92 to watch for state changes from the lb_policy. When a state change is seen,
93 we
Craig Tiller1ada6ad2015-07-16 16:19:14 -070094 update the channel, and create a new watcher */
Craig Tillera82950e2015-09-22 12:33:20 -070095typedef struct {
Craig Tiller1ada6ad2015-07-16 16:19:14 -070096 channel_data *chand;
Craig Tiller33825112015-09-18 07:44:19 -070097 grpc_closure on_changed;
Craig Tiller1ada6ad2015-07-16 16:19:14 -070098 grpc_connectivity_state state;
99 grpc_lb_policy *lb_policy;
100} lb_policy_connectivity_watcher;
101
Craig Tillera82950e2015-09-22 12:33:20 -0700102typedef struct {
Craig Tiller33825112015-09-18 07:44:19 -0700103 grpc_closure closure;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700104 grpc_call_element *elem;
105} waiting_call;
106
Craig Tillera82950e2015-09-22 12:33:20 -0700107static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700108 channel_data *chand = elem->channel_data;
Craig Tiller577c9b22015-11-02 14:11:15 -0800109 return grpc_subchannel_call_holder_get_peer(exec_ctx, elem->call_data,
110 chand->master);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700111}
Craig Tillerf5f17122015-06-25 08:47:26 -0700112
Craig Tillera82950e2015-09-22 12:33:20 -0700113static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
114 grpc_call_element *elem,
115 grpc_transport_stream_op *op) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800116 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
117 grpc_subchannel_call_holder_perform_op(exec_ctx, elem->call_data, op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800118}
119
Craig Tillera82950e2015-09-22 12:33:20 -0700120static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
121 grpc_lb_policy *lb_policy,
122 grpc_connectivity_state current_state);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700123
Craig Tillera82950e2015-09-22 12:33:20 -0700124static void on_lb_policy_state_changed_locked(
125 grpc_exec_ctx *exec_ctx, lb_policy_connectivity_watcher *w) {
Craig Tiller5795da72015-09-17 15:27:13 -0700126 /* check if the notification is for a stale policy */
Craig Tillera82950e2015-09-22 12:33:20 -0700127 if (w->lb_policy != w->chand->lb_policy) return;
Craig Tiller5795da72015-09-17 15:27:13 -0700128
Craig Tillera82950e2015-09-22 12:33:20 -0700129 grpc_connectivity_state_set(exec_ctx, &w->chand->state_tracker, w->state,
130 "lb_changed");
131 if (w->state != GRPC_CHANNEL_FATAL_FAILURE) {
132 watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state);
133 }
Craig Tiller5795da72015-09-17 15:27:13 -0700134}
135
Craig Tillera82950e2015-09-22 12:33:20 -0700136static void on_lb_policy_state_changed(grpc_exec_ctx *exec_ctx, void *arg,
137 int iomgr_success) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700138 lb_policy_connectivity_watcher *w = arg;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700139
Craig Tillera82950e2015-09-22 12:33:20 -0700140 gpr_mu_lock(&w->chand->mu_config);
141 on_lb_policy_state_changed_locked(exec_ctx, w);
142 gpr_mu_unlock(&w->chand->mu_config);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700143
Craig Tillera82950e2015-09-22 12:33:20 -0700144 GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, w->chand->master, "watch_lb_policy");
145 gpr_free(w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700146}
147
Craig Tillera82950e2015-09-22 12:33:20 -0700148static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
149 grpc_lb_policy *lb_policy,
150 grpc_connectivity_state current_state) {
151 lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
152 GRPC_CHANNEL_INTERNAL_REF(chand->master, "watch_lb_policy");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700153
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700154 w->chand = chand;
Craig Tillera82950e2015-09-22 12:33:20 -0700155 grpc_closure_init(&w->on_changed, on_lb_policy_state_changed, w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700156 w->state = current_state;
157 w->lb_policy = lb_policy;
Craig Tillera82950e2015-09-22 12:33:20 -0700158 grpc_lb_policy_notify_on_state_change(exec_ctx, lb_policy, &w->state,
159 &w->on_changed);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700160}
161
Craig Tillera82950e2015-09-22 12:33:20 -0700162static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
163 int iomgr_success) {
Craig Tiller3f475422015-06-25 10:43:05 -0700164 channel_data *chand = arg;
165 grpc_lb_policy *lb_policy = NULL;
166 grpc_lb_policy *old_lb_policy;
167 grpc_resolver *old_resolver;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700168 grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Craig Tiller48cb07c2015-07-15 16:16:15 -0700169 int exit_idle = 0;
Craig Tiller3f475422015-06-25 10:43:05 -0700170
Craig Tillera82950e2015-09-22 12:33:20 -0700171 if (chand->incoming_configuration != NULL) {
172 lb_policy = grpc_client_config_get_lb_policy(chand->incoming_configuration);
173 if (lb_policy != NULL) {
174 GRPC_LB_POLICY_REF(lb_policy, "channel");
175 GRPC_LB_POLICY_REF(lb_policy, "config_change");
176 state = grpc_lb_policy_check_connectivity(exec_ctx, lb_policy);
Craig Tiller45724b32015-09-22 10:42:19 -0700177 }
Craig Tiller3f475422015-06-25 10:43:05 -0700178
Craig Tillera82950e2015-09-22 12:33:20 -0700179 grpc_client_config_unref(exec_ctx, chand->incoming_configuration);
180 }
181
Craig Tiller3f475422015-06-25 10:43:05 -0700182 chand->incoming_configuration = NULL;
183
Craig Tillera82950e2015-09-22 12:33:20 -0700184 gpr_mu_lock(&chand->mu_config);
Craig Tiller3f475422015-06-25 10:43:05 -0700185 old_lb_policy = chand->lb_policy;
186 chand->lb_policy = lb_policy;
Craig Tillera82950e2015-09-22 12:33:20 -0700187 if (lb_policy != NULL || chand->resolver == NULL /* disconnected */) {
188 grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures);
189 }
190 if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
191 GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
192 exit_idle = 1;
193 chand->exit_idle_when_lb_policy_arrives = 0;
194 }
Craig Tiller98465032015-06-29 14:36:42 -0700195
Craig Tillera82950e2015-09-22 12:33:20 -0700196 if (iomgr_success && chand->resolver) {
197 grpc_resolver *resolver = chand->resolver;
198 GRPC_RESOLVER_REF(resolver, "channel-next");
199 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state,
200 "new_lb+resolver");
201 if (lb_policy != NULL) {
202 watch_lb_policy(exec_ctx, chand, lb_policy, state);
Craig Tiller45724b32015-09-22 10:42:19 -0700203 }
Craig Tillera82950e2015-09-22 12:33:20 -0700204 gpr_mu_unlock(&chand->mu_config);
205 GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
206 grpc_resolver_next(exec_ctx, resolver, &chand->incoming_configuration,
207 &chand->on_config_changed);
208 GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel-next");
209 } else {
210 old_resolver = chand->resolver;
211 chand->resolver = NULL;
212 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
213 GRPC_CHANNEL_FATAL_FAILURE, "resolver_gone");
214 gpr_mu_unlock(&chand->mu_config);
215 if (old_resolver != NULL) {
216 grpc_resolver_shutdown(exec_ctx, old_resolver);
217 GRPC_RESOLVER_UNREF(exec_ctx, old_resolver, "channel");
Craig Tiller45724b32015-09-22 10:42:19 -0700218 }
Craig Tillera82950e2015-09-22 12:33:20 -0700219 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700220
Craig Tillera82950e2015-09-22 12:33:20 -0700221 if (exit_idle) {
222 grpc_lb_policy_exit_idle(exec_ctx, lb_policy);
223 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
224 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700225
Craig Tillera82950e2015-09-22 12:33:20 -0700226 if (old_lb_policy != NULL) {
227 grpc_lb_policy_shutdown(exec_ctx, old_lb_policy);
228 GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
229 }
Craig Tiller000cd8f2015-09-18 07:20:29 -0700230
Craig Tillera82950e2015-09-22 12:33:20 -0700231 if (lb_policy != NULL) {
232 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
233 }
Craig Tiller45724b32015-09-22 10:42:19 -0700234
Craig Tillera82950e2015-09-22 12:33:20 -0700235 GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, chand->master, "resolver");
Craig Tiller3f475422015-06-25 10:43:05 -0700236}
237
Craig Tillera82950e2015-09-22 12:33:20 -0700238static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
239 grpc_channel_element *elem,
240 grpc_transport_op *op) {
Craig Tillerca3e9d32015-06-27 18:37:27 -0700241 grpc_lb_policy *lb_policy = NULL;
242 channel_data *chand = elem->channel_data;
Craig Tiller98465032015-06-29 14:36:42 -0700243 grpc_resolver *destroy_resolver = NULL;
Craig Tiller000cd8f2015-09-18 07:20:29 -0700244
Craig Tillera82950e2015-09-22 12:33:20 -0700245 grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, 1);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700246
Craig Tillera82950e2015-09-22 12:33:20 -0700247 GPR_ASSERT(op->set_accept_stream == NULL);
248 GPR_ASSERT(op->bind_pollset == NULL);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700249
Craig Tillera82950e2015-09-22 12:33:20 -0700250 gpr_mu_lock(&chand->mu_config);
251 if (op->on_connectivity_state_change != NULL) {
252 grpc_connectivity_state_notify_on_state_change(
253 exec_ctx, &chand->state_tracker, op->connectivity_state,
254 op->on_connectivity_state_change);
255 op->on_connectivity_state_change = NULL;
256 op->connectivity_state = NULL;
257 }
258
Craig Tiller577c9b22015-11-02 14:11:15 -0800259 lb_policy = chand->lb_policy;
260 if (lb_policy) {
261 GRPC_LB_POLICY_REF(lb_policy, "broadcast");
Craig Tillera82950e2015-09-22 12:33:20 -0700262 }
Craig Tiller03dc6552015-07-17 23:12:34 -0700263
Craig Tillera82950e2015-09-22 12:33:20 -0700264 if (op->disconnect && chand->resolver != NULL) {
265 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
266 GRPC_CHANNEL_FATAL_FAILURE, "disconnect");
267 destroy_resolver = chand->resolver;
268 chand->resolver = NULL;
269 if (chand->lb_policy != NULL) {
270 grpc_lb_policy_shutdown(exec_ctx, chand->lb_policy);
271 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
272 chand->lb_policy = NULL;
Craig Tillerd2cc4592015-07-01 07:50:47 -0700273 }
Craig Tillera82950e2015-09-22 12:33:20 -0700274 }
275 gpr_mu_unlock(&chand->mu_config);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700276
Craig Tillera82950e2015-09-22 12:33:20 -0700277 if (destroy_resolver) {
278 grpc_resolver_shutdown(exec_ctx, destroy_resolver);
279 GRPC_RESOLVER_UNREF(exec_ctx, destroy_resolver, "channel");
280 }
Craig Tiller98465032015-06-29 14:36:42 -0700281
Craig Tillera82950e2015-09-22 12:33:20 -0700282 if (lb_policy) {
283 grpc_lb_policy_broadcast(exec_ctx, lb_policy, op);
284 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "broadcast");
285 }
Craig Tillerca3e9d32015-06-27 18:37:27 -0700286}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800287
Craig Tiller577c9b22015-11-02 14:11:15 -0800288typedef struct {
289 grpc_metadata_batch *initial_metadata;
290 grpc_subchannel **subchannel;
291 grpc_closure *on_ready;
292 grpc_call_element *elem;
293 grpc_closure closure;
294} continue_picking_args;
295
296static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *arg,
297 grpc_metadata_batch *initial_metadata,
298 grpc_subchannel **subchannel,
299 grpc_closure *on_ready);
300
301static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg, int success) {
302 continue_picking_args *cpa = arg;
303 if (!success) {
304 grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, 0);
305 } else if (cpa->subchannel == NULL) {
306 /* cancelled, do nothing */
307 } else if (cc_pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata,
308 cpa->subchannel, cpa->on_ready)) {
309 grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, 1);
310 }
311 gpr_free(cpa);
312}
313
314static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
315 grpc_metadata_batch *initial_metadata,
316 grpc_subchannel **subchannel,
317 grpc_closure *on_ready) {
318 grpc_call_element *elem = elemp;
319 channel_data *chand = elem->channel_data;
320 call_data *calld = elem->call_data;
321 continue_picking_args *cpa;
322 grpc_closure *closure;
323
324 GPR_ASSERT(subchannel);
325
326 gpr_mu_lock(&chand->mu_config);
327 if (initial_metadata == NULL) {
328 if (chand->lb_policy != NULL) {
329 grpc_lb_policy_cancel_pick(exec_ctx, chand->lb_policy, subchannel);
330 }
331 for (closure = chand->waiting_for_config_closures.head; closure != NULL;
332 closure = grpc_closure_next(closure)) {
333 cpa = closure->cb_arg;
334 if (cpa->subchannel == subchannel) {
335 cpa->subchannel = NULL;
336 grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, 0);
337 }
338 }
339 gpr_mu_unlock(&chand->mu_config);
340 return 1;
341 }
342 if (chand->lb_policy != NULL) {
343 int r = grpc_lb_policy_pick(exec_ctx, chand->lb_policy, calld->pollset,
344 initial_metadata, subchannel, on_ready);
345 gpr_mu_unlock(&chand->mu_config);
346 return r;
347 }
348 if (chand->resolver != NULL && !chand->started_resolving) {
349 chand->started_resolving = 1;
350 GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
351 grpc_resolver_next(exec_ctx, chand->resolver,
352 &chand->incoming_configuration,
353 &chand->on_config_changed);
354 }
355 cpa = gpr_malloc(sizeof(*cpa));
356 cpa->initial_metadata = initial_metadata;
357 cpa->subchannel = subchannel;
358 cpa->on_ready = on_ready;
359 cpa->elem = elem;
360 grpc_closure_init(&cpa->closure, continue_picking, cpa);
361 grpc_closure_list_add(&chand->waiting_for_config_closures, &cpa->closure, 1);
362 gpr_mu_unlock(&chand->mu_config);
363 return 0;
364}
365
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800366/* Constructor for call_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700367static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
Craig Tiller577c9b22015-11-02 14:11:15 -0800368 grpc_call_element_args *args) {
369 grpc_subchannel_call_holder_init(elem->call_data, cc_pick_subchannel, elem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800370}
371
372/* Destructor for call_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700373static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
374 grpc_call_element *elem) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800375 grpc_subchannel_call_holder_destroy(exec_ctx, elem->call_data);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800376}
377
378/* Constructor for channel_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700379static void init_channel_elem(grpc_exec_ctx *exec_ctx,
Craig Tiller577c9b22015-11-02 14:11:15 -0800380 grpc_channel_element *elem,
381 grpc_channel_element_args *args) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800382 channel_data *chand = elem->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800383
Craig Tillera82950e2015-09-22 12:33:20 -0700384 memset(chand, 0, sizeof(*chand));
Craig Tillereb3b12e2015-06-26 14:42:49 -0700385
Craig Tiller577c9b22015-11-02 14:11:15 -0800386 GPR_ASSERT(args->is_last);
Craig Tillera82950e2015-09-22 12:33:20 -0700387 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800388
Craig Tillera82950e2015-09-22 12:33:20 -0700389 gpr_mu_init(&chand->mu_config);
Craig Tiller577c9b22015-11-02 14:11:15 -0800390 chand->mdctx = args->metadata_context;
391 chand->master = args->master;
Craig Tillera82950e2015-09-22 12:33:20 -0700392 grpc_pollset_set_init(&chand->pollset_set);
393 grpc_closure_init(&chand->on_config_changed, cc_on_config_changed, chand);
Craig Tiller98465032015-06-29 14:36:42 -0700394
Craig Tillera82950e2015-09-22 12:33:20 -0700395 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
396 "client_channel");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800397}
398
399/* Destructor for channel_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700400static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
401 grpc_channel_element *elem) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800402 channel_data *chand = elem->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800403
Craig Tillera82950e2015-09-22 12:33:20 -0700404 if (chand->resolver != NULL) {
405 grpc_resolver_shutdown(exec_ctx, chand->resolver);
406 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
407 }
408 if (chand->lb_policy != NULL) {
409 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
410 }
411 grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
412 grpc_pollset_set_destroy(&chand->pollset_set);
413 gpr_mu_destroy(&chand->mu_config);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800414}
415
Craig Tiller577c9b22015-11-02 14:11:15 -0800416static void cc_set_pollset(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
417 grpc_pollset *pollset) {
418 call_data *calld = elem->call_data;
419 calld->pollset = pollset;
420}
421
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800422const grpc_channel_filter grpc_client_channel_filter = {
Craig Tiller71a0f9d2015-09-28 17:22:01 -0700423 cc_start_transport_stream_op, cc_start_transport_op, sizeof(call_data),
Craig Tiller577c9b22015-11-02 14:11:15 -0800424 init_call_elem, cc_set_pollset, destroy_call_elem, sizeof(channel_data),
425 init_channel_elem, destroy_channel_elem, cc_get_peer, "client-channel",
Craig Tiller87d5b192015-04-16 14:37:57 -0700426};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800427
Craig Tillera82950e2015-09-22 12:33:20 -0700428void grpc_client_channel_set_resolver(grpc_exec_ctx *exec_ctx,
429 grpc_channel_stack *channel_stack,
430 grpc_resolver *resolver) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800431 /* post construction initialization: set the transport setup pointer */
Craig Tillera82950e2015-09-22 12:33:20 -0700432 grpc_channel_element *elem = grpc_channel_stack_last_element(channel_stack);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800433 channel_data *chand = elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700434 gpr_mu_lock(&chand->mu_config);
435 GPR_ASSERT(!chand->resolver);
Craig Tillerf5f17122015-06-25 08:47:26 -0700436 chand->resolver = resolver;
Craig Tillera82950e2015-09-22 12:33:20 -0700437 GRPC_RESOLVER_REF(resolver, "channel");
438 if (!grpc_closure_list_empty(chand->waiting_for_config_closures) ||
439 chand->exit_idle_when_lb_policy_arrives) {
440 chand->started_resolving = 1;
441 GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
442 grpc_resolver_next(exec_ctx, resolver, &chand->incoming_configuration,
443 &chand->on_config_changed);
444 }
445 gpr_mu_unlock(&chand->mu_config);
Craig Tiller190d3602015-02-18 09:23:38 -0800446}
Craig Tiller48cb07c2015-07-15 16:16:15 -0700447
Craig Tillera82950e2015-09-22 12:33:20 -0700448grpc_connectivity_state grpc_client_channel_check_connectivity_state(
449 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
Craig Tiller48cb07c2015-07-15 16:16:15 -0700450 channel_data *chand = elem->channel_data;
451 grpc_connectivity_state out;
Craig Tillera82950e2015-09-22 12:33:20 -0700452 gpr_mu_lock(&chand->mu_config);
453 out = grpc_connectivity_state_check(&chand->state_tracker);
454 if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
455 if (chand->lb_policy != NULL) {
456 grpc_lb_policy_exit_idle(exec_ctx, chand->lb_policy);
457 } else {
458 chand->exit_idle_when_lb_policy_arrives = 1;
459 if (!chand->started_resolving && chand->resolver != NULL) {
460 GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
461 chand->started_resolving = 1;
462 grpc_resolver_next(exec_ctx, chand->resolver,
463 &chand->incoming_configuration,
464 &chand->on_config_changed);
465 }
Craig Tiller48cb07c2015-07-15 16:16:15 -0700466 }
Craig Tillera82950e2015-09-22 12:33:20 -0700467 }
468 gpr_mu_unlock(&chand->mu_config);
Craig Tiller48cb07c2015-07-15 16:16:15 -0700469 return out;
470}
471
Craig Tillera82950e2015-09-22 12:33:20 -0700472void grpc_client_channel_watch_connectivity_state(
473 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
474 grpc_connectivity_state *state, grpc_closure *on_complete) {
Craig Tiller48cb07c2015-07-15 16:16:15 -0700475 channel_data *chand = elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700476 gpr_mu_lock(&chand->mu_config);
477 grpc_connectivity_state_notify_on_state_change(
478 exec_ctx, &chand->state_tracker, state, on_complete);
479 gpr_mu_unlock(&chand->mu_config);
Craig Tiller48cb07c2015-07-15 16:16:15 -0700480}
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700481
Craig Tillera82950e2015-09-22 12:33:20 -0700482grpc_pollset_set *grpc_client_channel_get_connecting_pollset_set(
483 grpc_channel_element *elem) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700484 channel_data *chand = elem->channel_data;
485 return &chand->pollset_set;
486}
487
Craig Tillera82950e2015-09-22 12:33:20 -0700488void grpc_client_channel_add_interested_party(grpc_exec_ctx *exec_ctx,
489 grpc_channel_element *elem,
490 grpc_pollset *pollset) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700491 channel_data *chand = elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700492 grpc_pollset_set_add_pollset(exec_ctx, &chand->pollset_set, pollset);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700493}
494
Craig Tillera82950e2015-09-22 12:33:20 -0700495void grpc_client_channel_del_interested_party(grpc_exec_ctx *exec_ctx,
496 grpc_channel_element *elem,
497 grpc_pollset *pollset) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700498 channel_data *chand = elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700499 grpc_pollset_set_del_pollset(exec_ctx, &chand->pollset_set, pollset);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700500}