blob: c9869746ca13cdb4a67143e34b3b241b9ae7ebe9 [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);
David Garcia Quintas228a5142017-03-30 19:43:00 -0700377 if (channel_arg != NULL && channel_arg->type != GRPC_ARG_POINTER) {
Mark D. Roth557c9902016-10-24 11:12:05 -0700378 grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
Mark D. Rothaf842452016-10-21 15:05:15 -0700379 bool found_backend_address = false;
380 for (size_t i = 0; i < addresses->num_addresses; ++i) {
381 if (!addresses->addresses[i].is_balancer) {
382 found_backend_address = true;
383 break;
384 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700385 }
Mark D. Rothaf842452016-10-21 15:05:15 -0700386 if (!found_backend_address) {
387 if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) {
388 gpr_log(GPR_INFO,
389 "resolver requested LB policy %s but provided only balancer "
390 "addresses, no backend addresses -- forcing use of grpclb LB "
391 "policy",
Mark D. Roth5f40e5d2016-10-24 13:09:05 -0700392 lb_policy_name);
Mark D. Rothaf842452016-10-21 15:05:15 -0700393 }
394 lb_policy_name = "grpclb";
Mark D. Roth88405f72016-10-03 08:24:52 -0700395 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700396 }
397 // Use pick_first if nothing was specified and we didn't select grpclb
398 // above.
399 if (lb_policy_name == NULL) lb_policy_name = "pick_first";
Mark D. Roth41124992016-11-03 11:22:20 -0700400 // Instantiate LB policy.
401 grpc_lb_policy_args lb_policy_args;
402 lb_policy_args.args = chand->resolver_result;
403 lb_policy_args.client_channel_factory = chand->client_channel_factory;
Craig Tiller2400bf52017-02-09 16:25:19 -0800404 lb_policy_args.combiner = chand->combiner;
Mark D. Roth88405f72016-10-03 08:24:52 -0700405 lb_policy =
406 grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700407 if (lb_policy != NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -0700408 GRPC_LB_POLICY_REF(lb_policy, "config_change");
Craig Tillerf707d622016-05-06 14:26:12 -0700409 GRPC_ERROR_UNREF(state_error);
Craig Tiller2400bf52017-02-09 16:25:19 -0800410 state = grpc_lb_policy_check_connectivity_locked(exec_ctx, lb_policy,
411 &state_error);
Craig Tiller45724b32015-09-22 10:42:19 -0700412 }
Mark D. Roth41124992016-11-03 11:22:20 -0700413 // Find service config.
Mark D. Rothaf842452016-10-21 15:05:15 -0700414 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700415 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVICE_CONFIG);
Mark D. Roth046cf762016-09-26 11:13:51 -0700416 if (channel_arg != NULL) {
Mark D. Roth9ec28af2016-11-03 12:32:39 -0700417 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800418 service_config_json = gpr_strdup(channel_arg->value.string);
Mark D. Roth70a1abd2016-11-04 09:26:37 -0700419 grpc_service_config *service_config =
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800420 grpc_service_config_create(service_config_json);
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700421 if (service_config != NULL) {
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800422 channel_arg =
423 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVER_URI);
424 GPR_ASSERT(channel_arg != NULL);
425 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -0700426 grpc_uri *uri =
427 grpc_uri_parse(exec_ctx, channel_arg->value.string, true);
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800428 GPR_ASSERT(uri->path[0] != '\0');
429 parsing_state.server_name =
430 uri->path[0] == '/' ? uri->path + 1 : uri->path;
431 grpc_service_config_parse_global_params(
432 service_config, parse_retry_throttle_params, &parsing_state);
433 parsing_state.server_name = NULL;
434 grpc_uri_destroy(uri);
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700435 method_params_table = grpc_service_config_create_method_config_table(
Craig Tillerb28c7e82016-11-18 10:29:04 -0800436 exec_ctx, service_config, method_parameters_create_from_json,
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700437 &method_parameters_vtable);
438 grpc_service_config_destroy(service_config);
439 }
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700440 }
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700441 // Before we clean up, save a copy of lb_policy_name, since it might
442 // be pointing to data inside chand->resolver_result.
443 // The copy will be saved in chand->lb_policy_name below.
444 lb_policy_name = gpr_strdup(lb_policy_name);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800445 grpc_channel_args_destroy(exec_ctx, chand->resolver_result);
Mark D. Roth046cf762016-09-26 11:13:51 -0700446 chand->resolver_result = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700447 }
448
Craig Tiller86c99582015-11-25 15:22:26 -0800449 if (lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800450 grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties,
451 chand->interested_parties);
Craig Tiller86c99582015-11-25 15:22:26 -0800452 }
453
Craig Tiller613dafa2017-02-09 12:00:43 -0800454 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700455 if (lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800456 gpr_free(chand->info_lb_policy_name);
457 chand->info_lb_policy_name = lb_policy_name;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700458 }
Craig Tiller3f475422015-06-25 10:43:05 -0700459 old_lb_policy = chand->lb_policy;
460 chand->lb_policy = lb_policy;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800461 if (service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800462 gpr_free(chand->info_service_config_json);
463 chand->info_service_config_json = service_config_json;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800464 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800465 gpr_mu_unlock(&chand->info_mu);
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800466
467 if (chand->retry_throttle_data != NULL) {
468 grpc_server_retry_throttle_data_unref(chand->retry_throttle_data);
469 }
470 chand->retry_throttle_data = parsing_state.retry_throttle_data;
Mark D. Roth9d480942016-10-19 14:18:05 -0700471 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800472 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth046cf762016-09-26 11:13:51 -0700473 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700474 chand->method_params_table = method_params_table;
Craig Tiller0ede5452016-04-23 12:21:45 -0700475 if (lb_policy != NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -0800476 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller0ede5452016-04-23 12:21:45 -0700477 } else if (chand->resolver == NULL /* disconnected */) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700478 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
479 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
480 "Channel disconnected", &error, 1));
Craig Tiller91031da2016-12-28 15:44:25 -0800481 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tillera82950e2015-09-22 12:33:20 -0700482 }
483 if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
484 GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700485 exit_idle = true;
486 chand->exit_idle_when_lb_policy_arrives = false;
Craig Tillera82950e2015-09-22 12:33:20 -0700487 }
Craig Tiller98465032015-06-29 14:36:42 -0700488
Craig Tiller804ff712016-05-05 16:25:40 -0700489 if (error == GRPC_ERROR_NONE && chand->resolver) {
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700490 set_channel_connectivity_state_locked(
491 exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700492 if (lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800493 watch_lb_policy_locked(exec_ctx, chand, lb_policy, state);
Craig Tiller45724b32015-09-22 10:42:19 -0700494 }
Craig Tiller906e3bc2015-11-24 07:31:31 -0800495 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -0800496 grpc_resolver_next_locked(exec_ctx, chand->resolver,
497 &chand->resolver_result,
498 &chand->on_resolver_result_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700499 } else {
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800500 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800501 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800502 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
503 chand->resolver = NULL;
504 }
Craig Tiller804ff712016-05-05 16:25:40 -0700505 grpc_error *refs[] = {error, state_error};
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800506 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700507 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
ncteisen4b36a3d2017-03-13 19:08:06 -0700508 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
509 "Got config after disconnection", refs, GPR_ARRAY_SIZE(refs)),
Craig Tiller804ff712016-05-05 16:25:40 -0700510 "resolver_gone");
Craig Tillera82950e2015-09-22 12:33:20 -0700511 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700512
Craig Tillera82950e2015-09-22 12:33:20 -0700513 if (exit_idle) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800514 grpc_lb_policy_exit_idle_locked(exec_ctx, lb_policy);
Craig Tillera82950e2015-09-22 12:33:20 -0700515 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
516 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700517
Craig Tillera82950e2015-09-22 12:33:20 -0700518 if (old_lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800519 grpc_pollset_set_del_pollset_set(
520 exec_ctx, old_lb_policy->interested_parties, chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700521 GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
522 }
Craig Tiller000cd8f2015-09-18 07:20:29 -0700523
Craig Tillera82950e2015-09-22 12:33:20 -0700524 if (lb_policy != NULL) {
525 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
526 }
Craig Tiller45724b32015-09-22 10:42:19 -0700527
Craig Tiller906e3bc2015-11-24 07:31:31 -0800528 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700529 GRPC_ERROR_UNREF(state_error);
Craig Tiller3f475422015-06-25 10:43:05 -0700530}
531
Craig Tillera8610c02017-02-14 10:05:11 -0800532static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
533 grpc_error *error_ignored) {
Craig Tillerbefafe62017-02-09 11:30:54 -0800534 grpc_transport_op *op = arg;
535 grpc_channel_element *elem = op->transport_private.args[0];
Craig Tillerca3e9d32015-06-27 18:37:27 -0700536 channel_data *chand = elem->channel_data;
Craig Tiller000cd8f2015-09-18 07:20:29 -0700537
Craig Tillera82950e2015-09-22 12:33:20 -0700538 if (op->on_connectivity_state_change != NULL) {
539 grpc_connectivity_state_notify_on_state_change(
540 exec_ctx, &chand->state_tracker, op->connectivity_state,
541 op->on_connectivity_state_change);
542 op->on_connectivity_state_change = NULL;
543 op->connectivity_state = NULL;
544 }
545
Craig Tiller26dab312015-12-07 14:43:47 -0800546 if (op->send_ping != NULL) {
Craig Tiller87b71e22015-12-07 15:14:14 -0800547 if (chand->lb_policy == NULL) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700548 grpc_closure_sched(
549 exec_ctx, op->send_ping,
550 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Ping with no load balancing"));
Craig Tiller26dab312015-12-07 14:43:47 -0800551 } else {
Craig Tiller2400bf52017-02-09 16:25:19 -0800552 grpc_lb_policy_ping_one_locked(exec_ctx, chand->lb_policy, op->send_ping);
Craig Tiller26dab312015-12-07 14:43:47 -0800553 op->bind_pollset = NULL;
554 }
555 op->send_ping = NULL;
556 }
557
Craig Tiller1c51edc2016-05-07 16:18:43 -0700558 if (op->disconnect_with_error != GRPC_ERROR_NONE) {
559 if (chand->resolver != NULL) {
560 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700561 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller1c51edc2016-05-07 16:18:43 -0700562 GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
Craig Tiller972470b2017-02-09 15:05:36 -0800563 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700564 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
565 chand->resolver = NULL;
566 if (!chand->started_resolving) {
567 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
568 GRPC_ERROR_REF(op->disconnect_with_error));
Craig Tiller91031da2016-12-28 15:44:25 -0800569 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700570 }
571 if (chand->lb_policy != NULL) {
572 grpc_pollset_set_del_pollset_set(exec_ctx,
573 chand->lb_policy->interested_parties,
574 chand->interested_parties);
575 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
576 chand->lb_policy = NULL;
577 }
Craig Tillerb12d22a2016-04-23 12:50:21 -0700578 }
Craig Tiller1c51edc2016-05-07 16:18:43 -0700579 GRPC_ERROR_UNREF(op->disconnect_with_error);
Craig Tillera82950e2015-09-22 12:33:20 -0700580 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800581 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "start_transport_op");
582
583 grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
Craig Tillerbefafe62017-02-09 11:30:54 -0800584}
585
586static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
587 grpc_channel_element *elem,
588 grpc_transport_op *op) {
589 channel_data *chand = elem->channel_data;
590
Craig Tillerbefafe62017-02-09 11:30:54 -0800591 GPR_ASSERT(op->set_accept_stream == false);
592 if (op->bind_pollset != NULL) {
593 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
594 op->bind_pollset);
595 }
596
597 op->transport_private.args[0] = elem;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800598 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "start_transport_op");
Craig Tillerbefafe62017-02-09 11:30:54 -0800599 grpc_closure_sched(
Craig Tillera8610c02017-02-14 10:05:11 -0800600 exec_ctx, grpc_closure_init(
601 &op->transport_private.closure, start_transport_op_locked,
602 op, grpc_combiner_scheduler(chand->combiner, false)),
Craig Tillerbefafe62017-02-09 11:30:54 -0800603 GRPC_ERROR_NONE);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700604}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800605
Mark D. Rothb2d24882016-10-27 15:44:07 -0700606static void cc_get_channel_info(grpc_exec_ctx *exec_ctx,
607 grpc_channel_element *elem,
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700608 const grpc_channel_info *info) {
Mark D. Rothb2d24882016-10-27 15:44:07 -0700609 channel_data *chand = elem->channel_data;
Craig Tiller613dafa2017-02-09 12:00:43 -0800610 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700611 if (info->lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800612 *info->lb_policy_name = chand->info_lb_policy_name == NULL
Mark D. Roth78afd772016-11-04 12:49:49 -0700613 ? NULL
Craig Tiller613dafa2017-02-09 12:00:43 -0800614 : gpr_strdup(chand->info_lb_policy_name);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700615 }
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800616 if (info->service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800617 *info->service_config_json =
618 chand->info_service_config_json == NULL
619 ? NULL
620 : gpr_strdup(chand->info_service_config_json);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800621 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800622 gpr_mu_unlock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700623}
624
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700625/* Constructor for channel_data */
Mark D. Rothc1087882016-11-18 10:54:45 -0800626static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800627 grpc_channel_element *elem,
628 grpc_channel_element_args *args) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700629 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700630 GPR_ASSERT(args->is_last);
631 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800632 // Initialize data members.
Craig Tillerbefafe62017-02-09 11:30:54 -0800633 chand->combiner = grpc_combiner_create(NULL);
Craig Tillerd85477512017-02-09 12:02:39 -0800634 gpr_mu_init(&chand->info_mu);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800635 chand->owning_stack = args->channel_stack;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700636 grpc_closure_init(&chand->on_resolver_result_changed,
Craig Tillerbefafe62017-02-09 11:30:54 -0800637 on_resolver_result_changed_locked, chand,
638 grpc_combiner_scheduler(chand->combiner, false));
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800639 chand->interested_parties = grpc_pollset_set_create();
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700640 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
641 "client_channel");
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800642 // Record client channel factory.
643 const grpc_arg *arg = grpc_channel_args_find(args->channel_args,
644 GRPC_ARG_CLIENT_CHANNEL_FACTORY);
David Garcia Quintas228a5142017-03-30 19:43:00 -0700645 if (arg == NULL) {
646 return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
647 "Missing client channel factory in args for client channel filter");
648 }
649 if (arg->type != GRPC_ARG_POINTER) {
650 return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
651 "client channel factory arg must be a pointer");
652 }
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800653 grpc_client_channel_factory_ref(arg->value.pointer.p);
654 chand->client_channel_factory = arg->value.pointer.p;
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800655 // Get server name to resolve, using proxy mapper if needed.
Mark D. Roth86e90592016-11-18 09:56:40 -0800656 arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI);
David Garcia Quintas228a5142017-03-30 19:43:00 -0700657 if (arg == NULL) {
658 return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
659 "Missing server uri in args for client channel filter");
660 }
661 if (arg->type != GRPC_ARG_STRING) {
662 return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
663 "server uri arg must be a string");
664 }
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800665 char *proxy_name = NULL;
666 grpc_channel_args *new_args = NULL;
667 grpc_proxy_mappers_map_name(exec_ctx, arg->value.string, args->channel_args,
668 &proxy_name, &new_args);
669 // Instantiate resolver.
Mark D. Roth45ccec52017-01-18 14:04:01 -0800670 chand->resolver = grpc_resolver_create(
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800671 exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string,
672 new_args != NULL ? new_args : args->channel_args,
Craig Tiller972470b2017-02-09 15:05:36 -0800673 chand->interested_parties, chand->combiner);
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800674 if (proxy_name != NULL) gpr_free(proxy_name);
675 if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args);
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800676 if (chand->resolver == NULL) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700677 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("resolver creation failed");
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800678 }
679 return GRPC_ERROR_NONE;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700680}
681
Craig Tiller972470b2017-02-09 15:05:36 -0800682static void shutdown_resolver_locked(grpc_exec_ctx *exec_ctx, void *arg,
683 grpc_error *error) {
684 grpc_resolver *resolver = arg;
685 grpc_resolver_shutdown_locked(exec_ctx, resolver);
686 GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel");
687}
688
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700689/* Destructor for channel_data */
690static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
691 grpc_channel_element *elem) {
692 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700693 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800694 grpc_closure_sched(
695 exec_ctx,
696 grpc_closure_create(shutdown_resolver_locked, chand->resolver,
697 grpc_combiner_scheduler(chand->combiner, false)),
698 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700699 }
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700700 if (chand->client_channel_factory != NULL) {
701 grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
702 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700703 if (chand->lb_policy != NULL) {
704 grpc_pollset_set_del_pollset_set(exec_ctx,
705 chand->lb_policy->interested_parties,
706 chand->interested_parties);
707 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
708 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800709 gpr_free(chand->info_lb_policy_name);
710 gpr_free(chand->info_service_config_json);
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800711 if (chand->retry_throttle_data != NULL) {
712 grpc_server_retry_throttle_data_unref(chand->retry_throttle_data);
713 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700714 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800715 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700716 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700717 grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
Craig Tiller9e5ac1b2017-02-14 22:25:50 -0800718 grpc_pollset_set_destroy(exec_ctx, chand->interested_parties);
Craig Tillerf1021672017-02-09 21:29:50 -0800719 GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel");
Craig Tillerd85477512017-02-09 12:02:39 -0800720 gpr_mu_destroy(&chand->info_mu);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700721}
722
723/*************************************************************************
724 * PER-CALL FUNCTIONS
725 */
726
727#define GET_CALL(call_data) \
728 ((grpc_subchannel_call *)(gpr_atm_acq_load(&(call_data)->subchannel_call)))
729
730#define CANCELLED_CALL ((grpc_subchannel_call *)1)
731
732typedef enum {
Craig Tiller7acc37e2017-02-28 10:01:37 -0800733 /* zero so that it can be default-initialized */
734 GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING = 0,
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700735 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL
736} subchannel_creation_phase;
737
738/** Call data. Holds a pointer to grpc_subchannel_call and the
739 associated machinery to create such a pointer.
740 Handles queueing of stream ops until a call object is ready, waiting
741 for initial metadata before trying to create a call object,
742 and handling cancellation gracefully. */
743typedef struct client_channel_call_data {
Mark D. Roth72f6da82016-09-02 13:42:38 -0700744 // State for handling deadlines.
745 // The code in deadline_filter.c requires this to be the first field.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700746 // TODO(roth): This is slightly sub-optimal in that grpc_deadline_state
747 // and this struct both independently store a pointer to the call
748 // stack and each has its own mutex. If/when we have time, find a way
Mark D. Roth6ad99172016-09-09 07:52:48 -0700749 // to avoid this without breaking the grpc_deadline_state abstraction.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700750 grpc_deadline_state deadline_state;
Mark D. Rothf28763c2016-09-14 15:18:40 -0700751
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800752 grpc_slice path; // Request path.
Mark D. Rothe40dd292016-10-05 14:58:37 -0700753 gpr_timespec call_start_time;
754 gpr_timespec deadline;
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -0700755 grpc_server_retry_throttle_data *retry_throttle_data;
Mark D. Roth95b627b2017-02-24 11:02:58 -0800756 method_parameters *method_params;
Mark D. Rothaa850a72016-09-26 13:38:02 -0700757
Mark D. Rothf28763c2016-09-14 15:18:40 -0700758 grpc_error *cancel_error;
Mark D. Roth72f6da82016-09-02 13:42:38 -0700759
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700760 /** either 0 for no call, 1 for cancelled, or a pointer to a
761 grpc_subchannel_call */
762 gpr_atm subchannel_call;
Craig Tillerd426cac2017-03-13 12:30:45 -0700763 gpr_arena *arena;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700764
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700765 subchannel_creation_phase creation_phase;
766 grpc_connected_subchannel *connected_subchannel;
767 grpc_polling_entity *pollent;
768
Craig Tiller57726ca2016-09-12 11:59:45 -0700769 grpc_transport_stream_op **waiting_ops;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700770 size_t waiting_ops_count;
771 size_t waiting_ops_capacity;
772
773 grpc_closure next_step;
774
775 grpc_call_stack *owning_call;
David Garcia Quintasd1a47f12016-09-02 12:46:44 +0200776
777 grpc_linked_mdelem lb_token_mdelem;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800778
779 grpc_closure on_complete;
780 grpc_closure *original_on_complete;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700781} call_data;
782
Craig Tiller8b1d59c2016-12-27 15:15:30 -0800783grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
784 grpc_call_element *call_elem) {
785 grpc_subchannel_call *scc = GET_CALL((call_data *)call_elem->call_data);
786 return scc == CANCELLED_CALL ? NULL : scc;
787}
788
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700789static void add_waiting_locked(call_data *calld, grpc_transport_stream_op *op) {
790 GPR_TIMER_BEGIN("add_waiting_locked", 0);
791 if (calld->waiting_ops_count == calld->waiting_ops_capacity) {
792 calld->waiting_ops_capacity = GPR_MAX(3, 2 * calld->waiting_ops_capacity);
793 calld->waiting_ops =
794 gpr_realloc(calld->waiting_ops,
795 calld->waiting_ops_capacity * sizeof(*calld->waiting_ops));
796 }
Craig Tiller57726ca2016-09-12 11:59:45 -0700797 calld->waiting_ops[calld->waiting_ops_count++] = op;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700798 GPR_TIMER_END("add_waiting_locked", 0);
799}
800
801static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld,
802 grpc_error *error) {
803 size_t i;
804 for (i = 0; i < calld->waiting_ops_count; i++) {
805 grpc_transport_stream_op_finish_with_failure(
Craig Tiller57726ca2016-09-12 11:59:45 -0700806 exec_ctx, calld->waiting_ops[i], GRPC_ERROR_REF(error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700807 }
808 calld->waiting_ops_count = 0;
809 GRPC_ERROR_UNREF(error);
810}
811
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700812static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
Craig Tiller57726ca2016-09-12 11:59:45 -0700813 if (calld->waiting_ops_count == 0) {
814 return;
815 }
816
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800817 grpc_subchannel_call *call = GET_CALL(calld);
818 grpc_transport_stream_op **ops = calld->waiting_ops;
819 size_t nops = calld->waiting_ops_count;
820 if (call == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700821 fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED);
822 return;
823 }
824 calld->waiting_ops = NULL;
825 calld->waiting_ops_count = 0;
826 calld->waiting_ops_capacity = 0;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800827 for (size_t i = 0; i < nops; i++) {
828 grpc_subchannel_call_process_op(exec_ctx, call, ops[i]);
829 }
Craig Tiller9efea882017-02-09 13:06:52 -0800830 gpr_free(ops);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700831}
832
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -0700833// Sets calld->method_params and calld->retry_throttle_data.
Craig Tiller11c17d42017-03-13 13:36:34 -0700834// If the method params specify a timeout, populates
835// *per_method_deadline and returns true.
836static bool set_call_method_params_from_service_config_locked(
837 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
838 gpr_timespec *per_method_deadline) {
839 channel_data *chand = elem->channel_data;
840 call_data *calld = elem->call_data;
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -0700841 if (chand->retry_throttle_data != NULL) {
842 calld->retry_throttle_data =
843 grpc_server_retry_throttle_data_ref(chand->retry_throttle_data);
844 }
Craig Tiller11c17d42017-03-13 13:36:34 -0700845 if (chand->method_params_table != NULL) {
846 calld->method_params = grpc_method_config_table_get(
847 exec_ctx, chand->method_params_table, calld->path);
848 if (calld->method_params != NULL) {
849 method_parameters_ref(calld->method_params);
850 if (gpr_time_cmp(calld->method_params->timeout,
851 gpr_time_0(GPR_TIMESPAN)) != 0) {
852 *per_method_deadline =
853 gpr_time_add(calld->call_start_time, calld->method_params->timeout);
854 return true;
855 }
856 }
857 }
858 return false;
859}
Craig Tillerea4a4f12017-03-13 13:36:52 -0700860
Craig Tiller11c17d42017-03-13 13:36:34 -0700861static void apply_final_configuration_locked(grpc_exec_ctx *exec_ctx,
862 grpc_call_element *elem) {
863 /* apply service-config level configuration to the call (now that we're
864 * certain it exists) */
865 call_data *calld = elem->call_data;
866 gpr_timespec per_method_deadline;
867 if (set_call_method_params_from_service_config_locked(exec_ctx, elem,
868 &per_method_deadline)) {
869 // If the deadline from the service config is shorter than the one
870 // from the client API, reset the deadline timer.
871 if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
872 calld->deadline = per_method_deadline;
873 grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
874 }
875 }
876}
877
Craig Tillerbefafe62017-02-09 11:30:54 -0800878static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
879 grpc_error *error) {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700880 grpc_call_element *elem = arg;
881 call_data *calld = elem->call_data;
882 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700883 GPR_ASSERT(calld->creation_phase ==
884 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
Yuchen Zeng19656b12016-09-01 18:00:45 -0700885 grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
886 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700887 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
888 if (calld->connected_subchannel == NULL) {
889 gpr_atm_no_barrier_store(&calld->subchannel_call, 1);
ncteisen4b36a3d2017-03-13 19:08:06 -0700890 fail_locked(exec_ctx, calld,
891 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
892 "Failed to create subchannel", &error, 1));
Mark D. Roth72f6da82016-09-02 13:42:38 -0700893 } else if (GET_CALL(calld) == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700894 /* already cancelled before subchannel became ready */
ncteisen4b36a3d2017-03-13 19:08:06 -0700895 grpc_error *cancellation_error =
896 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
897 "Cancelled before creating subchannel", &error, 1);
David Garcia Quintas68a9e382016-12-13 10:50:40 -0800898 /* if due to deadline, attach the deadline exceeded status to the error */
899 if (gpr_time_cmp(calld->deadline, gpr_now(GPR_CLOCK_MONOTONIC)) < 0) {
900 cancellation_error =
901 grpc_error_set_int(cancellation_error, GRPC_ERROR_INT_GRPC_STATUS,
902 GRPC_STATUS_DEADLINE_EXCEEDED);
903 }
904 fail_locked(exec_ctx, calld, cancellation_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700905 } else {
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700906 /* Create call on subchannel. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700907 grpc_subchannel_call *subchannel_call = NULL;
Craig Tillerfb9d1122017-03-14 09:26:27 -0700908 const grpc_connected_subchannel_call_args call_args = {
Craig Tillerd426cac2017-03-13 12:30:45 -0700909 .pollent = calld->pollent,
910 .path = calld->path,
911 .start_time = calld->call_start_time,
912 .deadline = calld->deadline,
913 .arena = calld->arena};
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700914 grpc_error *new_error = grpc_connected_subchannel_create_call(
Craig Tillerd426cac2017-03-13 12:30:45 -0700915 exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700916 if (new_error != GRPC_ERROR_NONE) {
917 new_error = grpc_error_add_child(new_error, error);
918 subchannel_call = CANCELLED_CALL;
919 fail_locked(exec_ctx, calld, new_error);
920 }
921 gpr_atm_rel_store(&calld->subchannel_call,
922 (gpr_atm)(uintptr_t)subchannel_call);
923 retry_waiting_locked(exec_ctx, calld);
924 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700925 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
926}
927
928static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
929 call_data *calld = elem->call_data;
930 grpc_subchannel_call *subchannel_call = GET_CALL(calld);
931 if (subchannel_call == NULL || subchannel_call == CANCELLED_CALL) {
932 return NULL;
933 } else {
934 return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
935 }
936}
937
Craig Tiller577c9b22015-11-02 14:11:15 -0800938typedef struct {
939 grpc_metadata_batch *initial_metadata;
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800940 uint32_t initial_metadata_flags;
Craig Tillerb5585d42015-11-17 07:18:31 -0800941 grpc_connected_subchannel **connected_subchannel;
Craig Tiller577c9b22015-11-02 14:11:15 -0800942 grpc_closure *on_ready;
943 grpc_call_element *elem;
944 grpc_closure closure;
945} continue_picking_args;
946
Yuchen Zeng144ce652016-09-01 18:19:34 -0700947/** Return true if subchannel is available immediately (in which case on_ready
948 should not be called), or false otherwise (in which case on_ready should be
949 called when the subchannel is available). */
Craig Tillerbefafe62017-02-09 11:30:54 -0800950static bool pick_subchannel_locked(
951 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
952 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
953 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
954 grpc_error *error);
Craig Tiller577c9b22015-11-02 14:11:15 -0800955
Craig Tillerbefafe62017-02-09 11:30:54 -0800956static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg,
957 grpc_error *error) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800958 continue_picking_args *cpa = arg;
Craig Tiller0ede5452016-04-23 12:21:45 -0700959 if (cpa->connected_subchannel == NULL) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800960 /* cancelled, do nothing */
Craig Tiller804ff712016-05-05 16:25:40 -0700961 } else if (error != GRPC_ERROR_NONE) {
Craig Tiller91031da2016-12-28 15:44:25 -0800962 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error));
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700963 } else {
Craig Tillerbefafe62017-02-09 11:30:54 -0800964 if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata,
965 cpa->initial_metadata_flags,
966 cpa->connected_subchannel, cpa->on_ready,
967 GRPC_ERROR_NONE)) {
Craig Tiller91031da2016-12-28 15:44:25 -0800968 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700969 }
Craig Tiller577c9b22015-11-02 14:11:15 -0800970 }
971 gpr_free(cpa);
972}
973
Craig Tillerbefafe62017-02-09 11:30:54 -0800974static bool pick_subchannel_locked(
975 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
976 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
977 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
978 grpc_error *error) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700979 GPR_TIMER_BEGIN("pick_subchannel", 0);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700980
Craig Tiller577c9b22015-11-02 14:11:15 -0800981 channel_data *chand = elem->channel_data;
982 call_data *calld = elem->call_data;
983 continue_picking_args *cpa;
984 grpc_closure *closure;
985
Craig Tillerb5585d42015-11-17 07:18:31 -0800986 GPR_ASSERT(connected_subchannel);
Craig Tiller577c9b22015-11-02 14:11:15 -0800987
Craig Tiller577c9b22015-11-02 14:11:15 -0800988 if (initial_metadata == NULL) {
989 if (chand->lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800990 grpc_lb_policy_cancel_pick_locked(exec_ctx, chand->lb_policy,
991 connected_subchannel,
992 GRPC_ERROR_REF(error));
Craig Tiller577c9b22015-11-02 14:11:15 -0800993 }
994 for (closure = chand->waiting_for_config_closures.head; closure != NULL;
Craig Tiller804ff712016-05-05 16:25:40 -0700995 closure = closure->next_data.next) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800996 cpa = closure->cb_arg;
Craig Tillerb5585d42015-11-17 07:18:31 -0800997 if (cpa->connected_subchannel == connected_subchannel) {
998 cpa->connected_subchannel = NULL;
ncteisen4b36a3d2017-03-13 19:08:06 -0700999 grpc_closure_sched(exec_ctx, cpa->on_ready,
1000 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
1001 "Pick cancelled", &error, 1));
Craig Tiller577c9b22015-11-02 14:11:15 -08001002 }
1003 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001004 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth697a1f62016-09-07 13:35:07 -07001005 GRPC_ERROR_UNREF(error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001006 return true;
Craig Tiller577c9b22015-11-02 14:11:15 -08001007 }
Mark D. Roth697a1f62016-09-07 13:35:07 -07001008 GPR_ASSERT(error == GRPC_ERROR_NONE);
Craig Tiller577c9b22015-11-02 14:11:15 -08001009 if (chand->lb_policy != NULL) {
Craig Tiller2e0788a2017-03-14 06:55:44 -07001010 apply_final_configuration_locked(exec_ctx, elem);
Craig Tiller86c0f8a2015-12-01 20:05:40 -08001011 grpc_lb_policy *lb_policy = chand->lb_policy;
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001012 GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel");
Mark D. Rothe40dd292016-10-05 14:58:37 -07001013 // If the application explicitly set wait_for_ready, use that.
1014 // Otherwise, if the service config specified a value for this
1015 // method, use that.
Mark D. Rothc1c38582016-10-11 11:03:27 -07001016 const bool wait_for_ready_set_from_api =
1017 initial_metadata_flags &
1018 GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
1019 const bool wait_for_ready_set_from_service_config =
Mark D. Roth95b627b2017-02-24 11:02:58 -08001020 calld->method_params != NULL &&
1021 calld->method_params->wait_for_ready != WAIT_FOR_READY_UNSET;
Mark D. Rothc1c38582016-10-11 11:03:27 -07001022 if (!wait_for_ready_set_from_api &&
1023 wait_for_ready_set_from_service_config) {
Mark D. Roth95b627b2017-02-24 11:02:58 -08001024 if (calld->method_params->wait_for_ready == WAIT_FOR_READY_TRUE) {
Mark D. Rothe40dd292016-10-05 14:58:37 -07001025 initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
1026 } else {
1027 initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
1028 }
1029 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001030 const grpc_lb_policy_pick_args inputs = {
Yuchen Zengac8bc422016-10-05 14:00:02 -07001031 initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem,
1032 gpr_inf_future(GPR_CLOCK_MONOTONIC)};
Craig Tiller2400bf52017-02-09 16:25:19 -08001033 const bool result = grpc_lb_policy_pick_locked(
Mark D. Roth55f25b62016-10-12 14:55:20 -07001034 exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, on_ready);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001035 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel");
1036 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth9dab7d52016-10-07 07:48:03 -07001037 return result;
Craig Tiller577c9b22015-11-02 14:11:15 -08001038 }
1039 if (chand->resolver != NULL && !chand->started_resolving) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001040 chand->started_resolving = true;
Craig Tiller906e3bc2015-11-24 07:31:31 -08001041 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -08001042 grpc_resolver_next_locked(exec_ctx, chand->resolver,
1043 &chand->resolver_result,
1044 &chand->on_resolver_result_changed);
Craig Tiller577c9b22015-11-02 14:11:15 -08001045 }
Craig Tiller0eab6972016-04-23 12:59:57 -07001046 if (chand->resolver != NULL) {
1047 cpa = gpr_malloc(sizeof(*cpa));
1048 cpa->initial_metadata = initial_metadata;
1049 cpa->initial_metadata_flags = initial_metadata_flags;
1050 cpa->connected_subchannel = connected_subchannel;
1051 cpa->on_ready = on_ready;
1052 cpa->elem = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -08001053 grpc_closure_init(&cpa->closure, continue_picking_locked, cpa,
1054 grpc_combiner_scheduler(chand->combiner, true));
Craig Tiller804ff712016-05-05 16:25:40 -07001055 grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
1056 GRPC_ERROR_NONE);
Craig Tiller0eab6972016-04-23 12:59:57 -07001057 } else {
ncteisen4b36a3d2017-03-13 19:08:06 -07001058 grpc_closure_sched(exec_ctx, on_ready,
1059 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected"));
Craig Tiller0eab6972016-04-23 12:59:57 -07001060 }
Craig Tillerbfc9adc2016-06-27 13:16:22 -07001061
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001062 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001063 return false;
Craig Tiller577c9b22015-11-02 14:11:15 -08001064}
1065
Craig Tillera8610c02017-02-14 10:05:11 -08001066static void start_transport_stream_op_locked_inner(grpc_exec_ctx *exec_ctx,
1067 grpc_transport_stream_op *op,
1068 grpc_call_element *elem) {
Yuchen Zeng19656b12016-09-01 18:00:45 -07001069 channel_data *chand = elem->channel_data;
Craig Tillera11bfc82017-02-14 09:56:33 -08001070 call_data *calld = elem->call_data;
Craig Tillerbefafe62017-02-09 11:30:54 -08001071 grpc_subchannel_call *call;
1072
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001073 /* need to recheck that another thread hasn't set the call */
1074 call = GET_CALL(calld);
1075 if (call == CANCELLED_CALL) {
Mark D. Rothf28763c2016-09-14 15:18:40 -07001076 grpc_transport_stream_op_finish_with_failure(
1077 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -08001078 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001079 return;
1080 }
1081 if (call != NULL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001082 grpc_subchannel_call_process_op(exec_ctx, call, op);
Craig Tillera11bfc82017-02-14 09:56:33 -08001083 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001084 return;
1085 }
1086 /* if this is a cancellation, then we can raise our cancelled flag */
1087 if (op->cancel_error != GRPC_ERROR_NONE) {
1088 if (!gpr_atm_rel_cas(&calld->subchannel_call, 0,
1089 (gpr_atm)(uintptr_t)CANCELLED_CALL)) {
Craig Tillera11bfc82017-02-14 09:56:33 -08001090 /* recurse to retry */
Craig Tillera8610c02017-02-14 10:05:11 -08001091 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001092 /* early out */
1093 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001094 } else {
Craig Tillerbe9691a2017-02-14 10:00:42 -08001095 /* Stash a copy of cancel_error in our call data, so that we can use
1096 it for subsequent operations. This ensures that if the call is
1097 cancelled before any ops are passed down (e.g., if the deadline
1098 is in the past when the call starts), we can return the right
1099 error to the caller when the first op does get passed down. */
Mark D. Rothf28763c2016-09-14 15:18:40 -07001100 calld->cancel_error = GRPC_ERROR_REF(op->cancel_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001101 switch (calld->creation_phase) {
1102 case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
1103 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error));
1104 break;
1105 case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
Craig Tillerbefafe62017-02-09 11:30:54 -08001106 pick_subchannel_locked(exec_ctx, elem, NULL, 0,
1107 &calld->connected_subchannel, NULL,
1108 GRPC_ERROR_REF(op->cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001109 break;
1110 }
Mark D. Roth72f6da82016-09-02 13:42:38 -07001111 grpc_transport_stream_op_finish_with_failure(
1112 exec_ctx, op, GRPC_ERROR_REF(op->cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -08001113 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001114 return;
1115 }
1116 }
1117 /* if we don't have a subchannel, try to get one */
1118 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
1119 calld->connected_subchannel == NULL &&
1120 op->send_initial_metadata != NULL) {
1121 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
Craig Tillerbefafe62017-02-09 11:30:54 -08001122 grpc_closure_init(&calld->next_step, subchannel_ready_locked, elem,
1123 grpc_combiner_scheduler(chand->combiner, true));
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001124 GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
Yuchen Zeng144ce652016-09-01 18:19:34 -07001125 /* If a subchannel is not available immediately, the polling entity from
1126 call_data should be provided to channel_data's interested_parties, so
1127 that IO of the lb_policy and resolver could be done under it. */
Craig Tillerbefafe62017-02-09 11:30:54 -08001128 if (pick_subchannel_locked(exec_ctx, elem, op->send_initial_metadata,
1129 op->send_initial_metadata_flags,
1130 &calld->connected_subchannel, &calld->next_step,
1131 GRPC_ERROR_NONE)) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001132 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
1133 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
Yuchen Zeng19656b12016-09-01 18:00:45 -07001134 } else {
Yuchen Zeng19656b12016-09-01 18:00:45 -07001135 grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
1136 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001137 }
1138 }
1139 /* if we've got a subchannel, then let's ask it to create a call */
1140 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
1141 calld->connected_subchannel != NULL) {
1142 grpc_subchannel_call *subchannel_call = NULL;
Craig Tillerfb9d1122017-03-14 09:26:27 -07001143 const grpc_connected_subchannel_call_args call_args = {
Craig Tillerd426cac2017-03-13 12:30:45 -07001144 .pollent = calld->pollent,
1145 .path = calld->path,
1146 .start_time = calld->call_start_time,
1147 .deadline = calld->deadline,
1148 .arena = calld->arena};
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001149 grpc_error *error = grpc_connected_subchannel_create_call(
Craig Tillerd426cac2017-03-13 12:30:45 -07001150 exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001151 if (error != GRPC_ERROR_NONE) {
1152 subchannel_call = CANCELLED_CALL;
1153 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
1154 grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
1155 }
1156 gpr_atm_rel_store(&calld->subchannel_call,
1157 (gpr_atm)(uintptr_t)subchannel_call);
1158 retry_waiting_locked(exec_ctx, calld);
Craig Tillera11bfc82017-02-14 09:56:33 -08001159 /* recurse to retry */
Craig Tillera8610c02017-02-14 10:05:11 -08001160 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001161 /* early out */
1162 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001163 }
1164 /* nothing to be done but wait */
1165 add_waiting_locked(calld, op);
Craig Tillera11bfc82017-02-14 09:56:33 -08001166}
1167
Mark D. Rothde144102017-03-15 10:11:03 -07001168static void on_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001169 grpc_call_element *elem = arg;
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001170 call_data *calld = elem->call_data;
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -07001171 if (calld->retry_throttle_data != NULL) {
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001172 if (error == GRPC_ERROR_NONE) {
1173 grpc_server_retry_throttle_data_record_success(
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -07001174 calld->retry_throttle_data);
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001175 } else {
1176 // TODO(roth): In a subsequent PR, check the return value here and
Mark D. Rothb3322562017-02-23 14:38:02 -08001177 // decide whether or not to retry. Note that we should only
1178 // record failures whose statuses match the configured retryable
1179 // or non-fatal status codes.
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001180 grpc_server_retry_throttle_data_record_failure(
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -07001181 calld->retry_throttle_data);
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001182 }
1183 }
Mark D. Roth95039b52017-02-24 07:59:45 -08001184 grpc_closure_run(exec_ctx, calld->original_on_complete,
1185 GRPC_ERROR_REF(error));
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001186}
1187
Mark D. Roth95b627b2017-02-24 11:02:58 -08001188static void start_transport_stream_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
Mark D. Roth722de8d2017-02-27 10:50:44 -08001189 grpc_error *error_ignored) {
Mark D. Roth95b627b2017-02-24 11:02:58 -08001190 GPR_TIMER_BEGIN("start_transport_stream_op_locked", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001191
1192 grpc_transport_stream_op *op = arg;
1193 grpc_call_element *elem = op->handler_private.args[0];
1194 call_data *calld = elem->call_data;
1195
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001196 if (op->recv_trailing_metadata != NULL) {
1197 GPR_ASSERT(op->on_complete != NULL);
1198 calld->original_on_complete = op->on_complete;
Mark D. Rothde144102017-03-15 10:11:03 -07001199 grpc_closure_init(&calld->on_complete, on_complete, elem,
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -07001200 grpc_schedule_on_exec_ctx);
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001201 op->on_complete = &calld->on_complete;
1202 }
1203
Craig Tillera8610c02017-02-14 10:05:11 -08001204 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001205
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001206 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
1207 "start_transport_stream_op");
Mark D. Roth95b627b2017-02-24 11:02:58 -08001208 GPR_TIMER_END("start_transport_stream_op_locked", 0);
Craig Tillerbefafe62017-02-09 11:30:54 -08001209}
1210
Craig Tillerbe9691a2017-02-14 10:00:42 -08001211/* The logic here is fairly complicated, due to (a) the fact that we
1212 need to handle the case where we receive the send op before the
1213 initial metadata op, and (b) the need for efficiency, especially in
1214 the streaming case.
1215
1216 We use double-checked locking to initially see if initialization has been
1217 performed. If it has not, we acquire the combiner and perform initialization.
1218 If it has, we proceed on the fast path. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001219static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
1220 grpc_call_element *elem,
1221 grpc_transport_stream_op *op) {
1222 call_data *calld = elem->call_data;
1223 channel_data *chand = elem->channel_data;
1224 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
1225 grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op);
1226 /* try to (atomically) get the call */
1227 grpc_subchannel_call *call = GET_CALL(calld);
1228 GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
1229 if (call == CANCELLED_CALL) {
1230 grpc_transport_stream_op_finish_with_failure(
1231 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
1232 GPR_TIMER_END("cc_start_transport_stream_op", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001233 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001234 return;
1235 }
1236 if (call != NULL) {
1237 grpc_subchannel_call_process_op(exec_ctx, call, op);
1238 GPR_TIMER_END("cc_start_transport_stream_op", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001239 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001240 return;
1241 }
1242 /* we failed; lock and figure out what to do */
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001243 GRPC_CALL_STACK_REF(calld->owning_call, "start_transport_stream_op");
Craig Tiller4a84bdd2017-02-14 09:48:41 -08001244 op->handler_private.args[0] = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -08001245 grpc_closure_sched(
1246 exec_ctx,
Craig Tiller4a84bdd2017-02-14 09:48:41 -08001247 grpc_closure_init(&op->handler_private.closure,
Mark D. Roth95b627b2017-02-24 11:02:58 -08001248 start_transport_stream_op_locked, op,
Craig Tillerbefafe62017-02-09 11:30:54 -08001249 grpc_combiner_scheduler(chand->combiner, false)),
1250 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001251 GPR_TIMER_END("cc_start_transport_stream_op", 0);
1252}
1253
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001254/* Constructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001255static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
1256 grpc_call_element *elem,
Craig Tillerc52ba3a2017-02-15 22:57:43 -08001257 const grpc_call_element_args *args) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001258 call_data *calld = elem->call_data;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001259 // Initialize data members.
1260 grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001261 calld->path = grpc_slice_ref_internal(args->path);
Mark D. Rothff08f332016-10-14 13:01:01 -07001262 calld->call_start_time = args->start_time;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001263 calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001264 calld->owning_call = args->call_stack;
Craig Tillerd426cac2017-03-13 12:30:45 -07001265 calld->arena = args->arena;
Craig Tiller2c3d0a92017-02-28 15:26:24 -08001266 grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
Mark D. Roth0badbe82016-06-23 10:15:12 -07001267 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001268}
1269
1270/* Destructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001271static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
1272 grpc_call_element *elem,
1273 const grpc_call_final_info *final_info,
Craig Tillerd426cac2017-03-13 12:30:45 -07001274 grpc_closure *then_schedule_closure) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001275 call_data *calld = elem->call_data;
Mark D. Rothf28763c2016-09-14 15:18:40 -07001276 grpc_deadline_state_destroy(exec_ctx, elem);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001277 grpc_slice_unref_internal(exec_ctx, calld->path);
Mark D. Roth95b627b2017-02-24 11:02:58 -08001278 if (calld->method_params != NULL) {
1279 method_parameters_unref(calld->method_params);
1280 }
Mark D. Rothf28763c2016-09-14 15:18:40 -07001281 GRPC_ERROR_UNREF(calld->cancel_error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001282 grpc_subchannel_call *call = GET_CALL(calld);
1283 if (call != NULL && call != CANCELLED_CALL) {
Craig Tillerd426cac2017-03-13 12:30:45 -07001284 grpc_subchannel_call_set_cleanup_closure(call, then_schedule_closure);
1285 then_schedule_closure = NULL;
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001286 GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
1287 }
1288 GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001289 GPR_ASSERT(calld->waiting_ops_count == 0);
Craig Tiller693d3942016-10-27 16:51:25 -07001290 if (calld->connected_subchannel != NULL) {
1291 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel,
1292 "picked");
1293 }
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001294 gpr_free(calld->waiting_ops);
Craig Tillerd426cac2017-03-13 12:30:45 -07001295 grpc_closure_sched(exec_ctx, then_schedule_closure, GRPC_ERROR_NONE);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001296}
1297
David Garcia Quintasf72eb972016-05-03 18:28:09 -07001298static void cc_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
1299 grpc_call_element *elem,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001300 grpc_polling_entity *pollent) {
Craig Tiller577c9b22015-11-02 14:11:15 -08001301 call_data *calld = elem->call_data;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001302 calld->pollent = pollent;
Craig Tiller577c9b22015-11-02 14:11:15 -08001303}
1304
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001305/*************************************************************************
1306 * EXPORTED SYMBOLS
1307 */
1308
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001309const grpc_channel_filter grpc_client_channel_filter = {
Craig Tillerf40df232016-03-25 13:38:14 -07001310 cc_start_transport_stream_op,
1311 cc_start_transport_op,
1312 sizeof(call_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001313 cc_init_call_elem,
David Garcia Quintas4afce7e2016-04-18 16:25:17 -07001314 cc_set_pollset_or_pollset_set,
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001315 cc_destroy_call_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001316 sizeof(channel_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001317 cc_init_channel_elem,
1318 cc_destroy_channel_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001319 cc_get_peer,
Mark D. Rothb2d24882016-10-27 15:44:07 -07001320 cc_get_channel_info,
Craig Tillerf40df232016-03-25 13:38:14 -07001321 "client-channel",
Craig Tiller87d5b192015-04-16 14:37:57 -07001322};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001323
Craig Tiller613dafa2017-02-09 12:00:43 -08001324static void try_to_connect_locked(grpc_exec_ctx *exec_ctx, void *arg,
1325 grpc_error *error_ignored) {
1326 channel_data *chand = arg;
1327 if (chand->lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -08001328 grpc_lb_policy_exit_idle_locked(exec_ctx, chand->lb_policy);
Craig Tiller613dafa2017-02-09 12:00:43 -08001329 } else {
1330 chand->exit_idle_when_lb_policy_arrives = true;
1331 if (!chand->started_resolving && chand->resolver != NULL) {
1332 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
1333 chand->started_resolving = true;
Craig Tiller972470b2017-02-09 15:05:36 -08001334 grpc_resolver_next_locked(exec_ctx, chand->resolver,
1335 &chand->resolver_result,
1336 &chand->on_resolver_result_changed);
Craig Tiller613dafa2017-02-09 12:00:43 -08001337 }
1338 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001339 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001340}
1341
Craig Tillera82950e2015-09-22 12:33:20 -07001342grpc_connectivity_state grpc_client_channel_check_connectivity_state(
1343 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001344 channel_data *chand = elem->channel_data;
Craig Tillera8610c02017-02-14 10:05:11 -08001345 grpc_connectivity_state out =
1346 grpc_connectivity_state_check(&chand->state_tracker);
Craig Tillera82950e2015-09-22 12:33:20 -07001347 if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001348 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001349 grpc_closure_sched(
1350 exec_ctx,
1351 grpc_closure_create(try_to_connect_locked, chand,
1352 grpc_combiner_scheduler(chand->combiner, false)),
1353 GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -07001354 }
Craig Tiller48cb07c2015-07-15 16:16:15 -07001355 return out;
1356}
1357
Craig Tiller86c99582015-11-25 15:22:26 -08001358typedef struct {
1359 channel_data *chand;
1360 grpc_pollset *pollset;
1361 grpc_closure *on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001362 grpc_connectivity_state *state;
Craig Tiller86c99582015-11-25 15:22:26 -08001363 grpc_closure my_closure;
1364} external_connectivity_watcher;
1365
Craig Tiller1d881fb2015-12-01 07:39:04 -08001366static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -07001367 grpc_error *error) {
Craig Tiller86c99582015-11-25 15:22:26 -08001368 external_connectivity_watcher *w = arg;
1369 grpc_closure *follow_up = w->on_complete;
Craig Tiller69b093b2016-02-25 19:04:07 -08001370 grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
Craig Tiller1d881fb2015-12-01 07:39:04 -08001371 w->pollset);
1372 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
1373 "external_connectivity_watcher");
Craig Tiller86c99582015-11-25 15:22:26 -08001374 gpr_free(w);
Craig Tiller613dafa2017-02-09 12:00:43 -08001375 grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
1376}
1377
Craig Tillera8610c02017-02-14 10:05:11 -08001378static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg,
1379 grpc_error *error_ignored) {
Craig Tiller613dafa2017-02-09 12:00:43 -08001380 external_connectivity_watcher *w = arg;
1381 grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
1382 grpc_schedule_on_exec_ctx);
1383 grpc_connectivity_state_notify_on_state_change(
1384 exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
Craig Tiller86c99582015-11-25 15:22:26 -08001385}
1386
Craig Tillera82950e2015-09-22 12:33:20 -07001387void grpc_client_channel_watch_connectivity_state(
Craig Tiller906e3bc2015-11-24 07:31:31 -08001388 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
Craig Tillera82950e2015-09-22 12:33:20 -07001389 grpc_connectivity_state *state, grpc_closure *on_complete) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001390 channel_data *chand = elem->channel_data;
Craig Tiller86c99582015-11-25 15:22:26 -08001391 external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
1392 w->chand = chand;
1393 w->pollset = pollset;
1394 w->on_complete = on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001395 w->state = state;
Craig Tiller69b093b2016-02-25 19:04:07 -08001396 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
Craig Tiller1d881fb2015-12-01 07:39:04 -08001397 GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
1398 "external_connectivity_watcher");
Craig Tiller613dafa2017-02-09 12:00:43 -08001399 grpc_closure_sched(
1400 exec_ctx,
Craig Tillera8610c02017-02-14 10:05:11 -08001401 grpc_closure_init(&w->my_closure, watch_connectivity_state_locked, w,
Craig Tiller613dafa2017-02-09 12:00:43 -08001402 grpc_combiner_scheduler(chand->combiner, true)),
1403 GRPC_ERROR_NONE);
Craig Tiller48cb07c2015-07-15 16:16:15 -07001404}