blob: d01704f792c6899548568f3e91c7632e7622e136 [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. Rothd6d192d2017-02-23 08:58:42 -080050#include "src/core/ext/client_channel/retry_throttle.h"
Mark D. Roth2137cd82016-09-14 09:04:00 -070051#include "src/core/ext/client_channel/subchannel.h"
Craig Tiller9533d042016-03-25 17:11:06 -070052#include "src/core/lib/channel/channel_args.h"
53#include "src/core/lib/channel/connected_channel.h"
Mark D. Roth72f6da82016-09-02 13:42:38 -070054#include "src/core/lib/channel/deadline_filter.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;
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700186 /** client channel factory */
187 grpc_client_channel_factory *client_channel_factory;
Craig Tillerf5f17122015-06-25 08:47:26 -0700188
Craig Tillerbefafe62017-02-09 11:30:54 -0800189 /** combiner protecting all variables below in this data structure */
190 grpc_combiner *combiner;
Mark D. Roth046cf762016-09-26 11:13:51 -0700191 /** currently active load balancer */
Craig Tillerf5f17122015-06-25 08:47:26 -0700192 grpc_lb_policy *lb_policy;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800193 /** retry throttle data */
194 grpc_server_retry_throttle_data *retry_throttle_data;
Mark D. Roth9d480942016-10-19 14:18:05 -0700195 /** maps method names to method_parameters structs */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800196 grpc_slice_hash_table *method_params_table;
Mark D. Roth046cf762016-09-26 11:13:51 -0700197 /** incoming resolver result - set by resolver.next() */
Mark D. Rothaf842452016-10-21 15:05:15 -0700198 grpc_channel_args *resolver_result;
Craig Tiller3f475422015-06-25 10:43:05 -0700199 /** a list of closures that are all waiting for config to come in */
Craig Tillerd9ccbbf2015-09-22 09:30:00 -0700200 grpc_closure_list waiting_for_config_closures;
Craig Tiller3f475422015-06-25 10:43:05 -0700201 /** resolver callback */
Mark D. Rothff4df062016-08-22 15:02:49 -0700202 grpc_closure on_resolver_result_changed;
Craig Tiller3f475422015-06-25 10:43:05 -0700203 /** connectivity state being tracked */
Craig Tillerca3e9d32015-06-27 18:37:27 -0700204 grpc_connectivity_state_tracker state_tracker;
Craig Tiller48cb07c2015-07-15 16:16:15 -0700205 /** when an lb_policy arrives, should we try to exit idle */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700206 bool exit_idle_when_lb_policy_arrives;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800207 /** owning stack */
208 grpc_channel_stack *owning_stack;
Craig Tiller69b093b2016-02-25 19:04:07 -0800209 /** interested parties (owned) */
210 grpc_pollset_set *interested_parties;
Craig Tiller613dafa2017-02-09 12:00:43 -0800211
212 /* the following properties are guarded by a mutex since API's require them
Craig Tiller46dd7902017-02-23 09:42:16 -0800213 to be instantaneously available */
Craig Tiller613dafa2017-02-09 12:00:43 -0800214 gpr_mu info_mu;
215 char *info_lb_policy_name;
216 /** service config in JSON form */
217 char *info_service_config_json;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800218} channel_data;
219
Craig Tillerd6c98df2015-08-18 09:33:44 -0700220/** We create one watcher for each new lb_policy that is returned from a
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700221 resolver, to watch for state changes from the lb_policy. When a state
222 change is seen, we update the channel, and create a new watcher. */
Craig Tillera82950e2015-09-22 12:33:20 -0700223typedef struct {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700224 channel_data *chand;
Craig Tiller33825112015-09-18 07:44:19 -0700225 grpc_closure on_changed;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700226 grpc_connectivity_state state;
227 grpc_lb_policy *lb_policy;
228} lb_policy_connectivity_watcher;
229
Craig Tiller2400bf52017-02-09 16:25:19 -0800230static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
231 grpc_lb_policy *lb_policy,
232 grpc_connectivity_state current_state);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700233
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800234static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
235 channel_data *chand,
236 grpc_connectivity_state state,
Craig Tiller804ff712016-05-05 16:25:40 -0700237 grpc_error *error,
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800238 const char *reason) {
239 if ((state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
Craig Tiller48ed92e2016-06-02 11:07:12 -0700240 state == GRPC_CHANNEL_SHUTDOWN) &&
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800241 chand->lb_policy != NULL) {
Mark D. Roth59c9f902016-09-28 13:33:21 -0700242 /* cancel picks with wait_for_ready=false */
Craig Tiller2400bf52017-02-09 16:25:19 -0800243 grpc_lb_policy_cancel_picks_locked(
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800244 exec_ctx, chand->lb_policy,
Mark D. Roth59c9f902016-09-28 13:33:21 -0700245 /* mask= */ GRPC_INITIAL_METADATA_WAIT_FOR_READY,
Mark D. Roth58f52b72016-09-09 13:55:18 -0700246 /* check= */ 0, GRPC_ERROR_REF(error));
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800247 }
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700248 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, error,
249 reason);
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800250}
251
Craig Tiller804ff712016-05-05 16:25:40 -0700252static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
Craig Tillerbefafe62017-02-09 11:30:54 -0800253 void *arg, grpc_error *error) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700254 lb_policy_connectivity_watcher *w = arg;
Craig Tiller5d44c062015-07-01 08:55:28 -0700255 grpc_connectivity_state publish_state = w->state;
Craig Tillerc5de8352017-02-09 14:08:05 -0800256 /* check if the notification is for the latest policy */
257 if (w->lb_policy == w->chand->lb_policy) {
258 if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
259 publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Craig Tiller972470b2017-02-09 15:05:36 -0800260 grpc_resolver_channel_saw_error_locked(exec_ctx, w->chand->resolver);
Craig Tillerc5de8352017-02-09 14:08:05 -0800261 GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
262 w->chand->lb_policy = NULL;
263 }
264 set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
265 GRPC_ERROR_REF(error), "lb_changed");
266 if (w->state != GRPC_CHANNEL_SHUTDOWN) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800267 watch_lb_policy_locked(exec_ctx, w->chand, w->lb_policy, w->state);
Craig Tillerc5de8352017-02-09 14:08:05 -0800268 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800269 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700270
Craig Tiller906e3bc2015-11-24 07:31:31 -0800271 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
Craig Tillera82950e2015-09-22 12:33:20 -0700272 gpr_free(w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700273}
274
Craig Tiller2400bf52017-02-09 16:25:19 -0800275static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
276 grpc_lb_policy *lb_policy,
277 grpc_connectivity_state current_state) {
Craig Tillera82950e2015-09-22 12:33:20 -0700278 lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
Craig Tiller906e3bc2015-11-24 07:31:31 -0800279 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700280
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700281 w->chand = chand;
Craig Tillerbefafe62017-02-09 11:30:54 -0800282 grpc_closure_init(&w->on_changed, on_lb_policy_state_changed_locked, w,
283 grpc_combiner_scheduler(chand->combiner, false));
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700284 w->state = current_state;
285 w->lb_policy = lb_policy;
Craig Tiller2400bf52017-02-09 16:25:19 -0800286 grpc_lb_policy_notify_on_state_change_locked(exec_ctx, lb_policy, &w->state,
287 &w->on_changed);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700288}
289
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800290typedef struct {
291 char *server_name;
292 grpc_server_retry_throttle_data *retry_throttle_data;
293} service_config_parsing_state;
294
295static void parse_retry_throttle_params(const grpc_json *field, void *arg) {
296 service_config_parsing_state *parsing_state = arg;
297 if (strcmp(field->key, "retryThrottling") == 0) {
298 if (parsing_state->retry_throttle_data != NULL) return; // Duplicate.
299 if (field->type != GRPC_JSON_OBJECT) return;
300 int max_milli_tokens = 0;
301 int milli_token_ratio = 0;
302 for (grpc_json *sub_field = field->child; sub_field != NULL;
303 sub_field = sub_field->next) {
Mark D. Rothb3322562017-02-23 14:38:02 -0800304 if (sub_field->key == NULL) return;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800305 if (strcmp(sub_field->key, "maxTokens") == 0) {
306 if (max_milli_tokens != 0) return; // Duplicate.
307 if (sub_field->type != GRPC_JSON_NUMBER) return;
308 max_milli_tokens = gpr_parse_nonnegative_int(sub_field->value);
309 if (max_milli_tokens == -1) return;
310 max_milli_tokens *= 1000;
311 } else if (strcmp(sub_field->key, "tokenRatio") == 0) {
312 if (milli_token_ratio != 0) return; // Duplicate.
313 if (sub_field->type != GRPC_JSON_NUMBER) return;
314 // We support up to 3 decimal digits.
315 size_t whole_len = strlen(sub_field->value);
316 uint32_t multiplier = 1;
317 uint32_t decimal_value = 0;
318 const char *decimal_point = strchr(sub_field->value, '.');
319 if (decimal_point != NULL) {
320 whole_len = (size_t)(decimal_point - sub_field->value);
321 multiplier = 1000;
322 size_t decimal_len = strlen(decimal_point + 1);
323 if (decimal_len > 3) decimal_len = 3;
324 if (!gpr_parse_bytes_to_uint32(decimal_point + 1, decimal_len,
325 &decimal_value)) {
326 return;
327 }
328 uint32_t decimal_multiplier = 1;
329 for (size_t i = 0; i < (3 - decimal_len); ++i) {
330 decimal_multiplier *= 10;
331 }
332 decimal_value *= decimal_multiplier;
333 }
334 uint32_t whole_value;
335 if (!gpr_parse_bytes_to_uint32(sub_field->value, whole_len,
336 &whole_value)) {
337 return;
338 }
339 milli_token_ratio = (int)((whole_value * multiplier) + decimal_value);
Mark D. Rothb3322562017-02-23 14:38:02 -0800340 if (milli_token_ratio <= 0) return;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800341 }
342 }
343 parsing_state->retry_throttle_data =
344 grpc_retry_throttle_map_get_data_for_server(
345 parsing_state->server_name, max_milli_tokens, milli_token_ratio);
346 }
347}
348
Craig Tillerbefafe62017-02-09 11:30:54 -0800349static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
350 void *arg, grpc_error *error) {
Craig Tiller3f475422015-06-25 10:43:05 -0700351 channel_data *chand = arg;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700352 char *lb_policy_name = NULL;
Craig Tiller3f475422015-06-25 10:43:05 -0700353 grpc_lb_policy *lb_policy = NULL;
354 grpc_lb_policy *old_lb_policy;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800355 grpc_slice_hash_table *method_params_table = NULL;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700356 grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700357 bool exit_idle = false;
ncteisen4b36a3d2017-03-13 19:08:06 -0700358 grpc_error *state_error =
359 GRPC_ERROR_CREATE_FROM_STATIC_STRING("No load balancing policy");
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800360 char *service_config_json = NULL;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800361 service_config_parsing_state parsing_state;
362 memset(&parsing_state, 0, sizeof(parsing_state));
Craig Tiller3f475422015-06-25 10:43:05 -0700363
Mark D. Roth046cf762016-09-26 11:13:51 -0700364 if (chand->resolver_result != NULL) {
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700365 // Find LB policy name.
Mark D. Rothaf842452016-10-21 15:05:15 -0700366 const grpc_arg *channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700367 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_POLICY_NAME);
Mark D. Rothaf842452016-10-21 15:05:15 -0700368 if (channel_arg != NULL) {
369 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
370 lb_policy_name = channel_arg->value.string;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700371 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700372 // Special case: If all of the addresses are balancer addresses,
373 // assume that we should use the grpclb policy, regardless of what the
374 // resolver actually specified.
Mark D. Rothaf842452016-10-21 15:05:15 -0700375 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700376 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES);
Mark D. Rothaf842452016-10-21 15:05:15 -0700377 if (channel_arg != NULL) {
378 GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
Mark D. Roth557c9902016-10-24 11:12:05 -0700379 grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
Mark D. Rothaf842452016-10-21 15:05:15 -0700380 bool found_backend_address = false;
381 for (size_t i = 0; i < addresses->num_addresses; ++i) {
382 if (!addresses->addresses[i].is_balancer) {
383 found_backend_address = true;
384 break;
385 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700386 }
Mark D. Rothaf842452016-10-21 15:05:15 -0700387 if (!found_backend_address) {
388 if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) {
389 gpr_log(GPR_INFO,
390 "resolver requested LB policy %s but provided only balancer "
391 "addresses, no backend addresses -- forcing use of grpclb LB "
392 "policy",
Mark D. Roth5f40e5d2016-10-24 13:09:05 -0700393 lb_policy_name);
Mark D. Rothaf842452016-10-21 15:05:15 -0700394 }
395 lb_policy_name = "grpclb";
Mark D. Roth88405f72016-10-03 08:24:52 -0700396 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700397 }
398 // Use pick_first if nothing was specified and we didn't select grpclb
399 // above.
400 if (lb_policy_name == NULL) lb_policy_name = "pick_first";
Mark D. Roth41124992016-11-03 11:22:20 -0700401 // Instantiate LB policy.
402 grpc_lb_policy_args lb_policy_args;
403 lb_policy_args.args = chand->resolver_result;
404 lb_policy_args.client_channel_factory = chand->client_channel_factory;
Craig Tiller2400bf52017-02-09 16:25:19 -0800405 lb_policy_args.combiner = chand->combiner;
Mark D. Roth88405f72016-10-03 08:24:52 -0700406 lb_policy =
407 grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700408 if (lb_policy != NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -0700409 GRPC_LB_POLICY_REF(lb_policy, "config_change");
Craig Tillerf707d622016-05-06 14:26:12 -0700410 GRPC_ERROR_UNREF(state_error);
Craig Tiller2400bf52017-02-09 16:25:19 -0800411 state = grpc_lb_policy_check_connectivity_locked(exec_ctx, lb_policy,
412 &state_error);
Craig Tiller45724b32015-09-22 10:42:19 -0700413 }
Mark D. Roth41124992016-11-03 11:22:20 -0700414 // Find service config.
Mark D. Rothaf842452016-10-21 15:05:15 -0700415 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700416 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVICE_CONFIG);
Mark D. Roth046cf762016-09-26 11:13:51 -0700417 if (channel_arg != NULL) {
Mark D. Roth9ec28af2016-11-03 12:32:39 -0700418 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800419 service_config_json = gpr_strdup(channel_arg->value.string);
Mark D. Roth70a1abd2016-11-04 09:26:37 -0700420 grpc_service_config *service_config =
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800421 grpc_service_config_create(service_config_json);
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700422 if (service_config != NULL) {
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800423 channel_arg =
424 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVER_URI);
425 GPR_ASSERT(channel_arg != NULL);
426 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -0700427 grpc_uri *uri =
428 grpc_uri_parse(exec_ctx, channel_arg->value.string, true);
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800429 GPR_ASSERT(uri->path[0] != '\0');
430 parsing_state.server_name =
431 uri->path[0] == '/' ? uri->path + 1 : uri->path;
432 grpc_service_config_parse_global_params(
433 service_config, parse_retry_throttle_params, &parsing_state);
434 parsing_state.server_name = NULL;
435 grpc_uri_destroy(uri);
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700436 method_params_table = grpc_service_config_create_method_config_table(
Craig Tillerb28c7e82016-11-18 10:29:04 -0800437 exec_ctx, service_config, method_parameters_create_from_json,
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700438 &method_parameters_vtable);
439 grpc_service_config_destroy(service_config);
440 }
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700441 }
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700442 // Before we clean up, save a copy of lb_policy_name, since it might
443 // be pointing to data inside chand->resolver_result.
444 // The copy will be saved in chand->lb_policy_name below.
445 lb_policy_name = gpr_strdup(lb_policy_name);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800446 grpc_channel_args_destroy(exec_ctx, chand->resolver_result);
Mark D. Roth046cf762016-09-26 11:13:51 -0700447 chand->resolver_result = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700448 }
449
Craig Tiller86c99582015-11-25 15:22:26 -0800450 if (lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800451 grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties,
452 chand->interested_parties);
Craig Tiller86c99582015-11-25 15:22:26 -0800453 }
454
Craig Tiller613dafa2017-02-09 12:00:43 -0800455 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700456 if (lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800457 gpr_free(chand->info_lb_policy_name);
458 chand->info_lb_policy_name = lb_policy_name;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700459 }
Craig Tiller3f475422015-06-25 10:43:05 -0700460 old_lb_policy = chand->lb_policy;
461 chand->lb_policy = lb_policy;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800462 if (service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800463 gpr_free(chand->info_service_config_json);
464 chand->info_service_config_json = service_config_json;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800465 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800466 gpr_mu_unlock(&chand->info_mu);
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800467
468 if (chand->retry_throttle_data != NULL) {
469 grpc_server_retry_throttle_data_unref(chand->retry_throttle_data);
470 }
471 chand->retry_throttle_data = parsing_state.retry_throttle_data;
Mark D. Roth9d480942016-10-19 14:18:05 -0700472 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800473 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth046cf762016-09-26 11:13:51 -0700474 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700475 chand->method_params_table = method_params_table;
Craig Tiller0ede5452016-04-23 12:21:45 -0700476 if (lb_policy != NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -0800477 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller0ede5452016-04-23 12:21:45 -0700478 } else if (chand->resolver == NULL /* disconnected */) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700479 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
480 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
481 "Channel disconnected", &error, 1));
Craig Tiller91031da2016-12-28 15:44:25 -0800482 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tillera82950e2015-09-22 12:33:20 -0700483 }
484 if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
485 GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700486 exit_idle = true;
487 chand->exit_idle_when_lb_policy_arrives = false;
Craig Tillera82950e2015-09-22 12:33:20 -0700488 }
Craig Tiller98465032015-06-29 14:36:42 -0700489
Craig Tiller804ff712016-05-05 16:25:40 -0700490 if (error == GRPC_ERROR_NONE && chand->resolver) {
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700491 set_channel_connectivity_state_locked(
492 exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700493 if (lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800494 watch_lb_policy_locked(exec_ctx, chand, lb_policy, state);
Craig Tiller45724b32015-09-22 10:42:19 -0700495 }
Craig Tiller906e3bc2015-11-24 07:31:31 -0800496 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -0800497 grpc_resolver_next_locked(exec_ctx, chand->resolver,
498 &chand->resolver_result,
499 &chand->on_resolver_result_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700500 } else {
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800501 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800502 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800503 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
504 chand->resolver = NULL;
505 }
Craig Tiller804ff712016-05-05 16:25:40 -0700506 grpc_error *refs[] = {error, state_error};
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800507 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700508 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
ncteisen4b36a3d2017-03-13 19:08:06 -0700509 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
510 "Got config after disconnection", refs, GPR_ARRAY_SIZE(refs)),
Craig Tiller804ff712016-05-05 16:25:40 -0700511 "resolver_gone");
Craig Tillera82950e2015-09-22 12:33:20 -0700512 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700513
Craig Tillera82950e2015-09-22 12:33:20 -0700514 if (exit_idle) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800515 grpc_lb_policy_exit_idle_locked(exec_ctx, lb_policy);
Craig Tillera82950e2015-09-22 12:33:20 -0700516 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
517 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700518
Craig Tillera82950e2015-09-22 12:33:20 -0700519 if (old_lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800520 grpc_pollset_set_del_pollset_set(
521 exec_ctx, old_lb_policy->interested_parties, chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700522 GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
523 }
Craig Tiller000cd8f2015-09-18 07:20:29 -0700524
Craig Tillera82950e2015-09-22 12:33:20 -0700525 if (lb_policy != NULL) {
526 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
527 }
Craig Tiller45724b32015-09-22 10:42:19 -0700528
Craig Tiller906e3bc2015-11-24 07:31:31 -0800529 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700530 GRPC_ERROR_UNREF(state_error);
Craig Tiller3f475422015-06-25 10:43:05 -0700531}
532
Craig Tillera8610c02017-02-14 10:05:11 -0800533static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
534 grpc_error *error_ignored) {
Craig Tillerbefafe62017-02-09 11:30:54 -0800535 grpc_transport_op *op = arg;
Craig Tillerc55c1022017-03-10 10:26:42 -0800536 grpc_channel_element *elem = op->handler_private.extra_arg;
Craig Tillerca3e9d32015-06-27 18:37:27 -0700537 channel_data *chand = elem->channel_data;
Craig Tiller000cd8f2015-09-18 07:20:29 -0700538
Craig Tillera82950e2015-09-22 12:33:20 -0700539 if (op->on_connectivity_state_change != NULL) {
540 grpc_connectivity_state_notify_on_state_change(
541 exec_ctx, &chand->state_tracker, op->connectivity_state,
542 op->on_connectivity_state_change);
543 op->on_connectivity_state_change = NULL;
544 op->connectivity_state = NULL;
545 }
546
Craig Tiller26dab312015-12-07 14:43:47 -0800547 if (op->send_ping != NULL) {
Craig Tiller87b71e22015-12-07 15:14:14 -0800548 if (chand->lb_policy == NULL) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700549 grpc_closure_sched(
550 exec_ctx, op->send_ping,
551 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Ping with no load balancing"));
Craig Tiller26dab312015-12-07 14:43:47 -0800552 } else {
Craig Tiller2400bf52017-02-09 16:25:19 -0800553 grpc_lb_policy_ping_one_locked(exec_ctx, chand->lb_policy, op->send_ping);
Craig Tiller26dab312015-12-07 14:43:47 -0800554 op->bind_pollset = NULL;
555 }
556 op->send_ping = NULL;
557 }
558
Craig Tiller1c51edc2016-05-07 16:18:43 -0700559 if (op->disconnect_with_error != GRPC_ERROR_NONE) {
560 if (chand->resolver != NULL) {
561 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700562 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller1c51edc2016-05-07 16:18:43 -0700563 GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
Craig Tiller972470b2017-02-09 15:05:36 -0800564 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700565 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
566 chand->resolver = NULL;
567 if (!chand->started_resolving) {
568 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
569 GRPC_ERROR_REF(op->disconnect_with_error));
Craig Tiller91031da2016-12-28 15:44:25 -0800570 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700571 }
572 if (chand->lb_policy != NULL) {
573 grpc_pollset_set_del_pollset_set(exec_ctx,
574 chand->lb_policy->interested_parties,
575 chand->interested_parties);
576 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
577 chand->lb_policy = NULL;
578 }
Craig Tillerb12d22a2016-04-23 12:50:21 -0700579 }
Craig Tiller1c51edc2016-05-07 16:18:43 -0700580 GRPC_ERROR_UNREF(op->disconnect_with_error);
Craig Tillera82950e2015-09-22 12:33:20 -0700581 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800582 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "start_transport_op");
583
584 grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
Craig Tillerbefafe62017-02-09 11:30:54 -0800585}
586
587static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
588 grpc_channel_element *elem,
589 grpc_transport_op *op) {
590 channel_data *chand = elem->channel_data;
591
Craig Tillerbefafe62017-02-09 11:30:54 -0800592 GPR_ASSERT(op->set_accept_stream == false);
593 if (op->bind_pollset != NULL) {
594 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
595 op->bind_pollset);
596 }
597
Craig Tillerc55c1022017-03-10 10:26:42 -0800598 op->handler_private.extra_arg = elem;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800599 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "start_transport_op");
Craig Tillerbefafe62017-02-09 11:30:54 -0800600 grpc_closure_sched(
Craig Tillerc55c1022017-03-10 10:26:42 -0800601 exec_ctx,
602 grpc_closure_init(&op->handler_private.closure, start_transport_op_locked,
603 op, grpc_combiner_scheduler(chand->combiner, false)),
Craig Tillerbefafe62017-02-09 11:30:54 -0800604 GRPC_ERROR_NONE);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700605}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800606
Mark D. Rothb2d24882016-10-27 15:44:07 -0700607static void cc_get_channel_info(grpc_exec_ctx *exec_ctx,
608 grpc_channel_element *elem,
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700609 const grpc_channel_info *info) {
Mark D. Rothb2d24882016-10-27 15:44:07 -0700610 channel_data *chand = elem->channel_data;
Craig Tiller613dafa2017-02-09 12:00:43 -0800611 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700612 if (info->lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800613 *info->lb_policy_name = chand->info_lb_policy_name == NULL
Mark D. Roth78afd772016-11-04 12:49:49 -0700614 ? NULL
Craig Tiller613dafa2017-02-09 12:00:43 -0800615 : gpr_strdup(chand->info_lb_policy_name);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700616 }
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800617 if (info->service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800618 *info->service_config_json =
619 chand->info_service_config_json == NULL
620 ? NULL
621 : gpr_strdup(chand->info_service_config_json);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800622 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800623 gpr_mu_unlock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700624}
625
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700626/* Constructor for channel_data */
Mark D. Rothc1087882016-11-18 10:54:45 -0800627static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800628 grpc_channel_element *elem,
629 grpc_channel_element_args *args) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700630 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700631 GPR_ASSERT(args->is_last);
632 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800633 // Initialize data members.
Craig Tillerbefafe62017-02-09 11:30:54 -0800634 chand->combiner = grpc_combiner_create(NULL);
Craig Tillerd85477512017-02-09 12:02:39 -0800635 gpr_mu_init(&chand->info_mu);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800636 chand->owning_stack = args->channel_stack;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700637 grpc_closure_init(&chand->on_resolver_result_changed,
Craig Tillerbefafe62017-02-09 11:30:54 -0800638 on_resolver_result_changed_locked, chand,
639 grpc_combiner_scheduler(chand->combiner, false));
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800640 chand->interested_parties = grpc_pollset_set_create();
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700641 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
642 "client_channel");
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800643 // Record client channel factory.
644 const grpc_arg *arg = grpc_channel_args_find(args->channel_args,
645 GRPC_ARG_CLIENT_CHANNEL_FACTORY);
646 GPR_ASSERT(arg != NULL);
647 GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
648 grpc_client_channel_factory_ref(arg->value.pointer.p);
649 chand->client_channel_factory = arg->value.pointer.p;
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800650 // Get server name to resolve, using proxy mapper if needed.
Mark D. Roth86e90592016-11-18 09:56:40 -0800651 arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800652 GPR_ASSERT(arg != NULL);
653 GPR_ASSERT(arg->type == GRPC_ARG_STRING);
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800654 char *proxy_name = NULL;
655 grpc_channel_args *new_args = NULL;
656 grpc_proxy_mappers_map_name(exec_ctx, arg->value.string, args->channel_args,
657 &proxy_name, &new_args);
658 // Instantiate resolver.
Mark D. Roth45ccec52017-01-18 14:04:01 -0800659 chand->resolver = grpc_resolver_create(
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800660 exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string,
661 new_args != NULL ? new_args : args->channel_args,
Craig Tiller972470b2017-02-09 15:05:36 -0800662 chand->interested_parties, chand->combiner);
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800663 if (proxy_name != NULL) gpr_free(proxy_name);
664 if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args);
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800665 if (chand->resolver == NULL) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700666 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("resolver creation failed");
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800667 }
668 return GRPC_ERROR_NONE;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700669}
670
Craig Tiller972470b2017-02-09 15:05:36 -0800671static void shutdown_resolver_locked(grpc_exec_ctx *exec_ctx, void *arg,
672 grpc_error *error) {
673 grpc_resolver *resolver = arg;
674 grpc_resolver_shutdown_locked(exec_ctx, resolver);
675 GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel");
676}
677
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700678/* Destructor for channel_data */
679static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
680 grpc_channel_element *elem) {
681 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700682 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800683 grpc_closure_sched(
684 exec_ctx,
685 grpc_closure_create(shutdown_resolver_locked, chand->resolver,
686 grpc_combiner_scheduler(chand->combiner, false)),
687 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700688 }
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700689 if (chand->client_channel_factory != NULL) {
690 grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
691 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700692 if (chand->lb_policy != NULL) {
693 grpc_pollset_set_del_pollset_set(exec_ctx,
694 chand->lb_policy->interested_parties,
695 chand->interested_parties);
696 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
697 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800698 gpr_free(chand->info_lb_policy_name);
699 gpr_free(chand->info_service_config_json);
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800700 if (chand->retry_throttle_data != NULL) {
701 grpc_server_retry_throttle_data_unref(chand->retry_throttle_data);
702 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700703 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800704 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700705 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700706 grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
Craig Tiller9e5ac1b2017-02-14 22:25:50 -0800707 grpc_pollset_set_destroy(exec_ctx, chand->interested_parties);
Craig Tillerf1021672017-02-09 21:29:50 -0800708 GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel");
Craig Tillerd85477512017-02-09 12:02:39 -0800709 gpr_mu_destroy(&chand->info_mu);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700710}
711
712/*************************************************************************
713 * PER-CALL FUNCTIONS
714 */
715
716#define GET_CALL(call_data) \
717 ((grpc_subchannel_call *)(gpr_atm_acq_load(&(call_data)->subchannel_call)))
718
719#define CANCELLED_CALL ((grpc_subchannel_call *)1)
720
721typedef enum {
Craig Tiller7acc37e2017-02-28 10:01:37 -0800722 /* zero so that it can be default-initialized */
723 GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING = 0,
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700724 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL
725} subchannel_creation_phase;
726
727/** Call data. Holds a pointer to grpc_subchannel_call and the
728 associated machinery to create such a pointer.
729 Handles queueing of stream ops until a call object is ready, waiting
730 for initial metadata before trying to create a call object,
731 and handling cancellation gracefully. */
732typedef struct client_channel_call_data {
Mark D. Roth72f6da82016-09-02 13:42:38 -0700733 // State for handling deadlines.
734 // The code in deadline_filter.c requires this to be the first field.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700735 // TODO(roth): This is slightly sub-optimal in that grpc_deadline_state
736 // and this struct both independently store a pointer to the call
737 // stack and each has its own mutex. If/when we have time, find a way
Mark D. Roth6ad99172016-09-09 07:52:48 -0700738 // to avoid this without breaking the grpc_deadline_state abstraction.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700739 grpc_deadline_state deadline_state;
Mark D. Rothf28763c2016-09-14 15:18:40 -0700740
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800741 grpc_slice path; // Request path.
Mark D. Rothe40dd292016-10-05 14:58:37 -0700742 gpr_timespec call_start_time;
743 gpr_timespec deadline;
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -0700744 grpc_server_retry_throttle_data *retry_throttle_data;
Mark D. Roth95b627b2017-02-24 11:02:58 -0800745 method_parameters *method_params;
Mark D. Rothaa850a72016-09-26 13:38:02 -0700746
Mark D. Rothf28763c2016-09-14 15:18:40 -0700747 grpc_error *cancel_error;
Mark D. Roth72f6da82016-09-02 13:42:38 -0700748
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700749 /** either 0 for no call, 1 for cancelled, or a pointer to a
750 grpc_subchannel_call */
751 gpr_atm subchannel_call;
Craig Tillerd426cac2017-03-13 12:30:45 -0700752 gpr_arena *arena;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700753
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700754 subchannel_creation_phase creation_phase;
755 grpc_connected_subchannel *connected_subchannel;
756 grpc_polling_entity *pollent;
757
Craig Tillera0f3abd2017-03-31 15:42:16 -0700758 grpc_transport_stream_op_batch **waiting_ops;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700759 size_t waiting_ops_count;
760 size_t waiting_ops_capacity;
761
762 grpc_closure next_step;
763
764 grpc_call_stack *owning_call;
David Garcia Quintasd1a47f12016-09-02 12:46:44 +0200765
766 grpc_linked_mdelem lb_token_mdelem;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800767
768 grpc_closure on_complete;
769 grpc_closure *original_on_complete;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700770} call_data;
771
Craig Tiller8b1d59c2016-12-27 15:15:30 -0800772grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
773 grpc_call_element *call_elem) {
774 grpc_subchannel_call *scc = GET_CALL((call_data *)call_elem->call_data);
775 return scc == CANCELLED_CALL ? NULL : scc;
776}
777
Craig Tillere1b51da2017-03-31 15:44:33 -0700778static void add_waiting_locked(call_data *calld,
779 grpc_transport_stream_op_batch *op) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700780 GPR_TIMER_BEGIN("add_waiting_locked", 0);
781 if (calld->waiting_ops_count == calld->waiting_ops_capacity) {
782 calld->waiting_ops_capacity = GPR_MAX(3, 2 * calld->waiting_ops_capacity);
783 calld->waiting_ops =
784 gpr_realloc(calld->waiting_ops,
785 calld->waiting_ops_capacity * sizeof(*calld->waiting_ops));
786 }
Craig Tiller57726ca2016-09-12 11:59:45 -0700787 calld->waiting_ops[calld->waiting_ops_count++] = op;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700788 GPR_TIMER_END("add_waiting_locked", 0);
789}
790
791static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld,
792 grpc_error *error) {
793 size_t i;
794 for (i = 0; i < calld->waiting_ops_count; i++) {
Craig Tillera0f3abd2017-03-31 15:42:16 -0700795 grpc_transport_stream_op_batch_finish_with_failure(
Craig Tiller57726ca2016-09-12 11:59:45 -0700796 exec_ctx, calld->waiting_ops[i], GRPC_ERROR_REF(error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700797 }
798 calld->waiting_ops_count = 0;
799 GRPC_ERROR_UNREF(error);
800}
801
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700802static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
Craig Tiller57726ca2016-09-12 11:59:45 -0700803 if (calld->waiting_ops_count == 0) {
804 return;
805 }
806
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800807 grpc_subchannel_call *call = GET_CALL(calld);
Craig Tillera0f3abd2017-03-31 15:42:16 -0700808 grpc_transport_stream_op_batch **ops = calld->waiting_ops;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800809 size_t nops = calld->waiting_ops_count;
810 if (call == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700811 fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED);
812 return;
813 }
814 calld->waiting_ops = NULL;
815 calld->waiting_ops_count = 0;
816 calld->waiting_ops_capacity = 0;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800817 for (size_t i = 0; i < nops; i++) {
818 grpc_subchannel_call_process_op(exec_ctx, call, ops[i]);
819 }
Craig Tiller9efea882017-02-09 13:06:52 -0800820 gpr_free(ops);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700821}
822
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -0700823// Sets calld->method_params and calld->retry_throttle_data.
Craig Tiller11c17d42017-03-13 13:36:34 -0700824// If the method params specify a timeout, populates
825// *per_method_deadline and returns true.
826static bool set_call_method_params_from_service_config_locked(
827 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
828 gpr_timespec *per_method_deadline) {
829 channel_data *chand = elem->channel_data;
830 call_data *calld = elem->call_data;
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -0700831 if (chand->retry_throttle_data != NULL) {
832 calld->retry_throttle_data =
833 grpc_server_retry_throttle_data_ref(chand->retry_throttle_data);
834 }
Craig Tiller11c17d42017-03-13 13:36:34 -0700835 if (chand->method_params_table != NULL) {
836 calld->method_params = grpc_method_config_table_get(
837 exec_ctx, chand->method_params_table, calld->path);
838 if (calld->method_params != NULL) {
839 method_parameters_ref(calld->method_params);
840 if (gpr_time_cmp(calld->method_params->timeout,
841 gpr_time_0(GPR_TIMESPAN)) != 0) {
842 *per_method_deadline =
843 gpr_time_add(calld->call_start_time, calld->method_params->timeout);
844 return true;
845 }
846 }
847 }
848 return false;
849}
Craig Tillerea4a4f12017-03-13 13:36:52 -0700850
Craig Tiller11c17d42017-03-13 13:36:34 -0700851static void apply_final_configuration_locked(grpc_exec_ctx *exec_ctx,
852 grpc_call_element *elem) {
853 /* apply service-config level configuration to the call (now that we're
854 * certain it exists) */
855 call_data *calld = elem->call_data;
856 gpr_timespec per_method_deadline;
857 if (set_call_method_params_from_service_config_locked(exec_ctx, elem,
858 &per_method_deadline)) {
859 // If the deadline from the service config is shorter than the one
860 // from the client API, reset the deadline timer.
861 if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
862 calld->deadline = per_method_deadline;
863 grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
864 }
865 }
866}
867
Craig Tillerbefafe62017-02-09 11:30:54 -0800868static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
869 grpc_error *error) {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700870 grpc_call_element *elem = arg;
871 call_data *calld = elem->call_data;
872 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700873 GPR_ASSERT(calld->creation_phase ==
874 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
Yuchen Zeng19656b12016-09-01 18:00:45 -0700875 grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
876 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700877 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
878 if (calld->connected_subchannel == NULL) {
879 gpr_atm_no_barrier_store(&calld->subchannel_call, 1);
ncteisen4b36a3d2017-03-13 19:08:06 -0700880 fail_locked(exec_ctx, calld,
881 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
882 "Failed to create subchannel", &error, 1));
Mark D. Roth72f6da82016-09-02 13:42:38 -0700883 } else if (GET_CALL(calld) == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700884 /* already cancelled before subchannel became ready */
ncteisen4b36a3d2017-03-13 19:08:06 -0700885 grpc_error *cancellation_error =
886 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
887 "Cancelled before creating subchannel", &error, 1);
David Garcia Quintas68a9e382016-12-13 10:50:40 -0800888 /* if due to deadline, attach the deadline exceeded status to the error */
889 if (gpr_time_cmp(calld->deadline, gpr_now(GPR_CLOCK_MONOTONIC)) < 0) {
890 cancellation_error =
891 grpc_error_set_int(cancellation_error, GRPC_ERROR_INT_GRPC_STATUS,
892 GRPC_STATUS_DEADLINE_EXCEEDED);
893 }
894 fail_locked(exec_ctx, calld, cancellation_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700895 } else {
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700896 /* Create call on subchannel. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700897 grpc_subchannel_call *subchannel_call = NULL;
Craig Tillerfb9d1122017-03-14 09:26:27 -0700898 const grpc_connected_subchannel_call_args call_args = {
Craig Tillerd426cac2017-03-13 12:30:45 -0700899 .pollent = calld->pollent,
900 .path = calld->path,
901 .start_time = calld->call_start_time,
902 .deadline = calld->deadline,
903 .arena = calld->arena};
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700904 grpc_error *new_error = grpc_connected_subchannel_create_call(
Craig Tillerd426cac2017-03-13 12:30:45 -0700905 exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700906 if (new_error != GRPC_ERROR_NONE) {
907 new_error = grpc_error_add_child(new_error, error);
908 subchannel_call = CANCELLED_CALL;
909 fail_locked(exec_ctx, calld, new_error);
910 }
911 gpr_atm_rel_store(&calld->subchannel_call,
912 (gpr_atm)(uintptr_t)subchannel_call);
913 retry_waiting_locked(exec_ctx, calld);
914 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700915 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
916}
917
918static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
919 call_data *calld = elem->call_data;
920 grpc_subchannel_call *subchannel_call = GET_CALL(calld);
921 if (subchannel_call == NULL || subchannel_call == CANCELLED_CALL) {
922 return NULL;
923 } else {
924 return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
925 }
926}
927
Craig Tiller577c9b22015-11-02 14:11:15 -0800928typedef struct {
929 grpc_metadata_batch *initial_metadata;
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800930 uint32_t initial_metadata_flags;
Craig Tillerb5585d42015-11-17 07:18:31 -0800931 grpc_connected_subchannel **connected_subchannel;
Craig Tiller577c9b22015-11-02 14:11:15 -0800932 grpc_closure *on_ready;
933 grpc_call_element *elem;
934 grpc_closure closure;
935} continue_picking_args;
936
Yuchen Zeng144ce652016-09-01 18:19:34 -0700937/** Return true if subchannel is available immediately (in which case on_ready
938 should not be called), or false otherwise (in which case on_ready should be
939 called when the subchannel is available). */
Craig Tillerbefafe62017-02-09 11:30:54 -0800940static bool pick_subchannel_locked(
941 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
942 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
943 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
944 grpc_error *error);
Craig Tiller577c9b22015-11-02 14:11:15 -0800945
Craig Tillerbefafe62017-02-09 11:30:54 -0800946static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg,
947 grpc_error *error) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800948 continue_picking_args *cpa = arg;
Craig Tiller0ede5452016-04-23 12:21:45 -0700949 if (cpa->connected_subchannel == NULL) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800950 /* cancelled, do nothing */
Craig Tiller804ff712016-05-05 16:25:40 -0700951 } else if (error != GRPC_ERROR_NONE) {
Craig Tiller91031da2016-12-28 15:44:25 -0800952 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error));
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700953 } else {
Craig Tillerbefafe62017-02-09 11:30:54 -0800954 if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata,
955 cpa->initial_metadata_flags,
956 cpa->connected_subchannel, cpa->on_ready,
957 GRPC_ERROR_NONE)) {
Craig Tiller91031da2016-12-28 15:44:25 -0800958 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700959 }
Craig Tiller577c9b22015-11-02 14:11:15 -0800960 }
961 gpr_free(cpa);
962}
963
Craig Tillerbefafe62017-02-09 11:30:54 -0800964static bool pick_subchannel_locked(
965 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
966 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
967 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
968 grpc_error *error) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700969 GPR_TIMER_BEGIN("pick_subchannel", 0);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700970
Craig Tiller577c9b22015-11-02 14:11:15 -0800971 channel_data *chand = elem->channel_data;
972 call_data *calld = elem->call_data;
973 continue_picking_args *cpa;
974 grpc_closure *closure;
975
Craig Tillerb5585d42015-11-17 07:18:31 -0800976 GPR_ASSERT(connected_subchannel);
Craig Tiller577c9b22015-11-02 14:11:15 -0800977
Craig Tiller577c9b22015-11-02 14:11:15 -0800978 if (initial_metadata == NULL) {
979 if (chand->lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800980 grpc_lb_policy_cancel_pick_locked(exec_ctx, chand->lb_policy,
981 connected_subchannel,
982 GRPC_ERROR_REF(error));
Craig Tiller577c9b22015-11-02 14:11:15 -0800983 }
984 for (closure = chand->waiting_for_config_closures.head; closure != NULL;
Craig Tiller804ff712016-05-05 16:25:40 -0700985 closure = closure->next_data.next) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800986 cpa = closure->cb_arg;
Craig Tillerb5585d42015-11-17 07:18:31 -0800987 if (cpa->connected_subchannel == connected_subchannel) {
988 cpa->connected_subchannel = NULL;
ncteisen4b36a3d2017-03-13 19:08:06 -0700989 grpc_closure_sched(exec_ctx, cpa->on_ready,
990 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
991 "Pick cancelled", &error, 1));
Craig Tiller577c9b22015-11-02 14:11:15 -0800992 }
993 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700994 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth697a1f62016-09-07 13:35:07 -0700995 GRPC_ERROR_UNREF(error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700996 return true;
Craig Tiller577c9b22015-11-02 14:11:15 -0800997 }
Mark D. Roth697a1f62016-09-07 13:35:07 -0700998 GPR_ASSERT(error == GRPC_ERROR_NONE);
Craig Tiller577c9b22015-11-02 14:11:15 -0800999 if (chand->lb_policy != NULL) {
Craig Tiller2e0788a2017-03-14 06:55:44 -07001000 apply_final_configuration_locked(exec_ctx, elem);
Craig Tiller86c0f8a2015-12-01 20:05:40 -08001001 grpc_lb_policy *lb_policy = chand->lb_policy;
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001002 GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel");
Mark D. Rothe40dd292016-10-05 14:58:37 -07001003 // If the application explicitly set wait_for_ready, use that.
1004 // Otherwise, if the service config specified a value for this
1005 // method, use that.
Mark D. Rothc1c38582016-10-11 11:03:27 -07001006 const bool wait_for_ready_set_from_api =
1007 initial_metadata_flags &
1008 GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
1009 const bool wait_for_ready_set_from_service_config =
Mark D. Roth95b627b2017-02-24 11:02:58 -08001010 calld->method_params != NULL &&
1011 calld->method_params->wait_for_ready != WAIT_FOR_READY_UNSET;
Mark D. Rothc1c38582016-10-11 11:03:27 -07001012 if (!wait_for_ready_set_from_api &&
1013 wait_for_ready_set_from_service_config) {
Mark D. Roth95b627b2017-02-24 11:02:58 -08001014 if (calld->method_params->wait_for_ready == WAIT_FOR_READY_TRUE) {
Mark D. Rothe40dd292016-10-05 14:58:37 -07001015 initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
1016 } else {
1017 initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
1018 }
1019 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001020 const grpc_lb_policy_pick_args inputs = {
Yuchen Zengac8bc422016-10-05 14:00:02 -07001021 initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem,
1022 gpr_inf_future(GPR_CLOCK_MONOTONIC)};
Craig Tiller2400bf52017-02-09 16:25:19 -08001023 const bool result = grpc_lb_policy_pick_locked(
Mark D. Roth55f25b62016-10-12 14:55:20 -07001024 exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, on_ready);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001025 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel");
1026 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth9dab7d52016-10-07 07:48:03 -07001027 return result;
Craig Tiller577c9b22015-11-02 14:11:15 -08001028 }
1029 if (chand->resolver != NULL && !chand->started_resolving) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001030 chand->started_resolving = true;
Craig Tiller906e3bc2015-11-24 07:31:31 -08001031 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -08001032 grpc_resolver_next_locked(exec_ctx, chand->resolver,
1033 &chand->resolver_result,
1034 &chand->on_resolver_result_changed);
Craig Tiller577c9b22015-11-02 14:11:15 -08001035 }
Craig Tiller0eab6972016-04-23 12:59:57 -07001036 if (chand->resolver != NULL) {
1037 cpa = gpr_malloc(sizeof(*cpa));
1038 cpa->initial_metadata = initial_metadata;
1039 cpa->initial_metadata_flags = initial_metadata_flags;
1040 cpa->connected_subchannel = connected_subchannel;
1041 cpa->on_ready = on_ready;
1042 cpa->elem = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -08001043 grpc_closure_init(&cpa->closure, continue_picking_locked, cpa,
1044 grpc_combiner_scheduler(chand->combiner, true));
Craig Tiller804ff712016-05-05 16:25:40 -07001045 grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
1046 GRPC_ERROR_NONE);
Craig Tiller0eab6972016-04-23 12:59:57 -07001047 } else {
ncteisen4b36a3d2017-03-13 19:08:06 -07001048 grpc_closure_sched(exec_ctx, on_ready,
1049 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected"));
Craig Tiller0eab6972016-04-23 12:59:57 -07001050 }
Craig Tillerbfc9adc2016-06-27 13:16:22 -07001051
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001052 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001053 return false;
Craig Tiller577c9b22015-11-02 14:11:15 -08001054}
1055
Craig Tillere1b51da2017-03-31 15:44:33 -07001056static void start_transport_stream_op_batch_locked_inner(
1057 grpc_exec_ctx *exec_ctx, grpc_transport_stream_op_batch *op,
1058 grpc_call_element *elem) {
Yuchen Zeng19656b12016-09-01 18:00:45 -07001059 channel_data *chand = elem->channel_data;
Craig Tillera11bfc82017-02-14 09:56:33 -08001060 call_data *calld = elem->call_data;
Craig Tillerbefafe62017-02-09 11:30:54 -08001061 grpc_subchannel_call *call;
1062
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001063 /* need to recheck that another thread hasn't set the call */
1064 call = GET_CALL(calld);
1065 if (call == CANCELLED_CALL) {
Craig Tillera0f3abd2017-03-31 15:42:16 -07001066 grpc_transport_stream_op_batch_finish_with_failure(
Mark D. Rothf28763c2016-09-14 15:18:40 -07001067 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -08001068 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001069 return;
1070 }
1071 if (call != NULL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001072 grpc_subchannel_call_process_op(exec_ctx, call, op);
Craig Tillera11bfc82017-02-14 09:56:33 -08001073 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001074 return;
1075 }
1076 /* if this is a cancellation, then we can raise our cancelled flag */
Craig Tillerc55c1022017-03-10 10:26:42 -08001077 if (op->cancel_stream) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001078 if (!gpr_atm_rel_cas(&calld->subchannel_call, 0,
1079 (gpr_atm)(uintptr_t)CANCELLED_CALL)) {
Craig Tillera11bfc82017-02-14 09:56:33 -08001080 /* recurse to retry */
Craig Tillera0f3abd2017-03-31 15:42:16 -07001081 start_transport_stream_op_batch_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001082 /* early out */
1083 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001084 } else {
Craig Tillerbe9691a2017-02-14 10:00:42 -08001085 /* Stash a copy of cancel_error in our call data, so that we can use
1086 it for subsequent operations. This ensures that if the call is
1087 cancelled before any ops are passed down (e.g., if the deadline
1088 is in the past when the call starts), we can return the right
1089 error to the caller when the first op does get passed down. */
Craig Tillerc55c1022017-03-10 10:26:42 -08001090 calld->cancel_error =
1091 GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001092 switch (calld->creation_phase) {
1093 case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
Craig Tillerc55c1022017-03-10 10:26:42 -08001094 fail_locked(exec_ctx, calld,
1095 GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001096 break;
1097 case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
Craig Tillerc55c1022017-03-10 10:26:42 -08001098 pick_subchannel_locked(
1099 exec_ctx, elem, NULL, 0, &calld->connected_subchannel, NULL,
1100 GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001101 break;
1102 }
Craig Tillera0f3abd2017-03-31 15:42:16 -07001103 grpc_transport_stream_op_batch_finish_with_failure(
Craig Tillerc55c1022017-03-10 10:26:42 -08001104 exec_ctx, op,
1105 GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -08001106 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001107 return;
1108 }
1109 }
1110 /* if we don't have a subchannel, try to get one */
1111 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
Craig Tillerc55c1022017-03-10 10:26:42 -08001112 calld->connected_subchannel == NULL && op->send_initial_metadata) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001113 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
Craig Tillerbefafe62017-02-09 11:30:54 -08001114 grpc_closure_init(&calld->next_step, subchannel_ready_locked, elem,
1115 grpc_combiner_scheduler(chand->combiner, true));
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001116 GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
Yuchen Zeng144ce652016-09-01 18:19:34 -07001117 /* If a subchannel is not available immediately, the polling entity from
1118 call_data should be provided to channel_data's interested_parties, so
1119 that IO of the lb_policy and resolver could be done under it. */
Craig Tillerc55c1022017-03-10 10:26:42 -08001120 if (pick_subchannel_locked(
1121 exec_ctx, elem,
1122 op->payload->send_initial_metadata.send_initial_metadata,
1123 op->payload->send_initial_metadata.send_initial_metadata_flags,
1124 &calld->connected_subchannel, &calld->next_step, GRPC_ERROR_NONE)) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001125 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
1126 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
Yuchen Zeng19656b12016-09-01 18:00:45 -07001127 } else {
Yuchen Zeng19656b12016-09-01 18:00:45 -07001128 grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
1129 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001130 }
1131 }
1132 /* if we've got a subchannel, then let's ask it to create a call */
1133 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
1134 calld->connected_subchannel != NULL) {
1135 grpc_subchannel_call *subchannel_call = NULL;
Craig Tillerfb9d1122017-03-14 09:26:27 -07001136 const grpc_connected_subchannel_call_args call_args = {
Craig Tillerd426cac2017-03-13 12:30:45 -07001137 .pollent = calld->pollent,
1138 .path = calld->path,
1139 .start_time = calld->call_start_time,
1140 .deadline = calld->deadline,
1141 .arena = calld->arena};
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001142 grpc_error *error = grpc_connected_subchannel_create_call(
Craig Tillerd426cac2017-03-13 12:30:45 -07001143 exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001144 if (error != GRPC_ERROR_NONE) {
1145 subchannel_call = CANCELLED_CALL;
1146 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
Craig Tillera0f3abd2017-03-31 15:42:16 -07001147 grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, op, error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001148 }
1149 gpr_atm_rel_store(&calld->subchannel_call,
1150 (gpr_atm)(uintptr_t)subchannel_call);
1151 retry_waiting_locked(exec_ctx, calld);
Craig Tillera11bfc82017-02-14 09:56:33 -08001152 /* recurse to retry */
Craig Tillera0f3abd2017-03-31 15:42:16 -07001153 start_transport_stream_op_batch_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001154 /* early out */
1155 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001156 }
1157 /* nothing to be done but wait */
1158 add_waiting_locked(calld, op);
Craig Tillera11bfc82017-02-14 09:56:33 -08001159}
1160
Mark D. Rothde144102017-03-15 10:11:03 -07001161static void on_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001162 grpc_call_element *elem = arg;
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001163 call_data *calld = elem->call_data;
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -07001164 if (calld->retry_throttle_data != NULL) {
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001165 if (error == GRPC_ERROR_NONE) {
1166 grpc_server_retry_throttle_data_record_success(
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -07001167 calld->retry_throttle_data);
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001168 } else {
1169 // TODO(roth): In a subsequent PR, check the return value here and
Mark D. Rothb3322562017-02-23 14:38:02 -08001170 // decide whether or not to retry. Note that we should only
1171 // record failures whose statuses match the configured retryable
1172 // or non-fatal status codes.
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001173 grpc_server_retry_throttle_data_record_failure(
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -07001174 calld->retry_throttle_data);
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001175 }
1176 }
Mark D. Roth95039b52017-02-24 07:59:45 -08001177 grpc_closure_run(exec_ctx, calld->original_on_complete,
1178 GRPC_ERROR_REF(error));
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001179}
1180
Craig Tillere1b51da2017-03-31 15:44:33 -07001181static void start_transport_stream_op_batch_locked(grpc_exec_ctx *exec_ctx,
1182 void *arg,
1183 grpc_error *error_ignored) {
Craig Tillera0f3abd2017-03-31 15:42:16 -07001184 GPR_TIMER_BEGIN("start_transport_stream_op_batch_locked", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001185
Craig Tillera0f3abd2017-03-31 15:42:16 -07001186 grpc_transport_stream_op_batch *op = arg;
Craig Tillerc55c1022017-03-10 10:26:42 -08001187 grpc_call_element *elem = op->handler_private.extra_arg;
Craig Tillera11bfc82017-02-14 09:56:33 -08001188 call_data *calld = elem->call_data;
1189
Craig Tillerf6cb0c02017-03-28 14:11:49 -07001190 if (op->recv_trailing_metadata) {
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001191 GPR_ASSERT(op->on_complete != NULL);
1192 calld->original_on_complete = op->on_complete;
Mark D. Rothde144102017-03-15 10:11:03 -07001193 grpc_closure_init(&calld->on_complete, on_complete, elem,
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -07001194 grpc_schedule_on_exec_ctx);
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001195 op->on_complete = &calld->on_complete;
1196 }
1197
Craig Tillera0f3abd2017-03-31 15:42:16 -07001198 start_transport_stream_op_batch_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001199
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001200 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
Craig Tillera0f3abd2017-03-31 15:42:16 -07001201 "start_transport_stream_op_batch");
1202 GPR_TIMER_END("start_transport_stream_op_batch_locked", 0);
Craig Tillerbefafe62017-02-09 11:30:54 -08001203}
1204
Craig Tillerbe9691a2017-02-14 10:00:42 -08001205/* The logic here is fairly complicated, due to (a) the fact that we
1206 need to handle the case where we receive the send op before the
1207 initial metadata op, and (b) the need for efficiency, especially in
1208 the streaming case.
1209
1210 We use double-checked locking to initially see if initialization has been
1211 performed. If it has not, we acquire the combiner and perform initialization.
1212 If it has, we proceed on the fast path. */
Craig Tillere1b51da2017-03-31 15:44:33 -07001213static void cc_start_transport_stream_op_batch(
1214 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
1215 grpc_transport_stream_op_batch *op) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001216 call_data *calld = elem->call_data;
1217 channel_data *chand = elem->channel_data;
1218 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
Craig Tillere1b51da2017-03-31 15:44:33 -07001219 grpc_deadline_state_client_start_transport_stream_op_batch(exec_ctx, elem,
1220 op);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001221 /* try to (atomically) get the call */
1222 grpc_subchannel_call *call = GET_CALL(calld);
Craig Tillera0f3abd2017-03-31 15:42:16 -07001223 GPR_TIMER_BEGIN("cc_start_transport_stream_op_batch", 0);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001224 if (call == CANCELLED_CALL) {
Craig Tillera0f3abd2017-03-31 15:42:16 -07001225 grpc_transport_stream_op_batch_finish_with_failure(
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001226 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
Craig Tillera0f3abd2017-03-31 15:42:16 -07001227 GPR_TIMER_END("cc_start_transport_stream_op_batch", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001228 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001229 return;
1230 }
1231 if (call != NULL) {
1232 grpc_subchannel_call_process_op(exec_ctx, call, op);
Craig Tillera0f3abd2017-03-31 15:42:16 -07001233 GPR_TIMER_END("cc_start_transport_stream_op_batch", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001234 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001235 return;
1236 }
1237 /* we failed; lock and figure out what to do */
Craig Tillera0f3abd2017-03-31 15:42:16 -07001238 GRPC_CALL_STACK_REF(calld->owning_call, "start_transport_stream_op_batch");
Craig Tillerc55c1022017-03-10 10:26:42 -08001239 op->handler_private.extra_arg = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -08001240 grpc_closure_sched(
1241 exec_ctx,
Craig Tiller4a84bdd2017-02-14 09:48:41 -08001242 grpc_closure_init(&op->handler_private.closure,
Craig Tillera0f3abd2017-03-31 15:42:16 -07001243 start_transport_stream_op_batch_locked, op,
Craig Tillerbefafe62017-02-09 11:30:54 -08001244 grpc_combiner_scheduler(chand->combiner, false)),
1245 GRPC_ERROR_NONE);
Craig Tillera0f3abd2017-03-31 15:42:16 -07001246 GPR_TIMER_END("cc_start_transport_stream_op_batch", 0);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001247}
1248
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001249/* Constructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001250static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
1251 grpc_call_element *elem,
Craig Tillerc52ba3a2017-02-15 22:57:43 -08001252 const grpc_call_element_args *args) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001253 call_data *calld = elem->call_data;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001254 // Initialize data members.
1255 grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001256 calld->path = grpc_slice_ref_internal(args->path);
Mark D. Rothff08f332016-10-14 13:01:01 -07001257 calld->call_start_time = args->start_time;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001258 calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001259 calld->owning_call = args->call_stack;
Craig Tillerd426cac2017-03-13 12:30:45 -07001260 calld->arena = args->arena;
Craig Tiller2c3d0a92017-02-28 15:26:24 -08001261 grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
Mark D. Roth0badbe82016-06-23 10:15:12 -07001262 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001263}
1264
1265/* Destructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001266static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
1267 grpc_call_element *elem,
1268 const grpc_call_final_info *final_info,
Craig Tillerd426cac2017-03-13 12:30:45 -07001269 grpc_closure *then_schedule_closure) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001270 call_data *calld = elem->call_data;
Mark D. Rothf28763c2016-09-14 15:18:40 -07001271 grpc_deadline_state_destroy(exec_ctx, elem);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001272 grpc_slice_unref_internal(exec_ctx, calld->path);
Mark D. Roth95b627b2017-02-24 11:02:58 -08001273 if (calld->method_params != NULL) {
1274 method_parameters_unref(calld->method_params);
1275 }
Mark D. Rothf28763c2016-09-14 15:18:40 -07001276 GRPC_ERROR_UNREF(calld->cancel_error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001277 grpc_subchannel_call *call = GET_CALL(calld);
1278 if (call != NULL && call != CANCELLED_CALL) {
Craig Tillerd426cac2017-03-13 12:30:45 -07001279 grpc_subchannel_call_set_cleanup_closure(call, then_schedule_closure);
1280 then_schedule_closure = NULL;
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001281 GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
1282 }
1283 GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001284 GPR_ASSERT(calld->waiting_ops_count == 0);
Craig Tiller693d3942016-10-27 16:51:25 -07001285 if (calld->connected_subchannel != NULL) {
1286 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel,
1287 "picked");
1288 }
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001289 gpr_free(calld->waiting_ops);
Craig Tillerd426cac2017-03-13 12:30:45 -07001290 grpc_closure_sched(exec_ctx, then_schedule_closure, GRPC_ERROR_NONE);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001291}
1292
David Garcia Quintasf72eb972016-05-03 18:28:09 -07001293static void cc_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
1294 grpc_call_element *elem,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001295 grpc_polling_entity *pollent) {
Craig Tiller577c9b22015-11-02 14:11:15 -08001296 call_data *calld = elem->call_data;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001297 calld->pollent = pollent;
Craig Tiller577c9b22015-11-02 14:11:15 -08001298}
1299
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001300/*************************************************************************
1301 * EXPORTED SYMBOLS
1302 */
1303
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001304const grpc_channel_filter grpc_client_channel_filter = {
Craig Tillera0f3abd2017-03-31 15:42:16 -07001305 cc_start_transport_stream_op_batch,
Craig Tillerf40df232016-03-25 13:38:14 -07001306 cc_start_transport_op,
1307 sizeof(call_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001308 cc_init_call_elem,
David Garcia Quintas4afce7e2016-04-18 16:25:17 -07001309 cc_set_pollset_or_pollset_set,
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001310 cc_destroy_call_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001311 sizeof(channel_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001312 cc_init_channel_elem,
1313 cc_destroy_channel_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001314 cc_get_peer,
Mark D. Rothb2d24882016-10-27 15:44:07 -07001315 cc_get_channel_info,
Craig Tillerf40df232016-03-25 13:38:14 -07001316 "client-channel",
Craig Tiller87d5b192015-04-16 14:37:57 -07001317};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001318
Craig Tiller613dafa2017-02-09 12:00:43 -08001319static void try_to_connect_locked(grpc_exec_ctx *exec_ctx, void *arg,
1320 grpc_error *error_ignored) {
1321 channel_data *chand = arg;
1322 if (chand->lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -08001323 grpc_lb_policy_exit_idle_locked(exec_ctx, chand->lb_policy);
Craig Tiller613dafa2017-02-09 12:00:43 -08001324 } else {
1325 chand->exit_idle_when_lb_policy_arrives = true;
1326 if (!chand->started_resolving && chand->resolver != NULL) {
1327 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
1328 chand->started_resolving = true;
Craig Tiller972470b2017-02-09 15:05:36 -08001329 grpc_resolver_next_locked(exec_ctx, chand->resolver,
1330 &chand->resolver_result,
1331 &chand->on_resolver_result_changed);
Craig Tiller613dafa2017-02-09 12:00:43 -08001332 }
1333 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001334 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001335}
1336
Craig Tillera82950e2015-09-22 12:33:20 -07001337grpc_connectivity_state grpc_client_channel_check_connectivity_state(
1338 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001339 channel_data *chand = elem->channel_data;
Craig Tillera8610c02017-02-14 10:05:11 -08001340 grpc_connectivity_state out =
1341 grpc_connectivity_state_check(&chand->state_tracker);
Craig Tillera82950e2015-09-22 12:33:20 -07001342 if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001343 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001344 grpc_closure_sched(
1345 exec_ctx,
1346 grpc_closure_create(try_to_connect_locked, chand,
1347 grpc_combiner_scheduler(chand->combiner, false)),
1348 GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -07001349 }
Craig Tiller48cb07c2015-07-15 16:16:15 -07001350 return out;
1351}
1352
Craig Tiller86c99582015-11-25 15:22:26 -08001353typedef struct {
1354 channel_data *chand;
1355 grpc_pollset *pollset;
1356 grpc_closure *on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001357 grpc_connectivity_state *state;
Craig Tiller86c99582015-11-25 15:22:26 -08001358 grpc_closure my_closure;
1359} external_connectivity_watcher;
1360
Craig Tiller1d881fb2015-12-01 07:39:04 -08001361static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -07001362 grpc_error *error) {
Craig Tiller86c99582015-11-25 15:22:26 -08001363 external_connectivity_watcher *w = arg;
1364 grpc_closure *follow_up = w->on_complete;
Craig Tiller69b093b2016-02-25 19:04:07 -08001365 grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
Craig Tiller1d881fb2015-12-01 07:39:04 -08001366 w->pollset);
1367 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
1368 "external_connectivity_watcher");
Craig Tiller86c99582015-11-25 15:22:26 -08001369 gpr_free(w);
Craig Tiller613dafa2017-02-09 12:00:43 -08001370 grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
1371}
1372
Craig Tillera8610c02017-02-14 10:05:11 -08001373static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg,
1374 grpc_error *error_ignored) {
Craig Tiller613dafa2017-02-09 12:00:43 -08001375 external_connectivity_watcher *w = arg;
1376 grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
1377 grpc_schedule_on_exec_ctx);
1378 grpc_connectivity_state_notify_on_state_change(
1379 exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
Craig Tiller86c99582015-11-25 15:22:26 -08001380}
1381
Craig Tillera82950e2015-09-22 12:33:20 -07001382void grpc_client_channel_watch_connectivity_state(
Craig Tiller906e3bc2015-11-24 07:31:31 -08001383 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
Craig Tillera82950e2015-09-22 12:33:20 -07001384 grpc_connectivity_state *state, grpc_closure *on_complete) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001385 channel_data *chand = elem->channel_data;
Craig Tiller86c99582015-11-25 15:22:26 -08001386 external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
1387 w->chand = chand;
1388 w->pollset = pollset;
1389 w->on_complete = on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001390 w->state = state;
Craig Tiller69b093b2016-02-25 19:04:07 -08001391 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
Craig Tiller1d881fb2015-12-01 07:39:04 -08001392 GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
1393 "external_connectivity_watcher");
Craig Tiller613dafa2017-02-09 12:00:43 -08001394 grpc_closure_sched(
1395 exec_ctx,
Craig Tillera8610c02017-02-14 10:05:11 -08001396 grpc_closure_init(&w->my_closure, watch_connectivity_state_locked, w,
Craig Tiller613dafa2017-02-09 12:00:43 -08001397 grpc_combiner_scheduler(chand->combiner, true)),
1398 GRPC_ERROR_NONE);
Craig Tiller48cb07c2015-07-15 16:16:15 -07001399}