blob: f424f833351d8fa5484dcffcc5d44ba23d06cd5e [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;
ncteisen4b36a3d2017-03-13 19:08:06 -0700295 grpc_error *state_error =
296 GRPC_ERROR_CREATE_FROM_STATIC_STRING("No load balancing policy");
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800297 char *service_config_json = NULL;
Craig Tiller3f475422015-06-25 10:43:05 -0700298
Mark D. Roth046cf762016-09-26 11:13:51 -0700299 if (chand->resolver_result != NULL) {
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700300 // Find LB policy name.
Mark D. Rothaf842452016-10-21 15:05:15 -0700301 const grpc_arg *channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700302 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_POLICY_NAME);
Mark D. Rothaf842452016-10-21 15:05:15 -0700303 if (channel_arg != NULL) {
304 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
305 lb_policy_name = channel_arg->value.string;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700306 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700307 // Special case: If all of the addresses are balancer addresses,
308 // assume that we should use the grpclb policy, regardless of what the
309 // resolver actually specified.
Mark D. Rothaf842452016-10-21 15:05:15 -0700310 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700311 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES);
Mark D. Rothaf842452016-10-21 15:05:15 -0700312 if (channel_arg != NULL) {
313 GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
Mark D. Roth557c9902016-10-24 11:12:05 -0700314 grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
Mark D. Rothaf842452016-10-21 15:05:15 -0700315 bool found_backend_address = false;
316 for (size_t i = 0; i < addresses->num_addresses; ++i) {
317 if (!addresses->addresses[i].is_balancer) {
318 found_backend_address = true;
319 break;
320 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700321 }
Mark D. Rothaf842452016-10-21 15:05:15 -0700322 if (!found_backend_address) {
323 if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) {
324 gpr_log(GPR_INFO,
325 "resolver requested LB policy %s but provided only balancer "
326 "addresses, no backend addresses -- forcing use of grpclb LB "
327 "policy",
Mark D. Roth5f40e5d2016-10-24 13:09:05 -0700328 lb_policy_name);
Mark D. Rothaf842452016-10-21 15:05:15 -0700329 }
330 lb_policy_name = "grpclb";
Mark D. Roth88405f72016-10-03 08:24:52 -0700331 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700332 }
333 // Use pick_first if nothing was specified and we didn't select grpclb
334 // above.
335 if (lb_policy_name == NULL) lb_policy_name = "pick_first";
Mark D. Roth41124992016-11-03 11:22:20 -0700336 // Instantiate LB policy.
337 grpc_lb_policy_args lb_policy_args;
338 lb_policy_args.args = chand->resolver_result;
339 lb_policy_args.client_channel_factory = chand->client_channel_factory;
Craig Tiller2400bf52017-02-09 16:25:19 -0800340 lb_policy_args.combiner = chand->combiner;
Mark D. Roth88405f72016-10-03 08:24:52 -0700341 lb_policy =
342 grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700343 if (lb_policy != NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -0700344 GRPC_LB_POLICY_REF(lb_policy, "config_change");
Craig Tillerf707d622016-05-06 14:26:12 -0700345 GRPC_ERROR_UNREF(state_error);
Craig Tiller2400bf52017-02-09 16:25:19 -0800346 state = grpc_lb_policy_check_connectivity_locked(exec_ctx, lb_policy,
347 &state_error);
Craig Tiller45724b32015-09-22 10:42:19 -0700348 }
Mark D. Roth41124992016-11-03 11:22:20 -0700349 // Find service config.
Mark D. Rothaf842452016-10-21 15:05:15 -0700350 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700351 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVICE_CONFIG);
Mark D. Roth046cf762016-09-26 11:13:51 -0700352 if (channel_arg != NULL) {
Mark D. Roth9ec28af2016-11-03 12:32:39 -0700353 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800354 service_config_json = gpr_strdup(channel_arg->value.string);
Mark D. Roth70a1abd2016-11-04 09:26:37 -0700355 grpc_service_config *service_config =
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800356 grpc_service_config_create(service_config_json);
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700357 if (service_config != NULL) {
358 method_params_table = grpc_service_config_create_method_config_table(
Craig Tillerb28c7e82016-11-18 10:29:04 -0800359 exec_ctx, service_config, method_parameters_create_from_json,
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700360 &method_parameters_vtable);
361 grpc_service_config_destroy(service_config);
362 }
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700363 }
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700364 // Before we clean up, save a copy of lb_policy_name, since it might
365 // be pointing to data inside chand->resolver_result.
366 // The copy will be saved in chand->lb_policy_name below.
367 lb_policy_name = gpr_strdup(lb_policy_name);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800368 grpc_channel_args_destroy(exec_ctx, chand->resolver_result);
Mark D. Roth046cf762016-09-26 11:13:51 -0700369 chand->resolver_result = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700370 }
371
Craig Tiller86c99582015-11-25 15:22:26 -0800372 if (lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800373 grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties,
374 chand->interested_parties);
Craig Tiller86c99582015-11-25 15:22:26 -0800375 }
376
Craig Tiller613dafa2017-02-09 12:00:43 -0800377 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700378 if (lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800379 gpr_free(chand->info_lb_policy_name);
380 chand->info_lb_policy_name = lb_policy_name;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700381 }
Craig Tiller3f475422015-06-25 10:43:05 -0700382 old_lb_policy = chand->lb_policy;
383 chand->lb_policy = lb_policy;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800384 if (service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800385 gpr_free(chand->info_service_config_json);
386 chand->info_service_config_json = service_config_json;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800387 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800388 gpr_mu_unlock(&chand->info_mu);
Mark D. Roth9d480942016-10-19 14:18:05 -0700389 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800390 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth046cf762016-09-26 11:13:51 -0700391 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700392 chand->method_params_table = method_params_table;
Craig Tiller0ede5452016-04-23 12:21:45 -0700393 if (lb_policy != NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -0800394 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller0ede5452016-04-23 12:21:45 -0700395 } else if (chand->resolver == NULL /* disconnected */) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700396 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
397 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
398 "Channel disconnected", &error, 1));
Craig Tiller91031da2016-12-28 15:44:25 -0800399 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tillera82950e2015-09-22 12:33:20 -0700400 }
401 if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
402 GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700403 exit_idle = true;
404 chand->exit_idle_when_lb_policy_arrives = false;
Craig Tillera82950e2015-09-22 12:33:20 -0700405 }
Craig Tiller98465032015-06-29 14:36:42 -0700406
Craig Tiller804ff712016-05-05 16:25:40 -0700407 if (error == GRPC_ERROR_NONE && chand->resolver) {
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700408 set_channel_connectivity_state_locked(
409 exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700410 if (lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800411 watch_lb_policy_locked(exec_ctx, chand, lb_policy, state);
Craig Tiller45724b32015-09-22 10:42:19 -0700412 }
Craig Tiller906e3bc2015-11-24 07:31:31 -0800413 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -0800414 grpc_resolver_next_locked(exec_ctx, chand->resolver,
415 &chand->resolver_result,
416 &chand->on_resolver_result_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700417 } else {
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800418 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800419 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800420 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
421 chand->resolver = NULL;
422 }
Craig Tiller804ff712016-05-05 16:25:40 -0700423 grpc_error *refs[] = {error, state_error};
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800424 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700425 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
ncteisen4b36a3d2017-03-13 19:08:06 -0700426 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
427 "Got config after disconnection", refs, GPR_ARRAY_SIZE(refs)),
Craig Tiller804ff712016-05-05 16:25:40 -0700428 "resolver_gone");
Craig Tillera82950e2015-09-22 12:33:20 -0700429 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700430
Craig Tillera82950e2015-09-22 12:33:20 -0700431 if (exit_idle) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800432 grpc_lb_policy_exit_idle_locked(exec_ctx, lb_policy);
Craig Tillera82950e2015-09-22 12:33:20 -0700433 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
434 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700435
Craig Tillera82950e2015-09-22 12:33:20 -0700436 if (old_lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800437 grpc_pollset_set_del_pollset_set(
438 exec_ctx, old_lb_policy->interested_parties, chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700439 GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
440 }
Craig Tiller000cd8f2015-09-18 07:20:29 -0700441
Craig Tillera82950e2015-09-22 12:33:20 -0700442 if (lb_policy != NULL) {
443 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
444 }
Craig Tiller45724b32015-09-22 10:42:19 -0700445
Craig Tiller906e3bc2015-11-24 07:31:31 -0800446 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700447 GRPC_ERROR_UNREF(state_error);
Craig Tiller3f475422015-06-25 10:43:05 -0700448}
449
Craig Tillera8610c02017-02-14 10:05:11 -0800450static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
451 grpc_error *error_ignored) {
Craig Tillerbefafe62017-02-09 11:30:54 -0800452 grpc_transport_op *op = arg;
453 grpc_channel_element *elem = op->transport_private.args[0];
Craig Tillerca3e9d32015-06-27 18:37:27 -0700454 channel_data *chand = elem->channel_data;
Craig Tiller000cd8f2015-09-18 07:20:29 -0700455
Craig Tillera82950e2015-09-22 12:33:20 -0700456 if (op->on_connectivity_state_change != NULL) {
457 grpc_connectivity_state_notify_on_state_change(
458 exec_ctx, &chand->state_tracker, op->connectivity_state,
459 op->on_connectivity_state_change);
460 op->on_connectivity_state_change = NULL;
461 op->connectivity_state = NULL;
462 }
463
Craig Tiller26dab312015-12-07 14:43:47 -0800464 if (op->send_ping != NULL) {
Craig Tiller87b71e22015-12-07 15:14:14 -0800465 if (chand->lb_policy == NULL) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700466 grpc_closure_sched(
467 exec_ctx, op->send_ping,
468 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Ping with no load balancing"));
Craig Tiller26dab312015-12-07 14:43:47 -0800469 } else {
Craig Tiller2400bf52017-02-09 16:25:19 -0800470 grpc_lb_policy_ping_one_locked(exec_ctx, chand->lb_policy, op->send_ping);
Craig Tiller26dab312015-12-07 14:43:47 -0800471 op->bind_pollset = NULL;
472 }
473 op->send_ping = NULL;
474 }
475
Craig Tiller1c51edc2016-05-07 16:18:43 -0700476 if (op->disconnect_with_error != GRPC_ERROR_NONE) {
477 if (chand->resolver != NULL) {
478 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700479 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller1c51edc2016-05-07 16:18:43 -0700480 GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
Craig Tiller972470b2017-02-09 15:05:36 -0800481 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700482 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
483 chand->resolver = NULL;
484 if (!chand->started_resolving) {
485 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
486 GRPC_ERROR_REF(op->disconnect_with_error));
Craig Tiller91031da2016-12-28 15:44:25 -0800487 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700488 }
489 if (chand->lb_policy != NULL) {
490 grpc_pollset_set_del_pollset_set(exec_ctx,
491 chand->lb_policy->interested_parties,
492 chand->interested_parties);
493 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
494 chand->lb_policy = NULL;
495 }
Craig Tillerb12d22a2016-04-23 12:50:21 -0700496 }
Craig Tiller1c51edc2016-05-07 16:18:43 -0700497 GRPC_ERROR_UNREF(op->disconnect_with_error);
Craig Tillera82950e2015-09-22 12:33:20 -0700498 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800499 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "start_transport_op");
500
501 grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
Craig Tillerbefafe62017-02-09 11:30:54 -0800502}
503
504static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
505 grpc_channel_element *elem,
506 grpc_transport_op *op) {
507 channel_data *chand = elem->channel_data;
508
Craig Tillerbefafe62017-02-09 11:30:54 -0800509 GPR_ASSERT(op->set_accept_stream == false);
510 if (op->bind_pollset != NULL) {
511 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
512 op->bind_pollset);
513 }
514
515 op->transport_private.args[0] = elem;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800516 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "start_transport_op");
Craig Tillerbefafe62017-02-09 11:30:54 -0800517 grpc_closure_sched(
Craig Tillera8610c02017-02-14 10:05:11 -0800518 exec_ctx, grpc_closure_init(
519 &op->transport_private.closure, start_transport_op_locked,
520 op, grpc_combiner_scheduler(chand->combiner, false)),
Craig Tillerbefafe62017-02-09 11:30:54 -0800521 GRPC_ERROR_NONE);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700522}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800523
Mark D. Rothb2d24882016-10-27 15:44:07 -0700524static void cc_get_channel_info(grpc_exec_ctx *exec_ctx,
525 grpc_channel_element *elem,
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700526 const grpc_channel_info *info) {
Mark D. Rothb2d24882016-10-27 15:44:07 -0700527 channel_data *chand = elem->channel_data;
Craig Tiller613dafa2017-02-09 12:00:43 -0800528 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700529 if (info->lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800530 *info->lb_policy_name = chand->info_lb_policy_name == NULL
Mark D. Roth78afd772016-11-04 12:49:49 -0700531 ? NULL
Craig Tiller613dafa2017-02-09 12:00:43 -0800532 : gpr_strdup(chand->info_lb_policy_name);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700533 }
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800534 if (info->service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800535 *info->service_config_json =
536 chand->info_service_config_json == NULL
537 ? NULL
538 : gpr_strdup(chand->info_service_config_json);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800539 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800540 gpr_mu_unlock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700541}
542
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700543/* Constructor for channel_data */
Mark D. Rothc1087882016-11-18 10:54:45 -0800544static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800545 grpc_channel_element *elem,
546 grpc_channel_element_args *args) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700547 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700548 GPR_ASSERT(args->is_last);
549 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800550 // Initialize data members.
Craig Tillerbefafe62017-02-09 11:30:54 -0800551 chand->combiner = grpc_combiner_create(NULL);
Craig Tillerd85477512017-02-09 12:02:39 -0800552 gpr_mu_init(&chand->info_mu);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800553 chand->owning_stack = args->channel_stack;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700554 grpc_closure_init(&chand->on_resolver_result_changed,
Craig Tillerbefafe62017-02-09 11:30:54 -0800555 on_resolver_result_changed_locked, chand,
556 grpc_combiner_scheduler(chand->combiner, false));
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800557 chand->interested_parties = grpc_pollset_set_create();
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700558 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
559 "client_channel");
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800560 // Record client channel factory.
561 const grpc_arg *arg = grpc_channel_args_find(args->channel_args,
562 GRPC_ARG_CLIENT_CHANNEL_FACTORY);
563 GPR_ASSERT(arg != NULL);
564 GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
565 grpc_client_channel_factory_ref(arg->value.pointer.p);
566 chand->client_channel_factory = arg->value.pointer.p;
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800567 // Get server name to resolve, using proxy mapper if needed.
Mark D. Roth86e90592016-11-18 09:56:40 -0800568 arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800569 GPR_ASSERT(arg != NULL);
570 GPR_ASSERT(arg->type == GRPC_ARG_STRING);
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800571 char *proxy_name = NULL;
572 grpc_channel_args *new_args = NULL;
573 grpc_proxy_mappers_map_name(exec_ctx, arg->value.string, args->channel_args,
574 &proxy_name, &new_args);
575 // Instantiate resolver.
Mark D. Roth45ccec52017-01-18 14:04:01 -0800576 chand->resolver = grpc_resolver_create(
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800577 exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string,
578 new_args != NULL ? new_args : args->channel_args,
Craig Tiller972470b2017-02-09 15:05:36 -0800579 chand->interested_parties, chand->combiner);
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800580 if (proxy_name != NULL) gpr_free(proxy_name);
581 if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args);
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800582 if (chand->resolver == NULL) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700583 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("resolver creation failed");
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800584 }
585 return GRPC_ERROR_NONE;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700586}
587
Craig Tiller972470b2017-02-09 15:05:36 -0800588static void shutdown_resolver_locked(grpc_exec_ctx *exec_ctx, void *arg,
589 grpc_error *error) {
590 grpc_resolver *resolver = arg;
591 grpc_resolver_shutdown_locked(exec_ctx, resolver);
592 GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel");
593}
594
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700595/* Destructor for channel_data */
596static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
597 grpc_channel_element *elem) {
598 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700599 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800600 grpc_closure_sched(
601 exec_ctx,
602 grpc_closure_create(shutdown_resolver_locked, chand->resolver,
603 grpc_combiner_scheduler(chand->combiner, false)),
604 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700605 }
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700606 if (chand->client_channel_factory != NULL) {
607 grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
608 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700609 if (chand->lb_policy != NULL) {
610 grpc_pollset_set_del_pollset_set(exec_ctx,
611 chand->lb_policy->interested_parties,
612 chand->interested_parties);
613 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
614 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800615 gpr_free(chand->info_lb_policy_name);
616 gpr_free(chand->info_service_config_json);
Mark D. Roth9d480942016-10-19 14:18:05 -0700617 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800618 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700619 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700620 grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
Craig Tiller9e5ac1b2017-02-14 22:25:50 -0800621 grpc_pollset_set_destroy(exec_ctx, chand->interested_parties);
Craig Tillerf1021672017-02-09 21:29:50 -0800622 GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel");
Craig Tillerd85477512017-02-09 12:02:39 -0800623 gpr_mu_destroy(&chand->info_mu);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700624}
625
626/*************************************************************************
627 * PER-CALL FUNCTIONS
628 */
629
630#define GET_CALL(call_data) \
631 ((grpc_subchannel_call *)(gpr_atm_acq_load(&(call_data)->subchannel_call)))
632
633#define CANCELLED_CALL ((grpc_subchannel_call *)1)
634
635typedef enum {
636 GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING,
637 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL
638} subchannel_creation_phase;
639
640/** Call data. Holds a pointer to grpc_subchannel_call and the
641 associated machinery to create such a pointer.
642 Handles queueing of stream ops until a call object is ready, waiting
643 for initial metadata before trying to create a call object,
644 and handling cancellation gracefully. */
645typedef struct client_channel_call_data {
Mark D. Roth72f6da82016-09-02 13:42:38 -0700646 // State for handling deadlines.
647 // The code in deadline_filter.c requires this to be the first field.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700648 // TODO(roth): This is slightly sub-optimal in that grpc_deadline_state
649 // and this struct both independently store a pointer to the call
650 // stack and each has its own mutex. If/when we have time, find a way
Mark D. Roth6ad99172016-09-09 07:52:48 -0700651 // to avoid this without breaking the grpc_deadline_state abstraction.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700652 grpc_deadline_state deadline_state;
Mark D. Rothf28763c2016-09-14 15:18:40 -0700653
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800654 grpc_slice path; // Request path.
Mark D. Rothe40dd292016-10-05 14:58:37 -0700655 gpr_timespec call_start_time;
656 gpr_timespec deadline;
Mark D. Roth95b627b2017-02-24 11:02:58 -0800657 method_parameters *method_params;
Mark D. Rothe40dd292016-10-05 14:58:37 -0700658 grpc_closure read_service_config;
Mark D. Rothaa850a72016-09-26 13:38:02 -0700659
Mark D. Rothf28763c2016-09-14 15:18:40 -0700660 grpc_error *cancel_error;
Mark D. Roth72f6da82016-09-02 13:42:38 -0700661
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700662 /** either 0 for no call, 1 for cancelled, or a pointer to a
663 grpc_subchannel_call */
664 gpr_atm subchannel_call;
665
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700666 subchannel_creation_phase creation_phase;
667 grpc_connected_subchannel *connected_subchannel;
668 grpc_polling_entity *pollent;
669
Craig Tiller57726ca2016-09-12 11:59:45 -0700670 grpc_transport_stream_op **waiting_ops;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700671 size_t waiting_ops_count;
672 size_t waiting_ops_capacity;
673
674 grpc_closure next_step;
675
676 grpc_call_stack *owning_call;
David Garcia Quintasd1a47f12016-09-02 12:46:44 +0200677
678 grpc_linked_mdelem lb_token_mdelem;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700679} call_data;
680
Craig Tiller8b1d59c2016-12-27 15:15:30 -0800681grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
682 grpc_call_element *call_elem) {
683 grpc_subchannel_call *scc = GET_CALL((call_data *)call_elem->call_data);
684 return scc == CANCELLED_CALL ? NULL : scc;
685}
686
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700687static void add_waiting_locked(call_data *calld, grpc_transport_stream_op *op) {
688 GPR_TIMER_BEGIN("add_waiting_locked", 0);
689 if (calld->waiting_ops_count == calld->waiting_ops_capacity) {
690 calld->waiting_ops_capacity = GPR_MAX(3, 2 * calld->waiting_ops_capacity);
691 calld->waiting_ops =
692 gpr_realloc(calld->waiting_ops,
693 calld->waiting_ops_capacity * sizeof(*calld->waiting_ops));
694 }
Craig Tiller57726ca2016-09-12 11:59:45 -0700695 calld->waiting_ops[calld->waiting_ops_count++] = op;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700696 GPR_TIMER_END("add_waiting_locked", 0);
697}
698
699static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld,
700 grpc_error *error) {
701 size_t i;
702 for (i = 0; i < calld->waiting_ops_count; i++) {
703 grpc_transport_stream_op_finish_with_failure(
Craig Tiller57726ca2016-09-12 11:59:45 -0700704 exec_ctx, calld->waiting_ops[i], GRPC_ERROR_REF(error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700705 }
706 calld->waiting_ops_count = 0;
707 GRPC_ERROR_UNREF(error);
708}
709
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700710static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
Craig Tiller57726ca2016-09-12 11:59:45 -0700711 if (calld->waiting_ops_count == 0) {
712 return;
713 }
714
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800715 grpc_subchannel_call *call = GET_CALL(calld);
716 grpc_transport_stream_op **ops = calld->waiting_ops;
717 size_t nops = calld->waiting_ops_count;
718 if (call == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700719 fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED);
720 return;
721 }
722 calld->waiting_ops = NULL;
723 calld->waiting_ops_count = 0;
724 calld->waiting_ops_capacity = 0;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800725 for (size_t i = 0; i < nops; i++) {
726 grpc_subchannel_call_process_op(exec_ctx, call, ops[i]);
727 }
Craig Tiller9efea882017-02-09 13:06:52 -0800728 gpr_free(ops);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700729}
730
Craig Tillerbefafe62017-02-09 11:30:54 -0800731static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
732 grpc_error *error) {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700733 grpc_call_element *elem = arg;
734 call_data *calld = elem->call_data;
735 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700736 GPR_ASSERT(calld->creation_phase ==
737 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
Yuchen Zeng19656b12016-09-01 18:00:45 -0700738 grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
739 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700740 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
741 if (calld->connected_subchannel == NULL) {
742 gpr_atm_no_barrier_store(&calld->subchannel_call, 1);
ncteisen4b36a3d2017-03-13 19:08:06 -0700743 fail_locked(exec_ctx, calld,
744 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
745 "Failed to create subchannel", &error, 1));
Mark D. Roth72f6da82016-09-02 13:42:38 -0700746 } else if (GET_CALL(calld) == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700747 /* already cancelled before subchannel became ready */
ncteisen4b36a3d2017-03-13 19:08:06 -0700748 grpc_error *cancellation_error =
749 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
750 "Cancelled before creating subchannel", &error, 1);
David Garcia Quintas68a9e382016-12-13 10:50:40 -0800751 /* if due to deadline, attach the deadline exceeded status to the error */
752 if (gpr_time_cmp(calld->deadline, gpr_now(GPR_CLOCK_MONOTONIC)) < 0) {
753 cancellation_error =
754 grpc_error_set_int(cancellation_error, GRPC_ERROR_INT_GRPC_STATUS,
755 GRPC_STATUS_DEADLINE_EXCEEDED);
756 }
757 fail_locked(exec_ctx, calld, cancellation_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700758 } else {
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700759 /* Create call on subchannel. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700760 grpc_subchannel_call *subchannel_call = NULL;
761 grpc_error *new_error = grpc_connected_subchannel_create_call(
Mark D. Rothaa850a72016-09-26 13:38:02 -0700762 exec_ctx, calld->connected_subchannel, calld->pollent, calld->path,
Mark D. Roth3d883412016-11-07 13:42:54 -0800763 calld->call_start_time, calld->deadline, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700764 if (new_error != GRPC_ERROR_NONE) {
765 new_error = grpc_error_add_child(new_error, error);
766 subchannel_call = CANCELLED_CALL;
767 fail_locked(exec_ctx, calld, new_error);
768 }
769 gpr_atm_rel_store(&calld->subchannel_call,
770 (gpr_atm)(uintptr_t)subchannel_call);
771 retry_waiting_locked(exec_ctx, calld);
772 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700773 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
774}
775
776static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
777 call_data *calld = elem->call_data;
778 grpc_subchannel_call *subchannel_call = GET_CALL(calld);
779 if (subchannel_call == NULL || subchannel_call == CANCELLED_CALL) {
780 return NULL;
781 } else {
782 return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
783 }
784}
785
Craig Tiller577c9b22015-11-02 14:11:15 -0800786typedef struct {
787 grpc_metadata_batch *initial_metadata;
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800788 uint32_t initial_metadata_flags;
Craig Tillerb5585d42015-11-17 07:18:31 -0800789 grpc_connected_subchannel **connected_subchannel;
Craig Tiller577c9b22015-11-02 14:11:15 -0800790 grpc_closure *on_ready;
791 grpc_call_element *elem;
792 grpc_closure closure;
793} continue_picking_args;
794
Yuchen Zeng144ce652016-09-01 18:19:34 -0700795/** Return true if subchannel is available immediately (in which case on_ready
796 should not be called), or false otherwise (in which case on_ready should be
797 called when the subchannel is available). */
Craig Tillerbefafe62017-02-09 11:30:54 -0800798static bool pick_subchannel_locked(
799 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
800 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
801 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
802 grpc_error *error);
Craig Tiller577c9b22015-11-02 14:11:15 -0800803
Craig Tillerbefafe62017-02-09 11:30:54 -0800804static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg,
805 grpc_error *error) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800806 continue_picking_args *cpa = arg;
Craig Tiller0ede5452016-04-23 12:21:45 -0700807 if (cpa->connected_subchannel == NULL) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800808 /* cancelled, do nothing */
Craig Tiller804ff712016-05-05 16:25:40 -0700809 } else if (error != GRPC_ERROR_NONE) {
Craig Tiller91031da2016-12-28 15:44:25 -0800810 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error));
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700811 } else {
Craig Tillerbefafe62017-02-09 11:30:54 -0800812 if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata,
813 cpa->initial_metadata_flags,
814 cpa->connected_subchannel, cpa->on_ready,
815 GRPC_ERROR_NONE)) {
Craig Tiller91031da2016-12-28 15:44:25 -0800816 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700817 }
Craig Tiller577c9b22015-11-02 14:11:15 -0800818 }
819 gpr_free(cpa);
820}
821
Craig Tillerbefafe62017-02-09 11:30:54 -0800822static bool pick_subchannel_locked(
823 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
824 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
825 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
826 grpc_error *error) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700827 GPR_TIMER_BEGIN("pick_subchannel", 0);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700828
Craig Tiller577c9b22015-11-02 14:11:15 -0800829 channel_data *chand = elem->channel_data;
830 call_data *calld = elem->call_data;
831 continue_picking_args *cpa;
832 grpc_closure *closure;
833
Craig Tillerb5585d42015-11-17 07:18:31 -0800834 GPR_ASSERT(connected_subchannel);
Craig Tiller577c9b22015-11-02 14:11:15 -0800835
Craig Tiller577c9b22015-11-02 14:11:15 -0800836 if (initial_metadata == NULL) {
837 if (chand->lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800838 grpc_lb_policy_cancel_pick_locked(exec_ctx, chand->lb_policy,
839 connected_subchannel,
840 GRPC_ERROR_REF(error));
Craig Tiller577c9b22015-11-02 14:11:15 -0800841 }
842 for (closure = chand->waiting_for_config_closures.head; closure != NULL;
Craig Tiller804ff712016-05-05 16:25:40 -0700843 closure = closure->next_data.next) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800844 cpa = closure->cb_arg;
Craig Tillerb5585d42015-11-17 07:18:31 -0800845 if (cpa->connected_subchannel == connected_subchannel) {
846 cpa->connected_subchannel = NULL;
ncteisen4b36a3d2017-03-13 19:08:06 -0700847 grpc_closure_sched(exec_ctx, cpa->on_ready,
848 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
849 "Pick cancelled", &error, 1));
Craig Tiller577c9b22015-11-02 14:11:15 -0800850 }
851 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700852 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth697a1f62016-09-07 13:35:07 -0700853 GRPC_ERROR_UNREF(error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700854 return true;
Craig Tiller577c9b22015-11-02 14:11:15 -0800855 }
Mark D. Roth697a1f62016-09-07 13:35:07 -0700856 GPR_ASSERT(error == GRPC_ERROR_NONE);
Craig Tiller577c9b22015-11-02 14:11:15 -0800857 if (chand->lb_policy != NULL) {
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800858 grpc_lb_policy *lb_policy = chand->lb_policy;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700859 GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel");
Mark D. Rothe40dd292016-10-05 14:58:37 -0700860 // If the application explicitly set wait_for_ready, use that.
861 // Otherwise, if the service config specified a value for this
862 // method, use that.
Mark D. Rothc1c38582016-10-11 11:03:27 -0700863 const bool wait_for_ready_set_from_api =
864 initial_metadata_flags &
865 GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
866 const bool wait_for_ready_set_from_service_config =
Mark D. Roth95b627b2017-02-24 11:02:58 -0800867 calld->method_params != NULL &&
868 calld->method_params->wait_for_ready != WAIT_FOR_READY_UNSET;
Mark D. Rothc1c38582016-10-11 11:03:27 -0700869 if (!wait_for_ready_set_from_api &&
870 wait_for_ready_set_from_service_config) {
Mark D. Roth95b627b2017-02-24 11:02:58 -0800871 if (calld->method_params->wait_for_ready == WAIT_FOR_READY_TRUE) {
Mark D. Rothe40dd292016-10-05 14:58:37 -0700872 initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
873 } else {
874 initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
875 }
876 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700877 const grpc_lb_policy_pick_args inputs = {
Yuchen Zengac8bc422016-10-05 14:00:02 -0700878 initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem,
879 gpr_inf_future(GPR_CLOCK_MONOTONIC)};
Craig Tiller2400bf52017-02-09 16:25:19 -0800880 const bool result = grpc_lb_policy_pick_locked(
Mark D. Roth55f25b62016-10-12 14:55:20 -0700881 exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, on_ready);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700882 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel");
883 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700884 return result;
Craig Tiller577c9b22015-11-02 14:11:15 -0800885 }
886 if (chand->resolver != NULL && !chand->started_resolving) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700887 chand->started_resolving = true;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800888 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -0800889 grpc_resolver_next_locked(exec_ctx, chand->resolver,
890 &chand->resolver_result,
891 &chand->on_resolver_result_changed);
Craig Tiller577c9b22015-11-02 14:11:15 -0800892 }
Craig Tiller0eab6972016-04-23 12:59:57 -0700893 if (chand->resolver != NULL) {
894 cpa = gpr_malloc(sizeof(*cpa));
895 cpa->initial_metadata = initial_metadata;
896 cpa->initial_metadata_flags = initial_metadata_flags;
897 cpa->connected_subchannel = connected_subchannel;
898 cpa->on_ready = on_ready;
899 cpa->elem = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -0800900 grpc_closure_init(&cpa->closure, continue_picking_locked, cpa,
901 grpc_combiner_scheduler(chand->combiner, true));
Craig Tiller804ff712016-05-05 16:25:40 -0700902 grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
903 GRPC_ERROR_NONE);
Craig Tiller0eab6972016-04-23 12:59:57 -0700904 } else {
ncteisen4b36a3d2017-03-13 19:08:06 -0700905 grpc_closure_sched(exec_ctx, on_ready,
906 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected"));
Craig Tiller0eab6972016-04-23 12:59:57 -0700907 }
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700908
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700909 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700910 return false;
Craig Tiller577c9b22015-11-02 14:11:15 -0800911}
912
Craig Tillera8610c02017-02-14 10:05:11 -0800913static void start_transport_stream_op_locked_inner(grpc_exec_ctx *exec_ctx,
914 grpc_transport_stream_op *op,
915 grpc_call_element *elem) {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700916 channel_data *chand = elem->channel_data;
Craig Tillera11bfc82017-02-14 09:56:33 -0800917 call_data *calld = elem->call_data;
Craig Tillerbefafe62017-02-09 11:30:54 -0800918 grpc_subchannel_call *call;
919
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700920 /* need to recheck that another thread hasn't set the call */
921 call = GET_CALL(calld);
922 if (call == CANCELLED_CALL) {
Mark D. Rothf28763c2016-09-14 15:18:40 -0700923 grpc_transport_stream_op_finish_with_failure(
924 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -0800925 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700926 return;
927 }
928 if (call != NULL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700929 grpc_subchannel_call_process_op(exec_ctx, call, op);
Craig Tillera11bfc82017-02-14 09:56:33 -0800930 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700931 return;
932 }
933 /* if this is a cancellation, then we can raise our cancelled flag */
934 if (op->cancel_error != GRPC_ERROR_NONE) {
935 if (!gpr_atm_rel_cas(&calld->subchannel_call, 0,
936 (gpr_atm)(uintptr_t)CANCELLED_CALL)) {
Craig Tillera11bfc82017-02-14 09:56:33 -0800937 /* recurse to retry */
Craig Tillera8610c02017-02-14 10:05:11 -0800938 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -0800939 /* early out */
940 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700941 } else {
Craig Tillerbe9691a2017-02-14 10:00:42 -0800942 /* Stash a copy of cancel_error in our call data, so that we can use
943 it for subsequent operations. This ensures that if the call is
944 cancelled before any ops are passed down (e.g., if the deadline
945 is in the past when the call starts), we can return the right
946 error to the caller when the first op does get passed down. */
Mark D. Rothf28763c2016-09-14 15:18:40 -0700947 calld->cancel_error = GRPC_ERROR_REF(op->cancel_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700948 switch (calld->creation_phase) {
949 case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
950 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error));
951 break;
952 case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
Craig Tillerbefafe62017-02-09 11:30:54 -0800953 pick_subchannel_locked(exec_ctx, elem, NULL, 0,
954 &calld->connected_subchannel, NULL,
955 GRPC_ERROR_REF(op->cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700956 break;
957 }
Mark D. Roth72f6da82016-09-02 13:42:38 -0700958 grpc_transport_stream_op_finish_with_failure(
959 exec_ctx, op, GRPC_ERROR_REF(op->cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -0800960 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700961 return;
962 }
963 }
964 /* if we don't have a subchannel, try to get one */
965 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
966 calld->connected_subchannel == NULL &&
967 op->send_initial_metadata != NULL) {
968 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
Craig Tillerbefafe62017-02-09 11:30:54 -0800969 grpc_closure_init(&calld->next_step, subchannel_ready_locked, elem,
970 grpc_combiner_scheduler(chand->combiner, true));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700971 GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
Yuchen Zeng144ce652016-09-01 18:19:34 -0700972 /* If a subchannel is not available immediately, the polling entity from
973 call_data should be provided to channel_data's interested_parties, so
974 that IO of the lb_policy and resolver could be done under it. */
Craig Tillerbefafe62017-02-09 11:30:54 -0800975 if (pick_subchannel_locked(exec_ctx, elem, op->send_initial_metadata,
976 op->send_initial_metadata_flags,
977 &calld->connected_subchannel, &calld->next_step,
978 GRPC_ERROR_NONE)) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700979 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
980 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
Yuchen Zeng19656b12016-09-01 18:00:45 -0700981 } else {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700982 grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
983 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700984 }
985 }
986 /* if we've got a subchannel, then let's ask it to create a call */
987 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
988 calld->connected_subchannel != NULL) {
989 grpc_subchannel_call *subchannel_call = NULL;
990 grpc_error *error = grpc_connected_subchannel_create_call(
Mark D. Rothaa850a72016-09-26 13:38:02 -0700991 exec_ctx, calld->connected_subchannel, calld->pollent, calld->path,
Mark D. Roth3d883412016-11-07 13:42:54 -0800992 calld->call_start_time, calld->deadline, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700993 if (error != GRPC_ERROR_NONE) {
994 subchannel_call = CANCELLED_CALL;
995 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
996 grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
997 }
998 gpr_atm_rel_store(&calld->subchannel_call,
999 (gpr_atm)(uintptr_t)subchannel_call);
1000 retry_waiting_locked(exec_ctx, calld);
Craig Tillera11bfc82017-02-14 09:56:33 -08001001 /* recurse to retry */
Craig Tillera8610c02017-02-14 10:05:11 -08001002 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001003 /* early out */
1004 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001005 }
1006 /* nothing to be done but wait */
1007 add_waiting_locked(calld, op);
Craig Tillera11bfc82017-02-14 09:56:33 -08001008}
1009
Mark D. Roth95b627b2017-02-24 11:02:58 -08001010static void start_transport_stream_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
Mark D. Roth722de8d2017-02-27 10:50:44 -08001011 grpc_error *error_ignored) {
Mark D. Roth95b627b2017-02-24 11:02:58 -08001012 GPR_TIMER_BEGIN("start_transport_stream_op_locked", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001013
1014 grpc_transport_stream_op *op = arg;
1015 grpc_call_element *elem = op->handler_private.args[0];
1016 call_data *calld = elem->call_data;
1017
Craig Tillera8610c02017-02-14 10:05:11 -08001018 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001019
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001020 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
1021 "start_transport_stream_op");
Mark D. Roth95b627b2017-02-24 11:02:58 -08001022 GPR_TIMER_END("start_transport_stream_op_locked", 0);
Craig Tillerbefafe62017-02-09 11:30:54 -08001023}
1024
Craig Tillerbe9691a2017-02-14 10:00:42 -08001025/* The logic here is fairly complicated, due to (a) the fact that we
1026 need to handle the case where we receive the send op before the
1027 initial metadata op, and (b) the need for efficiency, especially in
1028 the streaming case.
1029
1030 We use double-checked locking to initially see if initialization has been
1031 performed. If it has not, we acquire the combiner and perform initialization.
1032 If it has, we proceed on the fast path. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001033static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
1034 grpc_call_element *elem,
1035 grpc_transport_stream_op *op) {
1036 call_data *calld = elem->call_data;
1037 channel_data *chand = elem->channel_data;
1038 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
1039 grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op);
1040 /* try to (atomically) get the call */
1041 grpc_subchannel_call *call = GET_CALL(calld);
1042 GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
1043 if (call == CANCELLED_CALL) {
1044 grpc_transport_stream_op_finish_with_failure(
1045 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
1046 GPR_TIMER_END("cc_start_transport_stream_op", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001047 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001048 return;
1049 }
1050 if (call != NULL) {
1051 grpc_subchannel_call_process_op(exec_ctx, call, op);
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 /* we failed; lock and figure out what to do */
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001057 GRPC_CALL_STACK_REF(calld->owning_call, "start_transport_stream_op");
Craig Tiller4a84bdd2017-02-14 09:48:41 -08001058 op->handler_private.args[0] = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -08001059 grpc_closure_sched(
1060 exec_ctx,
Craig Tiller4a84bdd2017-02-14 09:48:41 -08001061 grpc_closure_init(&op->handler_private.closure,
Mark D. Roth95b627b2017-02-24 11:02:58 -08001062 start_transport_stream_op_locked, op,
Craig Tillerbefafe62017-02-09 11:30:54 -08001063 grpc_combiner_scheduler(chand->combiner, false)),
1064 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001065 GPR_TIMER_END("cc_start_transport_stream_op", 0);
1066}
1067
Mark D. Roth95b627b2017-02-24 11:02:58 -08001068// Sets calld->method_params.
1069// If the method params specify a timeout, populates
1070// *per_method_deadline and returns true.
1071static bool set_call_method_params_from_service_config_locked(
1072 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
1073 gpr_timespec *per_method_deadline) {
1074 channel_data *chand = elem->channel_data;
1075 call_data *calld = elem->call_data;
1076 if (chand->method_params_table != NULL) {
1077 calld->method_params = grpc_method_config_table_get(
1078 exec_ctx, chand->method_params_table, calld->path);
1079 if (calld->method_params != NULL) {
1080 method_parameters_ref(calld->method_params);
1081 if (gpr_time_cmp(calld->method_params->timeout,
1082 gpr_time_0(GPR_TIMESPAN)) != 0) {
Mark D. Roth722de8d2017-02-27 10:50:44 -08001083 *per_method_deadline =
1084 gpr_time_add(calld->call_start_time, calld->method_params->timeout);
Mark D. Roth95b627b2017-02-24 11:02:58 -08001085 return true;
1086 }
1087 }
1088 }
1089 return false;
1090}
1091
Mark D. Rothe40dd292016-10-05 14:58:37 -07001092// Gets data from the service config. Invoked when the resolver returns
1093// its initial result.
Craig Tillerbefafe62017-02-09 11:30:54 -08001094static void read_service_config_locked(grpc_exec_ctx *exec_ctx, void *arg,
1095 grpc_error *error) {
Mark D. Rothe40dd292016-10-05 14:58:37 -07001096 grpc_call_element *elem = arg;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001097 call_data *calld = elem->call_data;
1098 // If this is an error, there's no point in looking at the service config.
Mark D. Roth196387a2016-10-12 14:53:36 -07001099 if (error == GRPC_ERROR_NONE) {
Mark D. Roth95b627b2017-02-24 11:02:58 -08001100 gpr_timespec per_method_deadline;
1101 if (set_call_method_params_from_service_config_locked(
1102 exec_ctx, elem, &per_method_deadline)) {
1103 // If the deadline from the service config is shorter than the one
1104 // from the client API, reset the deadline timer.
1105 if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
1106 calld->deadline = per_method_deadline;
1107 grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
Mark D. Roth196387a2016-10-12 14:53:36 -07001108 }
Mark D. Roth196387a2016-10-12 14:53:36 -07001109 }
Mark D. Rothe40dd292016-10-05 14:58:37 -07001110 }
Mark D. Roth31292f22016-10-12 13:14:07 -07001111 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "read_service_config");
Mark D. Rothe40dd292016-10-05 14:58:37 -07001112}
1113
Craig Tillerbefafe62017-02-09 11:30:54 -08001114static void initial_read_service_config_locked(grpc_exec_ctx *exec_ctx,
1115 void *arg,
1116 grpc_error *error_ignored) {
1117 grpc_call_element *elem = arg;
1118 channel_data *chand = elem->channel_data;
1119 call_data *calld = elem->call_data;
1120 // If the resolver has already returned results, then we can access
1121 // the service config parameters immediately. Otherwise, we need to
1122 // defer that work until the resolver returns an initial result.
Craig Tillerbefafe62017-02-09 11:30:54 -08001123 if (chand->lb_policy != NULL) {
1124 // We already have a resolver result, so check for service config.
Mark D. Roth95b627b2017-02-24 11:02:58 -08001125 gpr_timespec per_method_deadline;
1126 if (set_call_method_params_from_service_config_locked(
1127 exec_ctx, elem, &per_method_deadline)) {
1128 calld->deadline = gpr_time_min(calld->deadline, per_method_deadline);
Craig Tillerbefafe62017-02-09 11:30:54 -08001129 }
1130 } else {
1131 // We don't yet have a resolver result, so register a callback to
1132 // get the service config data once the resolver returns.
1133 // Take a reference to the call stack to be owned by the callback.
1134 GRPC_CALL_STACK_REF(calld->owning_call, "read_service_config");
1135 grpc_closure_init(&calld->read_service_config, read_service_config_locked,
1136 elem, grpc_combiner_scheduler(chand->combiner, false));
1137 grpc_closure_list_append(&chand->waiting_for_config_closures,
1138 &calld->read_service_config, GRPC_ERROR_NONE);
1139 }
1140 // Start the deadline timer with the current deadline value. If we
1141 // do not yet have service config data, then the timer may be reset
1142 // later.
1143 grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001144 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
1145 "initial_read_service_config");
Craig Tillerbefafe62017-02-09 11:30:54 -08001146}
1147
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001148/* Constructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001149static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
1150 grpc_call_element *elem,
Craig Tillerc52ba3a2017-02-15 22:57:43 -08001151 const grpc_call_element_args *args) {
Mark D. Rothaa850a72016-09-26 13:38:02 -07001152 channel_data *chand = elem->channel_data;
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001153 call_data *calld = elem->call_data;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001154 // Initialize data members.
1155 grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001156 calld->path = grpc_slice_ref_internal(args->path);
Mark D. Rothff08f332016-10-14 13:01:01 -07001157 calld->call_start_time = args->start_time;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001158 calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
Mark D. Roth95b627b2017-02-24 11:02:58 -08001159 calld->method_params = NULL;
Mark D. Rothf28763c2016-09-14 15:18:40 -07001160 calld->cancel_error = GRPC_ERROR_NONE;
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001161 gpr_atm_rel_store(&calld->subchannel_call, 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001162 calld->connected_subchannel = NULL;
1163 calld->waiting_ops = NULL;
1164 calld->waiting_ops_count = 0;
1165 calld->waiting_ops_capacity = 0;
1166 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
1167 calld->owning_call = args->call_stack;
1168 calld->pollent = NULL;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001169 GRPC_CALL_STACK_REF(calld->owning_call, "initial_read_service_config");
Craig Tillerbefafe62017-02-09 11:30:54 -08001170 grpc_closure_sched(
1171 exec_ctx,
1172 grpc_closure_init(&calld->read_service_config,
1173 initial_read_service_config_locked, elem,
1174 grpc_combiner_scheduler(chand->combiner, false)),
1175 GRPC_ERROR_NONE);
Mark D. Roth0badbe82016-06-23 10:15:12 -07001176 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001177}
1178
1179/* Destructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001180static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
1181 grpc_call_element *elem,
1182 const grpc_call_final_info *final_info,
1183 void *and_free_memory) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001184 call_data *calld = elem->call_data;
Mark D. Rothf28763c2016-09-14 15:18:40 -07001185 grpc_deadline_state_destroy(exec_ctx, elem);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001186 grpc_slice_unref_internal(exec_ctx, calld->path);
Mark D. Roth95b627b2017-02-24 11:02:58 -08001187 if (calld->method_params != NULL) {
1188 method_parameters_unref(calld->method_params);
1189 }
Mark D. Rothf28763c2016-09-14 15:18:40 -07001190 GRPC_ERROR_UNREF(calld->cancel_error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001191 grpc_subchannel_call *call = GET_CALL(calld);
1192 if (call != NULL && call != CANCELLED_CALL) {
1193 GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
1194 }
1195 GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001196 GPR_ASSERT(calld->waiting_ops_count == 0);
Craig Tiller693d3942016-10-27 16:51:25 -07001197 if (calld->connected_subchannel != NULL) {
1198 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel,
1199 "picked");
1200 }
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001201 gpr_free(calld->waiting_ops);
Craig Tiller2c8063c2016-03-22 22:12:15 -07001202 gpr_free(and_free_memory);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001203}
1204
David Garcia Quintasf72eb972016-05-03 18:28:09 -07001205static void cc_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
1206 grpc_call_element *elem,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001207 grpc_polling_entity *pollent) {
Craig Tiller577c9b22015-11-02 14:11:15 -08001208 call_data *calld = elem->call_data;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001209 calld->pollent = pollent;
Craig Tiller577c9b22015-11-02 14:11:15 -08001210}
1211
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001212/*************************************************************************
1213 * EXPORTED SYMBOLS
1214 */
1215
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001216const grpc_channel_filter grpc_client_channel_filter = {
Craig Tillerf40df232016-03-25 13:38:14 -07001217 cc_start_transport_stream_op,
1218 cc_start_transport_op,
1219 sizeof(call_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001220 cc_init_call_elem,
David Garcia Quintas4afce7e2016-04-18 16:25:17 -07001221 cc_set_pollset_or_pollset_set,
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001222 cc_destroy_call_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001223 sizeof(channel_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001224 cc_init_channel_elem,
1225 cc_destroy_channel_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001226 cc_get_peer,
Mark D. Rothb2d24882016-10-27 15:44:07 -07001227 cc_get_channel_info,
Craig Tillerf40df232016-03-25 13:38:14 -07001228 "client-channel",
Craig Tiller87d5b192015-04-16 14:37:57 -07001229};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001230
Craig Tiller613dafa2017-02-09 12:00:43 -08001231static void try_to_connect_locked(grpc_exec_ctx *exec_ctx, void *arg,
1232 grpc_error *error_ignored) {
1233 channel_data *chand = arg;
1234 if (chand->lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -08001235 grpc_lb_policy_exit_idle_locked(exec_ctx, chand->lb_policy);
Craig Tiller613dafa2017-02-09 12:00:43 -08001236 } else {
1237 chand->exit_idle_when_lb_policy_arrives = true;
1238 if (!chand->started_resolving && chand->resolver != NULL) {
1239 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
1240 chand->started_resolving = true;
Craig Tiller972470b2017-02-09 15:05:36 -08001241 grpc_resolver_next_locked(exec_ctx, chand->resolver,
1242 &chand->resolver_result,
1243 &chand->on_resolver_result_changed);
Craig Tiller613dafa2017-02-09 12:00:43 -08001244 }
1245 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001246 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001247}
1248
Craig Tillera82950e2015-09-22 12:33:20 -07001249grpc_connectivity_state grpc_client_channel_check_connectivity_state(
1250 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001251 channel_data *chand = elem->channel_data;
Craig Tillera8610c02017-02-14 10:05:11 -08001252 grpc_connectivity_state out =
1253 grpc_connectivity_state_check(&chand->state_tracker);
Craig Tillera82950e2015-09-22 12:33:20 -07001254 if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001255 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001256 grpc_closure_sched(
1257 exec_ctx,
1258 grpc_closure_create(try_to_connect_locked, chand,
1259 grpc_combiner_scheduler(chand->combiner, false)),
1260 GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -07001261 }
Craig Tiller48cb07c2015-07-15 16:16:15 -07001262 return out;
1263}
1264
Craig Tiller86c99582015-11-25 15:22:26 -08001265typedef struct {
1266 channel_data *chand;
1267 grpc_pollset *pollset;
1268 grpc_closure *on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001269 grpc_connectivity_state *state;
Craig Tiller86c99582015-11-25 15:22:26 -08001270 grpc_closure my_closure;
1271} external_connectivity_watcher;
1272
Craig Tiller1d881fb2015-12-01 07:39:04 -08001273static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -07001274 grpc_error *error) {
Craig Tiller86c99582015-11-25 15:22:26 -08001275 external_connectivity_watcher *w = arg;
1276 grpc_closure *follow_up = w->on_complete;
Craig Tiller69b093b2016-02-25 19:04:07 -08001277 grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
Craig Tiller1d881fb2015-12-01 07:39:04 -08001278 w->pollset);
1279 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
1280 "external_connectivity_watcher");
Craig Tiller86c99582015-11-25 15:22:26 -08001281 gpr_free(w);
Craig Tiller613dafa2017-02-09 12:00:43 -08001282 grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
1283}
1284
Craig Tillera8610c02017-02-14 10:05:11 -08001285static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg,
1286 grpc_error *error_ignored) {
Craig Tiller613dafa2017-02-09 12:00:43 -08001287 external_connectivity_watcher *w = arg;
1288 grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
1289 grpc_schedule_on_exec_ctx);
1290 grpc_connectivity_state_notify_on_state_change(
1291 exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
Craig Tiller86c99582015-11-25 15:22:26 -08001292}
1293
Craig Tillera82950e2015-09-22 12:33:20 -07001294void grpc_client_channel_watch_connectivity_state(
Craig Tiller906e3bc2015-11-24 07:31:31 -08001295 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
Craig Tillera82950e2015-09-22 12:33:20 -07001296 grpc_connectivity_state *state, grpc_closure *on_complete) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001297 channel_data *chand = elem->channel_data;
Craig Tiller86c99582015-11-25 15:22:26 -08001298 external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
1299 w->chand = chand;
1300 w->pollset = pollset;
1301 w->on_complete = on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001302 w->state = state;
Craig Tiller69b093b2016-02-25 19:04:07 -08001303 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
Craig Tiller1d881fb2015-12-01 07:39:04 -08001304 GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
1305 "external_connectivity_watcher");
Craig Tiller613dafa2017-02-09 12:00:43 -08001306 grpc_closure_sched(
1307 exec_ctx,
Craig Tillera8610c02017-02-14 10:05:11 -08001308 grpc_closure_init(&w->my_closure, watch_connectivity_state_locked, w,
Craig Tiller613dafa2017-02-09 12:00:43 -08001309 grpc_combiner_scheduler(chand->combiner, true)),
1310 GRPC_ERROR_NONE);
Craig Tiller48cb07c2015-07-15 16:16:15 -07001311}