blob: 4b6c53282023e3c1242191c00118e1b1d01c7885 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
Craig Tiller9eb0fde2017-03-31 16:59:30 -070034#include "src/core/ext/filters/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
Craig Tiller9eb0fde2017-03-31 16:59:30 -070046#include "src/core/ext/filters/client_channel/http_connect_handshaker.h"
47#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
48#include "src/core/ext/filters/client_channel/proxy_mapper_registry.h"
49#include "src/core/ext/filters/client_channel/resolver_registry.h"
50#include "src/core/ext/filters/client_channel/retry_throttle.h"
51#include "src/core/ext/filters/client_channel/subchannel.h"
Craig Tiller3be7dd02017-04-03 14:30:03 -070052#include "src/core/ext/filters/deadline/deadline_filter.h"
Craig Tiller9533d042016-03-25 17:11:06 -070053#include "src/core/lib/channel/channel_args.h"
54#include "src/core/lib/channel/connected_channel.h"
Craig Tillerbefafe62017-02-09 11:30:54 -080055#include "src/core/lib/iomgr/combiner.h"
Craig Tiller9533d042016-03-25 17:11:06 -070056#include "src/core/lib/iomgr/iomgr.h"
Mark D. Roth4c0fe492016-08-31 13:51:55 -070057#include "src/core/lib/iomgr/polling_entity.h"
Craig Tiller9533d042016-03-25 17:11:06 -070058#include "src/core/lib/profiling/timers.h"
Craig Tiller7c70b6c2017-01-23 07:48:42 -080059#include "src/core/lib/slice/slice_internal.h"
Craig Tiller9533d042016-03-25 17:11:06 -070060#include "src/core/lib/support/string.h"
61#include "src/core/lib/surface/channel.h"
62#include "src/core/lib/transport/connectivity_state.h"
Mark D. Roth9fe284e2016-09-12 11:22:27 -070063#include "src/core/lib/transport/metadata.h"
64#include "src/core/lib/transport/metadata_batch.h"
Mark D. Rothea846a02016-11-03 11:32:54 -070065#include "src/core/lib/transport/service_config.h"
Mark D. Roth9fe284e2016-09-12 11:22:27 -070066#include "src/core/lib/transport/static_metadata.h"
Craig Tiller8910ac62015-10-08 16:49:15 -070067
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080068/* Client channel implementation */
69
Mark D. Roth26b7be42016-10-24 10:08:07 -070070/*************************************************************************
71 * METHOD-CONFIG TABLE
72 */
73
Mark D. Roth9d480942016-10-19 14:18:05 -070074typedef enum {
Craig Tiller7acc37e2017-02-28 10:01:37 -080075 /* zero so it can be default initialized */
76 WAIT_FOR_READY_UNSET = 0,
Mark D. Roth9d480942016-10-19 14:18:05 -070077 WAIT_FOR_READY_FALSE,
78 WAIT_FOR_READY_TRUE
79} wait_for_ready_value;
80
Mark D. Roth95b627b2017-02-24 11:02:58 -080081typedef struct {
82 gpr_refcount refs;
Mark D. Roth9d480942016-10-19 14:18:05 -070083 gpr_timespec timeout;
84 wait_for_ready_value wait_for_ready;
85} method_parameters;
86
Mark D. Roth722de8d2017-02-27 10:50:44 -080087static method_parameters *method_parameters_ref(
Mark D. Roth95b627b2017-02-24 11:02:58 -080088 method_parameters *method_params) {
89 gpr_ref(&method_params->refs);
90 return method_params;
Mark D. Roth9d480942016-10-19 14:18:05 -070091}
92
Mark D. Roth95b627b2017-02-24 11:02:58 -080093static void method_parameters_unref(method_parameters *method_params) {
94 if (gpr_unref(&method_params->refs)) {
95 gpr_free(method_params);
96 }
97}
98
99static void *method_parameters_copy(void *value) {
100 return method_parameters_ref(value);
101}
102
103static void method_parameters_free(grpc_exec_ctx *exec_ctx, void *value) {
104 method_parameters_unref(value);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800105}
106
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800107static const grpc_slice_hash_table_vtable method_parameters_vtable = {
Craig Tillerb28c7e82016-11-18 10:29:04 -0800108 method_parameters_free, method_parameters_copy};
Mark D. Roth9d480942016-10-19 14:18:05 -0700109
Mark D. Roth95b627b2017-02-24 11:02:58 -0800110static bool parse_wait_for_ready(grpc_json *field,
111 wait_for_ready_value *wait_for_ready) {
112 if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) {
113 return false;
114 }
115 *wait_for_ready = field->type == GRPC_JSON_TRUE ? WAIT_FOR_READY_TRUE
116 : WAIT_FOR_READY_FALSE;
117 return true;
118}
119
Mark D. Roth722de8d2017-02-27 10:50:44 -0800120static bool parse_timeout(grpc_json *field, gpr_timespec *timeout) {
Mark D. Roth95b627b2017-02-24 11:02:58 -0800121 if (field->type != GRPC_JSON_STRING) return false;
122 size_t len = strlen(field->value);
123 if (field->value[len - 1] != 's') return false;
124 char *buf = gpr_strdup(field->value);
125 buf[len - 1] = '\0'; // Remove trailing 's'.
126 char *decimal_point = strchr(buf, '.');
127 if (decimal_point != NULL) {
128 *decimal_point = '\0';
129 timeout->tv_nsec = gpr_parse_nonnegative_int(decimal_point + 1);
130 if (timeout->tv_nsec == -1) {
131 gpr_free(buf);
132 return false;
133 }
134 // There should always be exactly 3, 6, or 9 fractional digits.
135 int multiplier = 1;
136 switch (strlen(decimal_point + 1)) {
137 case 9:
138 break;
139 case 6:
140 multiplier *= 1000;
141 break;
142 case 3:
143 multiplier *= 1000000;
144 break;
145 default: // Unsupported number of digits.
146 gpr_free(buf);
147 return false;
148 }
149 timeout->tv_nsec *= multiplier;
150 }
151 timeout->tv_sec = gpr_parse_nonnegative_int(buf);
152 gpr_free(buf);
153 if (timeout->tv_sec == -1) return false;
154 return true;
155}
156
Mark D. Rothe30baeb2016-11-03 08:16:19 -0700157static void *method_parameters_create_from_json(const grpc_json *json) {
Mark D. Rothc968e602016-11-02 14:07:36 -0700158 wait_for_ready_value wait_for_ready = WAIT_FOR_READY_UNSET;
Mark D. Roth47f10842016-11-03 08:45:27 -0700159 gpr_timespec timeout = {0, 0, GPR_TIMESPAN};
160 for (grpc_json *field = json->child; field != NULL; field = field->next) {
Mark D. Rothc968e602016-11-02 14:07:36 -0700161 if (field->key == NULL) continue;
Mark D. Roth84c8a022016-11-10 09:39:34 -0800162 if (strcmp(field->key, "waitForReady") == 0) {
Mark D. Rothc968e602016-11-02 14:07:36 -0700163 if (wait_for_ready != WAIT_FOR_READY_UNSET) return NULL; // Duplicate.
Mark D. Roth95b627b2017-02-24 11:02:58 -0800164 if (!parse_wait_for_ready(field, &wait_for_ready)) return NULL;
Mark D. Rothc968e602016-11-02 14:07:36 -0700165 } else if (strcmp(field->key, "timeout") == 0) {
166 if (timeout.tv_sec > 0 || timeout.tv_nsec > 0) return NULL; // Duplicate.
Mark D. Roth95b627b2017-02-24 11:02:58 -0800167 if (!parse_timeout(field, &timeout)) return NULL;
Mark D. Rothc968e602016-11-02 14:07:36 -0700168 }
169 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700170 method_parameters *value = gpr_malloc(sizeof(method_parameters));
Mark D. Roth95b627b2017-02-24 11:02:58 -0800171 gpr_ref_init(&value->refs, 1);
Mark D. Rothc968e602016-11-02 14:07:36 -0700172 value->timeout = timeout;
173 value->wait_for_ready = wait_for_ready;
Mark D. Roth9d480942016-10-19 14:18:05 -0700174 return value;
175}
176
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700177/*************************************************************************
178 * CHANNEL-WIDE FUNCTIONS
179 */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800180
Craig Tiller800dacb2015-10-06 09:10:26 -0700181typedef struct client_channel_channel_data {
Craig Tillerf5f17122015-06-25 08:47:26 -0700182 /** resolver for this channel */
183 grpc_resolver *resolver;
Craig Tiller20a3c352015-08-05 08:39:50 -0700184 /** have we started resolving this channel */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700185 bool started_resolving;
Craig Tiller3be7dd02017-04-03 14:30:03 -0700186 /** is deadline checking enabled? */
187 bool deadline_checking_enabled;
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700188 /** client channel factory */
189 grpc_client_channel_factory *client_channel_factory;
Craig Tillerf5f17122015-06-25 08:47:26 -0700190
Craig Tillerbefafe62017-02-09 11:30:54 -0800191 /** combiner protecting all variables below in this data structure */
192 grpc_combiner *combiner;
Mark D. Roth046cf762016-09-26 11:13:51 -0700193 /** currently active load balancer */
Craig Tillerf5f17122015-06-25 08:47:26 -0700194 grpc_lb_policy *lb_policy;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800195 /** retry throttle data */
196 grpc_server_retry_throttle_data *retry_throttle_data;
Mark D. Roth9d480942016-10-19 14:18:05 -0700197 /** maps method names to method_parameters structs */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800198 grpc_slice_hash_table *method_params_table;
Mark D. Roth046cf762016-09-26 11:13:51 -0700199 /** incoming resolver result - set by resolver.next() */
Mark D. Rothaf842452016-10-21 15:05:15 -0700200 grpc_channel_args *resolver_result;
Craig Tiller3f475422015-06-25 10:43:05 -0700201 /** a list of closures that are all waiting for config to come in */
Craig Tillerd9ccbbf2015-09-22 09:30:00 -0700202 grpc_closure_list waiting_for_config_closures;
Craig Tiller3f475422015-06-25 10:43:05 -0700203 /** resolver callback */
Mark D. Rothff4df062016-08-22 15:02:49 -0700204 grpc_closure on_resolver_result_changed;
Craig Tiller3f475422015-06-25 10:43:05 -0700205 /** connectivity state being tracked */
Craig Tillerca3e9d32015-06-27 18:37:27 -0700206 grpc_connectivity_state_tracker state_tracker;
Craig Tiller48cb07c2015-07-15 16:16:15 -0700207 /** when an lb_policy arrives, should we try to exit idle */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700208 bool exit_idle_when_lb_policy_arrives;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800209 /** owning stack */
210 grpc_channel_stack *owning_stack;
Craig Tiller69b093b2016-02-25 19:04:07 -0800211 /** interested parties (owned) */
212 grpc_pollset_set *interested_parties;
Craig Tiller613dafa2017-02-09 12:00:43 -0800213
214 /* the following properties are guarded by a mutex since API's require them
Craig Tiller46dd7902017-02-23 09:42:16 -0800215 to be instantaneously available */
Craig Tiller613dafa2017-02-09 12:00:43 -0800216 gpr_mu info_mu;
217 char *info_lb_policy_name;
218 /** service config in JSON form */
219 char *info_service_config_json;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800220} channel_data;
221
Craig Tillerd6c98df2015-08-18 09:33:44 -0700222/** We create one watcher for each new lb_policy that is returned from a
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700223 resolver, to watch for state changes from the lb_policy. When a state
224 change is seen, we update the channel, and create a new watcher. */
Craig Tillera82950e2015-09-22 12:33:20 -0700225typedef struct {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700226 channel_data *chand;
Craig Tiller33825112015-09-18 07:44:19 -0700227 grpc_closure on_changed;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700228 grpc_connectivity_state state;
229 grpc_lb_policy *lb_policy;
230} lb_policy_connectivity_watcher;
231
Craig Tiller2400bf52017-02-09 16:25:19 -0800232static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
233 grpc_lb_policy *lb_policy,
234 grpc_connectivity_state current_state);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700235
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800236static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
237 channel_data *chand,
238 grpc_connectivity_state state,
Craig Tiller804ff712016-05-05 16:25:40 -0700239 grpc_error *error,
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800240 const char *reason) {
241 if ((state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
Craig Tiller48ed92e2016-06-02 11:07:12 -0700242 state == GRPC_CHANNEL_SHUTDOWN) &&
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800243 chand->lb_policy != NULL) {
Mark D. Roth59c9f902016-09-28 13:33:21 -0700244 /* cancel picks with wait_for_ready=false */
Craig Tiller2400bf52017-02-09 16:25:19 -0800245 grpc_lb_policy_cancel_picks_locked(
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800246 exec_ctx, chand->lb_policy,
Mark D. Roth59c9f902016-09-28 13:33:21 -0700247 /* mask= */ GRPC_INITIAL_METADATA_WAIT_FOR_READY,
Mark D. Roth58f52b72016-09-09 13:55:18 -0700248 /* check= */ 0, GRPC_ERROR_REF(error));
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800249 }
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700250 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, error,
251 reason);
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800252}
253
Craig Tiller804ff712016-05-05 16:25:40 -0700254static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
Craig Tillerbefafe62017-02-09 11:30:54 -0800255 void *arg, grpc_error *error) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700256 lb_policy_connectivity_watcher *w = arg;
Craig Tiller5d44c062015-07-01 08:55:28 -0700257 grpc_connectivity_state publish_state = w->state;
Craig Tillerc5de8352017-02-09 14:08:05 -0800258 /* check if the notification is for the latest policy */
259 if (w->lb_policy == w->chand->lb_policy) {
260 if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
261 publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Craig Tiller972470b2017-02-09 15:05:36 -0800262 grpc_resolver_channel_saw_error_locked(exec_ctx, w->chand->resolver);
Craig Tillerc5de8352017-02-09 14:08:05 -0800263 GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
264 w->chand->lb_policy = NULL;
265 }
266 set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
267 GRPC_ERROR_REF(error), "lb_changed");
268 if (w->state != GRPC_CHANNEL_SHUTDOWN) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800269 watch_lb_policy_locked(exec_ctx, w->chand, w->lb_policy, w->state);
Craig Tillerc5de8352017-02-09 14:08:05 -0800270 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800271 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700272
Craig Tiller906e3bc2015-11-24 07:31:31 -0800273 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
Craig Tillera82950e2015-09-22 12:33:20 -0700274 gpr_free(w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700275}
276
Craig Tiller2400bf52017-02-09 16:25:19 -0800277static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
278 grpc_lb_policy *lb_policy,
279 grpc_connectivity_state current_state) {
Craig Tillera82950e2015-09-22 12:33:20 -0700280 lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
Craig Tiller906e3bc2015-11-24 07:31:31 -0800281 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700282
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700283 w->chand = chand;
Craig Tillerbefafe62017-02-09 11:30:54 -0800284 grpc_closure_init(&w->on_changed, on_lb_policy_state_changed_locked, w,
285 grpc_combiner_scheduler(chand->combiner, false));
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700286 w->state = current_state;
287 w->lb_policy = lb_policy;
Craig Tiller2400bf52017-02-09 16:25:19 -0800288 grpc_lb_policy_notify_on_state_change_locked(exec_ctx, lb_policy, &w->state,
289 &w->on_changed);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700290}
291
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800292typedef struct {
293 char *server_name;
294 grpc_server_retry_throttle_data *retry_throttle_data;
295} service_config_parsing_state;
296
297static void parse_retry_throttle_params(const grpc_json *field, void *arg) {
298 service_config_parsing_state *parsing_state = arg;
299 if (strcmp(field->key, "retryThrottling") == 0) {
300 if (parsing_state->retry_throttle_data != NULL) return; // Duplicate.
301 if (field->type != GRPC_JSON_OBJECT) return;
302 int max_milli_tokens = 0;
303 int milli_token_ratio = 0;
304 for (grpc_json *sub_field = field->child; sub_field != NULL;
305 sub_field = sub_field->next) {
Mark D. Rothb3322562017-02-23 14:38:02 -0800306 if (sub_field->key == NULL) return;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800307 if (strcmp(sub_field->key, "maxTokens") == 0) {
308 if (max_milli_tokens != 0) return; // Duplicate.
309 if (sub_field->type != GRPC_JSON_NUMBER) return;
310 max_milli_tokens = gpr_parse_nonnegative_int(sub_field->value);
311 if (max_milli_tokens == -1) return;
312 max_milli_tokens *= 1000;
313 } else if (strcmp(sub_field->key, "tokenRatio") == 0) {
314 if (milli_token_ratio != 0) return; // Duplicate.
315 if (sub_field->type != GRPC_JSON_NUMBER) return;
316 // We support up to 3 decimal digits.
317 size_t whole_len = strlen(sub_field->value);
318 uint32_t multiplier = 1;
319 uint32_t decimal_value = 0;
320 const char *decimal_point = strchr(sub_field->value, '.');
321 if (decimal_point != NULL) {
322 whole_len = (size_t)(decimal_point - sub_field->value);
323 multiplier = 1000;
324 size_t decimal_len = strlen(decimal_point + 1);
325 if (decimal_len > 3) decimal_len = 3;
326 if (!gpr_parse_bytes_to_uint32(decimal_point + 1, decimal_len,
327 &decimal_value)) {
328 return;
329 }
330 uint32_t decimal_multiplier = 1;
331 for (size_t i = 0; i < (3 - decimal_len); ++i) {
332 decimal_multiplier *= 10;
333 }
334 decimal_value *= decimal_multiplier;
335 }
336 uint32_t whole_value;
337 if (!gpr_parse_bytes_to_uint32(sub_field->value, whole_len,
338 &whole_value)) {
339 return;
340 }
341 milli_token_ratio = (int)((whole_value * multiplier) + decimal_value);
Mark D. Rothb3322562017-02-23 14:38:02 -0800342 if (milli_token_ratio <= 0) return;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800343 }
344 }
345 parsing_state->retry_throttle_data =
346 grpc_retry_throttle_map_get_data_for_server(
347 parsing_state->server_name, max_milli_tokens, milli_token_ratio);
348 }
349}
350
Craig Tillerbefafe62017-02-09 11:30:54 -0800351static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
352 void *arg, grpc_error *error) {
Craig Tiller3f475422015-06-25 10:43:05 -0700353 channel_data *chand = arg;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700354 char *lb_policy_name = NULL;
Craig Tiller3f475422015-06-25 10:43:05 -0700355 grpc_lb_policy *lb_policy = NULL;
356 grpc_lb_policy *old_lb_policy;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800357 grpc_slice_hash_table *method_params_table = NULL;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700358 grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700359 bool exit_idle = false;
ncteisen4b36a3d2017-03-13 19:08:06 -0700360 grpc_error *state_error =
361 GRPC_ERROR_CREATE_FROM_STATIC_STRING("No load balancing policy");
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800362 char *service_config_json = NULL;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800363 service_config_parsing_state parsing_state;
364 memset(&parsing_state, 0, sizeof(parsing_state));
Craig Tiller3f475422015-06-25 10:43:05 -0700365
Mark D. Roth046cf762016-09-26 11:13:51 -0700366 if (chand->resolver_result != NULL) {
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700367 // Find LB policy name.
Mark D. Rothaf842452016-10-21 15:05:15 -0700368 const grpc_arg *channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700369 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_POLICY_NAME);
Mark D. Rothaf842452016-10-21 15:05:15 -0700370 if (channel_arg != NULL) {
371 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
372 lb_policy_name = channel_arg->value.string;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700373 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700374 // Special case: If all of the addresses are balancer addresses,
375 // assume that we should use the grpclb policy, regardless of what the
376 // resolver actually specified.
Mark D. Rothaf842452016-10-21 15:05:15 -0700377 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700378 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES);
David Garcia Quintas143cb772017-03-31 13:39:27 -0700379 if (channel_arg != NULL && channel_arg->type == GRPC_ARG_POINTER) {
Mark D. Roth557c9902016-10-24 11:12:05 -0700380 grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
Mark D. Rothaf842452016-10-21 15:05:15 -0700381 bool found_backend_address = false;
382 for (size_t i = 0; i < addresses->num_addresses; ++i) {
383 if (!addresses->addresses[i].is_balancer) {
384 found_backend_address = true;
385 break;
386 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700387 }
Mark D. Rothaf842452016-10-21 15:05:15 -0700388 if (!found_backend_address) {
389 if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) {
390 gpr_log(GPR_INFO,
391 "resolver requested LB policy %s but provided only balancer "
392 "addresses, no backend addresses -- forcing use of grpclb LB "
393 "policy",
Mark D. Roth5f40e5d2016-10-24 13:09:05 -0700394 lb_policy_name);
Mark D. Rothaf842452016-10-21 15:05:15 -0700395 }
396 lb_policy_name = "grpclb";
Mark D. Roth88405f72016-10-03 08:24:52 -0700397 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700398 }
399 // Use pick_first if nothing was specified and we didn't select grpclb
400 // above.
401 if (lb_policy_name == NULL) lb_policy_name = "pick_first";
Mark D. Roth41124992016-11-03 11:22:20 -0700402 // Instantiate LB policy.
403 grpc_lb_policy_args lb_policy_args;
404 lb_policy_args.args = chand->resolver_result;
405 lb_policy_args.client_channel_factory = chand->client_channel_factory;
Craig Tiller2400bf52017-02-09 16:25:19 -0800406 lb_policy_args.combiner = chand->combiner;
Mark D. Roth88405f72016-10-03 08:24:52 -0700407 lb_policy =
408 grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700409 if (lb_policy != NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -0700410 GRPC_LB_POLICY_REF(lb_policy, "config_change");
Craig Tillerf707d622016-05-06 14:26:12 -0700411 GRPC_ERROR_UNREF(state_error);
Craig Tiller2400bf52017-02-09 16:25:19 -0800412 state = grpc_lb_policy_check_connectivity_locked(exec_ctx, lb_policy,
413 &state_error);
Craig Tiller45724b32015-09-22 10:42:19 -0700414 }
Mark D. Roth41124992016-11-03 11:22:20 -0700415 // Find service config.
Mark D. Rothaf842452016-10-21 15:05:15 -0700416 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700417 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVICE_CONFIG);
Mark D. Roth046cf762016-09-26 11:13:51 -0700418 if (channel_arg != NULL) {
Mark D. Roth9ec28af2016-11-03 12:32:39 -0700419 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800420 service_config_json = gpr_strdup(channel_arg->value.string);
Mark D. Roth70a1abd2016-11-04 09:26:37 -0700421 grpc_service_config *service_config =
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800422 grpc_service_config_create(service_config_json);
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700423 if (service_config != NULL) {
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800424 channel_arg =
425 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVER_URI);
426 GPR_ASSERT(channel_arg != NULL);
427 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -0700428 grpc_uri *uri =
429 grpc_uri_parse(exec_ctx, channel_arg->value.string, true);
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800430 GPR_ASSERT(uri->path[0] != '\0');
431 parsing_state.server_name =
432 uri->path[0] == '/' ? uri->path + 1 : uri->path;
433 grpc_service_config_parse_global_params(
434 service_config, parse_retry_throttle_params, &parsing_state);
435 parsing_state.server_name = NULL;
436 grpc_uri_destroy(uri);
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700437 method_params_table = grpc_service_config_create_method_config_table(
Craig Tillerb28c7e82016-11-18 10:29:04 -0800438 exec_ctx, service_config, method_parameters_create_from_json,
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700439 &method_parameters_vtable);
440 grpc_service_config_destroy(service_config);
441 }
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700442 }
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700443 // Before we clean up, save a copy of lb_policy_name, since it might
444 // be pointing to data inside chand->resolver_result.
445 // The copy will be saved in chand->lb_policy_name below.
446 lb_policy_name = gpr_strdup(lb_policy_name);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800447 grpc_channel_args_destroy(exec_ctx, chand->resolver_result);
Mark D. Roth046cf762016-09-26 11:13:51 -0700448 chand->resolver_result = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700449 }
450
Craig Tiller86c99582015-11-25 15:22:26 -0800451 if (lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800452 grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties,
453 chand->interested_parties);
Craig Tiller86c99582015-11-25 15:22:26 -0800454 }
455
Craig Tiller613dafa2017-02-09 12:00:43 -0800456 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700457 if (lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800458 gpr_free(chand->info_lb_policy_name);
459 chand->info_lb_policy_name = lb_policy_name;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700460 }
Craig Tiller3f475422015-06-25 10:43:05 -0700461 old_lb_policy = chand->lb_policy;
462 chand->lb_policy = lb_policy;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800463 if (service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800464 gpr_free(chand->info_service_config_json);
465 chand->info_service_config_json = service_config_json;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800466 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800467 gpr_mu_unlock(&chand->info_mu);
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800468
469 if (chand->retry_throttle_data != NULL) {
470 grpc_server_retry_throttle_data_unref(chand->retry_throttle_data);
471 }
472 chand->retry_throttle_data = parsing_state.retry_throttle_data;
Mark D. Roth9d480942016-10-19 14:18:05 -0700473 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800474 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth046cf762016-09-26 11:13:51 -0700475 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700476 chand->method_params_table = method_params_table;
Craig Tiller0ede5452016-04-23 12:21:45 -0700477 if (lb_policy != NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -0800478 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller0ede5452016-04-23 12:21:45 -0700479 } else if (chand->resolver == NULL /* disconnected */) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700480 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
481 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
482 "Channel disconnected", &error, 1));
Craig Tiller91031da2016-12-28 15:44:25 -0800483 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tillera82950e2015-09-22 12:33:20 -0700484 }
485 if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
486 GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700487 exit_idle = true;
488 chand->exit_idle_when_lb_policy_arrives = false;
Craig Tillera82950e2015-09-22 12:33:20 -0700489 }
Craig Tiller98465032015-06-29 14:36:42 -0700490
Craig Tiller804ff712016-05-05 16:25:40 -0700491 if (error == GRPC_ERROR_NONE && chand->resolver) {
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700492 set_channel_connectivity_state_locked(
493 exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700494 if (lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800495 watch_lb_policy_locked(exec_ctx, chand, lb_policy, state);
Craig Tiller45724b32015-09-22 10:42:19 -0700496 }
Craig Tiller906e3bc2015-11-24 07:31:31 -0800497 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -0800498 grpc_resolver_next_locked(exec_ctx, chand->resolver,
499 &chand->resolver_result,
500 &chand->on_resolver_result_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700501 } else {
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800502 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800503 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800504 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
505 chand->resolver = NULL;
506 }
Craig Tiller804ff712016-05-05 16:25:40 -0700507 grpc_error *refs[] = {error, state_error};
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800508 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700509 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
ncteisen4b36a3d2017-03-13 19:08:06 -0700510 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
511 "Got config after disconnection", refs, GPR_ARRAY_SIZE(refs)),
Craig Tiller804ff712016-05-05 16:25:40 -0700512 "resolver_gone");
Craig Tillera82950e2015-09-22 12:33:20 -0700513 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700514
Craig Tillera82950e2015-09-22 12:33:20 -0700515 if (exit_idle) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800516 grpc_lb_policy_exit_idle_locked(exec_ctx, lb_policy);
Craig Tillera82950e2015-09-22 12:33:20 -0700517 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
518 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700519
Craig Tillera82950e2015-09-22 12:33:20 -0700520 if (old_lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800521 grpc_pollset_set_del_pollset_set(
522 exec_ctx, old_lb_policy->interested_parties, chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700523 GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
524 }
Craig Tiller000cd8f2015-09-18 07:20:29 -0700525
Craig Tillera82950e2015-09-22 12:33:20 -0700526 if (lb_policy != NULL) {
527 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
528 }
Craig Tiller45724b32015-09-22 10:42:19 -0700529
Craig Tiller906e3bc2015-11-24 07:31:31 -0800530 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700531 GRPC_ERROR_UNREF(state_error);
Craig Tiller3f475422015-06-25 10:43:05 -0700532}
533
Craig Tillera8610c02017-02-14 10:05:11 -0800534static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
535 grpc_error *error_ignored) {
Craig Tillerbefafe62017-02-09 11:30:54 -0800536 grpc_transport_op *op = arg;
537 grpc_channel_element *elem = op->transport_private.args[0];
Craig Tillerca3e9d32015-06-27 18:37:27 -0700538 channel_data *chand = elem->channel_data;
Craig Tiller000cd8f2015-09-18 07:20:29 -0700539
Craig Tillera82950e2015-09-22 12:33:20 -0700540 if (op->on_connectivity_state_change != NULL) {
541 grpc_connectivity_state_notify_on_state_change(
542 exec_ctx, &chand->state_tracker, op->connectivity_state,
543 op->on_connectivity_state_change);
544 op->on_connectivity_state_change = NULL;
545 op->connectivity_state = NULL;
546 }
547
Craig Tiller26dab312015-12-07 14:43:47 -0800548 if (op->send_ping != NULL) {
Craig Tiller87b71e22015-12-07 15:14:14 -0800549 if (chand->lb_policy == NULL) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700550 grpc_closure_sched(
551 exec_ctx, op->send_ping,
552 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Ping with no load balancing"));
Craig Tiller26dab312015-12-07 14:43:47 -0800553 } else {
Craig Tiller2400bf52017-02-09 16:25:19 -0800554 grpc_lb_policy_ping_one_locked(exec_ctx, chand->lb_policy, op->send_ping);
Craig Tiller26dab312015-12-07 14:43:47 -0800555 op->bind_pollset = NULL;
556 }
557 op->send_ping = NULL;
558 }
559
Craig Tiller1c51edc2016-05-07 16:18:43 -0700560 if (op->disconnect_with_error != GRPC_ERROR_NONE) {
561 if (chand->resolver != NULL) {
562 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700563 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller1c51edc2016-05-07 16:18:43 -0700564 GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
Craig Tiller972470b2017-02-09 15:05:36 -0800565 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700566 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
567 chand->resolver = NULL;
568 if (!chand->started_resolving) {
569 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
570 GRPC_ERROR_REF(op->disconnect_with_error));
Craig Tiller91031da2016-12-28 15:44:25 -0800571 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700572 }
573 if (chand->lb_policy != NULL) {
574 grpc_pollset_set_del_pollset_set(exec_ctx,
575 chand->lb_policy->interested_parties,
576 chand->interested_parties);
577 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
578 chand->lb_policy = NULL;
579 }
Craig Tillerb12d22a2016-04-23 12:50:21 -0700580 }
Craig Tiller1c51edc2016-05-07 16:18:43 -0700581 GRPC_ERROR_UNREF(op->disconnect_with_error);
Craig Tillera82950e2015-09-22 12:33:20 -0700582 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800583 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "start_transport_op");
584
585 grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
Craig Tillerbefafe62017-02-09 11:30:54 -0800586}
587
588static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
589 grpc_channel_element *elem,
590 grpc_transport_op *op) {
591 channel_data *chand = elem->channel_data;
592
Craig Tillerbefafe62017-02-09 11:30:54 -0800593 GPR_ASSERT(op->set_accept_stream == false);
594 if (op->bind_pollset != NULL) {
595 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
596 op->bind_pollset);
597 }
598
599 op->transport_private.args[0] = elem;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800600 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "start_transport_op");
Craig Tillerbefafe62017-02-09 11:30:54 -0800601 grpc_closure_sched(
Craig Tillera8610c02017-02-14 10:05:11 -0800602 exec_ctx, grpc_closure_init(
603 &op->transport_private.closure, start_transport_op_locked,
604 op, grpc_combiner_scheduler(chand->combiner, false)),
Craig Tillerbefafe62017-02-09 11:30:54 -0800605 GRPC_ERROR_NONE);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700606}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800607
Mark D. Rothb2d24882016-10-27 15:44:07 -0700608static void cc_get_channel_info(grpc_exec_ctx *exec_ctx,
609 grpc_channel_element *elem,
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700610 const grpc_channel_info *info) {
Mark D. Rothb2d24882016-10-27 15:44:07 -0700611 channel_data *chand = elem->channel_data;
Craig Tiller613dafa2017-02-09 12:00:43 -0800612 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700613 if (info->lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800614 *info->lb_policy_name = chand->info_lb_policy_name == NULL
Mark D. Roth78afd772016-11-04 12:49:49 -0700615 ? NULL
Craig Tiller613dafa2017-02-09 12:00:43 -0800616 : gpr_strdup(chand->info_lb_policy_name);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700617 }
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800618 if (info->service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800619 *info->service_config_json =
620 chand->info_service_config_json == NULL
621 ? NULL
622 : gpr_strdup(chand->info_service_config_json);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800623 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800624 gpr_mu_unlock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700625}
626
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700627/* Constructor for channel_data */
Mark D. Rothc1087882016-11-18 10:54:45 -0800628static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800629 grpc_channel_element *elem,
630 grpc_channel_element_args *args) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700631 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700632 GPR_ASSERT(args->is_last);
633 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800634 // Initialize data members.
Craig Tillerbefafe62017-02-09 11:30:54 -0800635 chand->combiner = grpc_combiner_create(NULL);
Craig Tillerd85477512017-02-09 12:02:39 -0800636 gpr_mu_init(&chand->info_mu);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800637 chand->owning_stack = args->channel_stack;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700638 grpc_closure_init(&chand->on_resolver_result_changed,
Craig Tillerbefafe62017-02-09 11:30:54 -0800639 on_resolver_result_changed_locked, chand,
640 grpc_combiner_scheduler(chand->combiner, false));
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800641 chand->interested_parties = grpc_pollset_set_create();
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700642 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
643 "client_channel");
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800644 // Record client channel factory.
645 const grpc_arg *arg = grpc_channel_args_find(args->channel_args,
646 GRPC_ARG_CLIENT_CHANNEL_FACTORY);
David Garcia Quintas228a5142017-03-30 19:43:00 -0700647 if (arg == NULL) {
648 return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
649 "Missing client channel factory in args for client channel filter");
650 }
651 if (arg->type != GRPC_ARG_POINTER) {
652 return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
653 "client channel factory arg must be a pointer");
654 }
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800655 grpc_client_channel_factory_ref(arg->value.pointer.p);
656 chand->client_channel_factory = arg->value.pointer.p;
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800657 // Get server name to resolve, using proxy mapper if needed.
Mark D. Roth86e90592016-11-18 09:56:40 -0800658 arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI);
David Garcia Quintas228a5142017-03-30 19:43:00 -0700659 if (arg == NULL) {
660 return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
661 "Missing server uri in args for client channel filter");
662 }
663 if (arg->type != GRPC_ARG_STRING) {
664 return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
665 "server uri arg must be a string");
666 }
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800667 char *proxy_name = NULL;
668 grpc_channel_args *new_args = NULL;
669 grpc_proxy_mappers_map_name(exec_ctx, arg->value.string, args->channel_args,
670 &proxy_name, &new_args);
671 // Instantiate resolver.
Mark D. Roth45ccec52017-01-18 14:04:01 -0800672 chand->resolver = grpc_resolver_create(
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800673 exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string,
674 new_args != NULL ? new_args : args->channel_args,
Craig Tiller972470b2017-02-09 15:05:36 -0800675 chand->interested_parties, chand->combiner);
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800676 if (proxy_name != NULL) gpr_free(proxy_name);
677 if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args);
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800678 if (chand->resolver == NULL) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700679 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("resolver creation failed");
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800680 }
Craig Tiller3be7dd02017-04-03 14:30:03 -0700681 chand->deadline_checking_enabled =
682 grpc_deadline_checking_enabled(args->channel_args);
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800683 return GRPC_ERROR_NONE;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700684}
685
Craig Tiller972470b2017-02-09 15:05:36 -0800686static void shutdown_resolver_locked(grpc_exec_ctx *exec_ctx, void *arg,
687 grpc_error *error) {
688 grpc_resolver *resolver = arg;
689 grpc_resolver_shutdown_locked(exec_ctx, resolver);
690 GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel");
691}
692
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700693/* Destructor for channel_data */
694static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
695 grpc_channel_element *elem) {
696 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700697 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800698 grpc_closure_sched(
699 exec_ctx,
700 grpc_closure_create(shutdown_resolver_locked, chand->resolver,
701 grpc_combiner_scheduler(chand->combiner, false)),
702 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700703 }
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700704 if (chand->client_channel_factory != NULL) {
705 grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
706 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700707 if (chand->lb_policy != NULL) {
708 grpc_pollset_set_del_pollset_set(exec_ctx,
709 chand->lb_policy->interested_parties,
710 chand->interested_parties);
711 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
712 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800713 gpr_free(chand->info_lb_policy_name);
714 gpr_free(chand->info_service_config_json);
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800715 if (chand->retry_throttle_data != NULL) {
716 grpc_server_retry_throttle_data_unref(chand->retry_throttle_data);
717 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700718 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800719 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700720 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700721 grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
Craig Tiller9e5ac1b2017-02-14 22:25:50 -0800722 grpc_pollset_set_destroy(exec_ctx, chand->interested_parties);
Craig Tillerf1021672017-02-09 21:29:50 -0800723 GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel");
Craig Tillerd85477512017-02-09 12:02:39 -0800724 gpr_mu_destroy(&chand->info_mu);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700725}
726
727/*************************************************************************
728 * PER-CALL FUNCTIONS
729 */
730
731#define GET_CALL(call_data) \
732 ((grpc_subchannel_call *)(gpr_atm_acq_load(&(call_data)->subchannel_call)))
733
734#define CANCELLED_CALL ((grpc_subchannel_call *)1)
735
736typedef enum {
Craig Tiller7acc37e2017-02-28 10:01:37 -0800737 /* zero so that it can be default-initialized */
738 GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING = 0,
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700739 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL
740} subchannel_creation_phase;
741
742/** Call data. Holds a pointer to grpc_subchannel_call and the
743 associated machinery to create such a pointer.
744 Handles queueing of stream ops until a call object is ready, waiting
745 for initial metadata before trying to create a call object,
746 and handling cancellation gracefully. */
747typedef struct client_channel_call_data {
Mark D. Roth72f6da82016-09-02 13:42:38 -0700748 // State for handling deadlines.
749 // The code in deadline_filter.c requires this to be the first field.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700750 // TODO(roth): This is slightly sub-optimal in that grpc_deadline_state
751 // and this struct both independently store a pointer to the call
752 // stack and each has its own mutex. If/when we have time, find a way
Mark D. Roth6ad99172016-09-09 07:52:48 -0700753 // to avoid this without breaking the grpc_deadline_state abstraction.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700754 grpc_deadline_state deadline_state;
Mark D. Rothf28763c2016-09-14 15:18:40 -0700755
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800756 grpc_slice path; // Request path.
Mark D. Rothe40dd292016-10-05 14:58:37 -0700757 gpr_timespec call_start_time;
758 gpr_timespec deadline;
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -0700759 grpc_server_retry_throttle_data *retry_throttle_data;
Mark D. Roth95b627b2017-02-24 11:02:58 -0800760 method_parameters *method_params;
Mark D. Rothaa850a72016-09-26 13:38:02 -0700761
Mark D. Rothf28763c2016-09-14 15:18:40 -0700762 grpc_error *cancel_error;
Mark D. Roth72f6da82016-09-02 13:42:38 -0700763
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700764 /** either 0 for no call, 1 for cancelled, or a pointer to a
765 grpc_subchannel_call */
766 gpr_atm subchannel_call;
Craig Tillerd426cac2017-03-13 12:30:45 -0700767 gpr_arena *arena;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700768
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700769 subchannel_creation_phase creation_phase;
770 grpc_connected_subchannel *connected_subchannel;
771 grpc_polling_entity *pollent;
772
Craig Tiller57726ca2016-09-12 11:59:45 -0700773 grpc_transport_stream_op **waiting_ops;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700774 size_t waiting_ops_count;
775 size_t waiting_ops_capacity;
776
777 grpc_closure next_step;
778
779 grpc_call_stack *owning_call;
David Garcia Quintasd1a47f12016-09-02 12:46:44 +0200780
781 grpc_linked_mdelem lb_token_mdelem;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800782
783 grpc_closure on_complete;
784 grpc_closure *original_on_complete;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700785} call_data;
786
Craig Tiller8b1d59c2016-12-27 15:15:30 -0800787grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
788 grpc_call_element *call_elem) {
789 grpc_subchannel_call *scc = GET_CALL((call_data *)call_elem->call_data);
790 return scc == CANCELLED_CALL ? NULL : scc;
791}
792
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700793static void add_waiting_locked(call_data *calld, grpc_transport_stream_op *op) {
794 GPR_TIMER_BEGIN("add_waiting_locked", 0);
795 if (calld->waiting_ops_count == calld->waiting_ops_capacity) {
796 calld->waiting_ops_capacity = GPR_MAX(3, 2 * calld->waiting_ops_capacity);
797 calld->waiting_ops =
798 gpr_realloc(calld->waiting_ops,
799 calld->waiting_ops_capacity * sizeof(*calld->waiting_ops));
800 }
Craig Tiller57726ca2016-09-12 11:59:45 -0700801 calld->waiting_ops[calld->waiting_ops_count++] = op;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700802 GPR_TIMER_END("add_waiting_locked", 0);
803}
804
805static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld,
806 grpc_error *error) {
807 size_t i;
808 for (i = 0; i < calld->waiting_ops_count; i++) {
809 grpc_transport_stream_op_finish_with_failure(
Craig Tiller57726ca2016-09-12 11:59:45 -0700810 exec_ctx, calld->waiting_ops[i], GRPC_ERROR_REF(error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700811 }
812 calld->waiting_ops_count = 0;
813 GRPC_ERROR_UNREF(error);
814}
815
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700816static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
Craig Tiller57726ca2016-09-12 11:59:45 -0700817 if (calld->waiting_ops_count == 0) {
818 return;
819 }
820
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800821 grpc_subchannel_call *call = GET_CALL(calld);
822 grpc_transport_stream_op **ops = calld->waiting_ops;
823 size_t nops = calld->waiting_ops_count;
824 if (call == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700825 fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED);
826 return;
827 }
828 calld->waiting_ops = NULL;
829 calld->waiting_ops_count = 0;
830 calld->waiting_ops_capacity = 0;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800831 for (size_t i = 0; i < nops; i++) {
832 grpc_subchannel_call_process_op(exec_ctx, call, ops[i]);
833 }
Craig Tiller9efea882017-02-09 13:06:52 -0800834 gpr_free(ops);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700835}
836
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -0700837// Sets calld->method_params and calld->retry_throttle_data.
Craig Tiller11c17d42017-03-13 13:36:34 -0700838// If the method params specify a timeout, populates
839// *per_method_deadline and returns true.
840static bool set_call_method_params_from_service_config_locked(
841 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
842 gpr_timespec *per_method_deadline) {
843 channel_data *chand = elem->channel_data;
844 call_data *calld = elem->call_data;
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -0700845 if (chand->retry_throttle_data != NULL) {
846 calld->retry_throttle_data =
847 grpc_server_retry_throttle_data_ref(chand->retry_throttle_data);
848 }
Craig Tiller11c17d42017-03-13 13:36:34 -0700849 if (chand->method_params_table != NULL) {
850 calld->method_params = grpc_method_config_table_get(
851 exec_ctx, chand->method_params_table, calld->path);
852 if (calld->method_params != NULL) {
853 method_parameters_ref(calld->method_params);
854 if (gpr_time_cmp(calld->method_params->timeout,
855 gpr_time_0(GPR_TIMESPAN)) != 0) {
856 *per_method_deadline =
857 gpr_time_add(calld->call_start_time, calld->method_params->timeout);
858 return true;
859 }
860 }
861 }
862 return false;
863}
Craig Tillerea4a4f12017-03-13 13:36:52 -0700864
Craig Tiller11c17d42017-03-13 13:36:34 -0700865static void apply_final_configuration_locked(grpc_exec_ctx *exec_ctx,
866 grpc_call_element *elem) {
867 /* apply service-config level configuration to the call (now that we're
868 * certain it exists) */
869 call_data *calld = elem->call_data;
Craig Tiller3be7dd02017-04-03 14:30:03 -0700870 channel_data *chand = elem->channel_data;
Craig Tiller11c17d42017-03-13 13:36:34 -0700871 gpr_timespec per_method_deadline;
872 if (set_call_method_params_from_service_config_locked(exec_ctx, elem,
873 &per_method_deadline)) {
874 // If the deadline from the service config is shorter than the one
875 // from the client API, reset the deadline timer.
Craig Tiller3be7dd02017-04-03 14:30:03 -0700876 if (chand->deadline_checking_enabled &&
877 gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
Craig Tiller11c17d42017-03-13 13:36:34 -0700878 calld->deadline = per_method_deadline;
879 grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
880 }
881 }
882}
883
Craig Tillerbefafe62017-02-09 11:30:54 -0800884static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
885 grpc_error *error) {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700886 grpc_call_element *elem = arg;
887 call_data *calld = elem->call_data;
888 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700889 GPR_ASSERT(calld->creation_phase ==
890 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
Yuchen Zeng19656b12016-09-01 18:00:45 -0700891 grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
892 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700893 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
894 if (calld->connected_subchannel == NULL) {
895 gpr_atm_no_barrier_store(&calld->subchannel_call, 1);
ncteisen4b36a3d2017-03-13 19:08:06 -0700896 fail_locked(exec_ctx, calld,
897 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
898 "Failed to create subchannel", &error, 1));
Mark D. Roth72f6da82016-09-02 13:42:38 -0700899 } else if (GET_CALL(calld) == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700900 /* already cancelled before subchannel became ready */
ncteisen4b36a3d2017-03-13 19:08:06 -0700901 grpc_error *cancellation_error =
902 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
903 "Cancelled before creating subchannel", &error, 1);
David Garcia Quintas68a9e382016-12-13 10:50:40 -0800904 /* if due to deadline, attach the deadline exceeded status to the error */
905 if (gpr_time_cmp(calld->deadline, gpr_now(GPR_CLOCK_MONOTONIC)) < 0) {
906 cancellation_error =
907 grpc_error_set_int(cancellation_error, GRPC_ERROR_INT_GRPC_STATUS,
908 GRPC_STATUS_DEADLINE_EXCEEDED);
909 }
910 fail_locked(exec_ctx, calld, cancellation_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700911 } else {
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700912 /* Create call on subchannel. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700913 grpc_subchannel_call *subchannel_call = NULL;
Craig Tillerfb9d1122017-03-14 09:26:27 -0700914 const grpc_connected_subchannel_call_args call_args = {
Craig Tillerd426cac2017-03-13 12:30:45 -0700915 .pollent = calld->pollent,
916 .path = calld->path,
917 .start_time = calld->call_start_time,
918 .deadline = calld->deadline,
919 .arena = calld->arena};
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700920 grpc_error *new_error = grpc_connected_subchannel_create_call(
Craig Tillerd426cac2017-03-13 12:30:45 -0700921 exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700922 if (new_error != GRPC_ERROR_NONE) {
923 new_error = grpc_error_add_child(new_error, error);
924 subchannel_call = CANCELLED_CALL;
925 fail_locked(exec_ctx, calld, new_error);
926 }
927 gpr_atm_rel_store(&calld->subchannel_call,
928 (gpr_atm)(uintptr_t)subchannel_call);
929 retry_waiting_locked(exec_ctx, calld);
930 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700931 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
932}
933
934static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
935 call_data *calld = elem->call_data;
936 grpc_subchannel_call *subchannel_call = GET_CALL(calld);
937 if (subchannel_call == NULL || subchannel_call == CANCELLED_CALL) {
938 return NULL;
939 } else {
940 return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
941 }
942}
943
Craig Tiller577c9b22015-11-02 14:11:15 -0800944typedef struct {
945 grpc_metadata_batch *initial_metadata;
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800946 uint32_t initial_metadata_flags;
Craig Tillerb5585d42015-11-17 07:18:31 -0800947 grpc_connected_subchannel **connected_subchannel;
Craig Tiller577c9b22015-11-02 14:11:15 -0800948 grpc_closure *on_ready;
949 grpc_call_element *elem;
950 grpc_closure closure;
951} continue_picking_args;
952
Yuchen Zeng144ce652016-09-01 18:19:34 -0700953/** Return true if subchannel is available immediately (in which case on_ready
954 should not be called), or false otherwise (in which case on_ready should be
955 called when the subchannel is available). */
Craig Tillerbefafe62017-02-09 11:30:54 -0800956static bool pick_subchannel_locked(
957 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
958 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
959 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
960 grpc_error *error);
Craig Tiller577c9b22015-11-02 14:11:15 -0800961
Craig Tillerbefafe62017-02-09 11:30:54 -0800962static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg,
963 grpc_error *error) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800964 continue_picking_args *cpa = arg;
Craig Tiller0ede5452016-04-23 12:21:45 -0700965 if (cpa->connected_subchannel == NULL) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800966 /* cancelled, do nothing */
Craig Tiller804ff712016-05-05 16:25:40 -0700967 } else if (error != GRPC_ERROR_NONE) {
Craig Tiller91031da2016-12-28 15:44:25 -0800968 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error));
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700969 } else {
Craig Tillerbefafe62017-02-09 11:30:54 -0800970 if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata,
971 cpa->initial_metadata_flags,
972 cpa->connected_subchannel, cpa->on_ready,
973 GRPC_ERROR_NONE)) {
Craig Tiller91031da2016-12-28 15:44:25 -0800974 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700975 }
Craig Tiller577c9b22015-11-02 14:11:15 -0800976 }
977 gpr_free(cpa);
978}
979
Craig Tillerbefafe62017-02-09 11:30:54 -0800980static bool pick_subchannel_locked(
981 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
982 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
983 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
984 grpc_error *error) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700985 GPR_TIMER_BEGIN("pick_subchannel", 0);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700986
Craig Tiller577c9b22015-11-02 14:11:15 -0800987 channel_data *chand = elem->channel_data;
988 call_data *calld = elem->call_data;
989 continue_picking_args *cpa;
990 grpc_closure *closure;
991
Craig Tillerb5585d42015-11-17 07:18:31 -0800992 GPR_ASSERT(connected_subchannel);
Craig Tiller577c9b22015-11-02 14:11:15 -0800993
Craig Tiller577c9b22015-11-02 14:11:15 -0800994 if (initial_metadata == NULL) {
995 if (chand->lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800996 grpc_lb_policy_cancel_pick_locked(exec_ctx, chand->lb_policy,
997 connected_subchannel,
998 GRPC_ERROR_REF(error));
Craig Tiller577c9b22015-11-02 14:11:15 -0800999 }
1000 for (closure = chand->waiting_for_config_closures.head; closure != NULL;
Craig Tiller804ff712016-05-05 16:25:40 -07001001 closure = closure->next_data.next) {
Craig Tiller577c9b22015-11-02 14:11:15 -08001002 cpa = closure->cb_arg;
Craig Tillerb5585d42015-11-17 07:18:31 -08001003 if (cpa->connected_subchannel == connected_subchannel) {
1004 cpa->connected_subchannel = NULL;
ncteisen4b36a3d2017-03-13 19:08:06 -07001005 grpc_closure_sched(exec_ctx, cpa->on_ready,
1006 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
1007 "Pick cancelled", &error, 1));
Craig Tiller577c9b22015-11-02 14:11:15 -08001008 }
1009 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001010 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth697a1f62016-09-07 13:35:07 -07001011 GRPC_ERROR_UNREF(error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001012 return true;
Craig Tiller577c9b22015-11-02 14:11:15 -08001013 }
Mark D. Roth697a1f62016-09-07 13:35:07 -07001014 GPR_ASSERT(error == GRPC_ERROR_NONE);
Craig Tiller577c9b22015-11-02 14:11:15 -08001015 if (chand->lb_policy != NULL) {
Craig Tiller2e0788a2017-03-14 06:55:44 -07001016 apply_final_configuration_locked(exec_ctx, elem);
Craig Tiller86c0f8a2015-12-01 20:05:40 -08001017 grpc_lb_policy *lb_policy = chand->lb_policy;
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001018 GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel");
Mark D. Rothe40dd292016-10-05 14:58:37 -07001019 // If the application explicitly set wait_for_ready, use that.
1020 // Otherwise, if the service config specified a value for this
1021 // method, use that.
Mark D. Rothc1c38582016-10-11 11:03:27 -07001022 const bool wait_for_ready_set_from_api =
1023 initial_metadata_flags &
1024 GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
1025 const bool wait_for_ready_set_from_service_config =
Mark D. Roth95b627b2017-02-24 11:02:58 -08001026 calld->method_params != NULL &&
1027 calld->method_params->wait_for_ready != WAIT_FOR_READY_UNSET;
Mark D. Rothc1c38582016-10-11 11:03:27 -07001028 if (!wait_for_ready_set_from_api &&
1029 wait_for_ready_set_from_service_config) {
Mark D. Roth95b627b2017-02-24 11:02:58 -08001030 if (calld->method_params->wait_for_ready == WAIT_FOR_READY_TRUE) {
Mark D. Rothe40dd292016-10-05 14:58:37 -07001031 initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
1032 } else {
1033 initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
1034 }
1035 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001036 const grpc_lb_policy_pick_args inputs = {
Yuchen Zengac8bc422016-10-05 14:00:02 -07001037 initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem,
1038 gpr_inf_future(GPR_CLOCK_MONOTONIC)};
Craig Tiller2400bf52017-02-09 16:25:19 -08001039 const bool result = grpc_lb_policy_pick_locked(
Mark D. Roth55f25b62016-10-12 14:55:20 -07001040 exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, on_ready);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001041 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel");
1042 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth9dab7d52016-10-07 07:48:03 -07001043 return result;
Craig Tiller577c9b22015-11-02 14:11:15 -08001044 }
1045 if (chand->resolver != NULL && !chand->started_resolving) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001046 chand->started_resolving = true;
Craig Tiller906e3bc2015-11-24 07:31:31 -08001047 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -08001048 grpc_resolver_next_locked(exec_ctx, chand->resolver,
1049 &chand->resolver_result,
1050 &chand->on_resolver_result_changed);
Craig Tiller577c9b22015-11-02 14:11:15 -08001051 }
Craig Tiller0eab6972016-04-23 12:59:57 -07001052 if (chand->resolver != NULL) {
1053 cpa = gpr_malloc(sizeof(*cpa));
1054 cpa->initial_metadata = initial_metadata;
1055 cpa->initial_metadata_flags = initial_metadata_flags;
1056 cpa->connected_subchannel = connected_subchannel;
1057 cpa->on_ready = on_ready;
1058 cpa->elem = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -08001059 grpc_closure_init(&cpa->closure, continue_picking_locked, cpa,
1060 grpc_combiner_scheduler(chand->combiner, true));
Craig Tiller804ff712016-05-05 16:25:40 -07001061 grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
1062 GRPC_ERROR_NONE);
Craig Tiller0eab6972016-04-23 12:59:57 -07001063 } else {
ncteisen4b36a3d2017-03-13 19:08:06 -07001064 grpc_closure_sched(exec_ctx, on_ready,
1065 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected"));
Craig Tiller0eab6972016-04-23 12:59:57 -07001066 }
Craig Tillerbfc9adc2016-06-27 13:16:22 -07001067
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001068 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001069 return false;
Craig Tiller577c9b22015-11-02 14:11:15 -08001070}
1071
Craig Tillera8610c02017-02-14 10:05:11 -08001072static void start_transport_stream_op_locked_inner(grpc_exec_ctx *exec_ctx,
1073 grpc_transport_stream_op *op,
1074 grpc_call_element *elem) {
Yuchen Zeng19656b12016-09-01 18:00:45 -07001075 channel_data *chand = elem->channel_data;
Craig Tillera11bfc82017-02-14 09:56:33 -08001076 call_data *calld = elem->call_data;
Craig Tillerbefafe62017-02-09 11:30:54 -08001077 grpc_subchannel_call *call;
1078
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001079 /* need to recheck that another thread hasn't set the call */
1080 call = GET_CALL(calld);
1081 if (call == CANCELLED_CALL) {
Mark D. Rothf28763c2016-09-14 15:18:40 -07001082 grpc_transport_stream_op_finish_with_failure(
1083 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -08001084 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001085 return;
1086 }
1087 if (call != NULL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001088 grpc_subchannel_call_process_op(exec_ctx, call, op);
Craig Tillera11bfc82017-02-14 09:56:33 -08001089 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001090 return;
1091 }
1092 /* if this is a cancellation, then we can raise our cancelled flag */
1093 if (op->cancel_error != GRPC_ERROR_NONE) {
1094 if (!gpr_atm_rel_cas(&calld->subchannel_call, 0,
1095 (gpr_atm)(uintptr_t)CANCELLED_CALL)) {
Craig Tillera11bfc82017-02-14 09:56:33 -08001096 /* recurse to retry */
Craig Tillera8610c02017-02-14 10:05:11 -08001097 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001098 /* early out */
1099 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001100 } else {
Craig Tillerbe9691a2017-02-14 10:00:42 -08001101 /* Stash a copy of cancel_error in our call data, so that we can use
1102 it for subsequent operations. This ensures that if the call is
1103 cancelled before any ops are passed down (e.g., if the deadline
1104 is in the past when the call starts), we can return the right
1105 error to the caller when the first op does get passed down. */
Mark D. Rothf28763c2016-09-14 15:18:40 -07001106 calld->cancel_error = GRPC_ERROR_REF(op->cancel_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001107 switch (calld->creation_phase) {
1108 case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
1109 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error));
1110 break;
1111 case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
Craig Tillerbefafe62017-02-09 11:30:54 -08001112 pick_subchannel_locked(exec_ctx, elem, NULL, 0,
1113 &calld->connected_subchannel, NULL,
1114 GRPC_ERROR_REF(op->cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001115 break;
1116 }
Mark D. Roth72f6da82016-09-02 13:42:38 -07001117 grpc_transport_stream_op_finish_with_failure(
1118 exec_ctx, op, GRPC_ERROR_REF(op->cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -08001119 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001120 return;
1121 }
1122 }
1123 /* if we don't have a subchannel, try to get one */
1124 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
1125 calld->connected_subchannel == NULL &&
1126 op->send_initial_metadata != NULL) {
1127 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
Craig Tillerbefafe62017-02-09 11:30:54 -08001128 grpc_closure_init(&calld->next_step, subchannel_ready_locked, elem,
1129 grpc_combiner_scheduler(chand->combiner, true));
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001130 GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
Yuchen Zeng144ce652016-09-01 18:19:34 -07001131 /* If a subchannel is not available immediately, the polling entity from
1132 call_data should be provided to channel_data's interested_parties, so
1133 that IO of the lb_policy and resolver could be done under it. */
Craig Tillerbefafe62017-02-09 11:30:54 -08001134 if (pick_subchannel_locked(exec_ctx, elem, op->send_initial_metadata,
1135 op->send_initial_metadata_flags,
1136 &calld->connected_subchannel, &calld->next_step,
1137 GRPC_ERROR_NONE)) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001138 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
1139 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
Yuchen Zeng19656b12016-09-01 18:00:45 -07001140 } else {
Yuchen Zeng19656b12016-09-01 18:00:45 -07001141 grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
1142 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001143 }
1144 }
1145 /* if we've got a subchannel, then let's ask it to create a call */
1146 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
1147 calld->connected_subchannel != NULL) {
1148 grpc_subchannel_call *subchannel_call = NULL;
Craig Tillerfb9d1122017-03-14 09:26:27 -07001149 const grpc_connected_subchannel_call_args call_args = {
Craig Tillerd426cac2017-03-13 12:30:45 -07001150 .pollent = calld->pollent,
1151 .path = calld->path,
1152 .start_time = calld->call_start_time,
1153 .deadline = calld->deadline,
1154 .arena = calld->arena};
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001155 grpc_error *error = grpc_connected_subchannel_create_call(
Craig Tillerd426cac2017-03-13 12:30:45 -07001156 exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001157 if (error != GRPC_ERROR_NONE) {
1158 subchannel_call = CANCELLED_CALL;
1159 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
1160 grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
1161 }
1162 gpr_atm_rel_store(&calld->subchannel_call,
1163 (gpr_atm)(uintptr_t)subchannel_call);
1164 retry_waiting_locked(exec_ctx, calld);
Craig Tillera11bfc82017-02-14 09:56:33 -08001165 /* recurse to retry */
Craig Tillera8610c02017-02-14 10:05:11 -08001166 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001167 /* early out */
1168 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001169 }
1170 /* nothing to be done but wait */
1171 add_waiting_locked(calld, op);
Craig Tillera11bfc82017-02-14 09:56:33 -08001172}
1173
Mark D. Rothde144102017-03-15 10:11:03 -07001174static void on_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001175 grpc_call_element *elem = arg;
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001176 call_data *calld = elem->call_data;
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -07001177 if (calld->retry_throttle_data != NULL) {
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001178 if (error == GRPC_ERROR_NONE) {
1179 grpc_server_retry_throttle_data_record_success(
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -07001180 calld->retry_throttle_data);
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001181 } else {
1182 // TODO(roth): In a subsequent PR, check the return value here and
Mark D. Rothb3322562017-02-23 14:38:02 -08001183 // decide whether or not to retry. Note that we should only
1184 // record failures whose statuses match the configured retryable
1185 // or non-fatal status codes.
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001186 grpc_server_retry_throttle_data_record_failure(
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -07001187 calld->retry_throttle_data);
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001188 }
1189 }
Mark D. Roth95039b52017-02-24 07:59:45 -08001190 grpc_closure_run(exec_ctx, calld->original_on_complete,
1191 GRPC_ERROR_REF(error));
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001192}
1193
Mark D. Roth95b627b2017-02-24 11:02:58 -08001194static void start_transport_stream_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
Mark D. Roth722de8d2017-02-27 10:50:44 -08001195 grpc_error *error_ignored) {
Mark D. Roth95b627b2017-02-24 11:02:58 -08001196 GPR_TIMER_BEGIN("start_transport_stream_op_locked", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001197
1198 grpc_transport_stream_op *op = arg;
1199 grpc_call_element *elem = op->handler_private.args[0];
1200 call_data *calld = elem->call_data;
1201
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001202 if (op->recv_trailing_metadata != NULL) {
1203 GPR_ASSERT(op->on_complete != NULL);
1204 calld->original_on_complete = op->on_complete;
Mark D. Rothde144102017-03-15 10:11:03 -07001205 grpc_closure_init(&calld->on_complete, on_complete, elem,
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -07001206 grpc_schedule_on_exec_ctx);
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001207 op->on_complete = &calld->on_complete;
1208 }
1209
Craig Tillera8610c02017-02-14 10:05:11 -08001210 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001211
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001212 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
1213 "start_transport_stream_op");
Mark D. Roth95b627b2017-02-24 11:02:58 -08001214 GPR_TIMER_END("start_transport_stream_op_locked", 0);
Craig Tillerbefafe62017-02-09 11:30:54 -08001215}
1216
Craig Tillerbe9691a2017-02-14 10:00:42 -08001217/* The logic here is fairly complicated, due to (a) the fact that we
1218 need to handle the case where we receive the send op before the
1219 initial metadata op, and (b) the need for efficiency, especially in
1220 the streaming case.
1221
1222 We use double-checked locking to initially see if initialization has been
1223 performed. If it has not, we acquire the combiner and perform initialization.
1224 If it has, we proceed on the fast path. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001225static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
1226 grpc_call_element *elem,
1227 grpc_transport_stream_op *op) {
1228 call_data *calld = elem->call_data;
1229 channel_data *chand = elem->channel_data;
1230 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
Craig Tiller3be7dd02017-04-03 14:30:03 -07001231 if (chand->deadline_checking_enabled) {
1232 grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op);
1233 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001234 /* try to (atomically) get the call */
1235 grpc_subchannel_call *call = GET_CALL(calld);
1236 GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
1237 if (call == CANCELLED_CALL) {
1238 grpc_transport_stream_op_finish_with_failure(
1239 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
1240 GPR_TIMER_END("cc_start_transport_stream_op", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001241 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001242 return;
1243 }
1244 if (call != NULL) {
1245 grpc_subchannel_call_process_op(exec_ctx, call, op);
1246 GPR_TIMER_END("cc_start_transport_stream_op", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001247 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001248 return;
1249 }
1250 /* we failed; lock and figure out what to do */
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001251 GRPC_CALL_STACK_REF(calld->owning_call, "start_transport_stream_op");
Craig Tiller4a84bdd2017-02-14 09:48:41 -08001252 op->handler_private.args[0] = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -08001253 grpc_closure_sched(
1254 exec_ctx,
Craig Tiller4a84bdd2017-02-14 09:48:41 -08001255 grpc_closure_init(&op->handler_private.closure,
Mark D. Roth95b627b2017-02-24 11:02:58 -08001256 start_transport_stream_op_locked, op,
Craig Tillerbefafe62017-02-09 11:30:54 -08001257 grpc_combiner_scheduler(chand->combiner, false)),
1258 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001259 GPR_TIMER_END("cc_start_transport_stream_op", 0);
1260}
1261
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001262/* Constructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001263static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
1264 grpc_call_element *elem,
Craig Tillerc52ba3a2017-02-15 22:57:43 -08001265 const grpc_call_element_args *args) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001266 call_data *calld = elem->call_data;
Craig Tiller3be7dd02017-04-03 14:30:03 -07001267 channel_data *chand = elem->channel_data;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001268 // Initialize data members.
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001269 calld->path = grpc_slice_ref_internal(args->path);
Mark D. Rothff08f332016-10-14 13:01:01 -07001270 calld->call_start_time = args->start_time;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001271 calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001272 calld->owning_call = args->call_stack;
Craig Tillerd426cac2017-03-13 12:30:45 -07001273 calld->arena = args->arena;
Craig Tiller3be7dd02017-04-03 14:30:03 -07001274 if (chand->deadline_checking_enabled) {
1275 grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
1276 grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
1277 }
Mark D. Roth0badbe82016-06-23 10:15:12 -07001278 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001279}
1280
1281/* Destructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001282static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
1283 grpc_call_element *elem,
1284 const grpc_call_final_info *final_info,
Craig Tillerd426cac2017-03-13 12:30:45 -07001285 grpc_closure *then_schedule_closure) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001286 call_data *calld = elem->call_data;
Craig Tiller3be7dd02017-04-03 14:30:03 -07001287 channel_data *chand = elem->channel_data;
1288 if (chand->deadline_checking_enabled) {
1289 grpc_deadline_state_destroy(exec_ctx, elem);
1290 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001291 grpc_slice_unref_internal(exec_ctx, calld->path);
Mark D. Roth95b627b2017-02-24 11:02:58 -08001292 if (calld->method_params != NULL) {
1293 method_parameters_unref(calld->method_params);
1294 }
Mark D. Rothf28763c2016-09-14 15:18:40 -07001295 GRPC_ERROR_UNREF(calld->cancel_error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001296 grpc_subchannel_call *call = GET_CALL(calld);
1297 if (call != NULL && call != CANCELLED_CALL) {
Craig Tillerd426cac2017-03-13 12:30:45 -07001298 grpc_subchannel_call_set_cleanup_closure(call, then_schedule_closure);
1299 then_schedule_closure = NULL;
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001300 GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
1301 }
1302 GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001303 GPR_ASSERT(calld->waiting_ops_count == 0);
Craig Tiller693d3942016-10-27 16:51:25 -07001304 if (calld->connected_subchannel != NULL) {
1305 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel,
1306 "picked");
1307 }
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001308 gpr_free(calld->waiting_ops);
Craig Tillerd426cac2017-03-13 12:30:45 -07001309 grpc_closure_sched(exec_ctx, then_schedule_closure, GRPC_ERROR_NONE);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001310}
1311
David Garcia Quintasf72eb972016-05-03 18:28:09 -07001312static void cc_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
1313 grpc_call_element *elem,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001314 grpc_polling_entity *pollent) {
Craig Tiller577c9b22015-11-02 14:11:15 -08001315 call_data *calld = elem->call_data;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001316 calld->pollent = pollent;
Craig Tiller577c9b22015-11-02 14:11:15 -08001317}
1318
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001319/*************************************************************************
1320 * EXPORTED SYMBOLS
1321 */
1322
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001323const grpc_channel_filter grpc_client_channel_filter = {
Craig Tillerf40df232016-03-25 13:38:14 -07001324 cc_start_transport_stream_op,
1325 cc_start_transport_op,
1326 sizeof(call_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001327 cc_init_call_elem,
David Garcia Quintas4afce7e2016-04-18 16:25:17 -07001328 cc_set_pollset_or_pollset_set,
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001329 cc_destroy_call_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001330 sizeof(channel_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001331 cc_init_channel_elem,
1332 cc_destroy_channel_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001333 cc_get_peer,
Mark D. Rothb2d24882016-10-27 15:44:07 -07001334 cc_get_channel_info,
Craig Tillerf40df232016-03-25 13:38:14 -07001335 "client-channel",
Craig Tiller87d5b192015-04-16 14:37:57 -07001336};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001337
Craig Tiller613dafa2017-02-09 12:00:43 -08001338static void try_to_connect_locked(grpc_exec_ctx *exec_ctx, void *arg,
1339 grpc_error *error_ignored) {
1340 channel_data *chand = arg;
1341 if (chand->lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -08001342 grpc_lb_policy_exit_idle_locked(exec_ctx, chand->lb_policy);
Craig Tiller613dafa2017-02-09 12:00:43 -08001343 } else {
1344 chand->exit_idle_when_lb_policy_arrives = true;
1345 if (!chand->started_resolving && chand->resolver != NULL) {
1346 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
1347 chand->started_resolving = true;
Craig Tiller972470b2017-02-09 15:05:36 -08001348 grpc_resolver_next_locked(exec_ctx, chand->resolver,
1349 &chand->resolver_result,
1350 &chand->on_resolver_result_changed);
Craig Tiller613dafa2017-02-09 12:00:43 -08001351 }
1352 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001353 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001354}
1355
Craig Tillera82950e2015-09-22 12:33:20 -07001356grpc_connectivity_state grpc_client_channel_check_connectivity_state(
1357 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001358 channel_data *chand = elem->channel_data;
Craig Tillera8610c02017-02-14 10:05:11 -08001359 grpc_connectivity_state out =
1360 grpc_connectivity_state_check(&chand->state_tracker);
Craig Tillera82950e2015-09-22 12:33:20 -07001361 if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001362 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001363 grpc_closure_sched(
1364 exec_ctx,
1365 grpc_closure_create(try_to_connect_locked, chand,
1366 grpc_combiner_scheduler(chand->combiner, false)),
1367 GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -07001368 }
Craig Tiller48cb07c2015-07-15 16:16:15 -07001369 return out;
1370}
1371
Craig Tiller86c99582015-11-25 15:22:26 -08001372typedef struct {
1373 channel_data *chand;
1374 grpc_pollset *pollset;
1375 grpc_closure *on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001376 grpc_connectivity_state *state;
Craig Tiller86c99582015-11-25 15:22:26 -08001377 grpc_closure my_closure;
1378} external_connectivity_watcher;
1379
Craig Tiller1d881fb2015-12-01 07:39:04 -08001380static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -07001381 grpc_error *error) {
Craig Tiller86c99582015-11-25 15:22:26 -08001382 external_connectivity_watcher *w = arg;
1383 grpc_closure *follow_up = w->on_complete;
Craig Tiller69b093b2016-02-25 19:04:07 -08001384 grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
Craig Tiller1d881fb2015-12-01 07:39:04 -08001385 w->pollset);
1386 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
1387 "external_connectivity_watcher");
Craig Tiller86c99582015-11-25 15:22:26 -08001388 gpr_free(w);
Craig Tiller613dafa2017-02-09 12:00:43 -08001389 grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
1390}
1391
Craig Tillera8610c02017-02-14 10:05:11 -08001392static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg,
1393 grpc_error *error_ignored) {
Craig Tiller613dafa2017-02-09 12:00:43 -08001394 external_connectivity_watcher *w = arg;
1395 grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
1396 grpc_schedule_on_exec_ctx);
1397 grpc_connectivity_state_notify_on_state_change(
1398 exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
Craig Tiller86c99582015-11-25 15:22:26 -08001399}
1400
Craig Tillera82950e2015-09-22 12:33:20 -07001401void grpc_client_channel_watch_connectivity_state(
Craig Tiller906e3bc2015-11-24 07:31:31 -08001402 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
Craig Tillera82950e2015-09-22 12:33:20 -07001403 grpc_connectivity_state *state, grpc_closure *on_complete) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001404 channel_data *chand = elem->channel_data;
Craig Tiller86c99582015-11-25 15:22:26 -08001405 external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
1406 w->chand = chand;
1407 w->pollset = pollset;
1408 w->on_complete = on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001409 w->state = state;
Craig Tiller69b093b2016-02-25 19:04:07 -08001410 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
Craig Tiller1d881fb2015-12-01 07:39:04 -08001411 GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
1412 "external_connectivity_watcher");
Craig Tiller613dafa2017-02-09 12:00:43 -08001413 grpc_closure_sched(
1414 exec_ctx,
Craig Tillera8610c02017-02-14 10:05:11 -08001415 grpc_closure_init(&w->my_closure, watch_connectivity_state_locked, w,
Craig Tiller613dafa2017-02-09 12:00:43 -08001416 grpc_combiner_scheduler(chand->combiner, true)),
1417 GRPC_ERROR_NONE);
Craig Tiller48cb07c2015-07-15 16:16:15 -07001418}