blob: 2c0c4abffc7f3ba5854a1b25ecee7c490eb2a86c [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * 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
Craig Tillerd4c98332016-03-31 13:45:47 -070034#include "src/core/ext/client_config/client_channel.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080035
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 Tiller97816152016-04-05 13:39:00 -070044#include "src/core/ext/client_config/subchannel_call_holder.h"
Craig Tiller9533d042016-03-25 17:11:06 -070045#include "src/core/lib/channel/channel_args.h"
46#include "src/core/lib/channel/connected_channel.h"
Craig Tiller9533d042016-03-25 17:11:06 -070047#include "src/core/lib/iomgr/iomgr.h"
48#include "src/core/lib/profiling/timers.h"
49#include "src/core/lib/support/string.h"
50#include "src/core/lib/surface/channel.h"
51#include "src/core/lib/transport/connectivity_state.h"
Craig Tiller8910ac62015-10-08 16:49:15 -070052
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 /** resolver for this channel */
59 grpc_resolver *resolver;
Craig Tiller20a3c352015-08-05 08:39:50 -070060 /** have we started resolving this channel */
61 int started_resolving;
Craig Tillerf5f17122015-06-25 08:47:26 -070062
Craig Tiller9d94b602015-07-01 14:23:18 -070063 /** mutex protecting client configuration, including all
64 variables below in this data structure */
Craig Tillerf5f17122015-06-25 08:47:26 -070065 gpr_mu mu_config;
Craig Tillerf5f17122015-06-25 08:47:26 -070066 /** currently active load balancer - guarded by mu_config */
67 grpc_lb_policy *lb_policy;
Craig Tillerf5f17122015-06-25 08:47:26 -070068 /** incoming configuration - set by resolver.next
69 guarded by mu_config */
70 grpc_client_config *incoming_configuration;
Craig Tiller3f475422015-06-25 10:43:05 -070071 /** a list of closures that are all waiting for config to come in */
Craig Tillerd9ccbbf2015-09-22 09:30:00 -070072 grpc_closure_list waiting_for_config_closures;
Craig Tiller3f475422015-06-25 10:43:05 -070073 /** resolver callback */
Craig Tiller33825112015-09-18 07:44:19 -070074 grpc_closure on_config_changed;
Craig Tiller3f475422015-06-25 10:43:05 -070075 /** connectivity state being tracked */
Craig Tillerca3e9d32015-06-27 18:37:27 -070076 grpc_connectivity_state_tracker state_tracker;
Craig Tiller48cb07c2015-07-15 16:16:15 -070077 /** when an lb_policy arrives, should we try to exit idle */
78 int exit_idle_when_lb_policy_arrives;
Craig Tiller906e3bc2015-11-24 07:31:31 -080079 /** owning stack */
80 grpc_channel_stack *owning_stack;
Craig Tiller69b093b2016-02-25 19:04:07 -080081 /** interested parties (owned) */
82 grpc_pollset_set *interested_parties;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080083} channel_data;
84
Craig Tillerd6c98df2015-08-18 09:33:44 -070085/** We create one watcher for each new lb_policy that is returned from a
86 resolver,
87 to watch for state changes from the lb_policy. When a state change is seen,
88 we
Craig Tiller1ada6ad2015-07-16 16:19:14 -070089 update the channel, and create a new watcher */
Craig Tillera82950e2015-09-22 12:33:20 -070090typedef struct {
Craig Tiller1ada6ad2015-07-16 16:19:14 -070091 channel_data *chand;
Craig Tiller33825112015-09-18 07:44:19 -070092 grpc_closure on_changed;
Craig Tiller1ada6ad2015-07-16 16:19:14 -070093 grpc_connectivity_state state;
94 grpc_lb_policy *lb_policy;
95} lb_policy_connectivity_watcher;
96
Craig Tillera82950e2015-09-22 12:33:20 -070097typedef struct {
Craig Tiller33825112015-09-18 07:44:19 -070098 grpc_closure closure;
Craig Tillereb3b12e2015-06-26 14:42:49 -070099 grpc_call_element *elem;
100} waiting_call;
101
Craig Tillera82950e2015-09-22 12:33:20 -0700102static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
Craig Tiller906e3bc2015-11-24 07:31:31 -0800103 return grpc_subchannel_call_holder_get_peer(exec_ctx, elem->call_data);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700104}
Craig Tillerf5f17122015-06-25 08:47:26 -0700105
Craig Tillera82950e2015-09-22 12:33:20 -0700106static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
107 grpc_call_element *elem,
108 grpc_transport_stream_op *op) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800109 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
110 grpc_subchannel_call_holder_perform_op(exec_ctx, elem->call_data, op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800111}
112
Craig Tillera82950e2015-09-22 12:33:20 -0700113static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
114 grpc_lb_policy *lb_policy,
115 grpc_connectivity_state current_state);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700116
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800117static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
118 channel_data *chand,
119 grpc_connectivity_state state,
Craig Tiller804ff712016-05-05 16:25:40 -0700120 grpc_error *error,
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800121 const char *reason) {
122 if ((state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
Craig Tiller48ed92e2016-06-02 11:07:12 -0700123 state == GRPC_CHANNEL_SHUTDOWN) &&
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800124 chand->lb_policy != NULL) {
125 /* cancel fail-fast picks */
126 grpc_lb_policy_cancel_picks(
127 exec_ctx, chand->lb_policy,
128 /* mask= */ GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY,
129 /* check= */ 0);
130 }
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700131 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, error,
132 reason);
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800133}
134
Craig Tiller804ff712016-05-05 16:25:40 -0700135static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
136 lb_policy_connectivity_watcher *w,
137 grpc_error *error) {
Craig Tillercb2609f2015-11-24 17:19:19 -0800138 grpc_connectivity_state publish_state = w->state;
Craig Tiller5795da72015-09-17 15:27:13 -0700139 /* check if the notification is for a stale policy */
Craig Tillera82950e2015-09-22 12:33:20 -0700140 if (w->lb_policy != w->chand->lb_policy) return;
Craig Tiller5795da72015-09-17 15:27:13 -0700141
Craig Tiller48ed92e2016-06-02 11:07:12 -0700142 if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
Craig Tillercb2609f2015-11-24 17:19:19 -0800143 publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
144 grpc_resolver_channel_saw_error(exec_ctx, w->chand->resolver);
Craig Tillerf62c4d52015-12-04 07:43:07 -0800145 GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
146 w->chand->lb_policy = NULL;
Craig Tillercb2609f2015-11-24 17:19:19 -0800147 }
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800148 set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
Craig Tillerfc353d62016-05-10 12:58:03 -0700149 GRPC_ERROR_REF(error), "lb_changed");
Craig Tiller48ed92e2016-06-02 11:07:12 -0700150 if (w->state != GRPC_CHANNEL_SHUTDOWN) {
Craig Tillera82950e2015-09-22 12:33:20 -0700151 watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state);
152 }
Craig Tiller5795da72015-09-17 15:27:13 -0700153}
154
Craig Tillera82950e2015-09-22 12:33:20 -0700155static void on_lb_policy_state_changed(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -0700156 grpc_error *error) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700157 lb_policy_connectivity_watcher *w = arg;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700158
Craig Tillera82950e2015-09-22 12:33:20 -0700159 gpr_mu_lock(&w->chand->mu_config);
Craig Tiller804ff712016-05-05 16:25:40 -0700160 on_lb_policy_state_changed_locked(exec_ctx, w, error);
Craig Tillera82950e2015-09-22 12:33:20 -0700161 gpr_mu_unlock(&w->chand->mu_config);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700162
Craig Tiller906e3bc2015-11-24 07:31:31 -0800163 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
Craig Tillera82950e2015-09-22 12:33:20 -0700164 gpr_free(w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700165}
166
Craig Tillera82950e2015-09-22 12:33:20 -0700167static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
168 grpc_lb_policy *lb_policy,
169 grpc_connectivity_state current_state) {
170 lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
Craig Tiller906e3bc2015-11-24 07:31:31 -0800171 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700172
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700173 w->chand = chand;
Craig Tillera82950e2015-09-22 12:33:20 -0700174 grpc_closure_init(&w->on_changed, on_lb_policy_state_changed, w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700175 w->state = current_state;
176 w->lb_policy = lb_policy;
Craig Tillera82950e2015-09-22 12:33:20 -0700177 grpc_lb_policy_notify_on_state_change(exec_ctx, lb_policy, &w->state,
178 &w->on_changed);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700179}
180
Craig Tillera82950e2015-09-22 12:33:20 -0700181static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -0700182 grpc_error *error) {
Craig Tiller3f475422015-06-25 10:43:05 -0700183 channel_data *chand = arg;
184 grpc_lb_policy *lb_policy = NULL;
185 grpc_lb_policy *old_lb_policy;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700186 grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Craig Tiller48cb07c2015-07-15 16:16:15 -0700187 int exit_idle = 0;
Craig Tiller804ff712016-05-05 16:25:40 -0700188 grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
Craig Tiller3f475422015-06-25 10:43:05 -0700189
Craig Tillera82950e2015-09-22 12:33:20 -0700190 if (chand->incoming_configuration != NULL) {
191 lb_policy = grpc_client_config_get_lb_policy(chand->incoming_configuration);
192 if (lb_policy != NULL) {
193 GRPC_LB_POLICY_REF(lb_policy, "channel");
194 GRPC_LB_POLICY_REF(lb_policy, "config_change");
Craig Tillerf707d622016-05-06 14:26:12 -0700195 GRPC_ERROR_UNREF(state_error);
Craig Tiller804ff712016-05-05 16:25:40 -0700196 state =
197 grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error);
Craig Tiller45724b32015-09-22 10:42:19 -0700198 }
Craig Tiller3f475422015-06-25 10:43:05 -0700199
Craig Tillera82950e2015-09-22 12:33:20 -0700200 grpc_client_config_unref(exec_ctx, chand->incoming_configuration);
201 }
202
Craig Tiller3f475422015-06-25 10:43:05 -0700203 chand->incoming_configuration = NULL;
204
Craig Tiller86c99582015-11-25 15:22:26 -0800205 if (lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800206 grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties,
207 chand->interested_parties);
Craig Tiller86c99582015-11-25 15:22:26 -0800208 }
209
Craig Tillera82950e2015-09-22 12:33:20 -0700210 gpr_mu_lock(&chand->mu_config);
Craig Tiller3f475422015-06-25 10:43:05 -0700211 old_lb_policy = chand->lb_policy;
212 chand->lb_policy = lb_policy;
Craig Tiller0ede5452016-04-23 12:21:45 -0700213 if (lb_policy != NULL) {
214 grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
215 NULL);
216 } else if (chand->resolver == NULL /* disconnected */) {
Craig Tiller804ff712016-05-05 16:25:40 -0700217 grpc_closure_list_fail_all(
218 &chand->waiting_for_config_closures,
219 GRPC_ERROR_CREATE_REFERENCING("Channel disconnected", &error, 1));
Craig Tiller6c396862016-01-28 13:53:40 -0800220 grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
221 NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700222 }
223 if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
224 GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
225 exit_idle = 1;
226 chand->exit_idle_when_lb_policy_arrives = 0;
227 }
Craig Tiller98465032015-06-29 14:36:42 -0700228
Craig Tiller804ff712016-05-05 16:25:40 -0700229 if (error == GRPC_ERROR_NONE && chand->resolver) {
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700230 set_channel_connectivity_state_locked(
231 exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700232 if (lb_policy != NULL) {
233 watch_lb_policy(exec_ctx, chand, lb_policy, state);
Craig Tiller45724b32015-09-22 10:42:19 -0700234 }
Craig Tiller906e3bc2015-11-24 07:31:31 -0800235 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800236 grpc_resolver_next(exec_ctx, chand->resolver,
237 &chand->incoming_configuration,
Craig Tillera82950e2015-09-22 12:33:20 -0700238 &chand->on_config_changed);
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800239 gpr_mu_unlock(&chand->mu_config);
Craig Tillera82950e2015-09-22 12:33:20 -0700240 } else {
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800241 if (chand->resolver != NULL) {
242 grpc_resolver_shutdown(exec_ctx, chand->resolver);
243 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
244 chand->resolver = NULL;
245 }
Craig Tiller804ff712016-05-05 16:25:40 -0700246 grpc_error *refs[] = {error, state_error};
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800247 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700248 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller804ff712016-05-05 16:25:40 -0700249 GRPC_ERROR_CREATE_REFERENCING("Got config after disconnection", refs,
250 GPR_ARRAY_SIZE(refs)),
251 "resolver_gone");
Craig Tillera82950e2015-09-22 12:33:20 -0700252 gpr_mu_unlock(&chand->mu_config);
Craig Tillera82950e2015-09-22 12:33:20 -0700253 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700254
Craig Tillera82950e2015-09-22 12:33:20 -0700255 if (exit_idle) {
256 grpc_lb_policy_exit_idle(exec_ctx, lb_policy);
257 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
258 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700259
Craig Tillera82950e2015-09-22 12:33:20 -0700260 if (old_lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800261 grpc_pollset_set_del_pollset_set(
262 exec_ctx, old_lb_policy->interested_parties, chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700263 GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
264 }
Craig Tiller000cd8f2015-09-18 07:20:29 -0700265
Craig Tillera82950e2015-09-22 12:33:20 -0700266 if (lb_policy != NULL) {
267 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
268 }
Craig Tiller45724b32015-09-22 10:42:19 -0700269
Craig Tiller906e3bc2015-11-24 07:31:31 -0800270 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700271 GRPC_ERROR_UNREF(state_error);
Craig Tiller3f475422015-06-25 10:43:05 -0700272}
273
Craig Tillera82950e2015-09-22 12:33:20 -0700274static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
275 grpc_channel_element *elem,
276 grpc_transport_op *op) {
Craig Tillerca3e9d32015-06-27 18:37:27 -0700277 channel_data *chand = elem->channel_data;
Craig Tiller000cd8f2015-09-18 07:20:29 -0700278
Craig Tiller332f1b32016-05-24 13:21:21 -0700279 grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700280
Craig Tillerd7f12e32016-03-03 10:08:31 -0800281 GPR_ASSERT(op->set_accept_stream == false);
Craig Tiller28bf8912015-12-07 16:07:04 -0800282 if (op->bind_pollset != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800283 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
Craig Tillere2c62372015-12-07 16:11:03 -0800284 op->bind_pollset);
Craig Tiller28bf8912015-12-07 16:07:04 -0800285 }
Craig Tillerca3e9d32015-06-27 18:37:27 -0700286
Craig Tillera82950e2015-09-22 12:33:20 -0700287 gpr_mu_lock(&chand->mu_config);
288 if (op->on_connectivity_state_change != NULL) {
289 grpc_connectivity_state_notify_on_state_change(
290 exec_ctx, &chand->state_tracker, op->connectivity_state,
291 op->on_connectivity_state_change);
292 op->on_connectivity_state_change = NULL;
293 op->connectivity_state = NULL;
294 }
295
Craig Tiller26dab312015-12-07 14:43:47 -0800296 if (op->send_ping != NULL) {
Craig Tiller87b71e22015-12-07 15:14:14 -0800297 if (chand->lb_policy == NULL) {
Craig Tiller332f1b32016-05-24 13:21:21 -0700298 grpc_exec_ctx_sched(exec_ctx, op->send_ping,
299 GRPC_ERROR_CREATE("Ping with no load balancing"),
300 NULL);
Craig Tiller26dab312015-12-07 14:43:47 -0800301 } else {
Craig Tiller28bf8912015-12-07 16:07:04 -0800302 grpc_lb_policy_ping_one(exec_ctx, chand->lb_policy, op->send_ping);
Craig Tiller26dab312015-12-07 14:43:47 -0800303 op->bind_pollset = NULL;
304 }
305 op->send_ping = NULL;
306 }
307
Craig Tiller1c51edc2016-05-07 16:18:43 -0700308 if (op->disconnect_with_error != GRPC_ERROR_NONE) {
309 if (chand->resolver != NULL) {
310 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700311 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller1c51edc2016-05-07 16:18:43 -0700312 GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
313 grpc_resolver_shutdown(exec_ctx, chand->resolver);
314 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
315 chand->resolver = NULL;
316 if (!chand->started_resolving) {
317 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
318 GRPC_ERROR_REF(op->disconnect_with_error));
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700319 grpc_exec_ctx_enqueue_list(exec_ctx,
320 &chand->waiting_for_config_closures, NULL);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700321 }
322 if (chand->lb_policy != NULL) {
323 grpc_pollset_set_del_pollset_set(exec_ctx,
324 chand->lb_policy->interested_parties,
325 chand->interested_parties);
326 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
327 chand->lb_policy = NULL;
328 }
Craig Tillerb12d22a2016-04-23 12:50:21 -0700329 }
Craig Tiller1c51edc2016-05-07 16:18:43 -0700330 GRPC_ERROR_UNREF(op->disconnect_with_error);
Craig Tillera82950e2015-09-22 12:33:20 -0700331 }
332 gpr_mu_unlock(&chand->mu_config);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700333}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800334
Craig Tiller577c9b22015-11-02 14:11:15 -0800335typedef struct {
336 grpc_metadata_batch *initial_metadata;
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800337 uint32_t initial_metadata_flags;
Craig Tillerb5585d42015-11-17 07:18:31 -0800338 grpc_connected_subchannel **connected_subchannel;
Craig Tiller577c9b22015-11-02 14:11:15 -0800339 grpc_closure *on_ready;
340 grpc_call_element *elem;
341 grpc_closure closure;
342} continue_picking_args;
343
344static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *arg,
345 grpc_metadata_batch *initial_metadata,
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800346 uint32_t initial_metadata_flags,
Craig Tillerb5585d42015-11-17 07:18:31 -0800347 grpc_connected_subchannel **connected_subchannel,
Craig Tiller577c9b22015-11-02 14:11:15 -0800348 grpc_closure *on_ready);
349
Craig Tiller804ff712016-05-05 16:25:40 -0700350static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg,
351 grpc_error *error) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800352 continue_picking_args *cpa = arg;
Craig Tiller0ede5452016-04-23 12:21:45 -0700353 if (cpa->connected_subchannel == NULL) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800354 /* cancelled, do nothing */
Craig Tiller804ff712016-05-05 16:25:40 -0700355 } else if (error != GRPC_ERROR_NONE) {
Craig Tiller332f1b32016-05-24 13:21:21 -0700356 grpc_exec_ctx_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error), NULL);
Craig Tiller577c9b22015-11-02 14:11:15 -0800357 } else if (cc_pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata,
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800358 cpa->initial_metadata_flags,
Craig Tillerb5585d42015-11-17 07:18:31 -0800359 cpa->connected_subchannel, cpa->on_ready)) {
Craig Tiller332f1b32016-05-24 13:21:21 -0700360 grpc_exec_ctx_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE, NULL);
Craig Tiller577c9b22015-11-02 14:11:15 -0800361 }
362 gpr_free(cpa);
363}
364
365static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
366 grpc_metadata_batch *initial_metadata,
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800367 uint32_t initial_metadata_flags,
Craig Tillerb5585d42015-11-17 07:18:31 -0800368 grpc_connected_subchannel **connected_subchannel,
Craig Tiller577c9b22015-11-02 14:11:15 -0800369 grpc_closure *on_ready) {
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700370 GPR_TIMER_BEGIN("cc_pick_subchannel", 0);
371
Craig Tiller577c9b22015-11-02 14:11:15 -0800372 grpc_call_element *elem = elemp;
373 channel_data *chand = elem->channel_data;
374 call_data *calld = elem->call_data;
375 continue_picking_args *cpa;
376 grpc_closure *closure;
377
Craig Tillerb5585d42015-11-17 07:18:31 -0800378 GPR_ASSERT(connected_subchannel);
Craig Tiller577c9b22015-11-02 14:11:15 -0800379
380 gpr_mu_lock(&chand->mu_config);
381 if (initial_metadata == NULL) {
382 if (chand->lb_policy != NULL) {
Craig Tillerab33b482015-11-21 08:11:04 -0800383 grpc_lb_policy_cancel_pick(exec_ctx, chand->lb_policy,
384 connected_subchannel);
Craig Tiller577c9b22015-11-02 14:11:15 -0800385 }
386 for (closure = chand->waiting_for_config_closures.head; closure != NULL;
Craig Tiller804ff712016-05-05 16:25:40 -0700387 closure = closure->next_data.next) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800388 cpa = closure->cb_arg;
Craig Tillerb5585d42015-11-17 07:18:31 -0800389 if (cpa->connected_subchannel == connected_subchannel) {
390 cpa->connected_subchannel = NULL;
Craig Tiller332f1b32016-05-24 13:21:21 -0700391 grpc_exec_ctx_sched(exec_ctx, cpa->on_ready,
392 GRPC_ERROR_CREATE("Pick cancelled"), NULL);
Craig Tiller577c9b22015-11-02 14:11:15 -0800393 }
394 }
395 gpr_mu_unlock(&chand->mu_config);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700396 GPR_TIMER_END("cc_pick_subchannel", 0);
Craig Tiller577c9b22015-11-02 14:11:15 -0800397 return 1;
398 }
399 if (chand->lb_policy != NULL) {
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800400 grpc_lb_policy *lb_policy = chand->lb_policy;
401 int r;
402 GRPC_LB_POLICY_REF(lb_policy, "cc_pick_subchannel");
Craig Tiller577c9b22015-11-02 14:11:15 -0800403 gpr_mu_unlock(&chand->mu_config);
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700404 r = grpc_lb_policy_pick(exec_ctx, lb_policy, calld->pollent,
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800405 initial_metadata, initial_metadata_flags,
406 connected_subchannel, on_ready);
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800407 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "cc_pick_subchannel");
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700408 GPR_TIMER_END("cc_pick_subchannel", 0);
Craig Tiller577c9b22015-11-02 14:11:15 -0800409 return r;
410 }
411 if (chand->resolver != NULL && !chand->started_resolving) {
412 chand->started_resolving = 1;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800413 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller577c9b22015-11-02 14:11:15 -0800414 grpc_resolver_next(exec_ctx, chand->resolver,
415 &chand->incoming_configuration,
416 &chand->on_config_changed);
417 }
Craig Tiller0eab6972016-04-23 12:59:57 -0700418 if (chand->resolver != NULL) {
419 cpa = gpr_malloc(sizeof(*cpa));
420 cpa->initial_metadata = initial_metadata;
421 cpa->initial_metadata_flags = initial_metadata_flags;
422 cpa->connected_subchannel = connected_subchannel;
423 cpa->on_ready = on_ready;
424 cpa->elem = elem;
425 grpc_closure_init(&cpa->closure, continue_picking, cpa);
Craig Tiller804ff712016-05-05 16:25:40 -0700426 grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
427 GRPC_ERROR_NONE);
Craig Tiller0eab6972016-04-23 12:59:57 -0700428 } else {
Craig Tiller332f1b32016-05-24 13:21:21 -0700429 grpc_exec_ctx_sched(exec_ctx, on_ready, GRPC_ERROR_CREATE("Disconnected"),
430 NULL);
Craig Tiller0eab6972016-04-23 12:59:57 -0700431 }
Craig Tiller577c9b22015-11-02 14:11:15 -0800432 gpr_mu_unlock(&chand->mu_config);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700433
434 GPR_TIMER_END("cc_pick_subchannel", 0);
Craig Tiller577c9b22015-11-02 14:11:15 -0800435 return 0;
436}
437
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800438/* Constructor for call_data */
Mark D. Roth76d24422016-06-23 13:22:10 -0700439static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
Mark D. Roth0badbe82016-06-23 10:15:12 -0700440 grpc_call_element *elem,
441 grpc_call_element_args *args) {
Craig Tiller11beb9a2015-11-24 10:29:32 -0800442 grpc_subchannel_call_holder_init(elem->call_data, cc_pick_subchannel, elem,
443 args->call_stack);
Mark D. Roth0badbe82016-06-23 10:15:12 -0700444 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800445}
446
447/* Destructor for call_data */
Craig Tiller2c8063c2016-03-22 22:12:15 -0700448static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
David Garcia Quintas01c4d992016-07-07 20:11:27 -0700449 const grpc_call_final_info *final_info,
Craig Tiller2c8063c2016-03-22 22:12:15 -0700450 void *and_free_memory) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800451 grpc_subchannel_call_holder_destroy(exec_ctx, elem->call_data);
Craig Tiller2c8063c2016-03-22 22:12:15 -0700452 gpr_free(and_free_memory);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800453}
454
455/* Constructor for channel_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700456static void init_channel_elem(grpc_exec_ctx *exec_ctx,
Craig Tiller577c9b22015-11-02 14:11:15 -0800457 grpc_channel_element *elem,
458 grpc_channel_element_args *args) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800459 channel_data *chand = elem->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800460
Craig Tillera82950e2015-09-22 12:33:20 -0700461 memset(chand, 0, sizeof(*chand));
Craig Tillereb3b12e2015-06-26 14:42:49 -0700462
Craig Tiller577c9b22015-11-02 14:11:15 -0800463 GPR_ASSERT(args->is_last);
Craig Tillera82950e2015-09-22 12:33:20 -0700464 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800465
Craig Tillera82950e2015-09-22 12:33:20 -0700466 gpr_mu_init(&chand->mu_config);
Craig Tillera82950e2015-09-22 12:33:20 -0700467 grpc_closure_init(&chand->on_config_changed, cc_on_config_changed, chand);
Craig Tiller11beb9a2015-11-24 10:29:32 -0800468 chand->owning_stack = args->channel_stack;
Craig Tiller98465032015-06-29 14:36:42 -0700469
Craig Tillera82950e2015-09-22 12:33:20 -0700470 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
471 "client_channel");
Craig Tiller69b093b2016-02-25 19:04:07 -0800472 chand->interested_parties = grpc_pollset_set_create();
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800473}
474
475/* Destructor for channel_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700476static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
477 grpc_channel_element *elem) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800478 channel_data *chand = elem->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800479
Craig Tillera82950e2015-09-22 12:33:20 -0700480 if (chand->resolver != NULL) {
481 grpc_resolver_shutdown(exec_ctx, chand->resolver);
482 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
483 }
484 if (chand->lb_policy != NULL) {
Craig Tiller1d881fb2015-12-01 07:39:04 -0800485 grpc_pollset_set_del_pollset_set(exec_ctx,
Craig Tiller69b093b2016-02-25 19:04:07 -0800486 chand->lb_policy->interested_parties,
487 chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700488 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
489 }
490 grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
Craig Tiller69b093b2016-02-25 19:04:07 -0800491 grpc_pollset_set_destroy(chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700492 gpr_mu_destroy(&chand->mu_config);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800493}
494
David Garcia Quintasf72eb972016-05-03 18:28:09 -0700495static void cc_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
496 grpc_call_element *elem,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700497 grpc_polling_entity *pollent) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800498 call_data *calld = elem->call_data;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700499 calld->pollent = pollent;
Craig Tiller577c9b22015-11-02 14:11:15 -0800500}
501
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800502const grpc_channel_filter grpc_client_channel_filter = {
Craig Tillerf40df232016-03-25 13:38:14 -0700503 cc_start_transport_stream_op,
504 cc_start_transport_op,
505 sizeof(call_data),
506 init_call_elem,
David Garcia Quintas4afce7e2016-04-18 16:25:17 -0700507 cc_set_pollset_or_pollset_set,
Craig Tillerf40df232016-03-25 13:38:14 -0700508 destroy_call_elem,
509 sizeof(channel_data),
510 init_channel_elem,
511 destroy_channel_elem,
512 cc_get_peer,
513 "client-channel",
Craig Tiller87d5b192015-04-16 14:37:57 -0700514};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800515
Craig Tillera82950e2015-09-22 12:33:20 -0700516void grpc_client_channel_set_resolver(grpc_exec_ctx *exec_ctx,
517 grpc_channel_stack *channel_stack,
518 grpc_resolver *resolver) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800519 /* post construction initialization: set the transport setup pointer */
Craig Tillera82950e2015-09-22 12:33:20 -0700520 grpc_channel_element *elem = grpc_channel_stack_last_element(channel_stack);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800521 channel_data *chand = elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700522 gpr_mu_lock(&chand->mu_config);
523 GPR_ASSERT(!chand->resolver);
Craig Tillerf5f17122015-06-25 08:47:26 -0700524 chand->resolver = resolver;
Craig Tillera82950e2015-09-22 12:33:20 -0700525 GRPC_RESOLVER_REF(resolver, "channel");
526 if (!grpc_closure_list_empty(chand->waiting_for_config_closures) ||
527 chand->exit_idle_when_lb_policy_arrives) {
528 chand->started_resolving = 1;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800529 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700530 grpc_resolver_next(exec_ctx, resolver, &chand->incoming_configuration,
531 &chand->on_config_changed);
532 }
533 gpr_mu_unlock(&chand->mu_config);
Craig Tiller190d3602015-02-18 09:23:38 -0800534}
Craig Tiller48cb07c2015-07-15 16:16:15 -0700535
Craig Tillera82950e2015-09-22 12:33:20 -0700536grpc_connectivity_state grpc_client_channel_check_connectivity_state(
537 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
Craig Tiller48cb07c2015-07-15 16:16:15 -0700538 channel_data *chand = elem->channel_data;
539 grpc_connectivity_state out;
Craig Tillera82950e2015-09-22 12:33:20 -0700540 gpr_mu_lock(&chand->mu_config);
Craig Tiller804ff712016-05-05 16:25:40 -0700541 out = grpc_connectivity_state_check(&chand->state_tracker, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700542 if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
543 if (chand->lb_policy != NULL) {
544 grpc_lb_policy_exit_idle(exec_ctx, chand->lb_policy);
545 } else {
546 chand->exit_idle_when_lb_policy_arrives = 1;
547 if (!chand->started_resolving && chand->resolver != NULL) {
Craig Tiller906e3bc2015-11-24 07:31:31 -0800548 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700549 chand->started_resolving = 1;
550 grpc_resolver_next(exec_ctx, chand->resolver,
551 &chand->incoming_configuration,
552 &chand->on_config_changed);
553 }
Craig Tiller48cb07c2015-07-15 16:16:15 -0700554 }
Craig Tillera82950e2015-09-22 12:33:20 -0700555 }
556 gpr_mu_unlock(&chand->mu_config);
Craig Tiller48cb07c2015-07-15 16:16:15 -0700557 return out;
558}
559
Craig Tiller86c99582015-11-25 15:22:26 -0800560typedef struct {
561 channel_data *chand;
562 grpc_pollset *pollset;
563 grpc_closure *on_complete;
564 grpc_closure my_closure;
565} external_connectivity_watcher;
566
Craig Tiller1d881fb2015-12-01 07:39:04 -0800567static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -0700568 grpc_error *error) {
Craig Tiller86c99582015-11-25 15:22:26 -0800569 external_connectivity_watcher *w = arg;
570 grpc_closure *follow_up = w->on_complete;
Craig Tiller69b093b2016-02-25 19:04:07 -0800571 grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800572 w->pollset);
573 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
574 "external_connectivity_watcher");
Craig Tiller86c99582015-11-25 15:22:26 -0800575 gpr_free(w);
Craig Tiller804ff712016-05-05 16:25:40 -0700576 follow_up->cb(exec_ctx, follow_up->cb_arg, error);
Craig Tiller86c99582015-11-25 15:22:26 -0800577}
578
Craig Tillera82950e2015-09-22 12:33:20 -0700579void grpc_client_channel_watch_connectivity_state(
Craig Tiller906e3bc2015-11-24 07:31:31 -0800580 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
Craig Tillera82950e2015-09-22 12:33:20 -0700581 grpc_connectivity_state *state, grpc_closure *on_complete) {
Craig Tiller48cb07c2015-07-15 16:16:15 -0700582 channel_data *chand = elem->channel_data;
Craig Tiller86c99582015-11-25 15:22:26 -0800583 external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
584 w->chand = chand;
585 w->pollset = pollset;
586 w->on_complete = on_complete;
Craig Tiller69b093b2016-02-25 19:04:07 -0800587 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
Craig Tiller86c99582015-11-25 15:22:26 -0800588 grpc_closure_init(&w->my_closure, on_external_watch_complete, w);
Craig Tiller1d881fb2015-12-01 07:39:04 -0800589 GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
590 "external_connectivity_watcher");
Craig Tillera82950e2015-09-22 12:33:20 -0700591 gpr_mu_lock(&chand->mu_config);
592 grpc_connectivity_state_notify_on_state_change(
Craig Tiller86c99582015-11-25 15:22:26 -0800593 exec_ctx, &chand->state_tracker, state, &w->my_closure);
Craig Tillera82950e2015-09-22 12:33:20 -0700594 gpr_mu_unlock(&chand->mu_config);
Craig Tiller48cb07c2015-07-15 16:16:15 -0700595}