blob: a73458821ec3bcbf435f86f0aa3162b779484722 [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
39#include "src/core/channel/channel_args.h"
40#include "src/core/channel/connected_channel.h"
Craig Tiller98465032015-06-29 14:36:42 -070041#include "src/core/surface/channel.h"
ctillerc6d61c42014-12-15 14:52:08 -080042#include "src/core/iomgr/iomgr.h"
Craig Tiller485d7762015-01-23 12:54:05 -080043#include "src/core/support/string.h"
Craig Tiller08a1cf82015-06-29 09:37:52 -070044#include "src/core/transport/connectivity_state.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080045#include <grpc/support/alloc.h>
46#include <grpc/support/log.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080047#include <grpc/support/sync.h>
48#include <grpc/support/useful.h>
49
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080050/* Client channel implementation */
51
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080052typedef struct call_data call_data;
53
54typedef struct {
Craig Tillerf5f17122015-06-25 08:47:26 -070055 /** metadata context for this channel */
Craig Tillere70413c2015-04-24 10:12:34 -070056 grpc_mdctx *mdctx;
Craig Tillerf5f17122015-06-25 08:47:26 -070057 /** resolver for this channel */
58 grpc_resolver *resolver;
Craig Tiller20a3c352015-08-05 08:39:50 -070059 /** have we started resolving this channel */
60 int started_resolving;
Craig Tiller50bc6092015-07-01 14:25:19 -070061 /** master channel - the grpc_channel instance that ultimately owns
62 this channel_data via its channel stack.
63 We occasionally use this to bump the refcount on the master channel
64 to keep ourselves alive through an asynchronous operation. */
Craig Tiller98465032015-06-29 14:36:42 -070065 grpc_channel *master;
Craig Tillerf5f17122015-06-25 08:47:26 -070066
Craig Tiller9d94b602015-07-01 14:23:18 -070067 /** mutex protecting client configuration, including all
68 variables below in this data structure */
Craig Tillerf5f17122015-06-25 08:47:26 -070069 gpr_mu mu_config;
Craig Tillerf5f17122015-06-25 08:47:26 -070070 /** currently active load balancer - guarded by mu_config */
71 grpc_lb_policy *lb_policy;
Craig Tillerf5f17122015-06-25 08:47:26 -070072 /** incoming configuration - set by resolver.next
73 guarded by mu_config */
74 grpc_client_config *incoming_configuration;
Craig Tiller3f475422015-06-25 10:43:05 -070075 /** a list of closures that are all waiting for config to come in */
76 grpc_iomgr_closure *waiting_for_config_closures;
77 /** resolver callback */
78 grpc_iomgr_closure on_config_changed;
79 /** connectivity state being tracked */
Craig Tillerca3e9d32015-06-27 18:37:27 -070080 grpc_connectivity_state_tracker state_tracker;
Craig Tiller48cb07c2015-07-15 16:16:15 -070081 /** when an lb_policy arrives, should we try to exit idle */
82 int exit_idle_when_lb_policy_arrives;
Craig Tiller1ada6ad2015-07-16 16:19:14 -070083 /** pollset_set of interested parties in a new connection */
84 grpc_pollset_set pollset_set;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080085} channel_data;
86
Craig Tillerd6c98df2015-08-18 09:33:44 -070087/** We create one watcher for each new lb_policy that is returned from a
88 resolver,
89 to watch for state changes from the lb_policy. When a state change is seen,
90 we
Craig Tiller1ada6ad2015-07-16 16:19:14 -070091 update the channel, and create a new watcher */
92typedef struct {
93 channel_data *chand;
94 grpc_iomgr_closure on_changed;
95 grpc_connectivity_state state;
96 grpc_lb_policy *lb_policy;
97} lb_policy_connectivity_watcher;
98
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080099typedef enum {
100 CALL_CREATED,
Craig Tiller5d44c062015-07-01 08:55:28 -0700101 CALL_WAITING_FOR_SEND,
Craig Tiller3f475422015-06-25 10:43:05 -0700102 CALL_WAITING_FOR_CONFIG,
103 CALL_WAITING_FOR_PICK,
Craig Tillereb3b12e2015-06-26 14:42:49 -0700104 CALL_WAITING_FOR_CALL,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800105 CALL_ACTIVE,
106 CALL_CANCELLED
107} call_state;
108
109struct call_data {
110 /* owning element */
111 grpc_call_element *elem;
112
Craig Tillerf5f17122015-06-25 08:47:26 -0700113 gpr_mu mu_state;
114
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800115 call_state state;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800116 gpr_timespec deadline;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700117 grpc_subchannel *picked_channel;
118 grpc_iomgr_closure async_setup_task;
119 grpc_transport_stream_op waiting_op;
120 /* our child call stack */
121 grpc_subchannel_call *subchannel_call;
122 grpc_linked_mdelem status;
123 grpc_linked_mdelem details;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800124};
125
Craig Tillerb3671532015-07-01 10:37:40 -0700126static grpc_iomgr_closure *merge_into_waiting_op(
127 grpc_call_element *elem,
128 grpc_transport_stream_op *new_op) GRPC_MUST_USE_RESULT;
Craig Tiller5d44c062015-07-01 08:55:28 -0700129
Craig Tiller1a727fd2015-04-24 13:21:22 -0700130static void handle_op_after_cancellation(grpc_call_element *elem,
Craig Tillerb7959a02015-06-25 08:50:54 -0700131 grpc_transport_stream_op *op) {
Craig Tillere70413c2015-04-24 10:12:34 -0700132 call_data *calld = elem->call_data;
133 channel_data *chand = elem->channel_data;
134 if (op->send_ops) {
Yang Gaodbf8fdc2015-05-28 00:52:31 -0700135 grpc_stream_ops_unref_owned_objects(op->send_ops->ops, op->send_ops->nops);
Craig Tiller1e6facb2015-06-11 22:47:11 -0700136 op->on_done_send->cb(op->on_done_send->cb_arg, 0);
Craig Tillere70413c2015-04-24 10:12:34 -0700137 }
138 if (op->recv_ops) {
139 char status[GPR_LTOA_MIN_BUFSIZE];
140 grpc_metadata_batch mdb;
141 gpr_ltoa(GRPC_STATUS_CANCELLED, status);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700142 calld->status.md =
Craig Tiller1a727fd2015-04-24 13:21:22 -0700143 grpc_mdelem_from_strings(chand->mdctx, "grpc-status", status);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700144 calld->details.md =
Craig Tiller1a727fd2015-04-24 13:21:22 -0700145 grpc_mdelem_from_strings(chand->mdctx, "grpc-message", "Cancelled");
Craig Tillereb3b12e2015-06-26 14:42:49 -0700146 calld->status.prev = calld->details.next = NULL;
147 calld->status.next = &calld->details;
148 calld->details.prev = &calld->status;
149 mdb.list.head = &calld->status;
150 mdb.list.tail = &calld->details;
Craig Tillere70413c2015-04-24 10:12:34 -0700151 mdb.garbage.head = mdb.garbage.tail = NULL;
Craig Tiller143e7bf2015-07-13 08:41:49 -0700152 mdb.deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
Craig Tillere70413c2015-04-24 10:12:34 -0700153 grpc_sopb_add_metadata(op->recv_ops, mdb);
154 *op->recv_state = GRPC_STREAM_CLOSED;
Craig Tiller1e6facb2015-06-11 22:47:11 -0700155 op->on_done_recv->cb(op->on_done_recv->cb_arg, 1);
Craig Tillere70413c2015-04-24 10:12:34 -0700156 }
Craig Tiller5dde66e2015-06-02 09:05:23 -0700157 if (op->on_consumed) {
Craig Tiller1e6facb2015-06-11 22:47:11 -0700158 op->on_consumed->cb(op->on_consumed->cb_arg, 0);
Craig Tiller5dde66e2015-06-02 09:05:23 -0700159 }
Craig Tillere70413c2015-04-24 10:12:34 -0700160}
Craig Tiller8b976d02015-02-05 21:41:23 -0800161
Craig Tillereb3b12e2015-06-26 14:42:49 -0700162typedef struct {
163 grpc_iomgr_closure closure;
164 grpc_call_element *elem;
165} waiting_call;
166
Craig Tiller079a11b2015-06-30 10:07:15 -0700167static void perform_transport_stream_op(grpc_call_element *elem,
168 grpc_transport_stream_op *op,
169 int continuation);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700170
171static void continue_with_pick(void *arg, int iomgr_success) {
172 waiting_call *wc = arg;
173 call_data *calld = wc->elem->call_data;
174 perform_transport_stream_op(wc->elem, &calld->waiting_op, 1);
175 gpr_free(wc);
176}
177
Craig Tiller079a11b2015-06-30 10:07:15 -0700178static void add_to_lb_policy_wait_queue_locked_state_config(
179 grpc_call_element *elem) {
Craig Tillereb3b12e2015-06-26 14:42:49 -0700180 channel_data *chand = elem->channel_data;
181 waiting_call *wc = gpr_malloc(sizeof(*wc));
182 grpc_iomgr_closure_init(&wc->closure, continue_with_pick, wc);
183 wc->elem = elem;
184 wc->closure.next = chand->waiting_for_config_closures;
185 chand->waiting_for_config_closures = &wc->closure;
186}
187
188static int is_empty(void *p, int len) {
189 char *ptr = p;
190 int i;
191 for (i = 0; i < len; i++) {
192 if (ptr[i] != 0) return 0;
193 }
194 return 1;
195}
196
197static void started_call(void *arg, int iomgr_success) {
198 call_data *calld = arg;
199 grpc_transport_stream_op op;
200 int have_waiting;
201
202 gpr_mu_lock(&calld->mu_state);
203 if (calld->state == CALL_CANCELLED && calld->subchannel_call != NULL) {
204 memset(&op, 0, sizeof(op));
205 op.cancel_with_status = GRPC_STATUS_CANCELLED;
206 gpr_mu_unlock(&calld->mu_state);
207 grpc_subchannel_call_process_op(calld->subchannel_call, &op);
208 } else if (calld->state == CALL_WAITING_FOR_CALL) {
209 have_waiting = !is_empty(&calld->waiting_op, sizeof(calld->waiting_op));
210 if (calld->subchannel_call != NULL) {
211 calld->state = CALL_ACTIVE;
212 gpr_mu_unlock(&calld->mu_state);
213 if (have_waiting) {
Craig Tiller079a11b2015-06-30 10:07:15 -0700214 grpc_subchannel_call_process_op(calld->subchannel_call,
215 &calld->waiting_op);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700216 }
217 } else {
218 calld->state = CALL_CANCELLED;
219 gpr_mu_unlock(&calld->mu_state);
220 if (have_waiting) {
221 handle_op_after_cancellation(calld->elem, &calld->waiting_op);
222 }
223 }
224 } else {
225 GPR_ASSERT(calld->state == CALL_CANCELLED);
Craig Tiller62b14732015-07-01 11:28:41 -0700226 gpr_mu_unlock(&calld->mu_state);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700227 }
228}
229
230static void picked_target(void *arg, int iomgr_success) {
231 call_data *calld = arg;
Craig Tillerabf36382015-06-29 16:13:27 -0700232 grpc_pollset *pollset;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700233
234 if (calld->picked_channel == NULL) {
235 /* treat this like a cancellation */
236 calld->waiting_op.cancel_with_status = GRPC_STATUS_UNAVAILABLE;
237 perform_transport_stream_op(calld->elem, &calld->waiting_op, 1);
238 } else {
239 gpr_mu_lock(&calld->mu_state);
240 if (calld->state == CALL_CANCELLED) {
241 gpr_mu_unlock(&calld->mu_state);
242 handle_op_after_cancellation(calld->elem, &calld->waiting_op);
243 } else {
244 GPR_ASSERT(calld->state == CALL_WAITING_FOR_PICK);
245 calld->state = CALL_WAITING_FOR_CALL;
Craig Tillerabf36382015-06-29 16:13:27 -0700246 pollset = calld->waiting_op.bind_pollset;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700247 gpr_mu_unlock(&calld->mu_state);
248 grpc_iomgr_closure_init(&calld->async_setup_task, started_call, calld);
Craig Tillerabf36382015-06-29 16:13:27 -0700249 grpc_subchannel_create_call(calld->picked_channel, pollset,
Craig Tiller5f84c842015-06-26 16:08:21 -0700250 &calld->subchannel_call,
251 &calld->async_setup_task);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700252 }
253 }
Craig Tillerf5f17122015-06-25 08:47:26 -0700254}
255
Craig Tillerb3671532015-07-01 10:37:40 -0700256static grpc_iomgr_closure *merge_into_waiting_op(
257 grpc_call_element *elem, grpc_transport_stream_op *new_op) {
Craig Tillerbb32ba32015-06-30 09:31:48 -0700258 call_data *calld = elem->call_data;
Craig Tiller5d44c062015-07-01 08:55:28 -0700259 grpc_iomgr_closure *consumed_op = NULL;
Craig Tillerbb32ba32015-06-30 09:31:48 -0700260 grpc_transport_stream_op *waiting_op = &calld->waiting_op;
Craig Tiller2e9dc502015-07-01 11:31:07 -0700261 GPR_ASSERT((waiting_op->send_ops != NULL) + (new_op->send_ops != NULL) <= 1);
262 GPR_ASSERT((waiting_op->recv_ops != NULL) + (new_op->recv_ops != NULL) <= 1);
Craig Tillerbb32ba32015-06-30 09:31:48 -0700263 if (new_op->send_ops != NULL) {
264 waiting_op->send_ops = new_op->send_ops;
265 waiting_op->is_last_send = new_op->is_last_send;
266 waiting_op->on_done_send = new_op->on_done_send;
267 }
268 if (new_op->recv_ops != NULL) {
269 waiting_op->recv_ops = new_op->recv_ops;
270 waiting_op->recv_state = new_op->recv_state;
271 waiting_op->on_done_recv = new_op->on_done_recv;
272 }
Craig Tiller5d44c062015-07-01 08:55:28 -0700273 if (new_op->on_consumed != NULL) {
274 if (waiting_op->on_consumed != NULL) {
275 consumed_op = waiting_op->on_consumed;
276 }
Craig Tillerbb32ba32015-06-30 09:31:48 -0700277 waiting_op->on_consumed = new_op->on_consumed;
Craig Tillerbb32ba32015-06-30 09:31:48 -0700278 }
279 if (new_op->cancel_with_status != GRPC_STATUS_OK) {
280 waiting_op->cancel_with_status = new_op->cancel_with_status;
281 }
Craig Tiller5d44c062015-07-01 08:55:28 -0700282 return consumed_op;
Craig Tillerbb32ba32015-06-30 09:31:48 -0700283}
284
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700285static char *cc_get_peer(grpc_call_element *elem) {
286 call_data *calld = elem->call_data;
287 channel_data *chand = elem->channel_data;
288 grpc_subchannel_call *subchannel_call;
289 char *result;
290
291 gpr_mu_lock(&calld->mu_state);
292 if (calld->state == CALL_ACTIVE) {
293 subchannel_call = calld->subchannel_call;
294 GRPC_SUBCHANNEL_CALL_REF(subchannel_call, "get_peer");
295 gpr_mu_unlock(&calld->mu_state);
296 result = grpc_subchannel_call_get_peer(subchannel_call);
297 GRPC_SUBCHANNEL_CALL_UNREF(subchannel_call, "get_peer");
298 return result;
299 } else {
300 gpr_mu_unlock(&calld->mu_state);
301 return grpc_channel_get_target(chand->master);
302 }
303}
304
Craig Tiller079a11b2015-06-30 10:07:15 -0700305static void perform_transport_stream_op(grpc_call_element *elem,
306 grpc_transport_stream_op *op,
307 int continuation) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800308 call_data *calld = elem->call_data;
309 channel_data *chand = elem->channel_data;
Craig Tillerf5f17122015-06-25 08:47:26 -0700310 grpc_subchannel_call *subchannel_call;
311 grpc_lb_policy *lb_policy;
Craig Tiller49924e02015-06-29 22:42:33 -0700312 grpc_transport_stream_op op2;
Craig Tiller5d44c062015-07-01 08:55:28 -0700313 grpc_iomgr_closure *consumed_op = NULL;
Craig Tillera9407522015-04-24 10:37:57 -0700314 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
315 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800316
Craig Tillerf5f17122015-06-25 08:47:26 -0700317 gpr_mu_lock(&calld->mu_state);
318 switch (calld->state) {
319 case CALL_ACTIVE:
Craig Tillereb3b12e2015-06-26 14:42:49 -0700320 GPR_ASSERT(!continuation);
321 subchannel_call = calld->subchannel_call;
Craig Tillerf5f17122015-06-25 08:47:26 -0700322 gpr_mu_unlock(&calld->mu_state);
323 grpc_subchannel_call_process_op(subchannel_call, op);
Craig Tillerf5f17122015-06-25 08:47:26 -0700324 break;
325 case CALL_CANCELLED:
326 gpr_mu_unlock(&calld->mu_state);
327 handle_op_after_cancellation(elem, op);
328 break;
Craig Tiller5d44c062015-07-01 08:55:28 -0700329 case CALL_WAITING_FOR_SEND:
330 GPR_ASSERT(!continuation);
331 consumed_op = merge_into_waiting_op(elem, op);
Craig Tillerb3671532015-07-01 10:37:40 -0700332 if (!calld->waiting_op.send_ops &&
333 calld->waiting_op.cancel_with_status == GRPC_STATUS_OK) {
Craig Tiller5d44c062015-07-01 08:55:28 -0700334 gpr_mu_unlock(&calld->mu_state);
335 break;
336 }
337 *op = calld->waiting_op;
338 memset(&calld->waiting_op, 0, sizeof(calld->waiting_op));
339 continuation = 1;
Craig Tillerb3671532015-07-01 10:37:40 -0700340 /* fall through */
Craig Tillereb3b12e2015-06-26 14:42:49 -0700341 case CALL_WAITING_FOR_CONFIG:
342 case CALL_WAITING_FOR_PICK:
343 case CALL_WAITING_FOR_CALL:
344 if (!continuation) {
345 if (op->cancel_with_status != GRPC_STATUS_OK) {
346 calld->state = CALL_CANCELLED;
Craig Tiller49924e02015-06-29 22:42:33 -0700347 op2 = calld->waiting_op;
348 memset(&calld->waiting_op, 0, sizeof(calld->waiting_op));
Craig Tillerbb32ba32015-06-30 09:31:48 -0700349 if (op->on_consumed) {
350 calld->waiting_op.on_consumed = op->on_consumed;
351 op->on_consumed = NULL;
352 } else if (op2.on_consumed) {
353 calld->waiting_op.on_consumed = op2.on_consumed;
354 op2.on_consumed = NULL;
355 }
Craig Tillereb3b12e2015-06-26 14:42:49 -0700356 gpr_mu_unlock(&calld->mu_state);
357 handle_op_after_cancellation(elem, op);
Craig Tiller49924e02015-06-29 22:42:33 -0700358 handle_op_after_cancellation(elem, &op2);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700359 } else {
Craig Tiller5d44c062015-07-01 08:55:28 -0700360 consumed_op = merge_into_waiting_op(elem, op);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700361 gpr_mu_unlock(&calld->mu_state);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700362 }
363 break;
364 }
Craig Tiller079a11b2015-06-30 10:07:15 -0700365 /* fall through */
Craig Tillerf5f17122015-06-25 08:47:26 -0700366 case CALL_CREATED:
367 if (op->cancel_with_status != GRPC_STATUS_OK) {
368 calld->state = CALL_CANCELLED;
369 gpr_mu_unlock(&calld->mu_state);
370 handle_op_after_cancellation(elem, op);
371 } else {
Craig Tillereb3b12e2015-06-26 14:42:49 -0700372 calld->waiting_op = *op;
Craig Tillerf5f17122015-06-25 08:47:26 -0700373
Craig Tiller5d44c062015-07-01 08:55:28 -0700374 if (op->send_ops == NULL) {
375 /* need to have some send ops before we can select the
376 lb target */
377 calld->state = CALL_WAITING_FOR_SEND;
Craig Tillerf5f17122015-06-25 08:47:26 -0700378 gpr_mu_unlock(&calld->mu_state);
Craig Tillerf5f17122015-06-25 08:47:26 -0700379 } else {
Craig Tiller5d44c062015-07-01 08:55:28 -0700380 gpr_mu_lock(&chand->mu_config);
381 lb_policy = chand->lb_policy;
382 if (lb_policy) {
Craig Tiller990f6422015-07-20 22:07:13 -0700383 grpc_transport_stream_op *op = &calld->waiting_op;
384 grpc_pollset *bind_pollset = op->bind_pollset;
Craig Tillerd6c98df2015-08-18 09:33:44 -0700385 grpc_metadata_batch *initial_metadata =
386 &op->send_ops->ops[0].data.metadata;
Craig Tiller5d44c062015-07-01 08:55:28 -0700387 GRPC_LB_POLICY_REF(lb_policy, "pick");
388 gpr_mu_unlock(&chand->mu_config);
389 calld->state = CALL_WAITING_FOR_PICK;
Craig Tiller3d578712015-07-20 22:00:24 -0700390
Craig Tiller990f6422015-07-20 22:07:13 -0700391 GPR_ASSERT(op->bind_pollset);
392 GPR_ASSERT(op->send_ops);
393 GPR_ASSERT(op->send_ops->nops >= 1);
Craig Tillerd6c98df2015-08-18 09:33:44 -0700394 GPR_ASSERT(op->send_ops->ops[0].type == GRPC_OP_METADATA);
Craig Tiller5d44c062015-07-01 08:55:28 -0700395 gpr_mu_unlock(&calld->mu_state);
396
Craig Tillerd6c98df2015-08-18 09:33:44 -0700397 grpc_iomgr_closure_init(&calld->async_setup_task, picked_target,
398 calld);
Craig Tiller990f6422015-07-20 22:07:13 -0700399 grpc_lb_policy_pick(lb_policy, bind_pollset, initial_metadata,
Craig Tillerd6c98df2015-08-18 09:33:44 -0700400 &calld->picked_channel,
401 &calld->async_setup_task);
Craig Tiller5d44c062015-07-01 08:55:28 -0700402
403 GRPC_LB_POLICY_UNREF(lb_policy, "pick");
Craig Tillerb9a46ae2015-07-01 09:45:21 -0700404 } else if (chand->resolver != NULL) {
Craig Tiller5d44c062015-07-01 08:55:28 -0700405 calld->state = CALL_WAITING_FOR_CONFIG;
406 add_to_lb_policy_wait_queue_locked_state_config(elem);
Craig Tiller20a3c352015-08-05 08:39:50 -0700407 if (!chand->started_resolving && chand->resolver != NULL) {
Craig Tiller6659d8b2015-08-06 18:02:22 -0700408 GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
Craig Tiller20a3c352015-08-05 08:39:50 -0700409 chand->started_resolving = 1;
410 grpc_resolver_next(chand->resolver,
411 &chand->incoming_configuration,
412 &chand->on_config_changed);
413 }
Craig Tiller5d44c062015-07-01 08:55:28 -0700414 gpr_mu_unlock(&chand->mu_config);
415 gpr_mu_unlock(&calld->mu_state);
Craig Tillerb9a46ae2015-07-01 09:45:21 -0700416 } else {
417 calld->state = CALL_CANCELLED;
418 gpr_mu_unlock(&chand->mu_config);
419 gpr_mu_unlock(&calld->mu_state);
420 handle_op_after_cancellation(elem, op);
Craig Tiller5d44c062015-07-01 08:55:28 -0700421 }
Craig Tillerf5f17122015-06-25 08:47:26 -0700422 }
423 }
424 break;
Craig Tillerf5f17122015-06-25 08:47:26 -0700425 }
Craig Tiller5d44c062015-07-01 08:55:28 -0700426
427 if (consumed_op != NULL) {
428 consumed_op->cb(consumed_op->cb_arg, 1);
429 }
Craig Tillereb3b12e2015-06-26 14:42:49 -0700430}
Craig Tillerf5f17122015-06-25 08:47:26 -0700431
Craig Tillereb3b12e2015-06-26 14:42:49 -0700432static void cc_start_transport_stream_op(grpc_call_element *elem,
Craig Tiller079a11b2015-06-30 10:07:15 -0700433 grpc_transport_stream_op *op) {
Craig Tillereb3b12e2015-06-26 14:42:49 -0700434 perform_transport_stream_op(elem, op, 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800435}
436
Craig Tillerd6c98df2015-08-18 09:33:44 -0700437static void watch_lb_policy(channel_data *chand, grpc_lb_policy *lb_policy,
438 grpc_connectivity_state current_state);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700439
440static void on_lb_policy_state_changed(void *arg, int iomgr_success) {
441 lb_policy_connectivity_watcher *w = arg;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700442
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700443 gpr_mu_lock(&w->chand->mu_config);
444 /* check if the notification is for a stale policy */
445 if (w->lb_policy == w->chand->lb_policy) {
Craig Tiller03dc6552015-07-17 23:12:34 -0700446 grpc_connectivity_state_set(&w->chand->state_tracker, w->state,
447 "lb_changed");
Craig Tiller52468382015-07-19 10:52:04 -0700448 if (w->state != GRPC_CHANNEL_FATAL_FAILURE) {
449 watch_lb_policy(w->chand, w->lb_policy, w->state);
450 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700451 }
452 gpr_mu_unlock(&w->chand->mu_config);
453
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700454 GRPC_CHANNEL_INTERNAL_UNREF(w->chand->master, "watch_lb_policy");
455 gpr_free(w);
456}
457
Craig Tillerd6c98df2015-08-18 09:33:44 -0700458static void watch_lb_policy(channel_data *chand, grpc_lb_policy *lb_policy,
459 grpc_connectivity_state current_state) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700460 lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
461 GRPC_CHANNEL_INTERNAL_REF(chand->master, "watch_lb_policy");
462
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700463 w->chand = chand;
464 grpc_iomgr_closure_init(&w->on_changed, on_lb_policy_state_changed, w);
465 w->state = current_state;
466 w->lb_policy = lb_policy;
467 grpc_lb_policy_notify_on_state_change(lb_policy, &w->state, &w->on_changed);
468}
469
Craig Tiller3f475422015-06-25 10:43:05 -0700470static void cc_on_config_changed(void *arg, int iomgr_success) {
471 channel_data *chand = arg;
472 grpc_lb_policy *lb_policy = NULL;
473 grpc_lb_policy *old_lb_policy;
474 grpc_resolver *old_resolver;
475 grpc_iomgr_closure *wakeup_closures = NULL;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700476 grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Craig Tiller48cb07c2015-07-15 16:16:15 -0700477 int exit_idle = 0;
Craig Tiller3f475422015-06-25 10:43:05 -0700478
Craig Tillerd7b68e72015-06-28 11:41:09 -0700479 if (chand->incoming_configuration != NULL) {
Craig Tiller3f475422015-06-25 10:43:05 -0700480 lb_policy = grpc_client_config_get_lb_policy(chand->incoming_configuration);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700481 if (lb_policy != NULL) {
482 GRPC_LB_POLICY_REF(lb_policy, "channel");
483 GRPC_LB_POLICY_REF(lb_policy, "config_change");
484 state = grpc_lb_policy_check_connectivity(lb_policy);
485 }
Craig Tillereb3b12e2015-06-26 14:42:49 -0700486
487 grpc_client_config_unref(chand->incoming_configuration);
Craig Tiller3f475422015-06-25 10:43:05 -0700488 }
489
Craig Tiller3f475422015-06-25 10:43:05 -0700490 chand->incoming_configuration = NULL;
491
492 gpr_mu_lock(&chand->mu_config);
493 old_lb_policy = chand->lb_policy;
494 chand->lb_policy = lb_policy;
Craig Tillerb9a46ae2015-07-01 09:45:21 -0700495 if (lb_policy != NULL || chand->resolver == NULL /* disconnected */) {
Craig Tiller3f475422015-06-25 10:43:05 -0700496 wakeup_closures = chand->waiting_for_config_closures;
497 chand->waiting_for_config_closures = NULL;
498 }
Craig Tiller48cb07c2015-07-15 16:16:15 -0700499 if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
500 GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
501 exit_idle = 1;
502 chand->exit_idle_when_lb_policy_arrives = 0;
503 }
Craig Tiller3f475422015-06-25 10:43:05 -0700504
Craig Tiller98465032015-06-29 14:36:42 -0700505 if (iomgr_success && chand->resolver) {
506 grpc_resolver *resolver = chand->resolver;
507 GRPC_RESOLVER_REF(resolver, "channel-next");
508 gpr_mu_unlock(&chand->mu_config);
509 GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
Craig Tillerab9f1922015-07-07 14:58:55 -0700510 grpc_resolver_next(resolver, &chand->incoming_configuration,
Craig Tiller079a11b2015-06-30 10:07:15 -0700511 &chand->on_config_changed);
Craig Tiller98465032015-06-29 14:36:42 -0700512 GRPC_RESOLVER_UNREF(resolver, "channel-next");
Craig Tiller03dc6552015-07-17 23:12:34 -0700513 grpc_connectivity_state_set(&chand->state_tracker, state,
514 "new_lb+resolver");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700515 if (lb_policy != NULL) {
516 watch_lb_policy(chand, lb_policy, state);
517 }
Craig Tiller98465032015-06-29 14:36:42 -0700518 } else {
519 old_resolver = chand->resolver;
520 chand->resolver = NULL;
Craig Tiller079a11b2015-06-30 10:07:15 -0700521 grpc_connectivity_state_set(&chand->state_tracker,
Craig Tiller03dc6552015-07-17 23:12:34 -0700522 GRPC_CHANNEL_FATAL_FAILURE, "resolver_gone");
Craig Tiller98465032015-06-29 14:36:42 -0700523 gpr_mu_unlock(&chand->mu_config);
524 if (old_resolver != NULL) {
525 grpc_resolver_shutdown(old_resolver);
526 GRPC_RESOLVER_UNREF(old_resolver, "channel");
527 }
528 }
529
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700530 if (exit_idle) {
531 grpc_lb_policy_exit_idle(lb_policy);
532 GRPC_LB_POLICY_UNREF(lb_policy, "exit_idle");
533 }
534
535 if (old_lb_policy != NULL) {
Craig Tillerde02ae62015-08-07 14:19:38 -0700536 grpc_lb_policy_shutdown(old_lb_policy);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700537 GRPC_LB_POLICY_UNREF(old_lb_policy, "channel");
538 }
539
Craig Tiller3f475422015-06-25 10:43:05 -0700540 while (wakeup_closures) {
541 grpc_iomgr_closure *next = wakeup_closures->next;
Craig Tiller994c2622015-07-23 14:00:58 -0700542 wakeup_closures->cb(wakeup_closures->cb_arg, 1);
Craig Tiller3f475422015-06-25 10:43:05 -0700543 wakeup_closures = next;
544 }
545
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700546 if (lb_policy != NULL) {
547 GRPC_LB_POLICY_UNREF(lb_policy, "config_change");
548 }
Craig Tiller98465032015-06-29 14:36:42 -0700549 GRPC_CHANNEL_INTERNAL_UNREF(chand->master, "resolver");
Craig Tiller3f475422015-06-25 10:43:05 -0700550}
551
Craig Tiller079a11b2015-06-30 10:07:15 -0700552static void cc_start_transport_op(grpc_channel_element *elem,
553 grpc_transport_op *op) {
Craig Tillerca3e9d32015-06-27 18:37:27 -0700554 grpc_lb_policy *lb_policy = NULL;
555 channel_data *chand = elem->channel_data;
Craig Tiller98465032015-06-29 14:36:42 -0700556 grpc_resolver *destroy_resolver = NULL;
Craig Tillerca3e9d32015-06-27 18:37:27 -0700557 grpc_iomgr_closure *on_consumed = op->on_consumed;
558 op->on_consumed = NULL;
559
560 GPR_ASSERT(op->set_accept_stream == NULL);
561 GPR_ASSERT(op->bind_pollset == NULL);
562
563 gpr_mu_lock(&chand->mu_config);
564 if (op->on_connectivity_state_change != NULL) {
Craig Tiller079a11b2015-06-30 10:07:15 -0700565 grpc_connectivity_state_notify_on_state_change(
566 &chand->state_tracker, op->connectivity_state,
567 op->on_connectivity_state_change);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700568 op->on_connectivity_state_change = NULL;
569 op->connectivity_state = NULL;
570 }
571
Craig Tiller03dc6552015-07-17 23:12:34 -0700572 if (!is_empty(op, sizeof(*op))) {
573 lb_policy = chand->lb_policy;
574 if (lb_policy) {
575 GRPC_LB_POLICY_REF(lb_policy, "broadcast");
576 }
577 }
578
Craig Tiller98465032015-06-29 14:36:42 -0700579 if (op->disconnect && chand->resolver != NULL) {
Craig Tiller079a11b2015-06-30 10:07:15 -0700580 grpc_connectivity_state_set(&chand->state_tracker,
Craig Tiller03dc6552015-07-17 23:12:34 -0700581 GRPC_CHANNEL_FATAL_FAILURE, "disconnect");
Craig Tiller98465032015-06-29 14:36:42 -0700582 destroy_resolver = chand->resolver;
583 chand->resolver = NULL;
Craig Tillerd2cc4592015-07-01 07:50:47 -0700584 if (chand->lb_policy != NULL) {
585 grpc_lb_policy_shutdown(chand->lb_policy);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700586 GRPC_LB_POLICY_UNREF(chand->lb_policy, "channel");
587 chand->lb_policy = NULL;
Craig Tillerd2cc4592015-07-01 07:50:47 -0700588 }
Craig Tiller98465032015-06-29 14:36:42 -0700589 }
Craig Tillerca3e9d32015-06-27 18:37:27 -0700590 gpr_mu_unlock(&chand->mu_config);
591
Craig Tiller98465032015-06-29 14:36:42 -0700592 if (destroy_resolver) {
593 grpc_resolver_shutdown(destroy_resolver);
594 GRPC_RESOLVER_UNREF(destroy_resolver, "channel");
595 }
596
Craig Tillerca3e9d32015-06-27 18:37:27 -0700597 if (lb_policy) {
598 grpc_lb_policy_broadcast(lb_policy, op);
Craig Tillerd7b68e72015-06-28 11:41:09 -0700599 GRPC_LB_POLICY_UNREF(lb_policy, "broadcast");
Craig Tillerca3e9d32015-06-27 18:37:27 -0700600 }
601
602 if (on_consumed) {
603 grpc_iomgr_add_callback(on_consumed);
604 }
605}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800606
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800607/* Constructor for call_data */
608static void init_call_elem(grpc_call_element *elem,
Craig Tiller06aeea72015-04-23 10:54:45 -0700609 const void *server_transport_data,
Craig Tillerb7959a02015-06-25 08:50:54 -0700610 grpc_transport_stream_op *initial_op) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800611 call_data *calld = elem->call_data;
612
Craig Tiller50d9db52015-04-23 10:52:14 -0700613 /* TODO(ctiller): is there something useful we can do here? */
614 GPR_ASSERT(initial_op == NULL);
615
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800616 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
617 GPR_ASSERT(server_transport_data == NULL);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700618 gpr_mu_init(&calld->mu_state);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800619 calld->elem = elem;
620 calld->state = CALL_CREATED;
Craig Tiller143e7bf2015-07-13 08:41:49 -0700621 calld->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800622}
623
624/* Destructor for call_data */
625static void destroy_call_elem(grpc_call_element *elem) {
626 call_data *calld = elem->call_data;
Craig Tiller3f475422015-06-25 10:43:05 -0700627 grpc_subchannel_call *subchannel_call;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800628
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800629 /* if the call got activated, we need to destroy the child stack also, and
630 remove it from the in-flight requests tracked by the child_entry we
631 picked */
Craig Tiller3f475422015-06-25 10:43:05 -0700632 gpr_mu_lock(&calld->mu_state);
Craig Tillerf93fd052015-06-02 08:15:33 -0700633 switch (calld->state) {
634 case CALL_ACTIVE:
Craig Tillereb3b12e2015-06-26 14:42:49 -0700635 subchannel_call = calld->subchannel_call;
Craig Tiller3f475422015-06-25 10:43:05 -0700636 gpr_mu_unlock(&calld->mu_state);
Craig Tillerc3967532015-06-29 14:59:38 -0700637 GRPC_SUBCHANNEL_CALL_UNREF(subchannel_call, "client_channel");
Craig Tillerf93fd052015-06-02 08:15:33 -0700638 break;
Craig Tiller3f475422015-06-25 10:43:05 -0700639 case CALL_CREATED:
640 case CALL_CANCELLED:
641 gpr_mu_unlock(&calld->mu_state);
Craig Tillerf93fd052015-06-02 08:15:33 -0700642 break;
Craig Tiller3f475422015-06-25 10:43:05 -0700643 case CALL_WAITING_FOR_PICK:
644 case CALL_WAITING_FOR_CONFIG:
Craig Tillereb3b12e2015-06-26 14:42:49 -0700645 case CALL_WAITING_FOR_CALL:
Craig Tiller5d44c062015-07-01 08:55:28 -0700646 case CALL_WAITING_FOR_SEND:
Craig Tiller3f475422015-06-25 10:43:05 -0700647 gpr_log(GPR_ERROR, "should never reach here");
648 abort();
Craig Tillerf93fd052015-06-02 08:15:33 -0700649 break;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800650 }
651}
652
653/* Constructor for channel_data */
Craig Tiller079a11b2015-06-30 10:07:15 -0700654static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800655 const grpc_channel_args *args,
656 grpc_mdctx *metadata_context, int is_first,
657 int is_last) {
658 channel_data *chand = elem->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800659
Craig Tillereb3b12e2015-06-26 14:42:49 -0700660 memset(chand, 0, sizeof(*chand));
661
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800662 GPR_ASSERT(is_last);
663 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
664
Craig Tiller3f475422015-06-25 10:43:05 -0700665 gpr_mu_init(&chand->mu_config);
Craig Tillere70413c2015-04-24 10:12:34 -0700666 chand->mdctx = metadata_context;
Craig Tiller98465032015-06-29 14:36:42 -0700667 chand->master = master;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700668 grpc_pollset_set_init(&chand->pollset_set);
Craig Tiller079a11b2015-06-30 10:07:15 -0700669 grpc_iomgr_closure_init(&chand->on_config_changed, cc_on_config_changed,
670 chand);
Craig Tiller98465032015-06-29 14:36:42 -0700671
Craig Tillerd6c98df2015-08-18 09:33:44 -0700672 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
673 "client_channel");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800674}
675
676/* Destructor for channel_data */
677static void destroy_channel_elem(grpc_channel_element *elem) {
678 channel_data *chand = elem->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800679
Craig Tillerd7b68e72015-06-28 11:41:09 -0700680 if (chand->resolver != NULL) {
Craig Tiller98465032015-06-29 14:36:42 -0700681 grpc_resolver_shutdown(chand->resolver);
682 GRPC_RESOLVER_UNREF(chand->resolver, "channel");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800683 }
Craig Tillerd7b68e72015-06-28 11:41:09 -0700684 if (chand->lb_policy != NULL) {
685 GRPC_LB_POLICY_UNREF(chand->lb_policy, "channel");
Craig Tiller3f475422015-06-25 10:43:05 -0700686 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700687 grpc_connectivity_state_destroy(&chand->state_tracker);
688 grpc_pollset_set_destroy(&chand->pollset_set);
Craig Tiller3f475422015-06-25 10:43:05 -0700689 gpr_mu_destroy(&chand->mu_config);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800690}
691
692const grpc_channel_filter grpc_client_channel_filter = {
Craig Tiller079a11b2015-06-30 10:07:15 -0700693 cc_start_transport_stream_op,
694 cc_start_transport_op,
695 sizeof(call_data),
696 init_call_elem,
697 destroy_call_elem,
698 sizeof(channel_data),
699 init_channel_elem,
700 destroy_channel_elem,
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700701 cc_get_peer,
Craig Tiller079a11b2015-06-30 10:07:15 -0700702 "client-channel",
Craig Tiller87d5b192015-04-16 14:37:57 -0700703};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800704
Craig Tillerf5f17122015-06-25 08:47:26 -0700705void grpc_client_channel_set_resolver(grpc_channel_stack *channel_stack,
706 grpc_resolver *resolver) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800707 /* post construction initialization: set the transport setup pointer */
708 grpc_channel_element *elem = grpc_channel_stack_last_element(channel_stack);
709 channel_data *chand = elem->channel_data;
Craig Tiller20a3c352015-08-05 08:39:50 -0700710 gpr_mu_lock(&chand->mu_config);
Craig Tillerf5f17122015-06-25 08:47:26 -0700711 GPR_ASSERT(!chand->resolver);
712 chand->resolver = resolver;
Craig Tiller98465032015-06-29 14:36:42 -0700713 GRPC_RESOLVER_REF(resolver, "channel");
Craig Tiller20a3c352015-08-05 08:39:50 -0700714 if (chand->waiting_for_config_closures != NULL ||
715 chand->exit_idle_when_lb_policy_arrives) {
716 chand->started_resolving = 1;
Craig Tiller6659d8b2015-08-06 18:02:22 -0700717 GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
Craig Tiller20a3c352015-08-05 08:39:50 -0700718 grpc_resolver_next(resolver, &chand->incoming_configuration,
719 &chand->on_config_changed);
720 }
721 gpr_mu_unlock(&chand->mu_config);
Craig Tiller190d3602015-02-18 09:23:38 -0800722}
Craig Tiller48cb07c2015-07-15 16:16:15 -0700723
724grpc_connectivity_state grpc_client_channel_check_connectivity_state(
725 grpc_channel_element *elem, int try_to_connect) {
726 channel_data *chand = elem->channel_data;
727 grpc_connectivity_state out;
728 gpr_mu_lock(&chand->mu_config);
729 out = grpc_connectivity_state_check(&chand->state_tracker);
730 if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
731 if (chand->lb_policy != NULL) {
732 grpc_lb_policy_exit_idle(chand->lb_policy);
733 } else {
734 chand->exit_idle_when_lb_policy_arrives = 1;
Craig Tiller20a3c352015-08-05 08:39:50 -0700735 if (!chand->started_resolving && chand->resolver != NULL) {
Craig Tiller6659d8b2015-08-06 18:02:22 -0700736 GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
Craig Tiller20a3c352015-08-05 08:39:50 -0700737 chand->started_resolving = 1;
738 grpc_resolver_next(chand->resolver, &chand->incoming_configuration,
739 &chand->on_config_changed);
740 }
Craig Tiller48cb07c2015-07-15 16:16:15 -0700741 }
742 }
743 gpr_mu_unlock(&chand->mu_config);
744 return out;
745}
746
747void grpc_client_channel_watch_connectivity_state(
748 grpc_channel_element *elem, grpc_connectivity_state *state,
749 grpc_iomgr_closure *on_complete) {
750 channel_data *chand = elem->channel_data;
751 gpr_mu_lock(&chand->mu_config);
752 grpc_connectivity_state_notify_on_state_change(&chand->state_tracker, state,
753 on_complete);
754 gpr_mu_unlock(&chand->mu_config);
755}
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700756
Craig Tillerd6c98df2015-08-18 09:33:44 -0700757grpc_pollset_set *grpc_client_channel_get_connecting_pollset_set(
758 grpc_channel_element *elem) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700759 channel_data *chand = elem->channel_data;
760 return &chand->pollset_set;
761}
762
763void grpc_client_channel_add_interested_party(grpc_channel_element *elem,
Craig Tillerd6c98df2015-08-18 09:33:44 -0700764 grpc_pollset *pollset) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700765 channel_data *chand = elem->channel_data;
766 grpc_pollset_set_add_pollset(&chand->pollset_set, pollset);
767}
768
769void grpc_client_channel_del_interested_party(grpc_channel_element *elem,
Craig Tillerd6c98df2015-08-18 09:33:44 -0700770 grpc_pollset *pollset) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700771 channel_data *chand = elem->channel_data;
772 grpc_pollset_set_del_pollset(&chand->pollset_set, pollset);
773}