blob: 1cc2b9455feb8db3ca9737013fcc09d509562a4d [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 {
75 WAIT_FOR_READY_UNSET,
76 WAIT_FOR_READY_FALSE,
77 WAIT_FOR_READY_TRUE
78} wait_for_ready_value;
79
80typedef struct method_parameters {
81 gpr_timespec timeout;
82 wait_for_ready_value wait_for_ready;
83} method_parameters;
84
85static void *method_parameters_copy(void *value) {
86 void *new_value = gpr_malloc(sizeof(method_parameters));
87 memcpy(new_value, value, sizeof(method_parameters));
88 return new_value;
89}
90
Craig Tillerb28c7e82016-11-18 10:29:04 -080091static void method_parameters_free(grpc_exec_ctx *exec_ctx, void *p) {
Craig Tiller87a7e1f2016-11-09 09:42:19 -080092 gpr_free(p);
93}
94
Craig Tiller7c70b6c2017-01-23 07:48:42 -080095static const grpc_slice_hash_table_vtable method_parameters_vtable = {
Craig Tillerb28c7e82016-11-18 10:29:04 -080096 method_parameters_free, method_parameters_copy};
Mark D. Roth9d480942016-10-19 14:18:05 -070097
Mark D. Rothe30baeb2016-11-03 08:16:19 -070098static void *method_parameters_create_from_json(const grpc_json *json) {
Mark D. Rothc968e602016-11-02 14:07:36 -070099 wait_for_ready_value wait_for_ready = WAIT_FOR_READY_UNSET;
Mark D. Roth47f10842016-11-03 08:45:27 -0700100 gpr_timespec timeout = {0, 0, GPR_TIMESPAN};
101 for (grpc_json *field = json->child; field != NULL; field = field->next) {
Mark D. Rothc968e602016-11-02 14:07:36 -0700102 if (field->key == NULL) continue;
Mark D. Roth84c8a022016-11-10 09:39:34 -0800103 if (strcmp(field->key, "waitForReady") == 0) {
Mark D. Rothc968e602016-11-02 14:07:36 -0700104 if (wait_for_ready != WAIT_FOR_READY_UNSET) return NULL; // Duplicate.
105 if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) {
106 return NULL;
107 }
Mark D. Roth47f10842016-11-03 08:45:27 -0700108 wait_for_ready = field->type == GRPC_JSON_TRUE ? WAIT_FOR_READY_TRUE
109 : WAIT_FOR_READY_FALSE;
Mark D. Rothc968e602016-11-02 14:07:36 -0700110 } else if (strcmp(field->key, "timeout") == 0) {
111 if (timeout.tv_sec > 0 || timeout.tv_nsec > 0) return NULL; // Duplicate.
Mark D. Roth84c8a022016-11-10 09:39:34 -0800112 if (field->type != GRPC_JSON_STRING) return NULL;
113 size_t len = strlen(field->value);
114 if (field->value[len - 1] != 's') return NULL;
Mark D. Rothc19049c2016-11-10 09:43:06 -0800115 char *buf = gpr_strdup(field->value);
Mark D. Roth84c8a022016-11-10 09:39:34 -0800116 buf[len - 1] = '\0'; // Remove trailing 's'.
Mark D. Rothc19049c2016-11-10 09:43:06 -0800117 char *decimal_point = strchr(buf, '.');
Mark D. Roth84c8a022016-11-10 09:39:34 -0800118 if (decimal_point != NULL) {
119 *decimal_point = '\0';
120 timeout.tv_nsec = gpr_parse_nonnegative_int(decimal_point + 1);
121 if (timeout.tv_nsec == -1) {
122 gpr_free(buf);
Mark D. Rothc968e602016-11-02 14:07:36 -0700123 return NULL;
124 }
Mark D. Roth84c8a022016-11-10 09:39:34 -0800125 // There should always be exactly 3, 6, or 9 fractional digits.
126 int multiplier = 1;
127 switch (strlen(decimal_point + 1)) {
128 case 9:
129 break;
130 case 6:
131 multiplier *= 1000;
132 break;
133 case 3:
134 multiplier *= 1000000;
135 break;
136 default: // Unsupported number of digits.
137 gpr_free(buf);
138 return NULL;
139 }
140 timeout.tv_nsec *= multiplier;
Mark D. Rothc968e602016-11-02 14:07:36 -0700141 }
Mark D. Roth84c8a022016-11-10 09:39:34 -0800142 timeout.tv_sec = gpr_parse_nonnegative_int(buf);
143 if (timeout.tv_sec == -1) return NULL;
144 gpr_free(buf);
Mark D. Rothc968e602016-11-02 14:07:36 -0700145 }
146 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700147 method_parameters *value = gpr_malloc(sizeof(method_parameters));
Mark D. Rothc968e602016-11-02 14:07:36 -0700148 value->timeout = timeout;
149 value->wait_for_ready = wait_for_ready;
Mark D. Roth9d480942016-10-19 14:18:05 -0700150 return value;
151}
152
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700153/*************************************************************************
154 * CHANNEL-WIDE FUNCTIONS
155 */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800156
Craig Tiller800dacb2015-10-06 09:10:26 -0700157typedef struct client_channel_channel_data {
Craig Tillerf5f17122015-06-25 08:47:26 -0700158 /** resolver for this channel */
159 grpc_resolver *resolver;
Craig Tiller20a3c352015-08-05 08:39:50 -0700160 /** have we started resolving this channel */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700161 bool started_resolving;
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700162 /** client channel factory */
163 grpc_client_channel_factory *client_channel_factory;
Craig Tillerf5f17122015-06-25 08:47:26 -0700164
Craig Tillerbefafe62017-02-09 11:30:54 -0800165 /** combiner protecting all variables below in this data structure */
166 grpc_combiner *combiner;
Mark D. Roth046cf762016-09-26 11:13:51 -0700167 /** currently active load balancer */
Craig Tillerf5f17122015-06-25 08:47:26 -0700168 grpc_lb_policy *lb_policy;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800169 /** retry throttle data */
170 grpc_server_retry_throttle_data *retry_throttle_data;
Mark D. Roth9d480942016-10-19 14:18:05 -0700171 /** maps method names to method_parameters structs */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800172 grpc_slice_hash_table *method_params_table;
Mark D. Roth046cf762016-09-26 11:13:51 -0700173 /** incoming resolver result - set by resolver.next() */
Mark D. Rothaf842452016-10-21 15:05:15 -0700174 grpc_channel_args *resolver_result;
Craig Tiller3f475422015-06-25 10:43:05 -0700175 /** a list of closures that are all waiting for config to come in */
Craig Tillerd9ccbbf2015-09-22 09:30:00 -0700176 grpc_closure_list waiting_for_config_closures;
Craig Tiller3f475422015-06-25 10:43:05 -0700177 /** resolver callback */
Mark D. Rothff4df062016-08-22 15:02:49 -0700178 grpc_closure on_resolver_result_changed;
Craig Tiller3f475422015-06-25 10:43:05 -0700179 /** connectivity state being tracked */
Craig Tillerca3e9d32015-06-27 18:37:27 -0700180 grpc_connectivity_state_tracker state_tracker;
Craig Tiller48cb07c2015-07-15 16:16:15 -0700181 /** when an lb_policy arrives, should we try to exit idle */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700182 bool exit_idle_when_lb_policy_arrives;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800183 /** owning stack */
184 grpc_channel_stack *owning_stack;
Craig Tiller69b093b2016-02-25 19:04:07 -0800185 /** interested parties (owned) */
186 grpc_pollset_set *interested_parties;
Craig Tiller613dafa2017-02-09 12:00:43 -0800187
188 /* the following properties are guarded by a mutex since API's require them
189 to be instantaniously available */
190 gpr_mu info_mu;
191 char *info_lb_policy_name;
192 /** service config in JSON form */
193 char *info_service_config_json;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800194} channel_data;
195
Craig Tillerd6c98df2015-08-18 09:33:44 -0700196/** We create one watcher for each new lb_policy that is returned from a
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700197 resolver, to watch for state changes from the lb_policy. When a state
198 change is seen, we update the channel, and create a new watcher. */
Craig Tillera82950e2015-09-22 12:33:20 -0700199typedef struct {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700200 channel_data *chand;
Craig Tiller33825112015-09-18 07:44:19 -0700201 grpc_closure on_changed;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700202 grpc_connectivity_state state;
203 grpc_lb_policy *lb_policy;
204} lb_policy_connectivity_watcher;
205
Craig Tillera82950e2015-09-22 12:33:20 -0700206static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
207 grpc_lb_policy *lb_policy,
208 grpc_connectivity_state current_state);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700209
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800210static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
211 channel_data *chand,
212 grpc_connectivity_state state,
Craig Tiller804ff712016-05-05 16:25:40 -0700213 grpc_error *error,
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800214 const char *reason) {
215 if ((state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
Craig Tiller48ed92e2016-06-02 11:07:12 -0700216 state == GRPC_CHANNEL_SHUTDOWN) &&
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800217 chand->lb_policy != NULL) {
Mark D. Roth59c9f902016-09-28 13:33:21 -0700218 /* cancel picks with wait_for_ready=false */
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800219 grpc_lb_policy_cancel_picks(
220 exec_ctx, chand->lb_policy,
Mark D. Roth59c9f902016-09-28 13:33:21 -0700221 /* mask= */ GRPC_INITIAL_METADATA_WAIT_FOR_READY,
Mark D. Roth58f52b72016-09-09 13:55:18 -0700222 /* check= */ 0, GRPC_ERROR_REF(error));
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800223 }
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700224 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, error,
225 reason);
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800226}
227
Craig Tiller804ff712016-05-05 16:25:40 -0700228static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
Craig Tillerbefafe62017-02-09 11:30:54 -0800229 void *arg, grpc_error *error) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700230 lb_policy_connectivity_watcher *w = arg;
Craig Tiller5d44c062015-07-01 08:55:28 -0700231 grpc_connectivity_state publish_state = w->state;
Craig Tillerc5de8352017-02-09 14:08:05 -0800232 /* check if the notification is for the latest policy */
233 if (w->lb_policy == w->chand->lb_policy) {
234 if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
235 publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Craig Tiller972470b2017-02-09 15:05:36 -0800236 grpc_resolver_channel_saw_error_locked(exec_ctx, w->chand->resolver);
Craig Tillerc5de8352017-02-09 14:08:05 -0800237 GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
238 w->chand->lb_policy = NULL;
239 }
240 set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
241 GRPC_ERROR_REF(error), "lb_changed");
242 if (w->state != GRPC_CHANNEL_SHUTDOWN) {
243 watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state);
244 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800245 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700246
Craig Tiller906e3bc2015-11-24 07:31:31 -0800247 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
Craig Tillera82950e2015-09-22 12:33:20 -0700248 gpr_free(w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700249}
250
Craig Tillera82950e2015-09-22 12:33:20 -0700251static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
252 grpc_lb_policy *lb_policy,
253 grpc_connectivity_state current_state) {
254 lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
Craig Tiller906e3bc2015-11-24 07:31:31 -0800255 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700256
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700257 w->chand = chand;
Craig Tillerbefafe62017-02-09 11:30:54 -0800258 grpc_closure_init(&w->on_changed, on_lb_policy_state_changed_locked, w,
259 grpc_combiner_scheduler(chand->combiner, false));
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700260 w->state = current_state;
261 w->lb_policy = lb_policy;
Craig Tillera82950e2015-09-22 12:33:20 -0700262 grpc_lb_policy_notify_on_state_change(exec_ctx, lb_policy, &w->state,
263 &w->on_changed);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700264}
265
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800266typedef struct {
267 char *server_name;
268 grpc_server_retry_throttle_data *retry_throttle_data;
269} service_config_parsing_state;
270
271static void parse_retry_throttle_params(const grpc_json *field, void *arg) {
272 service_config_parsing_state *parsing_state = arg;
273 if (strcmp(field->key, "retryThrottling") == 0) {
274 if (parsing_state->retry_throttle_data != NULL) return; // Duplicate.
275 if (field->type != GRPC_JSON_OBJECT) return;
276 int max_milli_tokens = 0;
277 int milli_token_ratio = 0;
278 for (grpc_json *sub_field = field->child; sub_field != NULL;
279 sub_field = sub_field->next) {
280 if (sub_field->key == NULL) continue;
281 if (strcmp(sub_field->key, "maxTokens") == 0) {
282 if (max_milli_tokens != 0) return; // Duplicate.
283 if (sub_field->type != GRPC_JSON_NUMBER) return;
284 max_milli_tokens = gpr_parse_nonnegative_int(sub_field->value);
285 if (max_milli_tokens == -1) return;
286 max_milli_tokens *= 1000;
287 } else if (strcmp(sub_field->key, "tokenRatio") == 0) {
288 if (milli_token_ratio != 0) return; // Duplicate.
289 if (sub_field->type != GRPC_JSON_NUMBER) return;
290 // We support up to 3 decimal digits.
291 size_t whole_len = strlen(sub_field->value);
292 uint32_t multiplier = 1;
293 uint32_t decimal_value = 0;
294 const char *decimal_point = strchr(sub_field->value, '.');
295 if (decimal_point != NULL) {
296 whole_len = (size_t)(decimal_point - sub_field->value);
297 multiplier = 1000;
298 size_t decimal_len = strlen(decimal_point + 1);
299 if (decimal_len > 3) decimal_len = 3;
300 if (!gpr_parse_bytes_to_uint32(decimal_point + 1, decimal_len,
301 &decimal_value)) {
302 return;
303 }
304 uint32_t decimal_multiplier = 1;
305 for (size_t i = 0; i < (3 - decimal_len); ++i) {
306 decimal_multiplier *= 10;
307 }
308 decimal_value *= decimal_multiplier;
309 }
310 uint32_t whole_value;
311 if (!gpr_parse_bytes_to_uint32(sub_field->value, whole_len,
312 &whole_value)) {
313 return;
314 }
315 milli_token_ratio = (int)((whole_value * multiplier) + decimal_value);
316 }
317 }
318 parsing_state->retry_throttle_data =
319 grpc_retry_throttle_map_get_data_for_server(
320 parsing_state->server_name, max_milli_tokens, milli_token_ratio);
321 }
322}
323
Craig Tillerbefafe62017-02-09 11:30:54 -0800324static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
325 void *arg, grpc_error *error) {
Craig Tiller3f475422015-06-25 10:43:05 -0700326 channel_data *chand = arg;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700327 char *lb_policy_name = NULL;
Craig Tiller3f475422015-06-25 10:43:05 -0700328 grpc_lb_policy *lb_policy = NULL;
329 grpc_lb_policy *old_lb_policy;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800330 grpc_slice_hash_table *method_params_table = NULL;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700331 grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700332 bool exit_idle = false;
Craig Tiller804ff712016-05-05 16:25:40 -0700333 grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800334 char *service_config_json = NULL;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800335 service_config_parsing_state parsing_state;
336 memset(&parsing_state, 0, sizeof(parsing_state));
Craig Tiller3f475422015-06-25 10:43:05 -0700337
Mark D. Roth046cf762016-09-26 11:13:51 -0700338 if (chand->resolver_result != NULL) {
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700339 // Find LB policy name.
Mark D. Rothaf842452016-10-21 15:05:15 -0700340 const grpc_arg *channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700341 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_POLICY_NAME);
Mark D. Rothaf842452016-10-21 15:05:15 -0700342 if (channel_arg != NULL) {
343 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
344 lb_policy_name = channel_arg->value.string;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700345 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700346 // Special case: If all of the addresses are balancer addresses,
347 // assume that we should use the grpclb policy, regardless of what the
348 // resolver actually specified.
Mark D. Rothaf842452016-10-21 15:05:15 -0700349 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700350 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES);
Mark D. Rothaf842452016-10-21 15:05:15 -0700351 if (channel_arg != NULL) {
352 GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
Mark D. Roth557c9902016-10-24 11:12:05 -0700353 grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
Mark D. Rothaf842452016-10-21 15:05:15 -0700354 bool found_backend_address = false;
355 for (size_t i = 0; i < addresses->num_addresses; ++i) {
356 if (!addresses->addresses[i].is_balancer) {
357 found_backend_address = true;
358 break;
359 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700360 }
Mark D. Rothaf842452016-10-21 15:05:15 -0700361 if (!found_backend_address) {
362 if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) {
363 gpr_log(GPR_INFO,
364 "resolver requested LB policy %s but provided only balancer "
365 "addresses, no backend addresses -- forcing use of grpclb LB "
366 "policy",
Mark D. Roth5f40e5d2016-10-24 13:09:05 -0700367 lb_policy_name);
Mark D. Rothaf842452016-10-21 15:05:15 -0700368 }
369 lb_policy_name = "grpclb";
Mark D. Roth88405f72016-10-03 08:24:52 -0700370 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700371 }
372 // Use pick_first if nothing was specified and we didn't select grpclb
373 // above.
374 if (lb_policy_name == NULL) lb_policy_name = "pick_first";
Mark D. Roth41124992016-11-03 11:22:20 -0700375 // Instantiate LB policy.
376 grpc_lb_policy_args lb_policy_args;
377 lb_policy_args.args = chand->resolver_result;
378 lb_policy_args.client_channel_factory = chand->client_channel_factory;
Mark D. Roth88405f72016-10-03 08:24:52 -0700379 lb_policy =
380 grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700381 if (lb_policy != NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -0700382 GRPC_LB_POLICY_REF(lb_policy, "config_change");
Craig Tillerf707d622016-05-06 14:26:12 -0700383 GRPC_ERROR_UNREF(state_error);
Craig Tiller804ff712016-05-05 16:25:40 -0700384 state =
385 grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error);
Craig Tiller45724b32015-09-22 10:42:19 -0700386 }
Mark D. Roth41124992016-11-03 11:22:20 -0700387 // Find service config.
Mark D. Rothaf842452016-10-21 15:05:15 -0700388 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700389 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVICE_CONFIG);
Mark D. Roth046cf762016-09-26 11:13:51 -0700390 if (channel_arg != NULL) {
Mark D. Roth9ec28af2016-11-03 12:32:39 -0700391 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800392 service_config_json = gpr_strdup(channel_arg->value.string);
Mark D. Roth70a1abd2016-11-04 09:26:37 -0700393 grpc_service_config *service_config =
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800394 grpc_service_config_create(service_config_json);
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700395 if (service_config != NULL) {
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800396 channel_arg =
397 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVER_URI);
398 GPR_ASSERT(channel_arg != NULL);
399 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
400 grpc_uri *uri = grpc_uri_parse(channel_arg->value.string, true);
401 GPR_ASSERT(uri->path[0] != '\0');
402 parsing_state.server_name =
403 uri->path[0] == '/' ? uri->path + 1 : uri->path;
404 grpc_service_config_parse_global_params(
405 service_config, parse_retry_throttle_params, &parsing_state);
406 parsing_state.server_name = NULL;
407 grpc_uri_destroy(uri);
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700408 method_params_table = grpc_service_config_create_method_config_table(
Craig Tillerb28c7e82016-11-18 10:29:04 -0800409 exec_ctx, service_config, method_parameters_create_from_json,
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700410 &method_parameters_vtable);
411 grpc_service_config_destroy(service_config);
412 }
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700413 }
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700414 // Before we clean up, save a copy of lb_policy_name, since it might
415 // be pointing to data inside chand->resolver_result.
416 // The copy will be saved in chand->lb_policy_name below.
417 lb_policy_name = gpr_strdup(lb_policy_name);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800418 grpc_channel_args_destroy(exec_ctx, chand->resolver_result);
Mark D. Roth046cf762016-09-26 11:13:51 -0700419 chand->resolver_result = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700420 }
421
Craig Tiller86c99582015-11-25 15:22:26 -0800422 if (lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800423 grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties,
424 chand->interested_parties);
Craig Tiller86c99582015-11-25 15:22:26 -0800425 }
426
Craig Tiller613dafa2017-02-09 12:00:43 -0800427 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700428 if (lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800429 gpr_free(chand->info_lb_policy_name);
430 chand->info_lb_policy_name = lb_policy_name;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700431 }
Craig Tiller3f475422015-06-25 10:43:05 -0700432 old_lb_policy = chand->lb_policy;
433 chand->lb_policy = lb_policy;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800434 if (service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800435 gpr_free(chand->info_service_config_json);
436 chand->info_service_config_json = service_config_json;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800437 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800438 gpr_mu_unlock(&chand->info_mu);
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800439
440 if (chand->retry_throttle_data != NULL) {
441 grpc_server_retry_throttle_data_unref(chand->retry_throttle_data);
442 }
443 chand->retry_throttle_data = parsing_state.retry_throttle_data;
Mark D. Roth9d480942016-10-19 14:18:05 -0700444 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800445 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth046cf762016-09-26 11:13:51 -0700446 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700447 chand->method_params_table = method_params_table;
Craig Tiller0ede5452016-04-23 12:21:45 -0700448 if (lb_policy != NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -0800449 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller0ede5452016-04-23 12:21:45 -0700450 } else if (chand->resolver == NULL /* disconnected */) {
Craig Tiller804ff712016-05-05 16:25:40 -0700451 grpc_closure_list_fail_all(
452 &chand->waiting_for_config_closures,
453 GRPC_ERROR_CREATE_REFERENCING("Channel disconnected", &error, 1));
Craig Tiller91031da2016-12-28 15:44:25 -0800454 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tillera82950e2015-09-22 12:33:20 -0700455 }
456 if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
457 GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700458 exit_idle = true;
459 chand->exit_idle_when_lb_policy_arrives = false;
Craig Tillera82950e2015-09-22 12:33:20 -0700460 }
Craig Tiller98465032015-06-29 14:36:42 -0700461
Craig Tiller804ff712016-05-05 16:25:40 -0700462 if (error == GRPC_ERROR_NONE && chand->resolver) {
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700463 set_channel_connectivity_state_locked(
464 exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700465 if (lb_policy != NULL) {
466 watch_lb_policy(exec_ctx, chand, lb_policy, state);
Craig Tiller45724b32015-09-22 10:42:19 -0700467 }
Craig Tiller906e3bc2015-11-24 07:31:31 -0800468 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -0800469 grpc_resolver_next_locked(exec_ctx, chand->resolver,
470 &chand->resolver_result,
471 &chand->on_resolver_result_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700472 } else {
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800473 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800474 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800475 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
476 chand->resolver = NULL;
477 }
Craig Tiller804ff712016-05-05 16:25:40 -0700478 grpc_error *refs[] = {error, state_error};
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800479 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700480 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller804ff712016-05-05 16:25:40 -0700481 GRPC_ERROR_CREATE_REFERENCING("Got config after disconnection", refs,
482 GPR_ARRAY_SIZE(refs)),
483 "resolver_gone");
Craig Tillera82950e2015-09-22 12:33:20 -0700484 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700485
Craig Tillera82950e2015-09-22 12:33:20 -0700486 if (exit_idle) {
487 grpc_lb_policy_exit_idle(exec_ctx, lb_policy);
488 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
489 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700490
Craig Tillera82950e2015-09-22 12:33:20 -0700491 if (old_lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800492 grpc_pollset_set_del_pollset_set(
493 exec_ctx, old_lb_policy->interested_parties, chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700494 GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
495 }
Craig Tiller000cd8f2015-09-18 07:20:29 -0700496
Craig Tillera82950e2015-09-22 12:33:20 -0700497 if (lb_policy != NULL) {
498 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
499 }
Craig Tiller45724b32015-09-22 10:42:19 -0700500
Craig Tiller906e3bc2015-11-24 07:31:31 -0800501 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700502 GRPC_ERROR_UNREF(state_error);
Craig Tiller3f475422015-06-25 10:43:05 -0700503}
504
Craig Tillera8610c02017-02-14 10:05:11 -0800505static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
506 grpc_error *error_ignored) {
Craig Tillerbefafe62017-02-09 11:30:54 -0800507 grpc_transport_op *op = arg;
508 grpc_channel_element *elem = op->transport_private.args[0];
Craig Tillerca3e9d32015-06-27 18:37:27 -0700509 channel_data *chand = elem->channel_data;
Craig Tiller000cd8f2015-09-18 07:20:29 -0700510
Craig Tillera82950e2015-09-22 12:33:20 -0700511 if (op->on_connectivity_state_change != NULL) {
512 grpc_connectivity_state_notify_on_state_change(
513 exec_ctx, &chand->state_tracker, op->connectivity_state,
514 op->on_connectivity_state_change);
515 op->on_connectivity_state_change = NULL;
516 op->connectivity_state = NULL;
517 }
518
Craig Tiller26dab312015-12-07 14:43:47 -0800519 if (op->send_ping != NULL) {
Craig Tiller87b71e22015-12-07 15:14:14 -0800520 if (chand->lb_policy == NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -0800521 grpc_closure_sched(exec_ctx, op->send_ping,
522 GRPC_ERROR_CREATE("Ping with no load balancing"));
Craig Tiller26dab312015-12-07 14:43:47 -0800523 } else {
Craig Tiller28bf8912015-12-07 16:07:04 -0800524 grpc_lb_policy_ping_one(exec_ctx, chand->lb_policy, op->send_ping);
Craig Tiller26dab312015-12-07 14:43:47 -0800525 op->bind_pollset = NULL;
526 }
527 op->send_ping = NULL;
528 }
529
Craig Tiller1c51edc2016-05-07 16:18:43 -0700530 if (op->disconnect_with_error != GRPC_ERROR_NONE) {
531 if (chand->resolver != NULL) {
532 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700533 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller1c51edc2016-05-07 16:18:43 -0700534 GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
Craig Tiller972470b2017-02-09 15:05:36 -0800535 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700536 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
537 chand->resolver = NULL;
538 if (!chand->started_resolving) {
539 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
540 GRPC_ERROR_REF(op->disconnect_with_error));
Craig Tiller91031da2016-12-28 15:44:25 -0800541 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700542 }
543 if (chand->lb_policy != NULL) {
544 grpc_pollset_set_del_pollset_set(exec_ctx,
545 chand->lb_policy->interested_parties,
546 chand->interested_parties);
547 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
548 chand->lb_policy = NULL;
549 }
Craig Tillerb12d22a2016-04-23 12:50:21 -0700550 }
Craig Tiller1c51edc2016-05-07 16:18:43 -0700551 GRPC_ERROR_UNREF(op->disconnect_with_error);
Craig Tillera82950e2015-09-22 12:33:20 -0700552 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800553 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "start_transport_op");
554
555 grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
Craig Tillerbefafe62017-02-09 11:30:54 -0800556}
557
558static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
559 grpc_channel_element *elem,
560 grpc_transport_op *op) {
561 channel_data *chand = elem->channel_data;
562
Craig Tillerbefafe62017-02-09 11:30:54 -0800563 GPR_ASSERT(op->set_accept_stream == false);
564 if (op->bind_pollset != NULL) {
565 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
566 op->bind_pollset);
567 }
568
569 op->transport_private.args[0] = elem;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800570 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "start_transport_op");
Craig Tillerbefafe62017-02-09 11:30:54 -0800571 grpc_closure_sched(
Craig Tillera8610c02017-02-14 10:05:11 -0800572 exec_ctx, grpc_closure_init(
573 &op->transport_private.closure, start_transport_op_locked,
574 op, grpc_combiner_scheduler(chand->combiner, false)),
Craig Tillerbefafe62017-02-09 11:30:54 -0800575 GRPC_ERROR_NONE);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700576}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800577
Mark D. Rothb2d24882016-10-27 15:44:07 -0700578static void cc_get_channel_info(grpc_exec_ctx *exec_ctx,
579 grpc_channel_element *elem,
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700580 const grpc_channel_info *info) {
Mark D. Rothb2d24882016-10-27 15:44:07 -0700581 channel_data *chand = elem->channel_data;
Craig Tiller613dafa2017-02-09 12:00:43 -0800582 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700583 if (info->lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800584 *info->lb_policy_name = chand->info_lb_policy_name == NULL
Mark D. Roth78afd772016-11-04 12:49:49 -0700585 ? NULL
Craig Tiller613dafa2017-02-09 12:00:43 -0800586 : gpr_strdup(chand->info_lb_policy_name);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700587 }
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800588 if (info->service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800589 *info->service_config_json =
590 chand->info_service_config_json == NULL
591 ? NULL
592 : gpr_strdup(chand->info_service_config_json);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800593 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800594 gpr_mu_unlock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700595}
596
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700597/* Constructor for channel_data */
Mark D. Rothc1087882016-11-18 10:54:45 -0800598static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800599 grpc_channel_element *elem,
600 grpc_channel_element_args *args) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700601 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700602 memset(chand, 0, sizeof(*chand));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700603 GPR_ASSERT(args->is_last);
604 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800605 // Initialize data members.
Craig Tillerbefafe62017-02-09 11:30:54 -0800606 chand->combiner = grpc_combiner_create(NULL);
Craig Tillerd85477512017-02-09 12:02:39 -0800607 gpr_mu_init(&chand->info_mu);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800608 chand->owning_stack = args->channel_stack;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700609 grpc_closure_init(&chand->on_resolver_result_changed,
Craig Tillerbefafe62017-02-09 11:30:54 -0800610 on_resolver_result_changed_locked, chand,
611 grpc_combiner_scheduler(chand->combiner, false));
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800612 chand->interested_parties = grpc_pollset_set_create();
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700613 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
614 "client_channel");
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800615 // Record client channel factory.
616 const grpc_arg *arg = grpc_channel_args_find(args->channel_args,
617 GRPC_ARG_CLIENT_CHANNEL_FACTORY);
618 GPR_ASSERT(arg != NULL);
619 GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
620 grpc_client_channel_factory_ref(arg->value.pointer.p);
621 chand->client_channel_factory = arg->value.pointer.p;
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800622 // Get server name to resolve, using proxy mapper if needed.
Mark D. Roth86e90592016-11-18 09:56:40 -0800623 arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800624 GPR_ASSERT(arg != NULL);
625 GPR_ASSERT(arg->type == GRPC_ARG_STRING);
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800626 char *proxy_name = NULL;
627 grpc_channel_args *new_args = NULL;
628 grpc_proxy_mappers_map_name(exec_ctx, arg->value.string, args->channel_args,
629 &proxy_name, &new_args);
630 // Instantiate resolver.
Mark D. Roth45ccec52017-01-18 14:04:01 -0800631 chand->resolver = grpc_resolver_create(
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800632 exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string,
633 new_args != NULL ? new_args : args->channel_args,
Craig Tiller972470b2017-02-09 15:05:36 -0800634 chand->interested_parties, chand->combiner);
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800635 if (proxy_name != NULL) gpr_free(proxy_name);
636 if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args);
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800637 if (chand->resolver == NULL) {
638 return GRPC_ERROR_CREATE("resolver creation failed");
639 }
640 return GRPC_ERROR_NONE;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700641}
642
Craig Tiller972470b2017-02-09 15:05:36 -0800643static void shutdown_resolver_locked(grpc_exec_ctx *exec_ctx, void *arg,
644 grpc_error *error) {
645 grpc_resolver *resolver = arg;
646 grpc_resolver_shutdown_locked(exec_ctx, resolver);
647 GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel");
648}
649
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700650/* Destructor for channel_data */
651static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
652 grpc_channel_element *elem) {
653 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700654 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800655 grpc_closure_sched(
656 exec_ctx,
657 grpc_closure_create(shutdown_resolver_locked, chand->resolver,
658 grpc_combiner_scheduler(chand->combiner, false)),
659 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700660 }
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700661 if (chand->client_channel_factory != NULL) {
662 grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
663 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700664 if (chand->lb_policy != NULL) {
665 grpc_pollset_set_del_pollset_set(exec_ctx,
666 chand->lb_policy->interested_parties,
667 chand->interested_parties);
668 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
669 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800670 gpr_free(chand->info_lb_policy_name);
671 gpr_free(chand->info_service_config_json);
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800672 if (chand->retry_throttle_data != NULL) {
673 grpc_server_retry_throttle_data_unref(chand->retry_throttle_data);
674 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700675 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800676 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700677 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700678 grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
Craig Tiller9e5ac1b2017-02-14 22:25:50 -0800679 grpc_pollset_set_destroy(exec_ctx, chand->interested_parties);
Craig Tillerf1021672017-02-09 21:29:50 -0800680 GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel");
Craig Tillerd85477512017-02-09 12:02:39 -0800681 gpr_mu_destroy(&chand->info_mu);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700682}
683
684/*************************************************************************
685 * PER-CALL FUNCTIONS
686 */
687
688#define GET_CALL(call_data) \
689 ((grpc_subchannel_call *)(gpr_atm_acq_load(&(call_data)->subchannel_call)))
690
691#define CANCELLED_CALL ((grpc_subchannel_call *)1)
692
693typedef enum {
694 GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING,
695 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL
696} subchannel_creation_phase;
697
698/** Call data. Holds a pointer to grpc_subchannel_call and the
699 associated machinery to create such a pointer.
700 Handles queueing of stream ops until a call object is ready, waiting
701 for initial metadata before trying to create a call object,
702 and handling cancellation gracefully. */
703typedef struct client_channel_call_data {
Mark D. Roth72f6da82016-09-02 13:42:38 -0700704 // State for handling deadlines.
705 // The code in deadline_filter.c requires this to be the first field.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700706 // TODO(roth): This is slightly sub-optimal in that grpc_deadline_state
707 // and this struct both independently store a pointer to the call
708 // stack and each has its own mutex. If/when we have time, find a way
Mark D. Roth6ad99172016-09-09 07:52:48 -0700709 // to avoid this without breaking the grpc_deadline_state abstraction.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700710 grpc_deadline_state deadline_state;
Mark D. Rothf28763c2016-09-14 15:18:40 -0700711
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800712 grpc_slice path; // Request path.
Mark D. Rothe40dd292016-10-05 14:58:37 -0700713 gpr_timespec call_start_time;
714 gpr_timespec deadline;
Mark D. Roth9d480942016-10-19 14:18:05 -0700715 wait_for_ready_value wait_for_ready_from_service_config;
Mark D. Rothe40dd292016-10-05 14:58:37 -0700716 grpc_closure read_service_config;
Mark D. Rothaa850a72016-09-26 13:38:02 -0700717
Mark D. Rothf28763c2016-09-14 15:18:40 -0700718 grpc_error *cancel_error;
Mark D. Roth72f6da82016-09-02 13:42:38 -0700719
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700720 /** either 0 for no call, 1 for cancelled, or a pointer to a
721 grpc_subchannel_call */
722 gpr_atm subchannel_call;
723
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700724 subchannel_creation_phase creation_phase;
725 grpc_connected_subchannel *connected_subchannel;
726 grpc_polling_entity *pollent;
727
Craig Tiller57726ca2016-09-12 11:59:45 -0700728 grpc_transport_stream_op **waiting_ops;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700729 size_t waiting_ops_count;
730 size_t waiting_ops_capacity;
731
732 grpc_closure next_step;
733
734 grpc_call_stack *owning_call;
David Garcia Quintasd1a47f12016-09-02 12:46:44 +0200735
736 grpc_linked_mdelem lb_token_mdelem;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800737
738 grpc_closure on_complete;
739 grpc_closure *original_on_complete;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700740} call_data;
741
Craig Tiller8b1d59c2016-12-27 15:15:30 -0800742grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
743 grpc_call_element *call_elem) {
744 grpc_subchannel_call *scc = GET_CALL((call_data *)call_elem->call_data);
745 return scc == CANCELLED_CALL ? NULL : scc;
746}
747
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700748static void add_waiting_locked(call_data *calld, grpc_transport_stream_op *op) {
749 GPR_TIMER_BEGIN("add_waiting_locked", 0);
750 if (calld->waiting_ops_count == calld->waiting_ops_capacity) {
751 calld->waiting_ops_capacity = GPR_MAX(3, 2 * calld->waiting_ops_capacity);
752 calld->waiting_ops =
753 gpr_realloc(calld->waiting_ops,
754 calld->waiting_ops_capacity * sizeof(*calld->waiting_ops));
755 }
Craig Tiller57726ca2016-09-12 11:59:45 -0700756 calld->waiting_ops[calld->waiting_ops_count++] = op;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700757 GPR_TIMER_END("add_waiting_locked", 0);
758}
759
760static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld,
761 grpc_error *error) {
762 size_t i;
763 for (i = 0; i < calld->waiting_ops_count; i++) {
764 grpc_transport_stream_op_finish_with_failure(
Craig Tiller57726ca2016-09-12 11:59:45 -0700765 exec_ctx, calld->waiting_ops[i], GRPC_ERROR_REF(error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700766 }
767 calld->waiting_ops_count = 0;
768 GRPC_ERROR_UNREF(error);
769}
770
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700771static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
Craig Tiller57726ca2016-09-12 11:59:45 -0700772 if (calld->waiting_ops_count == 0) {
773 return;
774 }
775
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800776 grpc_subchannel_call *call = GET_CALL(calld);
777 grpc_transport_stream_op **ops = calld->waiting_ops;
778 size_t nops = calld->waiting_ops_count;
779 if (call == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700780 fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED);
781 return;
782 }
783 calld->waiting_ops = NULL;
784 calld->waiting_ops_count = 0;
785 calld->waiting_ops_capacity = 0;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800786 for (size_t i = 0; i < nops; i++) {
787 grpc_subchannel_call_process_op(exec_ctx, call, ops[i]);
788 }
Craig Tiller9efea882017-02-09 13:06:52 -0800789 gpr_free(ops);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700790}
791
Craig Tillerbefafe62017-02-09 11:30:54 -0800792static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
793 grpc_error *error) {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700794 grpc_call_element *elem = arg;
795 call_data *calld = elem->call_data;
796 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700797 GPR_ASSERT(calld->creation_phase ==
798 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
Yuchen Zeng19656b12016-09-01 18:00:45 -0700799 grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
800 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700801 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
802 if (calld->connected_subchannel == NULL) {
803 gpr_atm_no_barrier_store(&calld->subchannel_call, 1);
804 fail_locked(exec_ctx, calld, GRPC_ERROR_CREATE_REFERENCING(
805 "Failed to create subchannel", &error, 1));
Mark D. Roth72f6da82016-09-02 13:42:38 -0700806 } else if (GET_CALL(calld) == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700807 /* already cancelled before subchannel became ready */
David Garcia Quintas68a9e382016-12-13 10:50:40 -0800808 grpc_error *cancellation_error = GRPC_ERROR_CREATE_REFERENCING(
809 "Cancelled before creating subchannel", &error, 1);
810 /* if due to deadline, attach the deadline exceeded status to the error */
811 if (gpr_time_cmp(calld->deadline, gpr_now(GPR_CLOCK_MONOTONIC)) < 0) {
812 cancellation_error =
813 grpc_error_set_int(cancellation_error, GRPC_ERROR_INT_GRPC_STATUS,
814 GRPC_STATUS_DEADLINE_EXCEEDED);
815 }
816 fail_locked(exec_ctx, calld, cancellation_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700817 } else {
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700818 /* Create call on subchannel. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700819 grpc_subchannel_call *subchannel_call = NULL;
820 grpc_error *new_error = grpc_connected_subchannel_create_call(
Mark D. Rothaa850a72016-09-26 13:38:02 -0700821 exec_ctx, calld->connected_subchannel, calld->pollent, calld->path,
Mark D. Roth3d883412016-11-07 13:42:54 -0800822 calld->call_start_time, calld->deadline, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700823 if (new_error != GRPC_ERROR_NONE) {
824 new_error = grpc_error_add_child(new_error, error);
825 subchannel_call = CANCELLED_CALL;
826 fail_locked(exec_ctx, calld, new_error);
827 }
828 gpr_atm_rel_store(&calld->subchannel_call,
829 (gpr_atm)(uintptr_t)subchannel_call);
830 retry_waiting_locked(exec_ctx, calld);
831 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700832 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
833}
834
835static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
836 call_data *calld = elem->call_data;
837 grpc_subchannel_call *subchannel_call = GET_CALL(calld);
838 if (subchannel_call == NULL || subchannel_call == CANCELLED_CALL) {
839 return NULL;
840 } else {
841 return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
842 }
843}
844
Craig Tiller577c9b22015-11-02 14:11:15 -0800845typedef struct {
846 grpc_metadata_batch *initial_metadata;
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800847 uint32_t initial_metadata_flags;
Craig Tillerb5585d42015-11-17 07:18:31 -0800848 grpc_connected_subchannel **connected_subchannel;
Craig Tiller577c9b22015-11-02 14:11:15 -0800849 grpc_closure *on_ready;
850 grpc_call_element *elem;
851 grpc_closure closure;
852} continue_picking_args;
853
Yuchen Zeng144ce652016-09-01 18:19:34 -0700854/** Return true if subchannel is available immediately (in which case on_ready
855 should not be called), or false otherwise (in which case on_ready should be
856 called when the subchannel is available). */
Craig Tillerbefafe62017-02-09 11:30:54 -0800857static bool pick_subchannel_locked(
858 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
859 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
860 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
861 grpc_error *error);
Craig Tiller577c9b22015-11-02 14:11:15 -0800862
Craig Tillerbefafe62017-02-09 11:30:54 -0800863static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg,
864 grpc_error *error) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800865 continue_picking_args *cpa = arg;
Craig Tiller0ede5452016-04-23 12:21:45 -0700866 if (cpa->connected_subchannel == NULL) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800867 /* cancelled, do nothing */
Craig Tiller804ff712016-05-05 16:25:40 -0700868 } else if (error != GRPC_ERROR_NONE) {
Craig Tiller91031da2016-12-28 15:44:25 -0800869 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error));
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700870 } else {
Craig Tillerbefafe62017-02-09 11:30:54 -0800871 if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata,
872 cpa->initial_metadata_flags,
873 cpa->connected_subchannel, cpa->on_ready,
874 GRPC_ERROR_NONE)) {
Craig Tiller91031da2016-12-28 15:44:25 -0800875 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700876 }
Craig Tiller577c9b22015-11-02 14:11:15 -0800877 }
878 gpr_free(cpa);
879}
880
Craig Tillerbefafe62017-02-09 11:30:54 -0800881static bool pick_subchannel_locked(
882 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
883 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
884 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
885 grpc_error *error) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700886 GPR_TIMER_BEGIN("pick_subchannel", 0);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700887
Craig Tiller577c9b22015-11-02 14:11:15 -0800888 channel_data *chand = elem->channel_data;
889 call_data *calld = elem->call_data;
890 continue_picking_args *cpa;
891 grpc_closure *closure;
892
Craig Tillerb5585d42015-11-17 07:18:31 -0800893 GPR_ASSERT(connected_subchannel);
Craig Tiller577c9b22015-11-02 14:11:15 -0800894
Craig Tiller577c9b22015-11-02 14:11:15 -0800895 if (initial_metadata == NULL) {
896 if (chand->lb_policy != NULL) {
Craig Tillerab33b482015-11-21 08:11:04 -0800897 grpc_lb_policy_cancel_pick(exec_ctx, chand->lb_policy,
Mark D. Roth5f844002016-09-08 08:20:53 -0700898 connected_subchannel, GRPC_ERROR_REF(error));
Craig Tiller577c9b22015-11-02 14:11:15 -0800899 }
900 for (closure = chand->waiting_for_config_closures.head; closure != NULL;
Craig Tiller804ff712016-05-05 16:25:40 -0700901 closure = closure->next_data.next) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800902 cpa = closure->cb_arg;
Craig Tillerb5585d42015-11-17 07:18:31 -0800903 if (cpa->connected_subchannel == connected_subchannel) {
904 cpa->connected_subchannel = NULL;
Craig Tiller91031da2016-12-28 15:44:25 -0800905 grpc_closure_sched(
Mark D. Roth932b10c2016-09-09 08:44:30 -0700906 exec_ctx, cpa->on_ready,
Craig Tiller91031da2016-12-28 15:44:25 -0800907 GRPC_ERROR_CREATE_REFERENCING("Pick cancelled", &error, 1));
Craig Tiller577c9b22015-11-02 14:11:15 -0800908 }
909 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700910 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth697a1f62016-09-07 13:35:07 -0700911 GRPC_ERROR_UNREF(error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700912 return true;
Craig Tiller577c9b22015-11-02 14:11:15 -0800913 }
Mark D. Roth697a1f62016-09-07 13:35:07 -0700914 GPR_ASSERT(error == GRPC_ERROR_NONE);
Craig Tiller577c9b22015-11-02 14:11:15 -0800915 if (chand->lb_policy != NULL) {
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800916 grpc_lb_policy *lb_policy = chand->lb_policy;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700917 GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel");
Mark D. Rothe40dd292016-10-05 14:58:37 -0700918 // If the application explicitly set wait_for_ready, use that.
919 // Otherwise, if the service config specified a value for this
920 // method, use that.
Mark D. Rothc1c38582016-10-11 11:03:27 -0700921 const bool wait_for_ready_set_from_api =
922 initial_metadata_flags &
923 GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
924 const bool wait_for_ready_set_from_service_config =
925 calld->wait_for_ready_from_service_config != WAIT_FOR_READY_UNSET;
926 if (!wait_for_ready_set_from_api &&
927 wait_for_ready_set_from_service_config) {
Mark D. Rothe40dd292016-10-05 14:58:37 -0700928 if (calld->wait_for_ready_from_service_config == WAIT_FOR_READY_TRUE) {
929 initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
930 } else {
931 initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
932 }
933 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700934 const grpc_lb_policy_pick_args inputs = {
Yuchen Zengac8bc422016-10-05 14:00:02 -0700935 initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem,
936 gpr_inf_future(GPR_CLOCK_MONOTONIC)};
Mark D. Roth55f25b62016-10-12 14:55:20 -0700937 const bool result = grpc_lb_policy_pick(
938 exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, on_ready);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700939 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel");
940 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700941 return result;
Craig Tiller577c9b22015-11-02 14:11:15 -0800942 }
943 if (chand->resolver != NULL && !chand->started_resolving) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700944 chand->started_resolving = true;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800945 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -0800946 grpc_resolver_next_locked(exec_ctx, chand->resolver,
947 &chand->resolver_result,
948 &chand->on_resolver_result_changed);
Craig Tiller577c9b22015-11-02 14:11:15 -0800949 }
Craig Tiller0eab6972016-04-23 12:59:57 -0700950 if (chand->resolver != NULL) {
951 cpa = gpr_malloc(sizeof(*cpa));
952 cpa->initial_metadata = initial_metadata;
953 cpa->initial_metadata_flags = initial_metadata_flags;
954 cpa->connected_subchannel = connected_subchannel;
955 cpa->on_ready = on_ready;
956 cpa->elem = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -0800957 grpc_closure_init(&cpa->closure, continue_picking_locked, cpa,
958 grpc_combiner_scheduler(chand->combiner, true));
Craig Tiller804ff712016-05-05 16:25:40 -0700959 grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
960 GRPC_ERROR_NONE);
Craig Tiller0eab6972016-04-23 12:59:57 -0700961 } else {
Craig Tiller91031da2016-12-28 15:44:25 -0800962 grpc_closure_sched(exec_ctx, on_ready, GRPC_ERROR_CREATE("Disconnected"));
Craig Tiller0eab6972016-04-23 12:59:57 -0700963 }
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700964
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700965 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700966 return false;
Craig Tiller577c9b22015-11-02 14:11:15 -0800967}
968
Craig Tillera8610c02017-02-14 10:05:11 -0800969static void start_transport_stream_op_locked_inner(grpc_exec_ctx *exec_ctx,
970 grpc_transport_stream_op *op,
971 grpc_call_element *elem) {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700972 channel_data *chand = elem->channel_data;
Craig Tillera11bfc82017-02-14 09:56:33 -0800973 call_data *calld = elem->call_data;
Craig Tillerbefafe62017-02-09 11:30:54 -0800974 grpc_subchannel_call *call;
975
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700976 /* need to recheck that another thread hasn't set the call */
977 call = GET_CALL(calld);
978 if (call == CANCELLED_CALL) {
Mark D. Rothf28763c2016-09-14 15:18:40 -0700979 grpc_transport_stream_op_finish_with_failure(
980 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -0800981 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700982 return;
983 }
984 if (call != NULL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700985 grpc_subchannel_call_process_op(exec_ctx, call, op);
Craig Tillera11bfc82017-02-14 09:56:33 -0800986 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700987 return;
988 }
989 /* if this is a cancellation, then we can raise our cancelled flag */
990 if (op->cancel_error != GRPC_ERROR_NONE) {
991 if (!gpr_atm_rel_cas(&calld->subchannel_call, 0,
992 (gpr_atm)(uintptr_t)CANCELLED_CALL)) {
Craig Tillera11bfc82017-02-14 09:56:33 -0800993 /* recurse to retry */
Craig Tillera8610c02017-02-14 10:05:11 -0800994 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -0800995 /* early out */
996 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700997 } else {
Craig Tillerbe9691a2017-02-14 10:00:42 -0800998 /* Stash a copy of cancel_error in our call data, so that we can use
999 it for subsequent operations. This ensures that if the call is
1000 cancelled before any ops are passed down (e.g., if the deadline
1001 is in the past when the call starts), we can return the right
1002 error to the caller when the first op does get passed down. */
Mark D. Rothf28763c2016-09-14 15:18:40 -07001003 calld->cancel_error = GRPC_ERROR_REF(op->cancel_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001004 switch (calld->creation_phase) {
1005 case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
1006 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error));
1007 break;
1008 case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
Craig Tillerbefafe62017-02-09 11:30:54 -08001009 pick_subchannel_locked(exec_ctx, elem, NULL, 0,
1010 &calld->connected_subchannel, NULL,
1011 GRPC_ERROR_REF(op->cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001012 break;
1013 }
Mark D. Roth72f6da82016-09-02 13:42:38 -07001014 grpc_transport_stream_op_finish_with_failure(
1015 exec_ctx, op, GRPC_ERROR_REF(op->cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -08001016 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001017 return;
1018 }
1019 }
1020 /* if we don't have a subchannel, try to get one */
1021 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
1022 calld->connected_subchannel == NULL &&
1023 op->send_initial_metadata != NULL) {
1024 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
Craig Tillerbefafe62017-02-09 11:30:54 -08001025 grpc_closure_init(&calld->next_step, subchannel_ready_locked, elem,
1026 grpc_combiner_scheduler(chand->combiner, true));
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001027 GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
Yuchen Zeng144ce652016-09-01 18:19:34 -07001028 /* If a subchannel is not available immediately, the polling entity from
1029 call_data should be provided to channel_data's interested_parties, so
1030 that IO of the lb_policy and resolver could be done under it. */
Craig Tillerbefafe62017-02-09 11:30:54 -08001031 if (pick_subchannel_locked(exec_ctx, elem, op->send_initial_metadata,
1032 op->send_initial_metadata_flags,
1033 &calld->connected_subchannel, &calld->next_step,
1034 GRPC_ERROR_NONE)) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001035 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
1036 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
Yuchen Zeng19656b12016-09-01 18:00:45 -07001037 } else {
Yuchen Zeng19656b12016-09-01 18:00:45 -07001038 grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
1039 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001040 }
1041 }
1042 /* if we've got a subchannel, then let's ask it to create a call */
1043 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
1044 calld->connected_subchannel != NULL) {
1045 grpc_subchannel_call *subchannel_call = NULL;
1046 grpc_error *error = grpc_connected_subchannel_create_call(
Mark D. Rothaa850a72016-09-26 13:38:02 -07001047 exec_ctx, calld->connected_subchannel, calld->pollent, calld->path,
Mark D. Roth3d883412016-11-07 13:42:54 -08001048 calld->call_start_time, calld->deadline, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001049 if (error != GRPC_ERROR_NONE) {
1050 subchannel_call = CANCELLED_CALL;
1051 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
1052 grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
1053 }
1054 gpr_atm_rel_store(&calld->subchannel_call,
1055 (gpr_atm)(uintptr_t)subchannel_call);
1056 retry_waiting_locked(exec_ctx, calld);
Craig Tillera11bfc82017-02-14 09:56:33 -08001057 /* recurse to retry */
Craig Tillera8610c02017-02-14 10:05:11 -08001058 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001059 /* early out */
1060 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001061 }
1062 /* nothing to be done but wait */
1063 add_waiting_locked(calld, op);
Craig Tillera11bfc82017-02-14 09:56:33 -08001064}
1065
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001066static void on_complete_locked(grpc_exec_ctx *exec_ctx, void *arg,
1067 grpc_error *error) {
1068 grpc_call_element *elem = arg;
1069 channel_data *chand = elem->channel_data;
1070 call_data *calld = elem->call_data;
1071 if (chand->retry_throttle_data != NULL) {
1072 if (error == GRPC_ERROR_NONE) {
1073 grpc_server_retry_throttle_data_record_success(
1074 &chand->retry_throttle_data);
1075 } else {
1076 // TODO(roth): In a subsequent PR, check the return value here and
1077 // decide whether or not to retry.
1078 grpc_server_retry_throttle_data_record_failure(
1079 &chand->retry_throttle_data);
1080 }
1081 }
1082 grpc_closure_run(exec_ctx, calld->original_on_complete, error);
1083}
1084
1085static void start_transport_stream_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
1086 grpc_error *error_ignored) {
1087 GPR_TIMER_BEGIN("start_transport_stream_op_locked", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001088
1089 grpc_transport_stream_op *op = arg;
1090 grpc_call_element *elem = op->handler_private.args[0];
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001091 channel_data *chand = elem->channel_data;
Craig Tillera11bfc82017-02-14 09:56:33 -08001092 call_data *calld = elem->call_data;
1093
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001094 if (op->recv_trailing_metadata != NULL) {
1095 GPR_ASSERT(op->on_complete != NULL);
1096 calld->original_on_complete = op->on_complete;
1097 grpc_closure_init(&calld->on_complete, on_complete_locked, elem,
1098 grpc_combiner_scheduler(chand->combiner, false));
1099 op->on_complete = &calld->on_complete;
1100 }
1101
Craig Tillera8610c02017-02-14 10:05:11 -08001102 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001103
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001104 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
1105 "start_transport_stream_op");
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001106 GPR_TIMER_END("start_transport_stream_op_locked", 0);
Craig Tillerbefafe62017-02-09 11:30:54 -08001107}
1108
Craig Tillerbe9691a2017-02-14 10:00:42 -08001109/* The logic here is fairly complicated, due to (a) the fact that we
1110 need to handle the case where we receive the send op before the
1111 initial metadata op, and (b) the need for efficiency, especially in
1112 the streaming case.
1113
1114 We use double-checked locking to initially see if initialization has been
1115 performed. If it has not, we acquire the combiner and perform initialization.
1116 If it has, we proceed on the fast path. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001117static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
1118 grpc_call_element *elem,
1119 grpc_transport_stream_op *op) {
1120 call_data *calld = elem->call_data;
1121 channel_data *chand = elem->channel_data;
1122 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
1123 grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op);
1124 /* try to (atomically) get the call */
1125 grpc_subchannel_call *call = GET_CALL(calld);
1126 GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
1127 if (call == CANCELLED_CALL) {
1128 grpc_transport_stream_op_finish_with_failure(
1129 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
1130 GPR_TIMER_END("cc_start_transport_stream_op", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001131 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001132 return;
1133 }
1134 if (call != NULL) {
1135 grpc_subchannel_call_process_op(exec_ctx, call, op);
1136 GPR_TIMER_END("cc_start_transport_stream_op", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001137 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001138 return;
1139 }
1140 /* we failed; lock and figure out what to do */
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001141 GRPC_CALL_STACK_REF(calld->owning_call, "start_transport_stream_op");
Craig Tiller4a84bdd2017-02-14 09:48:41 -08001142 op->handler_private.args[0] = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -08001143 grpc_closure_sched(
1144 exec_ctx,
Craig Tiller4a84bdd2017-02-14 09:48:41 -08001145 grpc_closure_init(&op->handler_private.closure,
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001146 start_transport_stream_op_locked, op,
Craig Tillerbefafe62017-02-09 11:30:54 -08001147 grpc_combiner_scheduler(chand->combiner, false)),
1148 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001149 GPR_TIMER_END("cc_start_transport_stream_op", 0);
1150}
1151
Mark D. Rothe40dd292016-10-05 14:58:37 -07001152// Gets data from the service config. Invoked when the resolver returns
1153// its initial result.
Craig Tillerbefafe62017-02-09 11:30:54 -08001154static void read_service_config_locked(grpc_exec_ctx *exec_ctx, void *arg,
1155 grpc_error *error) {
Mark D. Rothe40dd292016-10-05 14:58:37 -07001156 grpc_call_element *elem = arg;
1157 channel_data *chand = elem->channel_data;
1158 call_data *calld = elem->call_data;
1159 // If this is an error, there's no point in looking at the service config.
Mark D. Roth196387a2016-10-12 14:53:36 -07001160 if (error == GRPC_ERROR_NONE) {
1161 // Get the method config table from channel data.
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001162 grpc_slice_hash_table *method_params_table = NULL;
Mark D. Roth9d480942016-10-19 14:18:05 -07001163 if (chand->method_params_table != NULL) {
1164 method_params_table =
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001165 grpc_slice_hash_table_ref(chand->method_params_table);
Mark D. Rothe40dd292016-10-05 14:58:37 -07001166 }
Mark D. Roth196387a2016-10-12 14:53:36 -07001167 // If the method config table was present, use it.
Mark D. Roth9d480942016-10-19 14:18:05 -07001168 if (method_params_table != NULL) {
Craig Tiller87a7e1f2016-11-09 09:42:19 -08001169 const method_parameters *method_params = grpc_method_config_table_get(
1170 exec_ctx, method_params_table, calld->path);
Mark D. Roth9d480942016-10-19 14:18:05 -07001171 if (method_params != NULL) {
1172 const bool have_method_timeout =
1173 gpr_time_cmp(method_params->timeout, gpr_time_0(GPR_TIMESPAN)) != 0;
1174 if (have_method_timeout ||
1175 method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
Mark D. Roth9d480942016-10-19 14:18:05 -07001176 if (have_method_timeout) {
1177 const gpr_timespec per_method_deadline =
1178 gpr_time_add(calld->call_start_time, method_params->timeout);
Mark D. Roth196387a2016-10-12 14:53:36 -07001179 if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
1180 calld->deadline = per_method_deadline;
1181 // Reset deadline timer.
1182 grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
1183 }
1184 }
Mark D. Roth9d480942016-10-19 14:18:05 -07001185 if (method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
Mark D. Roth196387a2016-10-12 14:53:36 -07001186 calld->wait_for_ready_from_service_config =
Mark D. Roth9d480942016-10-19 14:18:05 -07001187 method_params->wait_for_ready;
Mark D. Roth196387a2016-10-12 14:53:36 -07001188 }
Mark D. Roth196387a2016-10-12 14:53:36 -07001189 }
1190 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001191 grpc_slice_hash_table_unref(exec_ctx, method_params_table);
Mark D. Roth196387a2016-10-12 14:53:36 -07001192 }
Mark D. Rothe40dd292016-10-05 14:58:37 -07001193 }
Mark D. Roth31292f22016-10-12 13:14:07 -07001194 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "read_service_config");
Mark D. Rothe40dd292016-10-05 14:58:37 -07001195}
1196
Craig Tillerbefafe62017-02-09 11:30:54 -08001197static void initial_read_service_config_locked(grpc_exec_ctx *exec_ctx,
1198 void *arg,
1199 grpc_error *error_ignored) {
1200 grpc_call_element *elem = arg;
1201 channel_data *chand = elem->channel_data;
1202 call_data *calld = elem->call_data;
1203 // If the resolver has already returned results, then we can access
1204 // the service config parameters immediately. Otherwise, we need to
1205 // defer that work until the resolver returns an initial result.
1206 // TODO(roth): This code is almost but not quite identical to the code
1207 // in read_service_config() above. It would be nice to find a way to
1208 // combine them, to avoid having to maintain it twice.
1209 if (chand->lb_policy != NULL) {
1210 // We already have a resolver result, so check for service config.
1211 if (chand->method_params_table != NULL) {
1212 grpc_slice_hash_table *method_params_table =
1213 grpc_slice_hash_table_ref(chand->method_params_table);
1214 method_parameters *method_params = grpc_method_config_table_get(
1215 exec_ctx, method_params_table, calld->path);
1216 if (method_params != NULL) {
1217 if (gpr_time_cmp(method_params->timeout,
1218 gpr_time_0(GPR_CLOCK_MONOTONIC)) != 0) {
1219 gpr_timespec per_method_deadline =
1220 gpr_time_add(calld->call_start_time, method_params->timeout);
1221 calld->deadline = gpr_time_min(calld->deadline, per_method_deadline);
1222 }
1223 if (method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
1224 calld->wait_for_ready_from_service_config =
1225 method_params->wait_for_ready;
1226 }
1227 }
1228 grpc_slice_hash_table_unref(exec_ctx, method_params_table);
1229 }
1230 } else {
1231 // We don't yet have a resolver result, so register a callback to
1232 // get the service config data once the resolver returns.
1233 // Take a reference to the call stack to be owned by the callback.
1234 GRPC_CALL_STACK_REF(calld->owning_call, "read_service_config");
1235 grpc_closure_init(&calld->read_service_config, read_service_config_locked,
1236 elem, grpc_combiner_scheduler(chand->combiner, false));
1237 grpc_closure_list_append(&chand->waiting_for_config_closures,
1238 &calld->read_service_config, GRPC_ERROR_NONE);
1239 }
1240 // Start the deadline timer with the current deadline value. If we
1241 // do not yet have service config data, then the timer may be reset
1242 // later.
1243 grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001244 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
1245 "initial_read_service_config");
Craig Tillerbefafe62017-02-09 11:30:54 -08001246}
1247
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001248/* Constructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001249static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
1250 grpc_call_element *elem,
Craig Tillerc52ba3a2017-02-15 22:57:43 -08001251 const grpc_call_element_args *args) {
Mark D. Rothaa850a72016-09-26 13:38:02 -07001252 channel_data *chand = elem->channel_data;
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001253 call_data *calld = elem->call_data;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001254 // Initialize data members.
1255 grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001256 calld->path = grpc_slice_ref_internal(args->path);
Mark D. Rothff08f332016-10-14 13:01:01 -07001257 calld->call_start_time = args->start_time;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001258 calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
1259 calld->wait_for_ready_from_service_config = WAIT_FOR_READY_UNSET;
Mark D. Rothf28763c2016-09-14 15:18:40 -07001260 calld->cancel_error = GRPC_ERROR_NONE;
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001261 gpr_atm_rel_store(&calld->subchannel_call, 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001262 calld->connected_subchannel = NULL;
1263 calld->waiting_ops = NULL;
1264 calld->waiting_ops_count = 0;
1265 calld->waiting_ops_capacity = 0;
1266 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
1267 calld->owning_call = args->call_stack;
1268 calld->pollent = NULL;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001269 GRPC_CALL_STACK_REF(calld->owning_call, "initial_read_service_config");
Craig Tillerbefafe62017-02-09 11:30:54 -08001270 grpc_closure_sched(
1271 exec_ctx,
1272 grpc_closure_init(&calld->read_service_config,
1273 initial_read_service_config_locked, elem,
1274 grpc_combiner_scheduler(chand->combiner, false)),
1275 GRPC_ERROR_NONE);
Mark D. Roth0badbe82016-06-23 10:15:12 -07001276 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001277}
1278
1279/* Destructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001280static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
1281 grpc_call_element *elem,
1282 const grpc_call_final_info *final_info,
1283 void *and_free_memory) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001284 call_data *calld = elem->call_data;
Mark D. Rothf28763c2016-09-14 15:18:40 -07001285 grpc_deadline_state_destroy(exec_ctx, elem);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001286 grpc_slice_unref_internal(exec_ctx, calld->path);
Mark D. Rothf28763c2016-09-14 15:18:40 -07001287 GRPC_ERROR_UNREF(calld->cancel_error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001288 grpc_subchannel_call *call = GET_CALL(calld);
1289 if (call != NULL && call != CANCELLED_CALL) {
1290 GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
1291 }
1292 GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001293 GPR_ASSERT(calld->waiting_ops_count == 0);
Craig Tiller693d3942016-10-27 16:51:25 -07001294 if (calld->connected_subchannel != NULL) {
1295 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel,
1296 "picked");
1297 }
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001298 gpr_free(calld->waiting_ops);
Craig Tiller2c8063c2016-03-22 22:12:15 -07001299 gpr_free(and_free_memory);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001300}
1301
David Garcia Quintasf72eb972016-05-03 18:28:09 -07001302static void cc_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
1303 grpc_call_element *elem,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001304 grpc_polling_entity *pollent) {
Craig Tiller577c9b22015-11-02 14:11:15 -08001305 call_data *calld = elem->call_data;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001306 calld->pollent = pollent;
Craig Tiller577c9b22015-11-02 14:11:15 -08001307}
1308
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001309/*************************************************************************
1310 * EXPORTED SYMBOLS
1311 */
1312
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001313const grpc_channel_filter grpc_client_channel_filter = {
Craig Tillerf40df232016-03-25 13:38:14 -07001314 cc_start_transport_stream_op,
1315 cc_start_transport_op,
1316 sizeof(call_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001317 cc_init_call_elem,
David Garcia Quintas4afce7e2016-04-18 16:25:17 -07001318 cc_set_pollset_or_pollset_set,
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001319 cc_destroy_call_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001320 sizeof(channel_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001321 cc_init_channel_elem,
1322 cc_destroy_channel_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001323 cc_get_peer,
Mark D. Rothb2d24882016-10-27 15:44:07 -07001324 cc_get_channel_info,
Craig Tillerf40df232016-03-25 13:38:14 -07001325 "client-channel",
Craig Tiller87d5b192015-04-16 14:37:57 -07001326};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001327
Craig Tiller613dafa2017-02-09 12:00:43 -08001328static void try_to_connect_locked(grpc_exec_ctx *exec_ctx, void *arg,
1329 grpc_error *error_ignored) {
1330 channel_data *chand = arg;
1331 if (chand->lb_policy != NULL) {
1332 grpc_lb_policy_exit_idle(exec_ctx, chand->lb_policy);
1333 } else {
1334 chand->exit_idle_when_lb_policy_arrives = true;
1335 if (!chand->started_resolving && chand->resolver != NULL) {
1336 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
1337 chand->started_resolving = true;
Craig Tiller972470b2017-02-09 15:05:36 -08001338 grpc_resolver_next_locked(exec_ctx, chand->resolver,
1339 &chand->resolver_result,
1340 &chand->on_resolver_result_changed);
Craig Tiller613dafa2017-02-09 12:00:43 -08001341 }
1342 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001343 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001344}
1345
Craig Tillera82950e2015-09-22 12:33:20 -07001346grpc_connectivity_state grpc_client_channel_check_connectivity_state(
1347 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001348 channel_data *chand = elem->channel_data;
Craig Tillera8610c02017-02-14 10:05:11 -08001349 grpc_connectivity_state out =
1350 grpc_connectivity_state_check(&chand->state_tracker);
Craig Tillera82950e2015-09-22 12:33:20 -07001351 if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001352 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001353 grpc_closure_sched(
1354 exec_ctx,
1355 grpc_closure_create(try_to_connect_locked, chand,
1356 grpc_combiner_scheduler(chand->combiner, false)),
1357 GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -07001358 }
Craig Tiller48cb07c2015-07-15 16:16:15 -07001359 return out;
1360}
1361
Craig Tiller86c99582015-11-25 15:22:26 -08001362typedef struct {
1363 channel_data *chand;
1364 grpc_pollset *pollset;
1365 grpc_closure *on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001366 grpc_connectivity_state *state;
Craig Tiller86c99582015-11-25 15:22:26 -08001367 grpc_closure my_closure;
1368} external_connectivity_watcher;
1369
Craig Tiller1d881fb2015-12-01 07:39:04 -08001370static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -07001371 grpc_error *error) {
Craig Tiller86c99582015-11-25 15:22:26 -08001372 external_connectivity_watcher *w = arg;
1373 grpc_closure *follow_up = w->on_complete;
Craig Tiller69b093b2016-02-25 19:04:07 -08001374 grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
Craig Tiller1d881fb2015-12-01 07:39:04 -08001375 w->pollset);
1376 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
1377 "external_connectivity_watcher");
Craig Tiller86c99582015-11-25 15:22:26 -08001378 gpr_free(w);
Craig Tiller613dafa2017-02-09 12:00:43 -08001379 grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
1380}
1381
Craig Tillera8610c02017-02-14 10:05:11 -08001382static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg,
1383 grpc_error *error_ignored) {
Craig Tiller613dafa2017-02-09 12:00:43 -08001384 external_connectivity_watcher *w = arg;
1385 grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
1386 grpc_schedule_on_exec_ctx);
1387 grpc_connectivity_state_notify_on_state_change(
1388 exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
Craig Tiller86c99582015-11-25 15:22:26 -08001389}
1390
Craig Tillera82950e2015-09-22 12:33:20 -07001391void grpc_client_channel_watch_connectivity_state(
Craig Tiller906e3bc2015-11-24 07:31:31 -08001392 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
Craig Tillera82950e2015-09-22 12:33:20 -07001393 grpc_connectivity_state *state, grpc_closure *on_complete) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001394 channel_data *chand = elem->channel_data;
Craig Tiller86c99582015-11-25 15:22:26 -08001395 external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
1396 w->chand = chand;
1397 w->pollset = pollset;
1398 w->on_complete = on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001399 w->state = state;
Craig Tiller69b093b2016-02-25 19:04:07 -08001400 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
Craig Tiller1d881fb2015-12-01 07:39:04 -08001401 GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
1402 "external_connectivity_watcher");
Craig Tiller613dafa2017-02-09 12:00:43 -08001403 grpc_closure_sched(
1404 exec_ctx,
Craig Tillera8610c02017-02-14 10:05:11 -08001405 grpc_closure_init(&w->my_closure, watch_connectivity_state_locked, w,
Craig Tiller613dafa2017-02-09 12:00:43 -08001406 grpc_combiner_scheduler(chand->combiner, true)),
1407 GRPC_ERROR_NONE);
Craig Tiller48cb07c2015-07-15 16:16:15 -07001408}