blob: f6550292a0aff2faa79d899180e719c10f6c44e0 [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
Mark D. Roth2137cd82016-09-14 09:04:00 -070034#include "src/core/ext/client_channel/client_channel.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080035
Mark D. Roth4c0fe492016-08-31 13:51:55 -070036#include <stdbool.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080037#include <stdio.h>
Craig Tillereb3b12e2015-06-26 14:42:49 -070038#include <string.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080039
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080040#include <grpc/support/alloc.h>
41#include <grpc/support/log.h>
Mark D. Rothb2d24882016-10-27 15:44:07 -070042#include <grpc/support/string_util.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080043#include <grpc/support/sync.h>
44#include <grpc/support/useful.h>
45
Mark D. Rothd58a9852017-01-18 08:28:57 -080046#include "src/core/ext/client_channel/http_connect_handshaker.h"
Mark D. Roth15195742016-10-07 09:02:28 -070047#include "src/core/ext/client_channel/lb_policy_registry.h"
Mark D. Rothdc9bee72017-02-07 12:29:14 -080048#include "src/core/ext/client_channel/proxy_mapper_registry.h"
Mark D. Roth21d4b2d2016-11-18 09:53:41 -080049#include "src/core/ext/client_channel/resolver_registry.h"
Mark D. Roth2137cd82016-09-14 09:04:00 -070050#include "src/core/ext/client_channel/subchannel.h"
Craig Tiller9533d042016-03-25 17:11:06 -070051#include "src/core/lib/channel/channel_args.h"
52#include "src/core/lib/channel/connected_channel.h"
Mark D. Roth72f6da82016-09-02 13:42:38 -070053#include "src/core/lib/channel/deadline_filter.h"
Craig Tillerbefafe62017-02-09 11:30:54 -080054#include "src/core/lib/iomgr/combiner.h"
Craig Tiller9533d042016-03-25 17:11:06 -070055#include "src/core/lib/iomgr/iomgr.h"
Mark D. Roth4c0fe492016-08-31 13:51:55 -070056#include "src/core/lib/iomgr/polling_entity.h"
Craig Tiller9533d042016-03-25 17:11:06 -070057#include "src/core/lib/profiling/timers.h"
Craig Tiller7c70b6c2017-01-23 07:48:42 -080058#include "src/core/lib/slice/slice_internal.h"
Craig Tiller9533d042016-03-25 17:11:06 -070059#include "src/core/lib/support/string.h"
60#include "src/core/lib/surface/channel.h"
61#include "src/core/lib/transport/connectivity_state.h"
Mark D. Roth9fe284e2016-09-12 11:22:27 -070062#include "src/core/lib/transport/metadata.h"
63#include "src/core/lib/transport/metadata_batch.h"
Mark D. Rothea846a02016-11-03 11:32:54 -070064#include "src/core/lib/transport/service_config.h"
Mark D. Roth9fe284e2016-09-12 11:22:27 -070065#include "src/core/lib/transport/static_metadata.h"
Craig Tiller8910ac62015-10-08 16:49:15 -070066
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080067/* Client channel implementation */
68
Mark D. Roth26b7be42016-10-24 10:08:07 -070069/*************************************************************************
70 * METHOD-CONFIG TABLE
71 */
72
Mark D. Roth9d480942016-10-19 14:18:05 -070073typedef enum {
74 WAIT_FOR_READY_UNSET,
75 WAIT_FOR_READY_FALSE,
76 WAIT_FOR_READY_TRUE
77} wait_for_ready_value;
78
Mark D. Roth95b627b2017-02-24 11:02:58 -080079typedef struct {
80 gpr_refcount refs;
Mark D. Roth9d480942016-10-19 14:18:05 -070081 gpr_timespec timeout;
82 wait_for_ready_value wait_for_ready;
83} method_parameters;
84
Mark D. Roth722de8d2017-02-27 10:50:44 -080085static method_parameters *method_parameters_ref(
Mark D. Roth95b627b2017-02-24 11:02:58 -080086 method_parameters *method_params) {
87 gpr_ref(&method_params->refs);
88 return method_params;
Mark D. Roth9d480942016-10-19 14:18:05 -070089}
90
Mark D. Roth95b627b2017-02-24 11:02:58 -080091static void method_parameters_unref(method_parameters *method_params) {
92 if (gpr_unref(&method_params->refs)) {
93 gpr_free(method_params);
94 }
95}
96
97static void *method_parameters_copy(void *value) {
98 return method_parameters_ref(value);
99}
100
101static void method_parameters_free(grpc_exec_ctx *exec_ctx, void *value) {
102 method_parameters_unref(value);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800103}
104
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800105static const grpc_slice_hash_table_vtable method_parameters_vtable = {
Craig Tillerb28c7e82016-11-18 10:29:04 -0800106 method_parameters_free, method_parameters_copy};
Mark D. Roth9d480942016-10-19 14:18:05 -0700107
Mark D. Roth95b627b2017-02-24 11:02:58 -0800108static bool parse_wait_for_ready(grpc_json *field,
109 wait_for_ready_value *wait_for_ready) {
110 if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) {
111 return false;
112 }
113 *wait_for_ready = field->type == GRPC_JSON_TRUE ? WAIT_FOR_READY_TRUE
114 : WAIT_FOR_READY_FALSE;
115 return true;
116}
117
Mark D. Roth722de8d2017-02-27 10:50:44 -0800118static bool parse_timeout(grpc_json *field, gpr_timespec *timeout) {
Mark D. Roth95b627b2017-02-24 11:02:58 -0800119 if (field->type != GRPC_JSON_STRING) return false;
120 size_t len = strlen(field->value);
121 if (field->value[len - 1] != 's') return false;
122 char *buf = gpr_strdup(field->value);
123 buf[len - 1] = '\0'; // Remove trailing 's'.
124 char *decimal_point = strchr(buf, '.');
125 if (decimal_point != NULL) {
126 *decimal_point = '\0';
127 timeout->tv_nsec = gpr_parse_nonnegative_int(decimal_point + 1);
128 if (timeout->tv_nsec == -1) {
129 gpr_free(buf);
130 return false;
131 }
132 // There should always be exactly 3, 6, or 9 fractional digits.
133 int multiplier = 1;
134 switch (strlen(decimal_point + 1)) {
135 case 9:
136 break;
137 case 6:
138 multiplier *= 1000;
139 break;
140 case 3:
141 multiplier *= 1000000;
142 break;
143 default: // Unsupported number of digits.
144 gpr_free(buf);
145 return false;
146 }
147 timeout->tv_nsec *= multiplier;
148 }
149 timeout->tv_sec = gpr_parse_nonnegative_int(buf);
150 gpr_free(buf);
151 if (timeout->tv_sec == -1) return false;
152 return true;
153}
154
Mark D. Rothe30baeb2016-11-03 08:16:19 -0700155static void *method_parameters_create_from_json(const grpc_json *json) {
Mark D. Rothc968e602016-11-02 14:07:36 -0700156 wait_for_ready_value wait_for_ready = WAIT_FOR_READY_UNSET;
Mark D. Roth47f10842016-11-03 08:45:27 -0700157 gpr_timespec timeout = {0, 0, GPR_TIMESPAN};
158 for (grpc_json *field = json->child; field != NULL; field = field->next) {
Mark D. Rothc968e602016-11-02 14:07:36 -0700159 if (field->key == NULL) continue;
Mark D. Roth84c8a022016-11-10 09:39:34 -0800160 if (strcmp(field->key, "waitForReady") == 0) {
Mark D. Rothc968e602016-11-02 14:07:36 -0700161 if (wait_for_ready != WAIT_FOR_READY_UNSET) return NULL; // Duplicate.
Mark D. Roth95b627b2017-02-24 11:02:58 -0800162 if (!parse_wait_for_ready(field, &wait_for_ready)) return NULL;
Mark D. Rothc968e602016-11-02 14:07:36 -0700163 } else if (strcmp(field->key, "timeout") == 0) {
164 if (timeout.tv_sec > 0 || timeout.tv_nsec > 0) return NULL; // Duplicate.
Mark D. Roth95b627b2017-02-24 11:02:58 -0800165 if (!parse_timeout(field, &timeout)) return NULL;
Mark D. Rothc968e602016-11-02 14:07:36 -0700166 }
167 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700168 method_parameters *value = gpr_malloc(sizeof(method_parameters));
Mark D. Roth95b627b2017-02-24 11:02:58 -0800169 gpr_ref_init(&value->refs, 1);
Mark D. Rothc968e602016-11-02 14:07:36 -0700170 value->timeout = timeout;
171 value->wait_for_ready = wait_for_ready;
Mark D. Roth9d480942016-10-19 14:18:05 -0700172 return value;
173}
174
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700175/*************************************************************************
176 * CHANNEL-WIDE FUNCTIONS
177 */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800178
Craig Tiller800dacb2015-10-06 09:10:26 -0700179typedef struct client_channel_channel_data {
Craig Tillerf5f17122015-06-25 08:47:26 -0700180 /** resolver for this channel */
181 grpc_resolver *resolver;
Craig Tiller20a3c352015-08-05 08:39:50 -0700182 /** have we started resolving this channel */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700183 bool started_resolving;
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700184 /** client channel factory */
185 grpc_client_channel_factory *client_channel_factory;
Craig Tillerf5f17122015-06-25 08:47:26 -0700186
Craig Tillerbefafe62017-02-09 11:30:54 -0800187 /** combiner protecting all variables below in this data structure */
188 grpc_combiner *combiner;
Mark D. Roth046cf762016-09-26 11:13:51 -0700189 /** currently active load balancer */
Craig Tillerf5f17122015-06-25 08:47:26 -0700190 grpc_lb_policy *lb_policy;
Mark D. Roth9d480942016-10-19 14:18:05 -0700191 /** maps method names to method_parameters structs */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800192 grpc_slice_hash_table *method_params_table;
Mark D. Roth046cf762016-09-26 11:13:51 -0700193 /** incoming resolver result - set by resolver.next() */
Mark D. Rothaf842452016-10-21 15:05:15 -0700194 grpc_channel_args *resolver_result;
Craig Tiller3f475422015-06-25 10:43:05 -0700195 /** a list of closures that are all waiting for config to come in */
Craig Tillerd9ccbbf2015-09-22 09:30:00 -0700196 grpc_closure_list waiting_for_config_closures;
Craig Tiller3f475422015-06-25 10:43:05 -0700197 /** resolver callback */
Mark D. Rothff4df062016-08-22 15:02:49 -0700198 grpc_closure on_resolver_result_changed;
Craig Tiller3f475422015-06-25 10:43:05 -0700199 /** connectivity state being tracked */
Craig Tillerca3e9d32015-06-27 18:37:27 -0700200 grpc_connectivity_state_tracker state_tracker;
Craig Tiller48cb07c2015-07-15 16:16:15 -0700201 /** when an lb_policy arrives, should we try to exit idle */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700202 bool exit_idle_when_lb_policy_arrives;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800203 /** owning stack */
204 grpc_channel_stack *owning_stack;
Craig Tiller69b093b2016-02-25 19:04:07 -0800205 /** interested parties (owned) */
206 grpc_pollset_set *interested_parties;
Craig Tiller613dafa2017-02-09 12:00:43 -0800207
208 /* the following properties are guarded by a mutex since API's require them
Craig Tiller46dd7902017-02-23 09:42:16 -0800209 to be instantaneously available */
Craig Tiller613dafa2017-02-09 12:00:43 -0800210 gpr_mu info_mu;
211 char *info_lb_policy_name;
212 /** service config in JSON form */
213 char *info_service_config_json;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800214} channel_data;
215
Craig Tillerd6c98df2015-08-18 09:33:44 -0700216/** We create one watcher for each new lb_policy that is returned from a
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700217 resolver, to watch for state changes from the lb_policy. When a state
218 change is seen, we update the channel, and create a new watcher. */
Craig Tillera82950e2015-09-22 12:33:20 -0700219typedef struct {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700220 channel_data *chand;
Craig Tiller33825112015-09-18 07:44:19 -0700221 grpc_closure on_changed;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700222 grpc_connectivity_state state;
223 grpc_lb_policy *lb_policy;
224} lb_policy_connectivity_watcher;
225
Craig Tiller2400bf52017-02-09 16:25:19 -0800226static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
227 grpc_lb_policy *lb_policy,
228 grpc_connectivity_state current_state);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700229
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800230static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
231 channel_data *chand,
232 grpc_connectivity_state state,
Craig Tiller804ff712016-05-05 16:25:40 -0700233 grpc_error *error,
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800234 const char *reason) {
235 if ((state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
Craig Tiller48ed92e2016-06-02 11:07:12 -0700236 state == GRPC_CHANNEL_SHUTDOWN) &&
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800237 chand->lb_policy != NULL) {
Mark D. Roth59c9f902016-09-28 13:33:21 -0700238 /* cancel picks with wait_for_ready=false */
Craig Tiller2400bf52017-02-09 16:25:19 -0800239 grpc_lb_policy_cancel_picks_locked(
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800240 exec_ctx, chand->lb_policy,
Mark D. Roth59c9f902016-09-28 13:33:21 -0700241 /* mask= */ GRPC_INITIAL_METADATA_WAIT_FOR_READY,
Mark D. Roth58f52b72016-09-09 13:55:18 -0700242 /* check= */ 0, GRPC_ERROR_REF(error));
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800243 }
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700244 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, error,
245 reason);
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800246}
247
Craig Tiller804ff712016-05-05 16:25:40 -0700248static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
Craig Tillerbefafe62017-02-09 11:30:54 -0800249 void *arg, grpc_error *error) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700250 lb_policy_connectivity_watcher *w = arg;
Craig Tiller5d44c062015-07-01 08:55:28 -0700251 grpc_connectivity_state publish_state = w->state;
Craig Tillerc5de8352017-02-09 14:08:05 -0800252 /* check if the notification is for the latest policy */
253 if (w->lb_policy == w->chand->lb_policy) {
254 if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
255 publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Craig Tiller972470b2017-02-09 15:05:36 -0800256 grpc_resolver_channel_saw_error_locked(exec_ctx, w->chand->resolver);
Craig Tillerc5de8352017-02-09 14:08:05 -0800257 GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
258 w->chand->lb_policy = NULL;
259 }
260 set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
261 GRPC_ERROR_REF(error), "lb_changed");
262 if (w->state != GRPC_CHANNEL_SHUTDOWN) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800263 watch_lb_policy_locked(exec_ctx, w->chand, w->lb_policy, w->state);
Craig Tillerc5de8352017-02-09 14:08:05 -0800264 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800265 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700266
Craig Tiller906e3bc2015-11-24 07:31:31 -0800267 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
Craig Tillera82950e2015-09-22 12:33:20 -0700268 gpr_free(w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700269}
270
Craig Tiller2400bf52017-02-09 16:25:19 -0800271static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
272 grpc_lb_policy *lb_policy,
273 grpc_connectivity_state current_state) {
Craig Tillera82950e2015-09-22 12:33:20 -0700274 lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
Craig Tiller906e3bc2015-11-24 07:31:31 -0800275 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700276
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700277 w->chand = chand;
Craig Tillerbefafe62017-02-09 11:30:54 -0800278 grpc_closure_init(&w->on_changed, on_lb_policy_state_changed_locked, w,
279 grpc_combiner_scheduler(chand->combiner, false));
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700280 w->state = current_state;
281 w->lb_policy = lb_policy;
Craig Tiller2400bf52017-02-09 16:25:19 -0800282 grpc_lb_policy_notify_on_state_change_locked(exec_ctx, lb_policy, &w->state,
283 &w->on_changed);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700284}
285
Craig Tillerbefafe62017-02-09 11:30:54 -0800286static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
287 void *arg, grpc_error *error) {
Craig Tiller3f475422015-06-25 10:43:05 -0700288 channel_data *chand = arg;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700289 char *lb_policy_name = NULL;
Craig Tiller3f475422015-06-25 10:43:05 -0700290 grpc_lb_policy *lb_policy = NULL;
291 grpc_lb_policy *old_lb_policy;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800292 grpc_slice_hash_table *method_params_table = NULL;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700293 grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700294 bool exit_idle = false;
Craig Tiller804ff712016-05-05 16:25:40 -0700295 grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800296 char *service_config_json = NULL;
Craig Tiller3f475422015-06-25 10:43:05 -0700297
Mark D. Roth046cf762016-09-26 11:13:51 -0700298 if (chand->resolver_result != NULL) {
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700299 // Find LB policy name.
Mark D. Rothaf842452016-10-21 15:05:15 -0700300 const grpc_arg *channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700301 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_POLICY_NAME);
Mark D. Rothaf842452016-10-21 15:05:15 -0700302 if (channel_arg != NULL) {
303 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
304 lb_policy_name = channel_arg->value.string;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700305 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700306 // Special case: If all of the addresses are balancer addresses,
307 // assume that we should use the grpclb policy, regardless of what the
308 // resolver actually specified.
Mark D. Rothaf842452016-10-21 15:05:15 -0700309 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700310 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES);
Mark D. Rothaf842452016-10-21 15:05:15 -0700311 if (channel_arg != NULL) {
312 GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
Mark D. Roth557c9902016-10-24 11:12:05 -0700313 grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
Mark D. Rothaf842452016-10-21 15:05:15 -0700314 bool found_backend_address = false;
315 for (size_t i = 0; i < addresses->num_addresses; ++i) {
316 if (!addresses->addresses[i].is_balancer) {
317 found_backend_address = true;
318 break;
319 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700320 }
Mark D. Rothaf842452016-10-21 15:05:15 -0700321 if (!found_backend_address) {
322 if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) {
323 gpr_log(GPR_INFO,
324 "resolver requested LB policy %s but provided only balancer "
325 "addresses, no backend addresses -- forcing use of grpclb LB "
326 "policy",
Mark D. Roth5f40e5d2016-10-24 13:09:05 -0700327 lb_policy_name);
Mark D. Rothaf842452016-10-21 15:05:15 -0700328 }
329 lb_policy_name = "grpclb";
Mark D. Roth88405f72016-10-03 08:24:52 -0700330 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700331 }
332 // Use pick_first if nothing was specified and we didn't select grpclb
333 // above.
334 if (lb_policy_name == NULL) lb_policy_name = "pick_first";
Mark D. Roth41124992016-11-03 11:22:20 -0700335 // Instantiate LB policy.
336 grpc_lb_policy_args lb_policy_args;
337 lb_policy_args.args = chand->resolver_result;
338 lb_policy_args.client_channel_factory = chand->client_channel_factory;
Craig Tiller2400bf52017-02-09 16:25:19 -0800339 lb_policy_args.combiner = chand->combiner;
Mark D. Roth88405f72016-10-03 08:24:52 -0700340 lb_policy =
341 grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700342 if (lb_policy != NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -0700343 GRPC_LB_POLICY_REF(lb_policy, "config_change");
Craig Tillerf707d622016-05-06 14:26:12 -0700344 GRPC_ERROR_UNREF(state_error);
Craig Tiller2400bf52017-02-09 16:25:19 -0800345 state = grpc_lb_policy_check_connectivity_locked(exec_ctx, lb_policy,
346 &state_error);
Craig Tiller45724b32015-09-22 10:42:19 -0700347 }
Mark D. Roth41124992016-11-03 11:22:20 -0700348 // Find service config.
Mark D. Rothaf842452016-10-21 15:05:15 -0700349 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700350 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVICE_CONFIG);
Mark D. Roth046cf762016-09-26 11:13:51 -0700351 if (channel_arg != NULL) {
Mark D. Roth9ec28af2016-11-03 12:32:39 -0700352 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800353 service_config_json = gpr_strdup(channel_arg->value.string);
Mark D. Roth70a1abd2016-11-04 09:26:37 -0700354 grpc_service_config *service_config =
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800355 grpc_service_config_create(service_config_json);
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700356 if (service_config != NULL) {
357 method_params_table = grpc_service_config_create_method_config_table(
Craig Tillerb28c7e82016-11-18 10:29:04 -0800358 exec_ctx, service_config, method_parameters_create_from_json,
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700359 &method_parameters_vtable);
360 grpc_service_config_destroy(service_config);
361 }
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700362 }
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700363 // Before we clean up, save a copy of lb_policy_name, since it might
364 // be pointing to data inside chand->resolver_result.
365 // The copy will be saved in chand->lb_policy_name below.
366 lb_policy_name = gpr_strdup(lb_policy_name);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800367 grpc_channel_args_destroy(exec_ctx, chand->resolver_result);
Mark D. Roth046cf762016-09-26 11:13:51 -0700368 chand->resolver_result = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700369 }
370
Craig Tiller86c99582015-11-25 15:22:26 -0800371 if (lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800372 grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties,
373 chand->interested_parties);
Craig Tiller86c99582015-11-25 15:22:26 -0800374 }
375
Craig Tiller613dafa2017-02-09 12:00:43 -0800376 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700377 if (lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800378 gpr_free(chand->info_lb_policy_name);
379 chand->info_lb_policy_name = lb_policy_name;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700380 }
Craig Tiller3f475422015-06-25 10:43:05 -0700381 old_lb_policy = chand->lb_policy;
382 chand->lb_policy = lb_policy;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800383 if (service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800384 gpr_free(chand->info_service_config_json);
385 chand->info_service_config_json = service_config_json;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800386 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800387 gpr_mu_unlock(&chand->info_mu);
Mark D. Roth9d480942016-10-19 14:18:05 -0700388 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800389 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth046cf762016-09-26 11:13:51 -0700390 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700391 chand->method_params_table = method_params_table;
Craig Tiller0ede5452016-04-23 12:21:45 -0700392 if (lb_policy != NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -0800393 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller0ede5452016-04-23 12:21:45 -0700394 } else if (chand->resolver == NULL /* disconnected */) {
Craig Tiller804ff712016-05-05 16:25:40 -0700395 grpc_closure_list_fail_all(
396 &chand->waiting_for_config_closures,
397 GRPC_ERROR_CREATE_REFERENCING("Channel disconnected", &error, 1));
Craig Tiller91031da2016-12-28 15:44:25 -0800398 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tillera82950e2015-09-22 12:33:20 -0700399 }
400 if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
401 GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700402 exit_idle = true;
403 chand->exit_idle_when_lb_policy_arrives = false;
Craig Tillera82950e2015-09-22 12:33:20 -0700404 }
Craig Tiller98465032015-06-29 14:36:42 -0700405
Craig Tiller804ff712016-05-05 16:25:40 -0700406 if (error == GRPC_ERROR_NONE && chand->resolver) {
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700407 set_channel_connectivity_state_locked(
408 exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700409 if (lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800410 watch_lb_policy_locked(exec_ctx, chand, lb_policy, state);
Craig Tiller45724b32015-09-22 10:42:19 -0700411 }
Craig Tiller906e3bc2015-11-24 07:31:31 -0800412 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -0800413 grpc_resolver_next_locked(exec_ctx, chand->resolver,
414 &chand->resolver_result,
415 &chand->on_resolver_result_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700416 } else {
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800417 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800418 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800419 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
420 chand->resolver = NULL;
421 }
Craig Tiller804ff712016-05-05 16:25:40 -0700422 grpc_error *refs[] = {error, state_error};
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800423 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700424 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller804ff712016-05-05 16:25:40 -0700425 GRPC_ERROR_CREATE_REFERENCING("Got config after disconnection", refs,
426 GPR_ARRAY_SIZE(refs)),
427 "resolver_gone");
Craig Tillera82950e2015-09-22 12:33:20 -0700428 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700429
Craig Tillera82950e2015-09-22 12:33:20 -0700430 if (exit_idle) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800431 grpc_lb_policy_exit_idle_locked(exec_ctx, lb_policy);
Craig Tillera82950e2015-09-22 12:33:20 -0700432 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
433 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700434
Craig Tillera82950e2015-09-22 12:33:20 -0700435 if (old_lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800436 grpc_pollset_set_del_pollset_set(
437 exec_ctx, old_lb_policy->interested_parties, chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700438 GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
439 }
Craig Tiller000cd8f2015-09-18 07:20:29 -0700440
Craig Tillera82950e2015-09-22 12:33:20 -0700441 if (lb_policy != NULL) {
442 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
443 }
Craig Tiller45724b32015-09-22 10:42:19 -0700444
Craig Tiller906e3bc2015-11-24 07:31:31 -0800445 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700446 GRPC_ERROR_UNREF(state_error);
Craig Tiller3f475422015-06-25 10:43:05 -0700447}
448
Craig Tillera8610c02017-02-14 10:05:11 -0800449static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
450 grpc_error *error_ignored) {
Craig Tillerbefafe62017-02-09 11:30:54 -0800451 grpc_transport_op *op = arg;
452 grpc_channel_element *elem = op->transport_private.args[0];
Craig Tillerca3e9d32015-06-27 18:37:27 -0700453 channel_data *chand = elem->channel_data;
Craig Tiller000cd8f2015-09-18 07:20:29 -0700454
Craig Tillera82950e2015-09-22 12:33:20 -0700455 if (op->on_connectivity_state_change != NULL) {
456 grpc_connectivity_state_notify_on_state_change(
457 exec_ctx, &chand->state_tracker, op->connectivity_state,
458 op->on_connectivity_state_change);
459 op->on_connectivity_state_change = NULL;
460 op->connectivity_state = NULL;
461 }
462
Craig Tiller26dab312015-12-07 14:43:47 -0800463 if (op->send_ping != NULL) {
Craig Tiller87b71e22015-12-07 15:14:14 -0800464 if (chand->lb_policy == NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -0800465 grpc_closure_sched(exec_ctx, op->send_ping,
466 GRPC_ERROR_CREATE("Ping with no load balancing"));
Craig Tiller26dab312015-12-07 14:43:47 -0800467 } else {
Craig Tiller2400bf52017-02-09 16:25:19 -0800468 grpc_lb_policy_ping_one_locked(exec_ctx, chand->lb_policy, op->send_ping);
Craig Tiller26dab312015-12-07 14:43:47 -0800469 op->bind_pollset = NULL;
470 }
471 op->send_ping = NULL;
472 }
473
Craig Tiller1c51edc2016-05-07 16:18:43 -0700474 if (op->disconnect_with_error != GRPC_ERROR_NONE) {
475 if (chand->resolver != NULL) {
476 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700477 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller1c51edc2016-05-07 16:18:43 -0700478 GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
Craig Tiller972470b2017-02-09 15:05:36 -0800479 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700480 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
481 chand->resolver = NULL;
482 if (!chand->started_resolving) {
483 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
484 GRPC_ERROR_REF(op->disconnect_with_error));
Craig Tiller91031da2016-12-28 15:44:25 -0800485 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700486 }
487 if (chand->lb_policy != NULL) {
488 grpc_pollset_set_del_pollset_set(exec_ctx,
489 chand->lb_policy->interested_parties,
490 chand->interested_parties);
491 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
492 chand->lb_policy = NULL;
493 }
Craig Tillerb12d22a2016-04-23 12:50:21 -0700494 }
Craig Tiller1c51edc2016-05-07 16:18:43 -0700495 GRPC_ERROR_UNREF(op->disconnect_with_error);
Craig Tillera82950e2015-09-22 12:33:20 -0700496 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800497 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "start_transport_op");
498
499 grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
Craig Tillerbefafe62017-02-09 11:30:54 -0800500}
501
502static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
503 grpc_channel_element *elem,
504 grpc_transport_op *op) {
505 channel_data *chand = elem->channel_data;
506
Craig Tillerbefafe62017-02-09 11:30:54 -0800507 GPR_ASSERT(op->set_accept_stream == false);
508 if (op->bind_pollset != NULL) {
509 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
510 op->bind_pollset);
511 }
512
513 op->transport_private.args[0] = elem;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800514 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "start_transport_op");
Craig Tillerbefafe62017-02-09 11:30:54 -0800515 grpc_closure_sched(
Craig Tillera8610c02017-02-14 10:05:11 -0800516 exec_ctx, grpc_closure_init(
517 &op->transport_private.closure, start_transport_op_locked,
518 op, grpc_combiner_scheduler(chand->combiner, false)),
Craig Tillerbefafe62017-02-09 11:30:54 -0800519 GRPC_ERROR_NONE);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700520}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800521
Mark D. Rothb2d24882016-10-27 15:44:07 -0700522static void cc_get_channel_info(grpc_exec_ctx *exec_ctx,
523 grpc_channel_element *elem,
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700524 const grpc_channel_info *info) {
Mark D. Rothb2d24882016-10-27 15:44:07 -0700525 channel_data *chand = elem->channel_data;
Craig Tiller613dafa2017-02-09 12:00:43 -0800526 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700527 if (info->lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800528 *info->lb_policy_name = chand->info_lb_policy_name == NULL
Mark D. Roth78afd772016-11-04 12:49:49 -0700529 ? NULL
Craig Tiller613dafa2017-02-09 12:00:43 -0800530 : gpr_strdup(chand->info_lb_policy_name);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700531 }
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800532 if (info->service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800533 *info->service_config_json =
534 chand->info_service_config_json == NULL
535 ? NULL
536 : gpr_strdup(chand->info_service_config_json);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800537 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800538 gpr_mu_unlock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700539}
540
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700541/* Constructor for channel_data */
Mark D. Rothc1087882016-11-18 10:54:45 -0800542static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800543 grpc_channel_element *elem,
544 grpc_channel_element_args *args) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700545 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700546 GPR_ASSERT(args->is_last);
547 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800548 // Initialize data members.
Craig Tillerbefafe62017-02-09 11:30:54 -0800549 chand->combiner = grpc_combiner_create(NULL);
Craig Tillerd85477512017-02-09 12:02:39 -0800550 gpr_mu_init(&chand->info_mu);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800551 chand->owning_stack = args->channel_stack;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700552 grpc_closure_init(&chand->on_resolver_result_changed,
Craig Tillerbefafe62017-02-09 11:30:54 -0800553 on_resolver_result_changed_locked, chand,
554 grpc_combiner_scheduler(chand->combiner, false));
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800555 chand->interested_parties = grpc_pollset_set_create();
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700556 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
557 "client_channel");
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800558 // Record client channel factory.
559 const grpc_arg *arg = grpc_channel_args_find(args->channel_args,
560 GRPC_ARG_CLIENT_CHANNEL_FACTORY);
561 GPR_ASSERT(arg != NULL);
562 GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
563 grpc_client_channel_factory_ref(arg->value.pointer.p);
564 chand->client_channel_factory = arg->value.pointer.p;
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800565 // Get server name to resolve, using proxy mapper if needed.
Mark D. Roth86e90592016-11-18 09:56:40 -0800566 arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800567 GPR_ASSERT(arg != NULL);
568 GPR_ASSERT(arg->type == GRPC_ARG_STRING);
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800569 char *proxy_name = NULL;
570 grpc_channel_args *new_args = NULL;
571 grpc_proxy_mappers_map_name(exec_ctx, arg->value.string, args->channel_args,
572 &proxy_name, &new_args);
573 // Instantiate resolver.
Mark D. Roth45ccec52017-01-18 14:04:01 -0800574 chand->resolver = grpc_resolver_create(
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800575 exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string,
576 new_args != NULL ? new_args : args->channel_args,
Craig Tiller972470b2017-02-09 15:05:36 -0800577 chand->interested_parties, chand->combiner);
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800578 if (proxy_name != NULL) gpr_free(proxy_name);
579 if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args);
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800580 if (chand->resolver == NULL) {
581 return GRPC_ERROR_CREATE("resolver creation failed");
582 }
583 return GRPC_ERROR_NONE;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700584}
585
Craig Tiller972470b2017-02-09 15:05:36 -0800586static void shutdown_resolver_locked(grpc_exec_ctx *exec_ctx, void *arg,
587 grpc_error *error) {
588 grpc_resolver *resolver = arg;
589 grpc_resolver_shutdown_locked(exec_ctx, resolver);
590 GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel");
591}
592
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700593/* Destructor for channel_data */
594static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
595 grpc_channel_element *elem) {
596 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700597 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800598 grpc_closure_sched(
599 exec_ctx,
600 grpc_closure_create(shutdown_resolver_locked, chand->resolver,
601 grpc_combiner_scheduler(chand->combiner, false)),
602 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700603 }
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700604 if (chand->client_channel_factory != NULL) {
605 grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
606 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700607 if (chand->lb_policy != NULL) {
608 grpc_pollset_set_del_pollset_set(exec_ctx,
609 chand->lb_policy->interested_parties,
610 chand->interested_parties);
611 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
612 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800613 gpr_free(chand->info_lb_policy_name);
614 gpr_free(chand->info_service_config_json);
Mark D. Roth9d480942016-10-19 14:18:05 -0700615 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800616 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700617 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700618 grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
Craig Tiller9e5ac1b2017-02-14 22:25:50 -0800619 grpc_pollset_set_destroy(exec_ctx, chand->interested_parties);
Craig Tillerf1021672017-02-09 21:29:50 -0800620 GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel");
Craig Tillerd85477512017-02-09 12:02:39 -0800621 gpr_mu_destroy(&chand->info_mu);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700622}
623
624/*************************************************************************
625 * PER-CALL FUNCTIONS
626 */
627
628#define GET_CALL(call_data) \
629 ((grpc_subchannel_call *)(gpr_atm_acq_load(&(call_data)->subchannel_call)))
630
631#define CANCELLED_CALL ((grpc_subchannel_call *)1)
632
633typedef enum {
634 GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING,
635 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL
636} subchannel_creation_phase;
637
638/** Call data. Holds a pointer to grpc_subchannel_call and the
639 associated machinery to create such a pointer.
640 Handles queueing of stream ops until a call object is ready, waiting
641 for initial metadata before trying to create a call object,
642 and handling cancellation gracefully. */
643typedef struct client_channel_call_data {
Mark D. Roth72f6da82016-09-02 13:42:38 -0700644 // State for handling deadlines.
645 // The code in deadline_filter.c requires this to be the first field.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700646 // TODO(roth): This is slightly sub-optimal in that grpc_deadline_state
647 // and this struct both independently store a pointer to the call
648 // stack and each has its own mutex. If/when we have time, find a way
Mark D. Roth6ad99172016-09-09 07:52:48 -0700649 // to avoid this without breaking the grpc_deadline_state abstraction.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700650 grpc_deadline_state deadline_state;
Mark D. Rothf28763c2016-09-14 15:18:40 -0700651
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800652 grpc_slice path; // Request path.
Mark D. Rothe40dd292016-10-05 14:58:37 -0700653 gpr_timespec call_start_time;
654 gpr_timespec deadline;
Mark D. Roth95b627b2017-02-24 11:02:58 -0800655 method_parameters *method_params;
Mark D. Rothe40dd292016-10-05 14:58:37 -0700656 grpc_closure read_service_config;
Mark D. Rothaa850a72016-09-26 13:38:02 -0700657
Mark D. Rothf28763c2016-09-14 15:18:40 -0700658 grpc_error *cancel_error;
Mark D. Roth72f6da82016-09-02 13:42:38 -0700659
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700660 /** either 0 for no call, 1 for cancelled, or a pointer to a
661 grpc_subchannel_call */
662 gpr_atm subchannel_call;
Craig Tillerd426cac2017-03-13 12:30:45 -0700663 gpr_arena *arena;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700664
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700665 subchannel_creation_phase creation_phase;
666 grpc_connected_subchannel *connected_subchannel;
667 grpc_polling_entity *pollent;
668
Craig Tiller57726ca2016-09-12 11:59:45 -0700669 grpc_transport_stream_op **waiting_ops;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700670 size_t waiting_ops_count;
671 size_t waiting_ops_capacity;
672
673 grpc_closure next_step;
674
675 grpc_call_stack *owning_call;
David Garcia Quintasd1a47f12016-09-02 12:46:44 +0200676
677 grpc_linked_mdelem lb_token_mdelem;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700678} call_data;
679
Craig Tiller8b1d59c2016-12-27 15:15:30 -0800680grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
681 grpc_call_element *call_elem) {
682 grpc_subchannel_call *scc = GET_CALL((call_data *)call_elem->call_data);
683 return scc == CANCELLED_CALL ? NULL : scc;
684}
685
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700686static void add_waiting_locked(call_data *calld, grpc_transport_stream_op *op) {
687 GPR_TIMER_BEGIN("add_waiting_locked", 0);
688 if (calld->waiting_ops_count == calld->waiting_ops_capacity) {
689 calld->waiting_ops_capacity = GPR_MAX(3, 2 * calld->waiting_ops_capacity);
690 calld->waiting_ops =
691 gpr_realloc(calld->waiting_ops,
692 calld->waiting_ops_capacity * sizeof(*calld->waiting_ops));
693 }
Craig Tiller57726ca2016-09-12 11:59:45 -0700694 calld->waiting_ops[calld->waiting_ops_count++] = op;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700695 GPR_TIMER_END("add_waiting_locked", 0);
696}
697
698static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld,
699 grpc_error *error) {
700 size_t i;
701 for (i = 0; i < calld->waiting_ops_count; i++) {
702 grpc_transport_stream_op_finish_with_failure(
Craig Tiller57726ca2016-09-12 11:59:45 -0700703 exec_ctx, calld->waiting_ops[i], GRPC_ERROR_REF(error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700704 }
705 calld->waiting_ops_count = 0;
706 GRPC_ERROR_UNREF(error);
707}
708
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700709static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
Craig Tiller57726ca2016-09-12 11:59:45 -0700710 if (calld->waiting_ops_count == 0) {
711 return;
712 }
713
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800714 grpc_subchannel_call *call = GET_CALL(calld);
715 grpc_transport_stream_op **ops = calld->waiting_ops;
716 size_t nops = calld->waiting_ops_count;
717 if (call == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700718 fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED);
719 return;
720 }
721 calld->waiting_ops = NULL;
722 calld->waiting_ops_count = 0;
723 calld->waiting_ops_capacity = 0;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800724 for (size_t i = 0; i < nops; i++) {
725 grpc_subchannel_call_process_op(exec_ctx, call, ops[i]);
726 }
Craig Tiller9efea882017-02-09 13:06:52 -0800727 gpr_free(ops);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700728}
729
Craig Tillerbefafe62017-02-09 11:30:54 -0800730static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
731 grpc_error *error) {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700732 grpc_call_element *elem = arg;
733 call_data *calld = elem->call_data;
734 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700735 GPR_ASSERT(calld->creation_phase ==
736 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
Yuchen Zeng19656b12016-09-01 18:00:45 -0700737 grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
738 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700739 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
740 if (calld->connected_subchannel == NULL) {
741 gpr_atm_no_barrier_store(&calld->subchannel_call, 1);
742 fail_locked(exec_ctx, calld, GRPC_ERROR_CREATE_REFERENCING(
743 "Failed to create subchannel", &error, 1));
Mark D. Roth72f6da82016-09-02 13:42:38 -0700744 } else if (GET_CALL(calld) == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700745 /* already cancelled before subchannel became ready */
David Garcia Quintas68a9e382016-12-13 10:50:40 -0800746 grpc_error *cancellation_error = GRPC_ERROR_CREATE_REFERENCING(
747 "Cancelled before creating subchannel", &error, 1);
748 /* if due to deadline, attach the deadline exceeded status to the error */
749 if (gpr_time_cmp(calld->deadline, gpr_now(GPR_CLOCK_MONOTONIC)) < 0) {
750 cancellation_error =
751 grpc_error_set_int(cancellation_error, GRPC_ERROR_INT_GRPC_STATUS,
752 GRPC_STATUS_DEADLINE_EXCEEDED);
753 }
754 fail_locked(exec_ctx, calld, cancellation_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700755 } else {
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700756 /* Create call on subchannel. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700757 grpc_subchannel_call *subchannel_call = NULL;
Craig Tillerd426cac2017-03-13 12:30:45 -0700758 grpc_connected_subchannel_call_args call_args = {
759 .pollent = calld->pollent,
760 .path = calld->path,
761 .start_time = calld->call_start_time,
762 .deadline = calld->deadline,
763 .arena = calld->arena};
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700764 grpc_error *new_error = grpc_connected_subchannel_create_call(
Craig Tillerd426cac2017-03-13 12:30:45 -0700765 exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700766 if (new_error != GRPC_ERROR_NONE) {
767 new_error = grpc_error_add_child(new_error, error);
768 subchannel_call = CANCELLED_CALL;
769 fail_locked(exec_ctx, calld, new_error);
770 }
771 gpr_atm_rel_store(&calld->subchannel_call,
772 (gpr_atm)(uintptr_t)subchannel_call);
773 retry_waiting_locked(exec_ctx, calld);
774 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700775 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
776}
777
778static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
779 call_data *calld = elem->call_data;
780 grpc_subchannel_call *subchannel_call = GET_CALL(calld);
781 if (subchannel_call == NULL || subchannel_call == CANCELLED_CALL) {
782 return NULL;
783 } else {
784 return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
785 }
786}
787
Craig Tiller577c9b22015-11-02 14:11:15 -0800788typedef struct {
789 grpc_metadata_batch *initial_metadata;
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800790 uint32_t initial_metadata_flags;
Craig Tillerb5585d42015-11-17 07:18:31 -0800791 grpc_connected_subchannel **connected_subchannel;
Craig Tiller577c9b22015-11-02 14:11:15 -0800792 grpc_closure *on_ready;
793 grpc_call_element *elem;
794 grpc_closure closure;
795} continue_picking_args;
796
Yuchen Zeng144ce652016-09-01 18:19:34 -0700797/** Return true if subchannel is available immediately (in which case on_ready
798 should not be called), or false otherwise (in which case on_ready should be
799 called when the subchannel is available). */
Craig Tillerbefafe62017-02-09 11:30:54 -0800800static bool pick_subchannel_locked(
801 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
802 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
803 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
804 grpc_error *error);
Craig Tiller577c9b22015-11-02 14:11:15 -0800805
Craig Tillerbefafe62017-02-09 11:30:54 -0800806static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg,
807 grpc_error *error) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800808 continue_picking_args *cpa = arg;
Craig Tiller0ede5452016-04-23 12:21:45 -0700809 if (cpa->connected_subchannel == NULL) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800810 /* cancelled, do nothing */
Craig Tiller804ff712016-05-05 16:25:40 -0700811 } else if (error != GRPC_ERROR_NONE) {
Craig Tiller91031da2016-12-28 15:44:25 -0800812 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error));
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700813 } else {
Craig Tillerbefafe62017-02-09 11:30:54 -0800814 if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata,
815 cpa->initial_metadata_flags,
816 cpa->connected_subchannel, cpa->on_ready,
817 GRPC_ERROR_NONE)) {
Craig Tiller91031da2016-12-28 15:44:25 -0800818 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700819 }
Craig Tiller577c9b22015-11-02 14:11:15 -0800820 }
821 gpr_free(cpa);
822}
823
Craig Tillerbefafe62017-02-09 11:30:54 -0800824static bool pick_subchannel_locked(
825 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
826 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
827 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
828 grpc_error *error) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700829 GPR_TIMER_BEGIN("pick_subchannel", 0);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700830
Craig Tiller577c9b22015-11-02 14:11:15 -0800831 channel_data *chand = elem->channel_data;
832 call_data *calld = elem->call_data;
833 continue_picking_args *cpa;
834 grpc_closure *closure;
835
Craig Tillerb5585d42015-11-17 07:18:31 -0800836 GPR_ASSERT(connected_subchannel);
Craig Tiller577c9b22015-11-02 14:11:15 -0800837
Craig Tiller577c9b22015-11-02 14:11:15 -0800838 if (initial_metadata == NULL) {
839 if (chand->lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800840 grpc_lb_policy_cancel_pick_locked(exec_ctx, chand->lb_policy,
841 connected_subchannel,
842 GRPC_ERROR_REF(error));
Craig Tiller577c9b22015-11-02 14:11:15 -0800843 }
844 for (closure = chand->waiting_for_config_closures.head; closure != NULL;
Craig Tiller804ff712016-05-05 16:25:40 -0700845 closure = closure->next_data.next) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800846 cpa = closure->cb_arg;
Craig Tillerb5585d42015-11-17 07:18:31 -0800847 if (cpa->connected_subchannel == connected_subchannel) {
848 cpa->connected_subchannel = NULL;
Craig Tiller91031da2016-12-28 15:44:25 -0800849 grpc_closure_sched(
Mark D. Roth932b10c2016-09-09 08:44:30 -0700850 exec_ctx, cpa->on_ready,
Craig Tiller91031da2016-12-28 15:44:25 -0800851 GRPC_ERROR_CREATE_REFERENCING("Pick cancelled", &error, 1));
Craig Tiller577c9b22015-11-02 14:11:15 -0800852 }
853 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700854 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth697a1f62016-09-07 13:35:07 -0700855 GRPC_ERROR_UNREF(error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700856 return true;
Craig Tiller577c9b22015-11-02 14:11:15 -0800857 }
Mark D. Roth697a1f62016-09-07 13:35:07 -0700858 GPR_ASSERT(error == GRPC_ERROR_NONE);
Craig Tiller577c9b22015-11-02 14:11:15 -0800859 if (chand->lb_policy != NULL) {
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800860 grpc_lb_policy *lb_policy = chand->lb_policy;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700861 GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel");
Mark D. Rothe40dd292016-10-05 14:58:37 -0700862 // If the application explicitly set wait_for_ready, use that.
863 // Otherwise, if the service config specified a value for this
864 // method, use that.
Mark D. Rothc1c38582016-10-11 11:03:27 -0700865 const bool wait_for_ready_set_from_api =
866 initial_metadata_flags &
867 GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
868 const bool wait_for_ready_set_from_service_config =
Mark D. Roth95b627b2017-02-24 11:02:58 -0800869 calld->method_params != NULL &&
870 calld->method_params->wait_for_ready != WAIT_FOR_READY_UNSET;
Mark D. Rothc1c38582016-10-11 11:03:27 -0700871 if (!wait_for_ready_set_from_api &&
872 wait_for_ready_set_from_service_config) {
Mark D. Roth95b627b2017-02-24 11:02:58 -0800873 if (calld->method_params->wait_for_ready == WAIT_FOR_READY_TRUE) {
Mark D. Rothe40dd292016-10-05 14:58:37 -0700874 initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
875 } else {
876 initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
877 }
878 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700879 const grpc_lb_policy_pick_args inputs = {
Yuchen Zengac8bc422016-10-05 14:00:02 -0700880 initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem,
881 gpr_inf_future(GPR_CLOCK_MONOTONIC)};
Craig Tiller2400bf52017-02-09 16:25:19 -0800882 const bool result = grpc_lb_policy_pick_locked(
Mark D. Roth55f25b62016-10-12 14:55:20 -0700883 exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, on_ready);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700884 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel");
885 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700886 return result;
Craig Tiller577c9b22015-11-02 14:11:15 -0800887 }
888 if (chand->resolver != NULL && !chand->started_resolving) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700889 chand->started_resolving = true;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800890 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -0800891 grpc_resolver_next_locked(exec_ctx, chand->resolver,
892 &chand->resolver_result,
893 &chand->on_resolver_result_changed);
Craig Tiller577c9b22015-11-02 14:11:15 -0800894 }
Craig Tiller0eab6972016-04-23 12:59:57 -0700895 if (chand->resolver != NULL) {
896 cpa = gpr_malloc(sizeof(*cpa));
897 cpa->initial_metadata = initial_metadata;
898 cpa->initial_metadata_flags = initial_metadata_flags;
899 cpa->connected_subchannel = connected_subchannel;
900 cpa->on_ready = on_ready;
901 cpa->elem = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -0800902 grpc_closure_init(&cpa->closure, continue_picking_locked, cpa,
903 grpc_combiner_scheduler(chand->combiner, true));
Craig Tiller804ff712016-05-05 16:25:40 -0700904 grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
905 GRPC_ERROR_NONE);
Craig Tiller0eab6972016-04-23 12:59:57 -0700906 } else {
Craig Tiller91031da2016-12-28 15:44:25 -0800907 grpc_closure_sched(exec_ctx, on_ready, GRPC_ERROR_CREATE("Disconnected"));
Craig Tiller0eab6972016-04-23 12:59:57 -0700908 }
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700909
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700910 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700911 return false;
Craig Tiller577c9b22015-11-02 14:11:15 -0800912}
913
Craig Tillera8610c02017-02-14 10:05:11 -0800914static void start_transport_stream_op_locked_inner(grpc_exec_ctx *exec_ctx,
915 grpc_transport_stream_op *op,
916 grpc_call_element *elem) {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700917 channel_data *chand = elem->channel_data;
Craig Tillera11bfc82017-02-14 09:56:33 -0800918 call_data *calld = elem->call_data;
Craig Tillerbefafe62017-02-09 11:30:54 -0800919 grpc_subchannel_call *call;
920
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700921 /* need to recheck that another thread hasn't set the call */
922 call = GET_CALL(calld);
923 if (call == CANCELLED_CALL) {
Mark D. Rothf28763c2016-09-14 15:18:40 -0700924 grpc_transport_stream_op_finish_with_failure(
925 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -0800926 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700927 return;
928 }
929 if (call != NULL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700930 grpc_subchannel_call_process_op(exec_ctx, call, op);
Craig Tillera11bfc82017-02-14 09:56:33 -0800931 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700932 return;
933 }
934 /* if this is a cancellation, then we can raise our cancelled flag */
935 if (op->cancel_error != GRPC_ERROR_NONE) {
936 if (!gpr_atm_rel_cas(&calld->subchannel_call, 0,
937 (gpr_atm)(uintptr_t)CANCELLED_CALL)) {
Craig Tillera11bfc82017-02-14 09:56:33 -0800938 /* recurse to retry */
Craig Tillera8610c02017-02-14 10:05:11 -0800939 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -0800940 /* early out */
941 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700942 } else {
Craig Tillerbe9691a2017-02-14 10:00:42 -0800943 /* Stash a copy of cancel_error in our call data, so that we can use
944 it for subsequent operations. This ensures that if the call is
945 cancelled before any ops are passed down (e.g., if the deadline
946 is in the past when the call starts), we can return the right
947 error to the caller when the first op does get passed down. */
Mark D. Rothf28763c2016-09-14 15:18:40 -0700948 calld->cancel_error = GRPC_ERROR_REF(op->cancel_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700949 switch (calld->creation_phase) {
950 case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
951 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error));
952 break;
953 case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
Craig Tillerbefafe62017-02-09 11:30:54 -0800954 pick_subchannel_locked(exec_ctx, elem, NULL, 0,
955 &calld->connected_subchannel, NULL,
956 GRPC_ERROR_REF(op->cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700957 break;
958 }
Mark D. Roth72f6da82016-09-02 13:42:38 -0700959 grpc_transport_stream_op_finish_with_failure(
960 exec_ctx, op, GRPC_ERROR_REF(op->cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -0800961 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700962 return;
963 }
964 }
965 /* if we don't have a subchannel, try to get one */
966 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
967 calld->connected_subchannel == NULL &&
968 op->send_initial_metadata != NULL) {
969 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
Craig Tillerbefafe62017-02-09 11:30:54 -0800970 grpc_closure_init(&calld->next_step, subchannel_ready_locked, elem,
971 grpc_combiner_scheduler(chand->combiner, true));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700972 GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
Yuchen Zeng144ce652016-09-01 18:19:34 -0700973 /* If a subchannel is not available immediately, the polling entity from
974 call_data should be provided to channel_data's interested_parties, so
975 that IO of the lb_policy and resolver could be done under it. */
Craig Tillerbefafe62017-02-09 11:30:54 -0800976 if (pick_subchannel_locked(exec_ctx, elem, op->send_initial_metadata,
977 op->send_initial_metadata_flags,
978 &calld->connected_subchannel, &calld->next_step,
979 GRPC_ERROR_NONE)) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700980 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
981 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
Yuchen Zeng19656b12016-09-01 18:00:45 -0700982 } else {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700983 grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
984 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700985 }
986 }
987 /* if we've got a subchannel, then let's ask it to create a call */
988 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
989 calld->connected_subchannel != NULL) {
990 grpc_subchannel_call *subchannel_call = NULL;
Craig Tillerd426cac2017-03-13 12:30:45 -0700991 grpc_connected_subchannel_call_args call_args = {
992 .pollent = calld->pollent,
993 .path = calld->path,
994 .start_time = calld->call_start_time,
995 .deadline = calld->deadline,
996 .arena = calld->arena};
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700997 grpc_error *error = grpc_connected_subchannel_create_call(
Craig Tillerd426cac2017-03-13 12:30:45 -0700998 exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700999 if (error != GRPC_ERROR_NONE) {
1000 subchannel_call = CANCELLED_CALL;
1001 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
1002 grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
1003 }
1004 gpr_atm_rel_store(&calld->subchannel_call,
1005 (gpr_atm)(uintptr_t)subchannel_call);
1006 retry_waiting_locked(exec_ctx, calld);
Craig Tillera11bfc82017-02-14 09:56:33 -08001007 /* recurse to retry */
Craig Tillera8610c02017-02-14 10:05:11 -08001008 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001009 /* early out */
1010 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001011 }
1012 /* nothing to be done but wait */
1013 add_waiting_locked(calld, op);
Craig Tillera11bfc82017-02-14 09:56:33 -08001014}
1015
Mark D. Roth95b627b2017-02-24 11:02:58 -08001016static void start_transport_stream_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
Mark D. Roth722de8d2017-02-27 10:50:44 -08001017 grpc_error *error_ignored) {
Mark D. Roth95b627b2017-02-24 11:02:58 -08001018 GPR_TIMER_BEGIN("start_transport_stream_op_locked", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001019
1020 grpc_transport_stream_op *op = arg;
1021 grpc_call_element *elem = op->handler_private.args[0];
1022 call_data *calld = elem->call_data;
1023
Craig Tillera8610c02017-02-14 10:05:11 -08001024 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001025
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001026 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
1027 "start_transport_stream_op");
Mark D. Roth95b627b2017-02-24 11:02:58 -08001028 GPR_TIMER_END("start_transport_stream_op_locked", 0);
Craig Tillerbefafe62017-02-09 11:30:54 -08001029}
1030
Craig Tillerbe9691a2017-02-14 10:00:42 -08001031/* The logic here is fairly complicated, due to (a) the fact that we
1032 need to handle the case where we receive the send op before the
1033 initial metadata op, and (b) the need for efficiency, especially in
1034 the streaming case.
1035
1036 We use double-checked locking to initially see if initialization has been
1037 performed. If it has not, we acquire the combiner and perform initialization.
1038 If it has, we proceed on the fast path. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001039static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
1040 grpc_call_element *elem,
1041 grpc_transport_stream_op *op) {
1042 call_data *calld = elem->call_data;
1043 channel_data *chand = elem->channel_data;
1044 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
1045 grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op);
1046 /* try to (atomically) get the call */
1047 grpc_subchannel_call *call = GET_CALL(calld);
1048 GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
1049 if (call == CANCELLED_CALL) {
1050 grpc_transport_stream_op_finish_with_failure(
1051 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
1052 GPR_TIMER_END("cc_start_transport_stream_op", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001053 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001054 return;
1055 }
1056 if (call != NULL) {
1057 grpc_subchannel_call_process_op(exec_ctx, call, op);
1058 GPR_TIMER_END("cc_start_transport_stream_op", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001059 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001060 return;
1061 }
1062 /* we failed; lock and figure out what to do */
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001063 GRPC_CALL_STACK_REF(calld->owning_call, "start_transport_stream_op");
Craig Tiller4a84bdd2017-02-14 09:48:41 -08001064 op->handler_private.args[0] = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -08001065 grpc_closure_sched(
1066 exec_ctx,
Craig Tiller4a84bdd2017-02-14 09:48:41 -08001067 grpc_closure_init(&op->handler_private.closure,
Mark D. Roth95b627b2017-02-24 11:02:58 -08001068 start_transport_stream_op_locked, op,
Craig Tillerbefafe62017-02-09 11:30:54 -08001069 grpc_combiner_scheduler(chand->combiner, false)),
1070 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001071 GPR_TIMER_END("cc_start_transport_stream_op", 0);
1072}
1073
Mark D. Roth95b627b2017-02-24 11:02:58 -08001074// Sets calld->method_params.
1075// If the method params specify a timeout, populates
1076// *per_method_deadline and returns true.
1077static bool set_call_method_params_from_service_config_locked(
1078 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
1079 gpr_timespec *per_method_deadline) {
1080 channel_data *chand = elem->channel_data;
1081 call_data *calld = elem->call_data;
1082 if (chand->method_params_table != NULL) {
1083 calld->method_params = grpc_method_config_table_get(
1084 exec_ctx, chand->method_params_table, calld->path);
1085 if (calld->method_params != NULL) {
1086 method_parameters_ref(calld->method_params);
1087 if (gpr_time_cmp(calld->method_params->timeout,
1088 gpr_time_0(GPR_TIMESPAN)) != 0) {
Mark D. Roth722de8d2017-02-27 10:50:44 -08001089 *per_method_deadline =
1090 gpr_time_add(calld->call_start_time, calld->method_params->timeout);
Mark D. Roth95b627b2017-02-24 11:02:58 -08001091 return true;
1092 }
1093 }
1094 }
1095 return false;
1096}
1097
Mark D. Rothe40dd292016-10-05 14:58:37 -07001098// Gets data from the service config. Invoked when the resolver returns
1099// its initial result.
Craig Tillerbefafe62017-02-09 11:30:54 -08001100static void read_service_config_locked(grpc_exec_ctx *exec_ctx, void *arg,
1101 grpc_error *error) {
Mark D. Rothe40dd292016-10-05 14:58:37 -07001102 grpc_call_element *elem = arg;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001103 call_data *calld = elem->call_data;
1104 // If this is an error, there's no point in looking at the service config.
Mark D. Roth196387a2016-10-12 14:53:36 -07001105 if (error == GRPC_ERROR_NONE) {
Mark D. Roth95b627b2017-02-24 11:02:58 -08001106 gpr_timespec per_method_deadline;
1107 if (set_call_method_params_from_service_config_locked(
1108 exec_ctx, elem, &per_method_deadline)) {
1109 // If the deadline from the service config is shorter than the one
1110 // from the client API, reset the deadline timer.
1111 if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
1112 calld->deadline = per_method_deadline;
1113 grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
Mark D. Roth196387a2016-10-12 14:53:36 -07001114 }
Mark D. Roth196387a2016-10-12 14:53:36 -07001115 }
Mark D. Rothe40dd292016-10-05 14:58:37 -07001116 }
Mark D. Roth31292f22016-10-12 13:14:07 -07001117 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "read_service_config");
Mark D. Rothe40dd292016-10-05 14:58:37 -07001118}
1119
Craig Tillerbefafe62017-02-09 11:30:54 -08001120static void initial_read_service_config_locked(grpc_exec_ctx *exec_ctx,
1121 void *arg,
1122 grpc_error *error_ignored) {
1123 grpc_call_element *elem = arg;
1124 channel_data *chand = elem->channel_data;
1125 call_data *calld = elem->call_data;
1126 // If the resolver has already returned results, then we can access
1127 // the service config parameters immediately. Otherwise, we need to
1128 // defer that work until the resolver returns an initial result.
Craig Tillerbefafe62017-02-09 11:30:54 -08001129 if (chand->lb_policy != NULL) {
1130 // We already have a resolver result, so check for service config.
Mark D. Roth95b627b2017-02-24 11:02:58 -08001131 gpr_timespec per_method_deadline;
1132 if (set_call_method_params_from_service_config_locked(
1133 exec_ctx, elem, &per_method_deadline)) {
1134 calld->deadline = gpr_time_min(calld->deadline, per_method_deadline);
Craig Tillerbefafe62017-02-09 11:30:54 -08001135 }
1136 } else {
1137 // We don't yet have a resolver result, so register a callback to
1138 // get the service config data once the resolver returns.
1139 // Take a reference to the call stack to be owned by the callback.
1140 GRPC_CALL_STACK_REF(calld->owning_call, "read_service_config");
1141 grpc_closure_init(&calld->read_service_config, read_service_config_locked,
1142 elem, grpc_combiner_scheduler(chand->combiner, false));
1143 grpc_closure_list_append(&chand->waiting_for_config_closures,
1144 &calld->read_service_config, GRPC_ERROR_NONE);
1145 }
1146 // Start the deadline timer with the current deadline value. If we
1147 // do not yet have service config data, then the timer may be reset
1148 // later.
1149 grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001150 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
1151 "initial_read_service_config");
Craig Tillerbefafe62017-02-09 11:30:54 -08001152}
1153
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001154/* Constructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001155static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
1156 grpc_call_element *elem,
Craig Tillerc52ba3a2017-02-15 22:57:43 -08001157 const grpc_call_element_args *args) {
Mark D. Rothaa850a72016-09-26 13:38:02 -07001158 channel_data *chand = elem->channel_data;
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001159 call_data *calld = elem->call_data;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001160 // Initialize data members.
1161 grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001162 calld->path = grpc_slice_ref_internal(args->path);
Mark D. Rothff08f332016-10-14 13:01:01 -07001163 calld->call_start_time = args->start_time;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001164 calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
Mark D. Roth95b627b2017-02-24 11:02:58 -08001165 calld->method_params = NULL;
Mark D. Rothf28763c2016-09-14 15:18:40 -07001166 calld->cancel_error = GRPC_ERROR_NONE;
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001167 gpr_atm_rel_store(&calld->subchannel_call, 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001168 calld->connected_subchannel = NULL;
1169 calld->waiting_ops = NULL;
1170 calld->waiting_ops_count = 0;
1171 calld->waiting_ops_capacity = 0;
1172 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
1173 calld->owning_call = args->call_stack;
1174 calld->pollent = NULL;
Craig Tillerd426cac2017-03-13 12:30:45 -07001175 calld->arena = args->arena;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001176 GRPC_CALL_STACK_REF(calld->owning_call, "initial_read_service_config");
Craig Tillerbefafe62017-02-09 11:30:54 -08001177 grpc_closure_sched(
1178 exec_ctx,
1179 grpc_closure_init(&calld->read_service_config,
1180 initial_read_service_config_locked, elem,
1181 grpc_combiner_scheduler(chand->combiner, false)),
1182 GRPC_ERROR_NONE);
Mark D. Roth0badbe82016-06-23 10:15:12 -07001183 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001184}
1185
1186/* Destructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001187static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
1188 grpc_call_element *elem,
1189 const grpc_call_final_info *final_info,
Craig Tillerd426cac2017-03-13 12:30:45 -07001190 grpc_closure *then_schedule_closure) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001191 call_data *calld = elem->call_data;
Mark D. Rothf28763c2016-09-14 15:18:40 -07001192 grpc_deadline_state_destroy(exec_ctx, elem);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001193 grpc_slice_unref_internal(exec_ctx, calld->path);
Mark D. Roth95b627b2017-02-24 11:02:58 -08001194 if (calld->method_params != NULL) {
1195 method_parameters_unref(calld->method_params);
1196 }
Mark D. Rothf28763c2016-09-14 15:18:40 -07001197 GRPC_ERROR_UNREF(calld->cancel_error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001198 grpc_subchannel_call *call = GET_CALL(calld);
1199 if (call != NULL && call != CANCELLED_CALL) {
Craig Tillerd426cac2017-03-13 12:30:45 -07001200 grpc_subchannel_call_set_cleanup_closure(call, then_schedule_closure);
1201 then_schedule_closure = NULL;
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001202 GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
1203 }
1204 GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001205 GPR_ASSERT(calld->waiting_ops_count == 0);
Craig Tiller693d3942016-10-27 16:51:25 -07001206 if (calld->connected_subchannel != NULL) {
1207 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel,
1208 "picked");
1209 }
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001210 gpr_free(calld->waiting_ops);
Craig Tillerd426cac2017-03-13 12:30:45 -07001211 grpc_closure_sched(exec_ctx, then_schedule_closure, GRPC_ERROR_NONE);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001212}
1213
David Garcia Quintasf72eb972016-05-03 18:28:09 -07001214static void cc_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
1215 grpc_call_element *elem,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001216 grpc_polling_entity *pollent) {
Craig Tiller577c9b22015-11-02 14:11:15 -08001217 call_data *calld = elem->call_data;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001218 calld->pollent = pollent;
Craig Tiller577c9b22015-11-02 14:11:15 -08001219}
1220
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001221/*************************************************************************
1222 * EXPORTED SYMBOLS
1223 */
1224
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001225const grpc_channel_filter grpc_client_channel_filter = {
Craig Tillerf40df232016-03-25 13:38:14 -07001226 cc_start_transport_stream_op,
1227 cc_start_transport_op,
1228 sizeof(call_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001229 cc_init_call_elem,
David Garcia Quintas4afce7e2016-04-18 16:25:17 -07001230 cc_set_pollset_or_pollset_set,
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001231 cc_destroy_call_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001232 sizeof(channel_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001233 cc_init_channel_elem,
1234 cc_destroy_channel_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001235 cc_get_peer,
Mark D. Rothb2d24882016-10-27 15:44:07 -07001236 cc_get_channel_info,
Craig Tillerf40df232016-03-25 13:38:14 -07001237 "client-channel",
Craig Tiller87d5b192015-04-16 14:37:57 -07001238};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001239
Craig Tiller613dafa2017-02-09 12:00:43 -08001240static void try_to_connect_locked(grpc_exec_ctx *exec_ctx, void *arg,
1241 grpc_error *error_ignored) {
1242 channel_data *chand = arg;
1243 if (chand->lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -08001244 grpc_lb_policy_exit_idle_locked(exec_ctx, chand->lb_policy);
Craig Tiller613dafa2017-02-09 12:00:43 -08001245 } else {
1246 chand->exit_idle_when_lb_policy_arrives = true;
1247 if (!chand->started_resolving && chand->resolver != NULL) {
1248 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
1249 chand->started_resolving = true;
Craig Tiller972470b2017-02-09 15:05:36 -08001250 grpc_resolver_next_locked(exec_ctx, chand->resolver,
1251 &chand->resolver_result,
1252 &chand->on_resolver_result_changed);
Craig Tiller613dafa2017-02-09 12:00:43 -08001253 }
1254 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001255 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001256}
1257
Craig Tillera82950e2015-09-22 12:33:20 -07001258grpc_connectivity_state grpc_client_channel_check_connectivity_state(
1259 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001260 channel_data *chand = elem->channel_data;
Craig Tillera8610c02017-02-14 10:05:11 -08001261 grpc_connectivity_state out =
1262 grpc_connectivity_state_check(&chand->state_tracker);
Craig Tillera82950e2015-09-22 12:33:20 -07001263 if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001264 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001265 grpc_closure_sched(
1266 exec_ctx,
1267 grpc_closure_create(try_to_connect_locked, chand,
1268 grpc_combiner_scheduler(chand->combiner, false)),
1269 GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -07001270 }
Craig Tiller48cb07c2015-07-15 16:16:15 -07001271 return out;
1272}
1273
Craig Tiller86c99582015-11-25 15:22:26 -08001274typedef struct {
1275 channel_data *chand;
1276 grpc_pollset *pollset;
1277 grpc_closure *on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001278 grpc_connectivity_state *state;
Craig Tiller86c99582015-11-25 15:22:26 -08001279 grpc_closure my_closure;
1280} external_connectivity_watcher;
1281
Craig Tiller1d881fb2015-12-01 07:39:04 -08001282static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -07001283 grpc_error *error) {
Craig Tiller86c99582015-11-25 15:22:26 -08001284 external_connectivity_watcher *w = arg;
1285 grpc_closure *follow_up = w->on_complete;
Craig Tiller69b093b2016-02-25 19:04:07 -08001286 grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
Craig Tiller1d881fb2015-12-01 07:39:04 -08001287 w->pollset);
1288 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
1289 "external_connectivity_watcher");
Craig Tiller86c99582015-11-25 15:22:26 -08001290 gpr_free(w);
Craig Tiller613dafa2017-02-09 12:00:43 -08001291 grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
1292}
1293
Craig Tillera8610c02017-02-14 10:05:11 -08001294static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg,
1295 grpc_error *error_ignored) {
Craig Tiller613dafa2017-02-09 12:00:43 -08001296 external_connectivity_watcher *w = arg;
1297 grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
1298 grpc_schedule_on_exec_ctx);
1299 grpc_connectivity_state_notify_on_state_change(
1300 exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
Craig Tiller86c99582015-11-25 15:22:26 -08001301}
1302
Craig Tillera82950e2015-09-22 12:33:20 -07001303void grpc_client_channel_watch_connectivity_state(
Craig Tiller906e3bc2015-11-24 07:31:31 -08001304 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
Craig Tillera82950e2015-09-22 12:33:20 -07001305 grpc_connectivity_state *state, grpc_closure *on_complete) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001306 channel_data *chand = elem->channel_data;
Craig Tiller86c99582015-11-25 15:22:26 -08001307 external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
1308 w->chand = chand;
1309 w->pollset = pollset;
1310 w->on_complete = on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001311 w->state = state;
Craig Tiller69b093b2016-02-25 19:04:07 -08001312 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
Craig Tiller1d881fb2015-12-01 07:39:04 -08001313 GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
1314 "external_connectivity_watcher");
Craig Tiller613dafa2017-02-09 12:00:43 -08001315 grpc_closure_sched(
1316 exec_ctx,
Craig Tillera8610c02017-02-14 10:05:11 -08001317 grpc_closure_init(&w->my_closure, watch_connectivity_state_locked, w,
Craig Tiller613dafa2017-02-09 12:00:43 -08001318 grpc_combiner_scheduler(chand->combiner, true)),
1319 GRPC_ERROR_NONE);
Craig Tiller48cb07c2015-07-15 16:16:15 -07001320}