blob: 4bd153e8ac733765940edf47cca66871833f9db7 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
Craig Tiller9eb0fde2017-03-31 16:59:30 -070034#include "src/core/ext/filters/client_channel/client_channel.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080035
Mark D. Roth4c0fe492016-08-31 13:51:55 -070036#include <stdbool.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080037#include <stdio.h>
Craig Tillereb3b12e2015-06-26 14:42:49 -070038#include <string.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080039
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080040#include <grpc/support/alloc.h>
41#include <grpc/support/log.h>
Mark D. Rothb2d24882016-10-27 15:44:07 -070042#include <grpc/support/string_util.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080043#include <grpc/support/sync.h>
44#include <grpc/support/useful.h>
45
Craig Tiller9eb0fde2017-03-31 16:59:30 -070046#include "src/core/ext/filters/client_channel/http_connect_handshaker.h"
47#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
48#include "src/core/ext/filters/client_channel/proxy_mapper_registry.h"
49#include "src/core/ext/filters/client_channel/resolver_registry.h"
50#include "src/core/ext/filters/client_channel/retry_throttle.h"
51#include "src/core/ext/filters/client_channel/subchannel.h"
Craig Tiller9533d042016-03-25 17:11:06 -070052#include "src/core/lib/channel/channel_args.h"
53#include "src/core/lib/channel/connected_channel.h"
Alexander Polcynf5521c32017-04-26 14:18:39 -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
Alexander Polcynf5521c32017-04-26 14:18:39 -070099static void *method_parameters_copy(void *value) {
100 return method_parameters_ref(value);
101}
102
Mark D. Roth95b627b2017-02-24 11:02:58 -0800103static 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
Alexander Polcynf5521c32017-04-26 14:18:39 -0700107static const grpc_slice_hash_table_vtable method_parameters_vtable = {
108 method_parameters_free, method_parameters_copy};
109
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
Alexander Polcync3b1f182017-04-18 13:51:36 -0700177struct external_connectivity_watcher;
178
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700179/*************************************************************************
180 * CHANNEL-WIDE FUNCTIONS
181 */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800182
Craig Tiller800dacb2015-10-06 09:10:26 -0700183typedef struct client_channel_channel_data {
Craig Tillerf5f17122015-06-25 08:47:26 -0700184 /** resolver for this channel */
185 grpc_resolver *resolver;
Craig Tiller20a3c352015-08-05 08:39:50 -0700186 /** have we started resolving this channel */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700187 bool started_resolving;
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700188 /** client channel factory */
189 grpc_client_channel_factory *client_channel_factory;
Craig Tillerf5f17122015-06-25 08:47:26 -0700190
Craig Tillerbefafe62017-02-09 11:30:54 -0800191 /** combiner protecting all variables below in this data structure */
192 grpc_combiner *combiner;
Mark D. Roth046cf762016-09-26 11:13:51 -0700193 /** currently active load balancer */
Craig Tillerf5f17122015-06-25 08:47:26 -0700194 grpc_lb_policy *lb_policy;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800195 /** retry throttle data */
196 grpc_server_retry_throttle_data *retry_throttle_data;
Mark D. Roth9d480942016-10-19 14:18:05 -0700197 /** maps method names to method_parameters structs */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800198 grpc_slice_hash_table *method_params_table;
Mark D. Roth046cf762016-09-26 11:13:51 -0700199 /** incoming resolver result - set by resolver.next() */
Mark D. Rothaf842452016-10-21 15:05:15 -0700200 grpc_channel_args *resolver_result;
Craig Tiller3f475422015-06-25 10:43:05 -0700201 /** a list of closures that are all waiting for config to come in */
Craig Tillerd9ccbbf2015-09-22 09:30:00 -0700202 grpc_closure_list waiting_for_config_closures;
Craig Tiller3f475422015-06-25 10:43:05 -0700203 /** resolver callback */
Mark D. Rothff4df062016-08-22 15:02:49 -0700204 grpc_closure on_resolver_result_changed;
Craig Tiller3f475422015-06-25 10:43:05 -0700205 /** connectivity state being tracked */
Craig Tillerca3e9d32015-06-27 18:37:27 -0700206 grpc_connectivity_state_tracker state_tracker;
Craig Tiller48cb07c2015-07-15 16:16:15 -0700207 /** when an lb_policy arrives, should we try to exit idle */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700208 bool exit_idle_when_lb_policy_arrives;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800209 /** owning stack */
210 grpc_channel_stack *owning_stack;
Craig Tiller69b093b2016-02-25 19:04:07 -0800211 /** interested parties (owned) */
212 grpc_pollset_set *interested_parties;
Craig Tiller613dafa2017-02-09 12:00:43 -0800213
Alexander Polcync3b1f182017-04-18 13:51:36 -0700214 /* external_connectivity_watcher_list head is guarded by its own mutex, since
215 * counts need to be grabbed immediately without polling on a cq */
216 gpr_mu external_connectivity_watcher_list_mu;
217 struct external_connectivity_watcher *external_connectivity_watcher_list_head;
218
Craig Tiller613dafa2017-02-09 12:00:43 -0800219 /* the following properties are guarded by a mutex since API's require them
Craig Tiller46dd7902017-02-23 09:42:16 -0800220 to be instantaneously available */
Craig Tiller613dafa2017-02-09 12:00:43 -0800221 gpr_mu info_mu;
222 char *info_lb_policy_name;
223 /** service config in JSON form */
224 char *info_service_config_json;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800225} channel_data;
226
Craig Tillerd6c98df2015-08-18 09:33:44 -0700227/** We create one watcher for each new lb_policy that is returned from a
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700228 resolver, to watch for state changes from the lb_policy. When a state
229 change is seen, we update the channel, and create a new watcher. */
Craig Tillera82950e2015-09-22 12:33:20 -0700230typedef struct {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700231 channel_data *chand;
Craig Tiller33825112015-09-18 07:44:19 -0700232 grpc_closure on_changed;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700233 grpc_connectivity_state state;
234 grpc_lb_policy *lb_policy;
235} lb_policy_connectivity_watcher;
236
Craig Tiller2400bf52017-02-09 16:25:19 -0800237static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
238 grpc_lb_policy *lb_policy,
239 grpc_connectivity_state current_state);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700240
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800241static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
242 channel_data *chand,
243 grpc_connectivity_state state,
Craig Tiller804ff712016-05-05 16:25:40 -0700244 grpc_error *error,
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800245 const char *reason) {
Alexander Polcynf5521c32017-04-26 14:18:39 -0700246 if ((state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
247 state == GRPC_CHANNEL_SHUTDOWN) &&
248 chand->lb_policy != NULL) {
249 /* cancel picks with wait_for_ready=false */
250 grpc_lb_policy_cancel_picks_locked(
251 exec_ctx, chand->lb_policy,
252 /* mask= */ GRPC_INITIAL_METADATA_WAIT_FOR_READY,
253 /* check= */ 0, GRPC_ERROR_REF(error));
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800254 }
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700255 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, error,
256 reason);
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800257}
258
Craig Tiller804ff712016-05-05 16:25:40 -0700259static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
Craig Tillerbefafe62017-02-09 11:30:54 -0800260 void *arg, grpc_error *error) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700261 lb_policy_connectivity_watcher *w = arg;
Craig Tiller5d44c062015-07-01 08:55:28 -0700262 grpc_connectivity_state publish_state = w->state;
Craig Tillerc5de8352017-02-09 14:08:05 -0800263 /* check if the notification is for the latest policy */
264 if (w->lb_policy == w->chand->lb_policy) {
265 if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
266 publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Craig Tiller972470b2017-02-09 15:05:36 -0800267 grpc_resolver_channel_saw_error_locked(exec_ctx, w->chand->resolver);
Craig Tillerc5de8352017-02-09 14:08:05 -0800268 GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
269 w->chand->lb_policy = NULL;
270 }
271 set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
272 GRPC_ERROR_REF(error), "lb_changed");
273 if (w->state != GRPC_CHANNEL_SHUTDOWN) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800274 watch_lb_policy_locked(exec_ctx, w->chand, w->lb_policy, w->state);
Craig Tillerc5de8352017-02-09 14:08:05 -0800275 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800276 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700277
Craig Tiller906e3bc2015-11-24 07:31:31 -0800278 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
Craig Tillera82950e2015-09-22 12:33:20 -0700279 gpr_free(w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700280}
281
Craig Tiller2400bf52017-02-09 16:25:19 -0800282static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
283 grpc_lb_policy *lb_policy,
284 grpc_connectivity_state current_state) {
Craig Tillera82950e2015-09-22 12:33:20 -0700285 lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
Craig Tiller906e3bc2015-11-24 07:31:31 -0800286 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700287
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700288 w->chand = chand;
Craig Tillerbefafe62017-02-09 11:30:54 -0800289 grpc_closure_init(&w->on_changed, on_lb_policy_state_changed_locked, w,
290 grpc_combiner_scheduler(chand->combiner, false));
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700291 w->state = current_state;
292 w->lb_policy = lb_policy;
Craig Tiller2400bf52017-02-09 16:25:19 -0800293 grpc_lb_policy_notify_on_state_change_locked(exec_ctx, lb_policy, &w->state,
294 &w->on_changed);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700295}
296
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800297typedef struct {
298 char *server_name;
299 grpc_server_retry_throttle_data *retry_throttle_data;
300} service_config_parsing_state;
301
302static void parse_retry_throttle_params(const grpc_json *field, void *arg) {
303 service_config_parsing_state *parsing_state = arg;
304 if (strcmp(field->key, "retryThrottling") == 0) {
305 if (parsing_state->retry_throttle_data != NULL) return; // Duplicate.
306 if (field->type != GRPC_JSON_OBJECT) return;
307 int max_milli_tokens = 0;
308 int milli_token_ratio = 0;
309 for (grpc_json *sub_field = field->child; sub_field != NULL;
310 sub_field = sub_field->next) {
Mark D. Rothb3322562017-02-23 14:38:02 -0800311 if (sub_field->key == NULL) return;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800312 if (strcmp(sub_field->key, "maxTokens") == 0) {
313 if (max_milli_tokens != 0) return; // Duplicate.
314 if (sub_field->type != GRPC_JSON_NUMBER) return;
315 max_milli_tokens = gpr_parse_nonnegative_int(sub_field->value);
316 if (max_milli_tokens == -1) return;
317 max_milli_tokens *= 1000;
318 } else if (strcmp(sub_field->key, "tokenRatio") == 0) {
319 if (milli_token_ratio != 0) return; // Duplicate.
320 if (sub_field->type != GRPC_JSON_NUMBER) return;
321 // We support up to 3 decimal digits.
322 size_t whole_len = strlen(sub_field->value);
323 uint32_t multiplier = 1;
324 uint32_t decimal_value = 0;
325 const char *decimal_point = strchr(sub_field->value, '.');
326 if (decimal_point != NULL) {
327 whole_len = (size_t)(decimal_point - sub_field->value);
328 multiplier = 1000;
329 size_t decimal_len = strlen(decimal_point + 1);
330 if (decimal_len > 3) decimal_len = 3;
331 if (!gpr_parse_bytes_to_uint32(decimal_point + 1, decimal_len,
332 &decimal_value)) {
333 return;
334 }
335 uint32_t decimal_multiplier = 1;
336 for (size_t i = 0; i < (3 - decimal_len); ++i) {
337 decimal_multiplier *= 10;
338 }
339 decimal_value *= decimal_multiplier;
340 }
341 uint32_t whole_value;
342 if (!gpr_parse_bytes_to_uint32(sub_field->value, whole_len,
343 &whole_value)) {
344 return;
345 }
346 milli_token_ratio = (int)((whole_value * multiplier) + decimal_value);
Mark D. Rothb3322562017-02-23 14:38:02 -0800347 if (milli_token_ratio <= 0) return;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800348 }
349 }
350 parsing_state->retry_throttle_data =
351 grpc_retry_throttle_map_get_data_for_server(
352 parsing_state->server_name, max_milli_tokens, milli_token_ratio);
353 }
354}
355
Craig Tillerbefafe62017-02-09 11:30:54 -0800356static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
357 void *arg, grpc_error *error) {
Craig Tiller3f475422015-06-25 10:43:05 -0700358 channel_data *chand = arg;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700359 char *lb_policy_name = NULL;
Craig Tiller3f475422015-06-25 10:43:05 -0700360 grpc_lb_policy *lb_policy = NULL;
361 grpc_lb_policy *old_lb_policy;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800362 grpc_slice_hash_table *method_params_table = NULL;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700363 grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700364 bool exit_idle = false;
ncteisen4b36a3d2017-03-13 19:08:06 -0700365 grpc_error *state_error =
366 GRPC_ERROR_CREATE_FROM_STATIC_STRING("No load balancing policy");
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800367 char *service_config_json = NULL;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800368 service_config_parsing_state parsing_state;
369 memset(&parsing_state, 0, sizeof(parsing_state));
Craig Tiller3f475422015-06-25 10:43:05 -0700370
Mark D. Roth046cf762016-09-26 11:13:51 -0700371 if (chand->resolver_result != NULL) {
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700372 // Find LB policy name.
Mark D. Rothaf842452016-10-21 15:05:15 -0700373 const grpc_arg *channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700374 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_POLICY_NAME);
Mark D. Rothaf842452016-10-21 15:05:15 -0700375 if (channel_arg != NULL) {
376 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
377 lb_policy_name = channel_arg->value.string;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700378 }
Alexander Polcynf5521c32017-04-26 14:18:39 -0700379 // Special case: If all of the addresses are balancer addresses,
380 // assume that we should use the grpclb policy, regardless of what the
381 // resolver actually specified.
Mark D. Rothaf842452016-10-21 15:05:15 -0700382 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700383 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES);
David Garcia Quintas143cb772017-03-31 13:39:27 -0700384 if (channel_arg != NULL && channel_arg->type == GRPC_ARG_POINTER) {
Mark D. Roth557c9902016-10-24 11:12:05 -0700385 grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
Alexander Polcynf5521c32017-04-26 14:18:39 -0700386 bool found_backend_address = false;
Mark D. Rothaf842452016-10-21 15:05:15 -0700387 for (size_t i = 0; i < addresses->num_addresses; ++i) {
Alexander Polcynf5521c32017-04-26 14:18:39 -0700388 if (!addresses->addresses[i].is_balancer) {
389 found_backend_address = true;
Mark D. Rothaf842452016-10-21 15:05:15 -0700390 break;
391 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700392 }
Alexander Polcynf5521c32017-04-26 14:18:39 -0700393 if (!found_backend_address) {
Mark D. Rothaf842452016-10-21 15:05:15 -0700394 if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) {
395 gpr_log(GPR_INFO,
Alexander Polcynf5521c32017-04-26 14:18:39 -0700396 "resolver requested LB policy %s but provided only balancer "
397 "addresses, no backend addresses -- forcing use of grpclb LB "
398 "policy",
Mark D. Roth5f40e5d2016-10-24 13:09:05 -0700399 lb_policy_name);
Mark D. Rothaf842452016-10-21 15:05:15 -0700400 }
401 lb_policy_name = "grpclb";
Mark D. Roth88405f72016-10-03 08:24:52 -0700402 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700403 }
404 // Use pick_first if nothing was specified and we didn't select grpclb
405 // above.
406 if (lb_policy_name == NULL) lb_policy_name = "pick_first";
Mark D. Roth41124992016-11-03 11:22:20 -0700407 // Instantiate LB policy.
408 grpc_lb_policy_args lb_policy_args;
409 lb_policy_args.args = chand->resolver_result;
410 lb_policy_args.client_channel_factory = chand->client_channel_factory;
Craig Tiller2400bf52017-02-09 16:25:19 -0800411 lb_policy_args.combiner = chand->combiner;
Mark D. Roth88405f72016-10-03 08:24:52 -0700412 lb_policy =
413 grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700414 if (lb_policy != NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -0700415 GRPC_LB_POLICY_REF(lb_policy, "config_change");
Craig Tillerf707d622016-05-06 14:26:12 -0700416 GRPC_ERROR_UNREF(state_error);
Craig Tiller2400bf52017-02-09 16:25:19 -0800417 state = grpc_lb_policy_check_connectivity_locked(exec_ctx, lb_policy,
418 &state_error);
Craig Tiller45724b32015-09-22 10:42:19 -0700419 }
Mark D. Roth41124992016-11-03 11:22:20 -0700420 // Find service config.
Mark D. Rothaf842452016-10-21 15:05:15 -0700421 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700422 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVICE_CONFIG);
Mark D. Roth046cf762016-09-26 11:13:51 -0700423 if (channel_arg != NULL) {
Mark D. Roth9ec28af2016-11-03 12:32:39 -0700424 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800425 service_config_json = gpr_strdup(channel_arg->value.string);
Mark D. Roth70a1abd2016-11-04 09:26:37 -0700426 grpc_service_config *service_config =
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800427 grpc_service_config_create(service_config_json);
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700428 if (service_config != NULL) {
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800429 channel_arg =
430 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVER_URI);
431 GPR_ASSERT(channel_arg != NULL);
432 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -0700433 grpc_uri *uri =
434 grpc_uri_parse(exec_ctx, channel_arg->value.string, true);
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800435 GPR_ASSERT(uri->path[0] != '\0');
436 parsing_state.server_name =
437 uri->path[0] == '/' ? uri->path + 1 : uri->path;
438 grpc_service_config_parse_global_params(
439 service_config, parse_retry_throttle_params, &parsing_state);
440 parsing_state.server_name = NULL;
441 grpc_uri_destroy(uri);
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700442 method_params_table = grpc_service_config_create_method_config_table(
Craig Tillerb28c7e82016-11-18 10:29:04 -0800443 exec_ctx, service_config, method_parameters_create_from_json,
Alexander Polcynf5521c32017-04-26 14:18:39 -0700444 &method_parameters_vtable);
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700445 grpc_service_config_destroy(service_config);
446 }
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700447 }
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700448 // Before we clean up, save a copy of lb_policy_name, since it might
449 // be pointing to data inside chand->resolver_result.
450 // The copy will be saved in chand->lb_policy_name below.
451 lb_policy_name = gpr_strdup(lb_policy_name);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800452 grpc_channel_args_destroy(exec_ctx, chand->resolver_result);
Mark D. Roth046cf762016-09-26 11:13:51 -0700453 chand->resolver_result = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700454 }
455
Craig Tiller86c99582015-11-25 15:22:26 -0800456 if (lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800457 grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties,
458 chand->interested_parties);
Craig Tiller86c99582015-11-25 15:22:26 -0800459 }
460
Craig Tiller613dafa2017-02-09 12:00:43 -0800461 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700462 if (lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800463 gpr_free(chand->info_lb_policy_name);
464 chand->info_lb_policy_name = lb_policy_name;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700465 }
Craig Tiller3f475422015-06-25 10:43:05 -0700466 old_lb_policy = chand->lb_policy;
467 chand->lb_policy = lb_policy;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800468 if (service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800469 gpr_free(chand->info_service_config_json);
470 chand->info_service_config_json = service_config_json;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800471 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800472 gpr_mu_unlock(&chand->info_mu);
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800473
474 if (chand->retry_throttle_data != NULL) {
475 grpc_server_retry_throttle_data_unref(chand->retry_throttle_data);
476 }
477 chand->retry_throttle_data = parsing_state.retry_throttle_data;
Mark D. Roth9d480942016-10-19 14:18:05 -0700478 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800479 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth046cf762016-09-26 11:13:51 -0700480 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700481 chand->method_params_table = method_params_table;
Craig Tiller0ede5452016-04-23 12:21:45 -0700482 if (lb_policy != NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -0800483 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller0ede5452016-04-23 12:21:45 -0700484 } else if (chand->resolver == NULL /* disconnected */) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700485 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
486 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
487 "Channel disconnected", &error, 1));
Craig Tiller91031da2016-12-28 15:44:25 -0800488 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tillera82950e2015-09-22 12:33:20 -0700489 }
490 if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
491 GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700492 exit_idle = true;
493 chand->exit_idle_when_lb_policy_arrives = false;
Craig Tillera82950e2015-09-22 12:33:20 -0700494 }
Craig Tiller98465032015-06-29 14:36:42 -0700495
Craig Tiller804ff712016-05-05 16:25:40 -0700496 if (error == GRPC_ERROR_NONE && chand->resolver) {
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700497 set_channel_connectivity_state_locked(
498 exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700499 if (lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800500 watch_lb_policy_locked(exec_ctx, chand, lb_policy, state);
Craig Tiller45724b32015-09-22 10:42:19 -0700501 }
Craig Tiller906e3bc2015-11-24 07:31:31 -0800502 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -0800503 grpc_resolver_next_locked(exec_ctx, chand->resolver,
504 &chand->resolver_result,
505 &chand->on_resolver_result_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700506 } else {
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800507 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800508 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800509 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
510 chand->resolver = NULL;
511 }
Craig Tiller804ff712016-05-05 16:25:40 -0700512 grpc_error *refs[] = {error, state_error};
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800513 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700514 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
ncteisen4b36a3d2017-03-13 19:08:06 -0700515 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
516 "Got config after disconnection", refs, GPR_ARRAY_SIZE(refs)),
Craig Tiller804ff712016-05-05 16:25:40 -0700517 "resolver_gone");
Craig Tillera82950e2015-09-22 12:33:20 -0700518 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700519
Craig Tillera82950e2015-09-22 12:33:20 -0700520 if (exit_idle) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800521 grpc_lb_policy_exit_idle_locked(exec_ctx, lb_policy);
Craig Tillera82950e2015-09-22 12:33:20 -0700522 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
523 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700524
Craig Tillera82950e2015-09-22 12:33:20 -0700525 if (old_lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800526 grpc_pollset_set_del_pollset_set(
527 exec_ctx, old_lb_policy->interested_parties, chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700528 GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
529 }
Craig Tiller000cd8f2015-09-18 07:20:29 -0700530
Craig Tillera82950e2015-09-22 12:33:20 -0700531 if (lb_policy != NULL) {
532 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
533 }
Craig Tiller45724b32015-09-22 10:42:19 -0700534
Craig Tiller906e3bc2015-11-24 07:31:31 -0800535 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700536 GRPC_ERROR_UNREF(state_error);
Craig Tiller3f475422015-06-25 10:43:05 -0700537}
538
Craig Tillera8610c02017-02-14 10:05:11 -0800539static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
540 grpc_error *error_ignored) {
Craig Tillerbefafe62017-02-09 11:30:54 -0800541 grpc_transport_op *op = arg;
Craig Tillerc55c1022017-03-10 10:26:42 -0800542 grpc_channel_element *elem = op->handler_private.extra_arg;
Craig Tillerca3e9d32015-06-27 18:37:27 -0700543 channel_data *chand = elem->channel_data;
Craig Tiller000cd8f2015-09-18 07:20:29 -0700544
Craig Tillera82950e2015-09-22 12:33:20 -0700545 if (op->on_connectivity_state_change != NULL) {
546 grpc_connectivity_state_notify_on_state_change(
547 exec_ctx, &chand->state_tracker, op->connectivity_state,
548 op->on_connectivity_state_change);
549 op->on_connectivity_state_change = NULL;
550 op->connectivity_state = NULL;
551 }
552
Craig Tiller26dab312015-12-07 14:43:47 -0800553 if (op->send_ping != NULL) {
Craig Tiller87b71e22015-12-07 15:14:14 -0800554 if (chand->lb_policy == NULL) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700555 grpc_closure_sched(
556 exec_ctx, op->send_ping,
557 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Ping with no load balancing"));
Craig Tiller26dab312015-12-07 14:43:47 -0800558 } else {
Craig Tiller2400bf52017-02-09 16:25:19 -0800559 grpc_lb_policy_ping_one_locked(exec_ctx, chand->lb_policy, op->send_ping);
Craig Tiller26dab312015-12-07 14:43:47 -0800560 op->bind_pollset = NULL;
561 }
562 op->send_ping = NULL;
563 }
564
Craig Tiller1c51edc2016-05-07 16:18:43 -0700565 if (op->disconnect_with_error != GRPC_ERROR_NONE) {
566 if (chand->resolver != NULL) {
567 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700568 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller1c51edc2016-05-07 16:18:43 -0700569 GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
Craig Tiller972470b2017-02-09 15:05:36 -0800570 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700571 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
572 chand->resolver = NULL;
573 if (!chand->started_resolving) {
574 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
575 GRPC_ERROR_REF(op->disconnect_with_error));
Craig Tiller91031da2016-12-28 15:44:25 -0800576 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700577 }
578 if (chand->lb_policy != NULL) {
579 grpc_pollset_set_del_pollset_set(exec_ctx,
580 chand->lb_policy->interested_parties,
581 chand->interested_parties);
582 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
583 chand->lb_policy = NULL;
584 }
Craig Tillerb12d22a2016-04-23 12:50:21 -0700585 }
Craig Tiller1c51edc2016-05-07 16:18:43 -0700586 GRPC_ERROR_UNREF(op->disconnect_with_error);
Craig Tillera82950e2015-09-22 12:33:20 -0700587 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800588 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "start_transport_op");
589
590 grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
Craig Tillerbefafe62017-02-09 11:30:54 -0800591}
592
593static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
594 grpc_channel_element *elem,
595 grpc_transport_op *op) {
596 channel_data *chand = elem->channel_data;
597
Craig Tillerbefafe62017-02-09 11:30:54 -0800598 GPR_ASSERT(op->set_accept_stream == false);
599 if (op->bind_pollset != NULL) {
600 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
601 op->bind_pollset);
602 }
603
Craig Tillerc55c1022017-03-10 10:26:42 -0800604 op->handler_private.extra_arg = elem;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800605 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "start_transport_op");
Craig Tillerbefafe62017-02-09 11:30:54 -0800606 grpc_closure_sched(
Craig Tillerc55c1022017-03-10 10:26:42 -0800607 exec_ctx,
608 grpc_closure_init(&op->handler_private.closure, start_transport_op_locked,
609 op, grpc_combiner_scheduler(chand->combiner, false)),
Craig Tillerbefafe62017-02-09 11:30:54 -0800610 GRPC_ERROR_NONE);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700611}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800612
Mark D. Rothb2d24882016-10-27 15:44:07 -0700613static void cc_get_channel_info(grpc_exec_ctx *exec_ctx,
614 grpc_channel_element *elem,
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700615 const grpc_channel_info *info) {
Mark D. Rothb2d24882016-10-27 15:44:07 -0700616 channel_data *chand = elem->channel_data;
Craig Tiller613dafa2017-02-09 12:00:43 -0800617 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700618 if (info->lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800619 *info->lb_policy_name = chand->info_lb_policy_name == NULL
Mark D. Roth78afd772016-11-04 12:49:49 -0700620 ? NULL
Craig Tiller613dafa2017-02-09 12:00:43 -0800621 : gpr_strdup(chand->info_lb_policy_name);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700622 }
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800623 if (info->service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800624 *info->service_config_json =
625 chand->info_service_config_json == NULL
626 ? NULL
627 : gpr_strdup(chand->info_service_config_json);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800628 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800629 gpr_mu_unlock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700630}
631
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700632/* Constructor for channel_data */
Mark D. Rothc1087882016-11-18 10:54:45 -0800633static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800634 grpc_channel_element *elem,
635 grpc_channel_element_args *args) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700636 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700637 GPR_ASSERT(args->is_last);
638 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800639 // Initialize data members.
Craig Tillerbefafe62017-02-09 11:30:54 -0800640 chand->combiner = grpc_combiner_create(NULL);
Craig Tillerd85477512017-02-09 12:02:39 -0800641 gpr_mu_init(&chand->info_mu);
Alexander Polcync3b1f182017-04-18 13:51:36 -0700642 gpr_mu_init(&chand->external_connectivity_watcher_list_mu);
643
644 gpr_mu_lock(&chand->external_connectivity_watcher_list_mu);
645 chand->external_connectivity_watcher_list_head = NULL;
646 gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu);
647
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800648 chand->owning_stack = args->channel_stack;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700649 grpc_closure_init(&chand->on_resolver_result_changed,
Craig Tillerbefafe62017-02-09 11:30:54 -0800650 on_resolver_result_changed_locked, chand,
651 grpc_combiner_scheduler(chand->combiner, false));
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800652 chand->interested_parties = grpc_pollset_set_create();
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700653 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
654 "client_channel");
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800655 // Record client channel factory.
656 const grpc_arg *arg = grpc_channel_args_find(args->channel_args,
657 GRPC_ARG_CLIENT_CHANNEL_FACTORY);
David Garcia Quintas228a5142017-03-30 19:43:00 -0700658 if (arg == NULL) {
659 return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
660 "Missing client channel factory in args for client channel filter");
661 }
662 if (arg->type != GRPC_ARG_POINTER) {
663 return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
664 "client channel factory arg must be a pointer");
665 }
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800666 grpc_client_channel_factory_ref(arg->value.pointer.p);
667 chand->client_channel_factory = arg->value.pointer.p;
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800668 // Get server name to resolve, using proxy mapper if needed.
Mark D. Roth86e90592016-11-18 09:56:40 -0800669 arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI);
David Garcia Quintas228a5142017-03-30 19:43:00 -0700670 if (arg == NULL) {
671 return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
672 "Missing server uri in args for client channel filter");
673 }
674 if (arg->type != GRPC_ARG_STRING) {
675 return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
676 "server uri arg must be a string");
677 }
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800678 char *proxy_name = NULL;
679 grpc_channel_args *new_args = NULL;
680 grpc_proxy_mappers_map_name(exec_ctx, arg->value.string, args->channel_args,
681 &proxy_name, &new_args);
682 // Instantiate resolver.
Mark D. Roth45ccec52017-01-18 14:04:01 -0800683 chand->resolver = grpc_resolver_create(
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800684 exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string,
685 new_args != NULL ? new_args : args->channel_args,
Craig Tiller972470b2017-02-09 15:05:36 -0800686 chand->interested_parties, chand->combiner);
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800687 if (proxy_name != NULL) gpr_free(proxy_name);
688 if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args);
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800689 if (chand->resolver == NULL) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700690 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("resolver creation failed");
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800691 }
692 return GRPC_ERROR_NONE;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700693}
694
Craig Tiller972470b2017-02-09 15:05:36 -0800695static void shutdown_resolver_locked(grpc_exec_ctx *exec_ctx, void *arg,
696 grpc_error *error) {
697 grpc_resolver *resolver = arg;
698 grpc_resolver_shutdown_locked(exec_ctx, resolver);
699 GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel");
700}
701
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700702/* Destructor for channel_data */
703static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
704 grpc_channel_element *elem) {
705 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700706 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800707 grpc_closure_sched(
708 exec_ctx,
709 grpc_closure_create(shutdown_resolver_locked, chand->resolver,
710 grpc_combiner_scheduler(chand->combiner, false)),
711 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700712 }
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700713 if (chand->client_channel_factory != NULL) {
714 grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
715 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700716 if (chand->lb_policy != NULL) {
717 grpc_pollset_set_del_pollset_set(exec_ctx,
718 chand->lb_policy->interested_parties,
719 chand->interested_parties);
720 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
721 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800722 gpr_free(chand->info_lb_policy_name);
723 gpr_free(chand->info_service_config_json);
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800724 if (chand->retry_throttle_data != NULL) {
725 grpc_server_retry_throttle_data_unref(chand->retry_throttle_data);
726 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700727 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800728 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700729 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700730 grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
Craig Tiller9e5ac1b2017-02-14 22:25:50 -0800731 grpc_pollset_set_destroy(exec_ctx, chand->interested_parties);
Craig Tillerf1021672017-02-09 21:29:50 -0800732 GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel");
Craig Tillerd85477512017-02-09 12:02:39 -0800733 gpr_mu_destroy(&chand->info_mu);
Alexander Polcync3b1f182017-04-18 13:51:36 -0700734 gpr_mu_destroy(&chand->external_connectivity_watcher_list_mu);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700735}
736
737/*************************************************************************
738 * PER-CALL FUNCTIONS
739 */
740
741#define GET_CALL(call_data) \
742 ((grpc_subchannel_call *)(gpr_atm_acq_load(&(call_data)->subchannel_call)))
743
744#define CANCELLED_CALL ((grpc_subchannel_call *)1)
745
746typedef enum {
Craig Tiller7acc37e2017-02-28 10:01:37 -0800747 /* zero so that it can be default-initialized */
748 GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING = 0,
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700749 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL
750} subchannel_creation_phase;
751
752/** Call data. Holds a pointer to grpc_subchannel_call and the
753 associated machinery to create such a pointer.
754 Handles queueing of stream ops until a call object is ready, waiting
755 for initial metadata before trying to create a call object,
756 and handling cancellation gracefully. */
757typedef struct client_channel_call_data {
Mark D. Roth72f6da82016-09-02 13:42:38 -0700758 // State for handling deadlines.
759 // The code in deadline_filter.c requires this to be the first field.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700760 // TODO(roth): This is slightly sub-optimal in that grpc_deadline_state
761 // and this struct both independently store a pointer to the call
762 // stack and each has its own mutex. If/when we have time, find a way
Mark D. Roth6ad99172016-09-09 07:52:48 -0700763 // to avoid this without breaking the grpc_deadline_state abstraction.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700764 grpc_deadline_state deadline_state;
Mark D. Rothf28763c2016-09-14 15:18:40 -0700765
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800766 grpc_slice path; // Request path.
Mark D. Rothe40dd292016-10-05 14:58:37 -0700767 gpr_timespec call_start_time;
768 gpr_timespec deadline;
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -0700769 grpc_server_retry_throttle_data *retry_throttle_data;
Mark D. Roth95b627b2017-02-24 11:02:58 -0800770 method_parameters *method_params;
Mark D. Rothaa850a72016-09-26 13:38:02 -0700771
Mark D. Rothf28763c2016-09-14 15:18:40 -0700772 grpc_error *cancel_error;
Mark D. Roth72f6da82016-09-02 13:42:38 -0700773
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700774 /** either 0 for no call, 1 for cancelled, or a pointer to a
775 grpc_subchannel_call */
776 gpr_atm subchannel_call;
Craig Tillerd426cac2017-03-13 12:30:45 -0700777 gpr_arena *arena;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700778
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700779 subchannel_creation_phase creation_phase;
780 grpc_connected_subchannel *connected_subchannel;
781 grpc_polling_entity *pollent;
782
Craig Tillera0f3abd2017-03-31 15:42:16 -0700783 grpc_transport_stream_op_batch **waiting_ops;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700784 size_t waiting_ops_count;
785 size_t waiting_ops_capacity;
786
787 grpc_closure next_step;
788
789 grpc_call_stack *owning_call;
David Garcia Quintasd1a47f12016-09-02 12:46:44 +0200790
791 grpc_linked_mdelem lb_token_mdelem;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800792
793 grpc_closure on_complete;
794 grpc_closure *original_on_complete;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700795} call_data;
796
Craig Tiller8b1d59c2016-12-27 15:15:30 -0800797grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
798 grpc_call_element *call_elem) {
799 grpc_subchannel_call *scc = GET_CALL((call_data *)call_elem->call_data);
800 return scc == CANCELLED_CALL ? NULL : scc;
801}
802
Craig Tillere1b51da2017-03-31 15:44:33 -0700803static void add_waiting_locked(call_data *calld,
804 grpc_transport_stream_op_batch *op) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700805 GPR_TIMER_BEGIN("add_waiting_locked", 0);
806 if (calld->waiting_ops_count == calld->waiting_ops_capacity) {
807 calld->waiting_ops_capacity = GPR_MAX(3, 2 * calld->waiting_ops_capacity);
808 calld->waiting_ops =
809 gpr_realloc(calld->waiting_ops,
810 calld->waiting_ops_capacity * sizeof(*calld->waiting_ops));
811 }
Craig Tiller57726ca2016-09-12 11:59:45 -0700812 calld->waiting_ops[calld->waiting_ops_count++] = op;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700813 GPR_TIMER_END("add_waiting_locked", 0);
814}
815
816static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld,
817 grpc_error *error) {
818 size_t i;
819 for (i = 0; i < calld->waiting_ops_count; i++) {
Craig Tillera0f3abd2017-03-31 15:42:16 -0700820 grpc_transport_stream_op_batch_finish_with_failure(
Craig Tiller57726ca2016-09-12 11:59:45 -0700821 exec_ctx, calld->waiting_ops[i], GRPC_ERROR_REF(error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700822 }
823 calld->waiting_ops_count = 0;
824 GRPC_ERROR_UNREF(error);
825}
826
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700827static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
Craig Tiller57726ca2016-09-12 11:59:45 -0700828 if (calld->waiting_ops_count == 0) {
829 return;
830 }
831
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800832 grpc_subchannel_call *call = GET_CALL(calld);
Craig Tillera0f3abd2017-03-31 15:42:16 -0700833 grpc_transport_stream_op_batch **ops = calld->waiting_ops;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800834 size_t nops = calld->waiting_ops_count;
835 if (call == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700836 fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED);
837 return;
838 }
839 calld->waiting_ops = NULL;
840 calld->waiting_ops_count = 0;
841 calld->waiting_ops_capacity = 0;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800842 for (size_t i = 0; i < nops; i++) {
843 grpc_subchannel_call_process_op(exec_ctx, call, ops[i]);
844 }
Craig Tiller9efea882017-02-09 13:06:52 -0800845 gpr_free(ops);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700846}
847
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -0700848// Sets calld->method_params and calld->retry_throttle_data.
Craig Tiller11c17d42017-03-13 13:36:34 -0700849// If the method params specify a timeout, populates
850// *per_method_deadline and returns true.
851static bool set_call_method_params_from_service_config_locked(
852 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
853 gpr_timespec *per_method_deadline) {
854 channel_data *chand = elem->channel_data;
855 call_data *calld = elem->call_data;
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -0700856 if (chand->retry_throttle_data != NULL) {
857 calld->retry_throttle_data =
858 grpc_server_retry_throttle_data_ref(chand->retry_throttle_data);
859 }
Craig Tiller11c17d42017-03-13 13:36:34 -0700860 if (chand->method_params_table != NULL) {
861 calld->method_params = grpc_method_config_table_get(
862 exec_ctx, chand->method_params_table, calld->path);
863 if (calld->method_params != NULL) {
864 method_parameters_ref(calld->method_params);
865 if (gpr_time_cmp(calld->method_params->timeout,
866 gpr_time_0(GPR_TIMESPAN)) != 0) {
867 *per_method_deadline =
868 gpr_time_add(calld->call_start_time, calld->method_params->timeout);
869 return true;
870 }
871 }
872 }
873 return false;
874}
Craig Tillerea4a4f12017-03-13 13:36:52 -0700875
Craig Tiller11c17d42017-03-13 13:36:34 -0700876static void apply_final_configuration_locked(grpc_exec_ctx *exec_ctx,
877 grpc_call_element *elem) {
878 /* apply service-config level configuration to the call (now that we're
879 * certain it exists) */
880 call_data *calld = elem->call_data;
881 gpr_timespec per_method_deadline;
882 if (set_call_method_params_from_service_config_locked(exec_ctx, elem,
883 &per_method_deadline)) {
884 // If the deadline from the service config is shorter than the one
885 // from the client API, reset the deadline timer.
Alexander Polcynf5521c32017-04-26 14:18:39 -0700886 if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
Craig Tiller11c17d42017-03-13 13:36:34 -0700887 calld->deadline = per_method_deadline;
888 grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
889 }
890 }
891}
892
Craig Tillerbefafe62017-02-09 11:30:54 -0800893static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
894 grpc_error *error) {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700895 grpc_call_element *elem = arg;
896 call_data *calld = elem->call_data;
897 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700898 GPR_ASSERT(calld->creation_phase ==
899 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
Yuchen Zeng19656b12016-09-01 18:00:45 -0700900 grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
901 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700902 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
903 if (calld->connected_subchannel == NULL) {
904 gpr_atm_no_barrier_store(&calld->subchannel_call, 1);
ncteisen4b36a3d2017-03-13 19:08:06 -0700905 fail_locked(exec_ctx, calld,
906 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
907 "Failed to create subchannel", &error, 1));
Mark D. Roth72f6da82016-09-02 13:42:38 -0700908 } else if (GET_CALL(calld) == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700909 /* already cancelled before subchannel became ready */
ncteisen4b36a3d2017-03-13 19:08:06 -0700910 grpc_error *cancellation_error =
911 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
912 "Cancelled before creating subchannel", &error, 1);
David Garcia Quintas68a9e382016-12-13 10:50:40 -0800913 /* if due to deadline, attach the deadline exceeded status to the error */
914 if (gpr_time_cmp(calld->deadline, gpr_now(GPR_CLOCK_MONOTONIC)) < 0) {
915 cancellation_error =
916 grpc_error_set_int(cancellation_error, GRPC_ERROR_INT_GRPC_STATUS,
917 GRPC_STATUS_DEADLINE_EXCEEDED);
918 }
919 fail_locked(exec_ctx, calld, cancellation_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700920 } else {
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700921 /* Create call on subchannel. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700922 grpc_subchannel_call *subchannel_call = NULL;
Craig Tillerfb9d1122017-03-14 09:26:27 -0700923 const grpc_connected_subchannel_call_args call_args = {
Craig Tillerd426cac2017-03-13 12:30:45 -0700924 .pollent = calld->pollent,
925 .path = calld->path,
926 .start_time = calld->call_start_time,
927 .deadline = calld->deadline,
928 .arena = calld->arena};
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700929 grpc_error *new_error = grpc_connected_subchannel_create_call(
Craig Tillerd426cac2017-03-13 12:30:45 -0700930 exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700931 gpr_atm_rel_store(&calld->subchannel_call,
932 (gpr_atm)(uintptr_t)subchannel_call);
Mark D. Roth61a63982017-04-05 09:56:12 -0700933 if (new_error != GRPC_ERROR_NONE) {
934 new_error = grpc_error_add_child(new_error, error);
935 fail_locked(exec_ctx, calld, new_error);
936 } else {
937 retry_waiting_locked(exec_ctx, calld);
938 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700939 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700940 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
941}
942
943static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
944 call_data *calld = elem->call_data;
945 grpc_subchannel_call *subchannel_call = GET_CALL(calld);
946 if (subchannel_call == NULL || subchannel_call == CANCELLED_CALL) {
947 return NULL;
948 } else {
949 return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
950 }
951}
952
Craig Tiller577c9b22015-11-02 14:11:15 -0800953typedef struct {
954 grpc_metadata_batch *initial_metadata;
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800955 uint32_t initial_metadata_flags;
Craig Tillerb5585d42015-11-17 07:18:31 -0800956 grpc_connected_subchannel **connected_subchannel;
Craig Tiller577c9b22015-11-02 14:11:15 -0800957 grpc_closure *on_ready;
958 grpc_call_element *elem;
959 grpc_closure closure;
960} continue_picking_args;
961
Yuchen Zeng144ce652016-09-01 18:19:34 -0700962/** Return true if subchannel is available immediately (in which case on_ready
963 should not be called), or false otherwise (in which case on_ready should be
964 called when the subchannel is available). */
Craig Tillerbefafe62017-02-09 11:30:54 -0800965static bool pick_subchannel_locked(
966 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
967 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
968 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
969 grpc_error *error);
Craig Tiller577c9b22015-11-02 14:11:15 -0800970
Craig Tillerbefafe62017-02-09 11:30:54 -0800971static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg,
972 grpc_error *error) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800973 continue_picking_args *cpa = arg;
Craig Tiller0ede5452016-04-23 12:21:45 -0700974 if (cpa->connected_subchannel == NULL) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800975 /* cancelled, do nothing */
Craig Tiller804ff712016-05-05 16:25:40 -0700976 } else if (error != GRPC_ERROR_NONE) {
Craig Tiller91031da2016-12-28 15:44:25 -0800977 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error));
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700978 } else {
Craig Tillerbefafe62017-02-09 11:30:54 -0800979 if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata,
980 cpa->initial_metadata_flags,
981 cpa->connected_subchannel, cpa->on_ready,
982 GRPC_ERROR_NONE)) {
Craig Tiller91031da2016-12-28 15:44:25 -0800983 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700984 }
Craig Tiller577c9b22015-11-02 14:11:15 -0800985 }
986 gpr_free(cpa);
987}
988
Craig Tillerbefafe62017-02-09 11:30:54 -0800989static bool pick_subchannel_locked(
990 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
991 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
992 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
993 grpc_error *error) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700994 GPR_TIMER_BEGIN("pick_subchannel", 0);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700995
Craig Tiller577c9b22015-11-02 14:11:15 -0800996 channel_data *chand = elem->channel_data;
997 call_data *calld = elem->call_data;
998 continue_picking_args *cpa;
999 grpc_closure *closure;
1000
Craig Tillerb5585d42015-11-17 07:18:31 -08001001 GPR_ASSERT(connected_subchannel);
Craig Tiller577c9b22015-11-02 14:11:15 -08001002
Craig Tiller577c9b22015-11-02 14:11:15 -08001003 if (initial_metadata == NULL) {
1004 if (chand->lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -08001005 grpc_lb_policy_cancel_pick_locked(exec_ctx, chand->lb_policy,
1006 connected_subchannel,
1007 GRPC_ERROR_REF(error));
Craig Tiller577c9b22015-11-02 14:11:15 -08001008 }
1009 for (closure = chand->waiting_for_config_closures.head; closure != NULL;
Craig Tiller804ff712016-05-05 16:25:40 -07001010 closure = closure->next_data.next) {
Craig Tiller577c9b22015-11-02 14:11:15 -08001011 cpa = closure->cb_arg;
Craig Tillerb5585d42015-11-17 07:18:31 -08001012 if (cpa->connected_subchannel == connected_subchannel) {
1013 cpa->connected_subchannel = NULL;
ncteisen4b36a3d2017-03-13 19:08:06 -07001014 grpc_closure_sched(exec_ctx, cpa->on_ready,
1015 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
1016 "Pick cancelled", &error, 1));
Craig Tiller577c9b22015-11-02 14:11:15 -08001017 }
1018 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001019 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth697a1f62016-09-07 13:35:07 -07001020 GRPC_ERROR_UNREF(error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001021 return true;
Craig Tiller577c9b22015-11-02 14:11:15 -08001022 }
Mark D. Roth697a1f62016-09-07 13:35:07 -07001023 GPR_ASSERT(error == GRPC_ERROR_NONE);
Craig Tiller577c9b22015-11-02 14:11:15 -08001024 if (chand->lb_policy != NULL) {
Craig Tiller2e0788a2017-03-14 06:55:44 -07001025 apply_final_configuration_locked(exec_ctx, elem);
Craig Tiller86c0f8a2015-12-01 20:05:40 -08001026 grpc_lb_policy *lb_policy = chand->lb_policy;
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001027 GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel");
Mark D. Rothe40dd292016-10-05 14:58:37 -07001028 // If the application explicitly set wait_for_ready, use that.
1029 // Otherwise, if the service config specified a value for this
1030 // method, use that.
Mark D. Rothc1c38582016-10-11 11:03:27 -07001031 const bool wait_for_ready_set_from_api =
1032 initial_metadata_flags &
1033 GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
1034 const bool wait_for_ready_set_from_service_config =
Mark D. Roth95b627b2017-02-24 11:02:58 -08001035 calld->method_params != NULL &&
1036 calld->method_params->wait_for_ready != WAIT_FOR_READY_UNSET;
Mark D. Rothc1c38582016-10-11 11:03:27 -07001037 if (!wait_for_ready_set_from_api &&
1038 wait_for_ready_set_from_service_config) {
Mark D. Roth95b627b2017-02-24 11:02:58 -08001039 if (calld->method_params->wait_for_ready == WAIT_FOR_READY_TRUE) {
Mark D. Rothe40dd292016-10-05 14:58:37 -07001040 initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
1041 } else {
1042 initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
1043 }
1044 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001045 const grpc_lb_policy_pick_args inputs = {
Yuchen Zengac8bc422016-10-05 14:00:02 -07001046 initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem,
1047 gpr_inf_future(GPR_CLOCK_MONOTONIC)};
Alexander Polcynf5521c32017-04-26 14:18:39 -07001048 const bool result = grpc_lb_policy_pick_locked(
1049 exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, on_ready);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001050 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel");
1051 GPR_TIMER_END("pick_subchannel", 0);
Alexander Polcynf5521c32017-04-26 14:18:39 -07001052 return result;
Craig Tiller577c9b22015-11-02 14:11:15 -08001053 }
1054 if (chand->resolver != NULL && !chand->started_resolving) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001055 chand->started_resolving = true;
Craig Tiller906e3bc2015-11-24 07:31:31 -08001056 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -08001057 grpc_resolver_next_locked(exec_ctx, chand->resolver,
1058 &chand->resolver_result,
1059 &chand->on_resolver_result_changed);
Craig Tiller577c9b22015-11-02 14:11:15 -08001060 }
Craig Tiller0eab6972016-04-23 12:59:57 -07001061 if (chand->resolver != NULL) {
1062 cpa = gpr_malloc(sizeof(*cpa));
1063 cpa->initial_metadata = initial_metadata;
1064 cpa->initial_metadata_flags = initial_metadata_flags;
1065 cpa->connected_subchannel = connected_subchannel;
1066 cpa->on_ready = on_ready;
1067 cpa->elem = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -08001068 grpc_closure_init(&cpa->closure, continue_picking_locked, cpa,
1069 grpc_combiner_scheduler(chand->combiner, true));
Craig Tiller804ff712016-05-05 16:25:40 -07001070 grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
1071 GRPC_ERROR_NONE);
Craig Tiller0eab6972016-04-23 12:59:57 -07001072 } else {
ncteisen4b36a3d2017-03-13 19:08:06 -07001073 grpc_closure_sched(exec_ctx, on_ready,
1074 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected"));
Craig Tiller0eab6972016-04-23 12:59:57 -07001075 }
Craig Tillerbfc9adc2016-06-27 13:16:22 -07001076
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001077 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001078 return false;
Craig Tiller577c9b22015-11-02 14:11:15 -08001079}
1080
Craig Tillere1b51da2017-03-31 15:44:33 -07001081static void start_transport_stream_op_batch_locked_inner(
1082 grpc_exec_ctx *exec_ctx, grpc_transport_stream_op_batch *op,
1083 grpc_call_element *elem) {
Yuchen Zeng19656b12016-09-01 18:00:45 -07001084 channel_data *chand = elem->channel_data;
Craig Tillera11bfc82017-02-14 09:56:33 -08001085 call_data *calld = elem->call_data;
Craig Tillerbefafe62017-02-09 11:30:54 -08001086 grpc_subchannel_call *call;
1087
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001088 /* need to recheck that another thread hasn't set the call */
1089 call = GET_CALL(calld);
1090 if (call == CANCELLED_CALL) {
Craig Tillera0f3abd2017-03-31 15:42:16 -07001091 grpc_transport_stream_op_batch_finish_with_failure(
Mark D. Rothf28763c2016-09-14 15:18:40 -07001092 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -08001093 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001094 return;
1095 }
1096 if (call != NULL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001097 grpc_subchannel_call_process_op(exec_ctx, call, op);
Craig Tillera11bfc82017-02-14 09:56:33 -08001098 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001099 return;
1100 }
1101 /* if this is a cancellation, then we can raise our cancelled flag */
Craig Tillerc55c1022017-03-10 10:26:42 -08001102 if (op->cancel_stream) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001103 if (!gpr_atm_rel_cas(&calld->subchannel_call, 0,
1104 (gpr_atm)(uintptr_t)CANCELLED_CALL)) {
Craig Tillera11bfc82017-02-14 09:56:33 -08001105 /* recurse to retry */
Craig Tillera0f3abd2017-03-31 15:42:16 -07001106 start_transport_stream_op_batch_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001107 /* early out */
1108 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001109 } else {
Craig Tillerbe9691a2017-02-14 10:00:42 -08001110 /* Stash a copy of cancel_error in our call data, so that we can use
1111 it for subsequent operations. This ensures that if the call is
1112 cancelled before any ops are passed down (e.g., if the deadline
1113 is in the past when the call starts), we can return the right
1114 error to the caller when the first op does get passed down. */
Craig Tillerc55c1022017-03-10 10:26:42 -08001115 calld->cancel_error =
1116 GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001117 switch (calld->creation_phase) {
1118 case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
Craig Tillerc55c1022017-03-10 10:26:42 -08001119 fail_locked(exec_ctx, calld,
1120 GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001121 break;
1122 case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
Craig Tillerc55c1022017-03-10 10:26:42 -08001123 pick_subchannel_locked(
1124 exec_ctx, elem, NULL, 0, &calld->connected_subchannel, NULL,
1125 GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001126 break;
1127 }
Craig Tillera0f3abd2017-03-31 15:42:16 -07001128 grpc_transport_stream_op_batch_finish_with_failure(
Craig Tillerc55c1022017-03-10 10:26:42 -08001129 exec_ctx, op,
1130 GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -08001131 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001132 return;
1133 }
1134 }
1135 /* if we don't have a subchannel, try to get one */
1136 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
Craig Tillerc55c1022017-03-10 10:26:42 -08001137 calld->connected_subchannel == NULL && op->send_initial_metadata) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001138 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
Craig Tillerbefafe62017-02-09 11:30:54 -08001139 grpc_closure_init(&calld->next_step, subchannel_ready_locked, elem,
1140 grpc_combiner_scheduler(chand->combiner, true));
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001141 GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
Yuchen Zeng144ce652016-09-01 18:19:34 -07001142 /* If a subchannel is not available immediately, the polling entity from
1143 call_data should be provided to channel_data's interested_parties, so
1144 that IO of the lb_policy and resolver could be done under it. */
Craig Tillerc55c1022017-03-10 10:26:42 -08001145 if (pick_subchannel_locked(
1146 exec_ctx, elem,
1147 op->payload->send_initial_metadata.send_initial_metadata,
1148 op->payload->send_initial_metadata.send_initial_metadata_flags,
1149 &calld->connected_subchannel, &calld->next_step, GRPC_ERROR_NONE)) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001150 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
1151 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
Yuchen Zeng19656b12016-09-01 18:00:45 -07001152 } else {
Yuchen Zeng19656b12016-09-01 18:00:45 -07001153 grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
1154 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001155 }
1156 }
1157 /* if we've got a subchannel, then let's ask it to create a call */
1158 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
1159 calld->connected_subchannel != NULL) {
1160 grpc_subchannel_call *subchannel_call = NULL;
Craig Tillerfb9d1122017-03-14 09:26:27 -07001161 const grpc_connected_subchannel_call_args call_args = {
Craig Tillerd426cac2017-03-13 12:30:45 -07001162 .pollent = calld->pollent,
1163 .path = calld->path,
1164 .start_time = calld->call_start_time,
1165 .deadline = calld->deadline,
1166 .arena = calld->arena};
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001167 grpc_error *error = grpc_connected_subchannel_create_call(
Craig Tillerd426cac2017-03-13 12:30:45 -07001168 exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001169 gpr_atm_rel_store(&calld->subchannel_call,
1170 (gpr_atm)(uintptr_t)subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001171 if (error != GRPC_ERROR_NONE) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001172 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
Craig Tillera0f3abd2017-03-31 15:42:16 -07001173 grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, op, error);
Mark D. Rothca136032017-04-04 13:53:29 -07001174 } else {
Mark D. Rothca136032017-04-04 13:53:29 -07001175 retry_waiting_locked(exec_ctx, calld);
1176 /* recurse to retry */
1177 start_transport_stream_op_batch_locked_inner(exec_ctx, op, elem);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001178 }
Craig Tillera11bfc82017-02-14 09:56:33 -08001179 /* early out */
1180 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001181 }
1182 /* nothing to be done but wait */
1183 add_waiting_locked(calld, op);
Craig Tillera11bfc82017-02-14 09:56:33 -08001184}
1185
Mark D. Rothde144102017-03-15 10:11:03 -07001186static void on_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001187 grpc_call_element *elem = arg;
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001188 call_data *calld = elem->call_data;
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -07001189 if (calld->retry_throttle_data != NULL) {
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001190 if (error == GRPC_ERROR_NONE) {
1191 grpc_server_retry_throttle_data_record_success(
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -07001192 calld->retry_throttle_data);
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001193 } else {
1194 // TODO(roth): In a subsequent PR, check the return value here and
Mark D. Rothb3322562017-02-23 14:38:02 -08001195 // decide whether or not to retry. Note that we should only
1196 // record failures whose statuses match the configured retryable
1197 // or non-fatal status codes.
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001198 grpc_server_retry_throttle_data_record_failure(
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -07001199 calld->retry_throttle_data);
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001200 }
1201 }
Mark D. Roth95039b52017-02-24 07:59:45 -08001202 grpc_closure_run(exec_ctx, calld->original_on_complete,
1203 GRPC_ERROR_REF(error));
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001204}
1205
Craig Tillere1b51da2017-03-31 15:44:33 -07001206static void start_transport_stream_op_batch_locked(grpc_exec_ctx *exec_ctx,
1207 void *arg,
1208 grpc_error *error_ignored) {
Craig Tillera0f3abd2017-03-31 15:42:16 -07001209 GPR_TIMER_BEGIN("start_transport_stream_op_batch_locked", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001210
Craig Tillera0f3abd2017-03-31 15:42:16 -07001211 grpc_transport_stream_op_batch *op = arg;
Craig Tillerc55c1022017-03-10 10:26:42 -08001212 grpc_call_element *elem = op->handler_private.extra_arg;
Craig Tillera11bfc82017-02-14 09:56:33 -08001213 call_data *calld = elem->call_data;
1214
Craig Tillerf6cb0c02017-03-28 14:11:49 -07001215 if (op->recv_trailing_metadata) {
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001216 GPR_ASSERT(op->on_complete != NULL);
1217 calld->original_on_complete = op->on_complete;
Mark D. Rothde144102017-03-15 10:11:03 -07001218 grpc_closure_init(&calld->on_complete, on_complete, elem,
Mark D. Roth9ccbc4d2017-03-15 08:30:04 -07001219 grpc_schedule_on_exec_ctx);
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001220 op->on_complete = &calld->on_complete;
1221 }
1222
Craig Tillera0f3abd2017-03-31 15:42:16 -07001223 start_transport_stream_op_batch_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001224
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001225 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
Craig Tillera0f3abd2017-03-31 15:42:16 -07001226 "start_transport_stream_op_batch");
1227 GPR_TIMER_END("start_transport_stream_op_batch_locked", 0);
Craig Tillerbefafe62017-02-09 11:30:54 -08001228}
1229
Craig Tillerbe9691a2017-02-14 10:00:42 -08001230/* The logic here is fairly complicated, due to (a) the fact that we
1231 need to handle the case where we receive the send op before the
1232 initial metadata op, and (b) the need for efficiency, especially in
1233 the streaming case.
1234
1235 We use double-checked locking to initially see if initialization has been
1236 performed. If it has not, we acquire the combiner and perform initialization.
1237 If it has, we proceed on the fast path. */
Craig Tillere1b51da2017-03-31 15:44:33 -07001238static void cc_start_transport_stream_op_batch(
1239 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
1240 grpc_transport_stream_op_batch *op) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001241 call_data *calld = elem->call_data;
1242 channel_data *chand = elem->channel_data;
1243 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
Alexander Polcynf5521c32017-04-26 14:18:39 -07001244 grpc_deadline_state_client_start_transport_stream_op_batch(exec_ctx, elem,
1245 op);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001246 /* try to (atomically) get the call */
1247 grpc_subchannel_call *call = GET_CALL(calld);
Craig Tillera0f3abd2017-03-31 15:42:16 -07001248 GPR_TIMER_BEGIN("cc_start_transport_stream_op_batch", 0);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001249 if (call == CANCELLED_CALL) {
Craig Tillera0f3abd2017-03-31 15:42:16 -07001250 grpc_transport_stream_op_batch_finish_with_failure(
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001251 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
Craig Tillera0f3abd2017-03-31 15:42:16 -07001252 GPR_TIMER_END("cc_start_transport_stream_op_batch", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001253 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001254 return;
1255 }
1256 if (call != NULL) {
1257 grpc_subchannel_call_process_op(exec_ctx, call, op);
Craig Tillera0f3abd2017-03-31 15:42:16 -07001258 GPR_TIMER_END("cc_start_transport_stream_op_batch", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001259 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001260 return;
1261 }
1262 /* we failed; lock and figure out what to do */
Craig Tillera0f3abd2017-03-31 15:42:16 -07001263 GRPC_CALL_STACK_REF(calld->owning_call, "start_transport_stream_op_batch");
Craig Tillerc55c1022017-03-10 10:26:42 -08001264 op->handler_private.extra_arg = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -08001265 grpc_closure_sched(
1266 exec_ctx,
Craig Tiller4a84bdd2017-02-14 09:48:41 -08001267 grpc_closure_init(&op->handler_private.closure,
Craig Tillera0f3abd2017-03-31 15:42:16 -07001268 start_transport_stream_op_batch_locked, op,
Craig Tillerbefafe62017-02-09 11:30:54 -08001269 grpc_combiner_scheduler(chand->combiner, false)),
1270 GRPC_ERROR_NONE);
Craig Tillera0f3abd2017-03-31 15:42:16 -07001271 GPR_TIMER_END("cc_start_transport_stream_op_batch", 0);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001272}
1273
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001274/* Constructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001275static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
1276 grpc_call_element *elem,
Craig Tillerc52ba3a2017-02-15 22:57:43 -08001277 const grpc_call_element_args *args) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001278 call_data *calld = elem->call_data;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001279 // Initialize data members.
Alexander Polcynf5521c32017-04-26 14:18:39 -07001280 grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001281 calld->path = grpc_slice_ref_internal(args->path);
Mark D. Rothff08f332016-10-14 13:01:01 -07001282 calld->call_start_time = args->start_time;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001283 calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001284 calld->owning_call = args->call_stack;
Craig Tillerd426cac2017-03-13 12:30:45 -07001285 calld->arena = args->arena;
Alexander Polcynf5521c32017-04-26 14:18:39 -07001286 grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
Mark D. Roth0badbe82016-06-23 10:15:12 -07001287 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001288}
1289
1290/* Destructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001291static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
1292 grpc_call_element *elem,
1293 const grpc_call_final_info *final_info,
Craig Tillerd426cac2017-03-13 12:30:45 -07001294 grpc_closure *then_schedule_closure) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001295 call_data *calld = elem->call_data;
Alexander Polcynf5521c32017-04-26 14:18:39 -07001296 grpc_deadline_state_destroy(exec_ctx, elem);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001297 grpc_slice_unref_internal(exec_ctx, calld->path);
Mark D. Roth95b627b2017-02-24 11:02:58 -08001298 if (calld->method_params != NULL) {
1299 method_parameters_unref(calld->method_params);
1300 }
Mark D. Rothf28763c2016-09-14 15:18:40 -07001301 GRPC_ERROR_UNREF(calld->cancel_error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001302 grpc_subchannel_call *call = GET_CALL(calld);
1303 if (call != NULL && call != CANCELLED_CALL) {
Craig Tillerd426cac2017-03-13 12:30:45 -07001304 grpc_subchannel_call_set_cleanup_closure(call, then_schedule_closure);
1305 then_schedule_closure = NULL;
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001306 GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
1307 }
1308 GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001309 GPR_ASSERT(calld->waiting_ops_count == 0);
Craig Tiller693d3942016-10-27 16:51:25 -07001310 if (calld->connected_subchannel != NULL) {
1311 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel,
1312 "picked");
1313 }
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001314 gpr_free(calld->waiting_ops);
Craig Tillerd426cac2017-03-13 12:30:45 -07001315 grpc_closure_sched(exec_ctx, then_schedule_closure, GRPC_ERROR_NONE);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001316}
1317
David Garcia Quintasf72eb972016-05-03 18:28:09 -07001318static void cc_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
1319 grpc_call_element *elem,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001320 grpc_polling_entity *pollent) {
Craig Tiller577c9b22015-11-02 14:11:15 -08001321 call_data *calld = elem->call_data;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001322 calld->pollent = pollent;
Craig Tiller577c9b22015-11-02 14:11:15 -08001323}
1324
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001325/*************************************************************************
1326 * EXPORTED SYMBOLS
1327 */
1328
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001329const grpc_channel_filter grpc_client_channel_filter = {
Craig Tillera0f3abd2017-03-31 15:42:16 -07001330 cc_start_transport_stream_op_batch,
Craig Tillerf40df232016-03-25 13:38:14 -07001331 cc_start_transport_op,
1332 sizeof(call_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001333 cc_init_call_elem,
David Garcia Quintas4afce7e2016-04-18 16:25:17 -07001334 cc_set_pollset_or_pollset_set,
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001335 cc_destroy_call_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001336 sizeof(channel_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001337 cc_init_channel_elem,
1338 cc_destroy_channel_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001339 cc_get_peer,
Mark D. Rothb2d24882016-10-27 15:44:07 -07001340 cc_get_channel_info,
Craig Tillerf40df232016-03-25 13:38:14 -07001341 "client-channel",
Craig Tiller87d5b192015-04-16 14:37:57 -07001342};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001343
Craig Tiller613dafa2017-02-09 12:00:43 -08001344static void try_to_connect_locked(grpc_exec_ctx *exec_ctx, void *arg,
1345 grpc_error *error_ignored) {
1346 channel_data *chand = arg;
1347 if (chand->lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -08001348 grpc_lb_policy_exit_idle_locked(exec_ctx, chand->lb_policy);
Craig Tiller613dafa2017-02-09 12:00:43 -08001349 } else {
1350 chand->exit_idle_when_lb_policy_arrives = true;
1351 if (!chand->started_resolving && chand->resolver != NULL) {
1352 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
1353 chand->started_resolving = true;
Craig Tiller972470b2017-02-09 15:05:36 -08001354 grpc_resolver_next_locked(exec_ctx, chand->resolver,
1355 &chand->resolver_result,
1356 &chand->on_resolver_result_changed);
Craig Tiller613dafa2017-02-09 12:00:43 -08001357 }
1358 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001359 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001360}
1361
Craig Tillera82950e2015-09-22 12:33:20 -07001362grpc_connectivity_state grpc_client_channel_check_connectivity_state(
1363 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001364 channel_data *chand = elem->channel_data;
Craig Tillera8610c02017-02-14 10:05:11 -08001365 grpc_connectivity_state out =
1366 grpc_connectivity_state_check(&chand->state_tracker);
Craig Tillera82950e2015-09-22 12:33:20 -07001367 if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001368 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001369 grpc_closure_sched(
1370 exec_ctx,
1371 grpc_closure_create(try_to_connect_locked, chand,
1372 grpc_combiner_scheduler(chand->combiner, false)),
1373 GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -07001374 }
Craig Tiller48cb07c2015-07-15 16:16:15 -07001375 return out;
1376}
1377
Alexander Polcync3b1f182017-04-18 13:51:36 -07001378typedef struct external_connectivity_watcher {
Craig Tiller86c99582015-11-25 15:22:26 -08001379 channel_data *chand;
1380 grpc_pollset *pollset;
1381 grpc_closure *on_complete;
Alexander Polcync3b1f182017-04-18 13:51:36 -07001382 grpc_closure *watcher_timer_init;
Craig Tiller613dafa2017-02-09 12:00:43 -08001383 grpc_connectivity_state *state;
Craig Tiller86c99582015-11-25 15:22:26 -08001384 grpc_closure my_closure;
Alexander Polcync3b1f182017-04-18 13:51:36 -07001385 struct external_connectivity_watcher *next;
Craig Tiller86c99582015-11-25 15:22:26 -08001386} external_connectivity_watcher;
1387
Alexander Polcync3b1f182017-04-18 13:51:36 -07001388static external_connectivity_watcher *lookup_external_connectivity_watcher(
1389 channel_data *chand, grpc_closure *on_complete) {
1390 gpr_mu_lock(&chand->external_connectivity_watcher_list_mu);
1391 external_connectivity_watcher *w =
1392 chand->external_connectivity_watcher_list_head;
1393 while (w != NULL && w->on_complete != on_complete) {
1394 w = w->next;
1395 }
1396 gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu);
1397 return w;
1398}
1399
1400static void external_connectivity_watcher_list_append(
1401 channel_data *chand, external_connectivity_watcher *w) {
1402 GPR_ASSERT(!lookup_external_connectivity_watcher(chand, w->on_complete));
1403
1404 gpr_mu_lock(&w->chand->external_connectivity_watcher_list_mu);
1405 GPR_ASSERT(!w->next);
1406 w->next = chand->external_connectivity_watcher_list_head;
1407 chand->external_connectivity_watcher_list_head = w;
1408 gpr_mu_unlock(&w->chand->external_connectivity_watcher_list_mu);
1409}
1410
1411static void external_connectivity_watcher_list_remove(
1412 channel_data *chand, external_connectivity_watcher *too_remove) {
1413 GPR_ASSERT(
1414 lookup_external_connectivity_watcher(chand, too_remove->on_complete));
1415 gpr_mu_lock(&chand->external_connectivity_watcher_list_mu);
1416 if (too_remove == chand->external_connectivity_watcher_list_head) {
1417 chand->external_connectivity_watcher_list_head = too_remove->next;
1418 gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu);
1419 return;
1420 }
1421 external_connectivity_watcher *w =
1422 chand->external_connectivity_watcher_list_head;
1423 while (w != NULL) {
1424 if (w->next == too_remove) {
1425 w->next = w->next->next;
1426 gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu);
1427 return;
1428 }
1429 w = w->next;
1430 }
1431 GPR_UNREACHABLE_CODE(return );
1432}
1433
1434int grpc_client_channel_num_external_connectivity_watchers(
1435 grpc_channel_element *elem) {
1436 channel_data *chand = elem->channel_data;
1437 int count = 0;
1438
1439 gpr_mu_lock(&chand->external_connectivity_watcher_list_mu);
1440 external_connectivity_watcher *w =
1441 chand->external_connectivity_watcher_list_head;
1442 while (w != NULL) {
1443 count++;
1444 w = w->next;
1445 }
1446 gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu);
1447
1448 return count;
1449}
1450
Craig Tiller1d881fb2015-12-01 07:39:04 -08001451static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -07001452 grpc_error *error) {
Craig Tiller86c99582015-11-25 15:22:26 -08001453 external_connectivity_watcher *w = arg;
1454 grpc_closure *follow_up = w->on_complete;
Craig Tiller69b093b2016-02-25 19:04:07 -08001455 grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
Craig Tiller1d881fb2015-12-01 07:39:04 -08001456 w->pollset);
1457 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
1458 "external_connectivity_watcher");
Alexander Polcync3b1f182017-04-18 13:51:36 -07001459 external_connectivity_watcher_list_remove(w->chand, w);
Craig Tiller86c99582015-11-25 15:22:26 -08001460 gpr_free(w);
Craig Tiller613dafa2017-02-09 12:00:43 -08001461 grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
1462}
1463
Craig Tillera8610c02017-02-14 10:05:11 -08001464static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg,
1465 grpc_error *error_ignored) {
Craig Tiller613dafa2017-02-09 12:00:43 -08001466 external_connectivity_watcher *w = arg;
Alexander Polcync3b1f182017-04-18 13:51:36 -07001467 external_connectivity_watcher *found = NULL;
1468 if (w->state != NULL) {
1469 external_connectivity_watcher_list_append(w->chand, w);
1470 grpc_closure_run(exec_ctx, w->watcher_timer_init, GRPC_ERROR_NONE);
1471 grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
1472 grpc_schedule_on_exec_ctx);
1473 grpc_connectivity_state_notify_on_state_change(
1474 exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
1475 } else {
1476 GPR_ASSERT(w->watcher_timer_init == NULL);
1477 found = lookup_external_connectivity_watcher(w->chand, w->on_complete);
1478 if (found) {
1479 GPR_ASSERT(found->on_complete == w->on_complete);
1480 grpc_connectivity_state_notify_on_state_change(
1481 exec_ctx, &found->chand->state_tracker, NULL, &found->my_closure);
1482 }
1483 grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
1484 w->pollset);
1485 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
1486 "external_connectivity_watcher");
1487 gpr_free(w);
1488 }
Craig Tiller86c99582015-11-25 15:22:26 -08001489}
1490
Craig Tillera82950e2015-09-22 12:33:20 -07001491void grpc_client_channel_watch_connectivity_state(
Craig Tiller906e3bc2015-11-24 07:31:31 -08001492 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
Alexander Polcync3b1f182017-04-18 13:51:36 -07001493 grpc_connectivity_state *state, grpc_closure *on_complete,
1494 grpc_closure *watcher_timer_init) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001495 channel_data *chand = elem->channel_data;
Alexander Polcync3b1f182017-04-18 13:51:36 -07001496 external_connectivity_watcher *w = gpr_zalloc(sizeof(*w));
Craig Tiller86c99582015-11-25 15:22:26 -08001497 w->chand = chand;
1498 w->pollset = pollset;
1499 w->on_complete = on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001500 w->state = state;
Alexander Polcync3b1f182017-04-18 13:51:36 -07001501 w->watcher_timer_init = watcher_timer_init;
1502
Craig Tiller69b093b2016-02-25 19:04:07 -08001503 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
Craig Tiller1d881fb2015-12-01 07:39:04 -08001504 GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
1505 "external_connectivity_watcher");
Craig Tiller613dafa2017-02-09 12:00:43 -08001506 grpc_closure_sched(
1507 exec_ctx,
Craig Tillera8610c02017-02-14 10:05:11 -08001508 grpc_closure_init(&w->my_closure, watch_connectivity_state_locked, w,
Craig Tiller613dafa2017-02-09 12:00:43 -08001509 grpc_combiner_scheduler(chand->combiner, true)),
1510 GRPC_ERROR_NONE);
Craig Tiller48cb07c2015-07-15 16:16:15 -07001511}