blob: 967709bf741fe6ecf0970ac384bcfab6b379490d [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) {
Mark D. Rothb3322562017-02-23 14:38:02 -0800280 if (sub_field->key == NULL) return;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800281 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);
Mark D. Rothb3322562017-02-23 14:38:02 -0800316 if (milli_token_ratio <= 0) return;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800317 }
318 }
319 parsing_state->retry_throttle_data =
320 grpc_retry_throttle_map_get_data_for_server(
321 parsing_state->server_name, max_milli_tokens, milli_token_ratio);
322 }
323}
324
Craig Tillerbefafe62017-02-09 11:30:54 -0800325static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
326 void *arg, grpc_error *error) {
Craig Tiller3f475422015-06-25 10:43:05 -0700327 channel_data *chand = arg;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700328 char *lb_policy_name = NULL;
Craig Tiller3f475422015-06-25 10:43:05 -0700329 grpc_lb_policy *lb_policy = NULL;
330 grpc_lb_policy *old_lb_policy;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800331 grpc_slice_hash_table *method_params_table = NULL;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700332 grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700333 bool exit_idle = false;
Craig Tiller804ff712016-05-05 16:25:40 -0700334 grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800335 char *service_config_json = NULL;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800336 service_config_parsing_state parsing_state;
337 memset(&parsing_state, 0, sizeof(parsing_state));
Craig Tiller3f475422015-06-25 10:43:05 -0700338
Mark D. Roth046cf762016-09-26 11:13:51 -0700339 if (chand->resolver_result != NULL) {
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700340 // Find LB policy name.
Mark D. Rothaf842452016-10-21 15:05:15 -0700341 const grpc_arg *channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700342 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_POLICY_NAME);
Mark D. Rothaf842452016-10-21 15:05:15 -0700343 if (channel_arg != NULL) {
344 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
345 lb_policy_name = channel_arg->value.string;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700346 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700347 // Special case: If all of the addresses are balancer addresses,
348 // assume that we should use the grpclb policy, regardless of what the
349 // resolver actually specified.
Mark D. Rothaf842452016-10-21 15:05:15 -0700350 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700351 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES);
Mark D. Rothaf842452016-10-21 15:05:15 -0700352 if (channel_arg != NULL) {
353 GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
Mark D. Roth557c9902016-10-24 11:12:05 -0700354 grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
Mark D. Rothaf842452016-10-21 15:05:15 -0700355 bool found_backend_address = false;
356 for (size_t i = 0; i < addresses->num_addresses; ++i) {
357 if (!addresses->addresses[i].is_balancer) {
358 found_backend_address = true;
359 break;
360 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700361 }
Mark D. Rothaf842452016-10-21 15:05:15 -0700362 if (!found_backend_address) {
363 if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) {
364 gpr_log(GPR_INFO,
365 "resolver requested LB policy %s but provided only balancer "
366 "addresses, no backend addresses -- forcing use of grpclb LB "
367 "policy",
Mark D. Roth5f40e5d2016-10-24 13:09:05 -0700368 lb_policy_name);
Mark D. Rothaf842452016-10-21 15:05:15 -0700369 }
370 lb_policy_name = "grpclb";
Mark D. Roth88405f72016-10-03 08:24:52 -0700371 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700372 }
373 // Use pick_first if nothing was specified and we didn't select grpclb
374 // above.
375 if (lb_policy_name == NULL) lb_policy_name = "pick_first";
Mark D. Roth41124992016-11-03 11:22:20 -0700376 // Instantiate LB policy.
377 grpc_lb_policy_args lb_policy_args;
378 lb_policy_args.args = chand->resolver_result;
379 lb_policy_args.client_channel_factory = chand->client_channel_factory;
Mark D. Roth88405f72016-10-03 08:24:52 -0700380 lb_policy =
381 grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700382 if (lb_policy != NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -0700383 GRPC_LB_POLICY_REF(lb_policy, "config_change");
Craig Tillerf707d622016-05-06 14:26:12 -0700384 GRPC_ERROR_UNREF(state_error);
Craig Tiller804ff712016-05-05 16:25:40 -0700385 state =
386 grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error);
Craig Tiller45724b32015-09-22 10:42:19 -0700387 }
Mark D. Roth41124992016-11-03 11:22:20 -0700388 // Find service config.
Mark D. Rothaf842452016-10-21 15:05:15 -0700389 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700390 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVICE_CONFIG);
Mark D. Roth046cf762016-09-26 11:13:51 -0700391 if (channel_arg != NULL) {
Mark D. Roth9ec28af2016-11-03 12:32:39 -0700392 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800393 service_config_json = gpr_strdup(channel_arg->value.string);
Mark D. Roth70a1abd2016-11-04 09:26:37 -0700394 grpc_service_config *service_config =
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800395 grpc_service_config_create(service_config_json);
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700396 if (service_config != NULL) {
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800397 channel_arg =
398 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVER_URI);
399 GPR_ASSERT(channel_arg != NULL);
400 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
401 grpc_uri *uri = grpc_uri_parse(channel_arg->value.string, true);
402 GPR_ASSERT(uri->path[0] != '\0');
403 parsing_state.server_name =
404 uri->path[0] == '/' ? uri->path + 1 : uri->path;
405 grpc_service_config_parse_global_params(
406 service_config, parse_retry_throttle_params, &parsing_state);
407 parsing_state.server_name = NULL;
408 grpc_uri_destroy(uri);
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700409 method_params_table = grpc_service_config_create_method_config_table(
Craig Tillerb28c7e82016-11-18 10:29:04 -0800410 exec_ctx, service_config, method_parameters_create_from_json,
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700411 &method_parameters_vtable);
412 grpc_service_config_destroy(service_config);
413 }
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700414 }
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700415 // Before we clean up, save a copy of lb_policy_name, since it might
416 // be pointing to data inside chand->resolver_result.
417 // The copy will be saved in chand->lb_policy_name below.
418 lb_policy_name = gpr_strdup(lb_policy_name);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800419 grpc_channel_args_destroy(exec_ctx, chand->resolver_result);
Mark D. Roth046cf762016-09-26 11:13:51 -0700420 chand->resolver_result = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700421 }
422
Craig Tiller86c99582015-11-25 15:22:26 -0800423 if (lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800424 grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties,
425 chand->interested_parties);
Craig Tiller86c99582015-11-25 15:22:26 -0800426 }
427
Craig Tiller613dafa2017-02-09 12:00:43 -0800428 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700429 if (lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800430 gpr_free(chand->info_lb_policy_name);
431 chand->info_lb_policy_name = lb_policy_name;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700432 }
Craig Tiller3f475422015-06-25 10:43:05 -0700433 old_lb_policy = chand->lb_policy;
434 chand->lb_policy = lb_policy;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800435 if (service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800436 gpr_free(chand->info_service_config_json);
437 chand->info_service_config_json = service_config_json;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800438 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800439 gpr_mu_unlock(&chand->info_mu);
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800440
441 if (chand->retry_throttle_data != NULL) {
442 grpc_server_retry_throttle_data_unref(chand->retry_throttle_data);
443 }
444 chand->retry_throttle_data = parsing_state.retry_throttle_data;
Mark D. Roth9d480942016-10-19 14:18:05 -0700445 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800446 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth046cf762016-09-26 11:13:51 -0700447 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700448 chand->method_params_table = method_params_table;
Craig Tiller0ede5452016-04-23 12:21:45 -0700449 if (lb_policy != NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -0800450 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller0ede5452016-04-23 12:21:45 -0700451 } else if (chand->resolver == NULL /* disconnected */) {
Craig Tiller804ff712016-05-05 16:25:40 -0700452 grpc_closure_list_fail_all(
453 &chand->waiting_for_config_closures,
454 GRPC_ERROR_CREATE_REFERENCING("Channel disconnected", &error, 1));
Craig Tiller91031da2016-12-28 15:44:25 -0800455 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tillera82950e2015-09-22 12:33:20 -0700456 }
457 if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
458 GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700459 exit_idle = true;
460 chand->exit_idle_when_lb_policy_arrives = false;
Craig Tillera82950e2015-09-22 12:33:20 -0700461 }
Craig Tiller98465032015-06-29 14:36:42 -0700462
Craig Tiller804ff712016-05-05 16:25:40 -0700463 if (error == GRPC_ERROR_NONE && chand->resolver) {
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700464 set_channel_connectivity_state_locked(
465 exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700466 if (lb_policy != NULL) {
467 watch_lb_policy(exec_ctx, chand, lb_policy, state);
Craig Tiller45724b32015-09-22 10:42:19 -0700468 }
Craig Tiller906e3bc2015-11-24 07:31:31 -0800469 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -0800470 grpc_resolver_next_locked(exec_ctx, chand->resolver,
471 &chand->resolver_result,
472 &chand->on_resolver_result_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700473 } else {
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800474 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800475 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800476 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
477 chand->resolver = NULL;
478 }
Craig Tiller804ff712016-05-05 16:25:40 -0700479 grpc_error *refs[] = {error, state_error};
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800480 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700481 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller804ff712016-05-05 16:25:40 -0700482 GRPC_ERROR_CREATE_REFERENCING("Got config after disconnection", refs,
483 GPR_ARRAY_SIZE(refs)),
484 "resolver_gone");
Craig Tillera82950e2015-09-22 12:33:20 -0700485 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700486
Craig Tillera82950e2015-09-22 12:33:20 -0700487 if (exit_idle) {
488 grpc_lb_policy_exit_idle(exec_ctx, lb_policy);
489 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
490 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700491
Craig Tillera82950e2015-09-22 12:33:20 -0700492 if (old_lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800493 grpc_pollset_set_del_pollset_set(
494 exec_ctx, old_lb_policy->interested_parties, chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700495 GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
496 }
Craig Tiller000cd8f2015-09-18 07:20:29 -0700497
Craig Tillera82950e2015-09-22 12:33:20 -0700498 if (lb_policy != NULL) {
499 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
500 }
Craig Tiller45724b32015-09-22 10:42:19 -0700501
Craig Tiller906e3bc2015-11-24 07:31:31 -0800502 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700503 GRPC_ERROR_UNREF(state_error);
Craig Tiller3f475422015-06-25 10:43:05 -0700504}
505
Craig Tillera8610c02017-02-14 10:05:11 -0800506static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
507 grpc_error *error_ignored) {
Craig Tillerbefafe62017-02-09 11:30:54 -0800508 grpc_transport_op *op = arg;
509 grpc_channel_element *elem = op->transport_private.args[0];
Craig Tillerca3e9d32015-06-27 18:37:27 -0700510 channel_data *chand = elem->channel_data;
Craig Tiller000cd8f2015-09-18 07:20:29 -0700511
Craig Tillera82950e2015-09-22 12:33:20 -0700512 if (op->on_connectivity_state_change != NULL) {
513 grpc_connectivity_state_notify_on_state_change(
514 exec_ctx, &chand->state_tracker, op->connectivity_state,
515 op->on_connectivity_state_change);
516 op->on_connectivity_state_change = NULL;
517 op->connectivity_state = NULL;
518 }
519
Craig Tiller26dab312015-12-07 14:43:47 -0800520 if (op->send_ping != NULL) {
Craig Tiller87b71e22015-12-07 15:14:14 -0800521 if (chand->lb_policy == NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -0800522 grpc_closure_sched(exec_ctx, op->send_ping,
523 GRPC_ERROR_CREATE("Ping with no load balancing"));
Craig Tiller26dab312015-12-07 14:43:47 -0800524 } else {
Craig Tiller28bf8912015-12-07 16:07:04 -0800525 grpc_lb_policy_ping_one(exec_ctx, chand->lb_policy, op->send_ping);
Craig Tiller26dab312015-12-07 14:43:47 -0800526 op->bind_pollset = NULL;
527 }
528 op->send_ping = NULL;
529 }
530
Craig Tiller1c51edc2016-05-07 16:18:43 -0700531 if (op->disconnect_with_error != GRPC_ERROR_NONE) {
532 if (chand->resolver != NULL) {
533 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700534 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller1c51edc2016-05-07 16:18:43 -0700535 GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
Craig Tiller972470b2017-02-09 15:05:36 -0800536 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700537 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
538 chand->resolver = NULL;
539 if (!chand->started_resolving) {
540 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
541 GRPC_ERROR_REF(op->disconnect_with_error));
Craig Tiller91031da2016-12-28 15:44:25 -0800542 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700543 }
544 if (chand->lb_policy != NULL) {
545 grpc_pollset_set_del_pollset_set(exec_ctx,
546 chand->lb_policy->interested_parties,
547 chand->interested_parties);
548 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
549 chand->lb_policy = NULL;
550 }
Craig Tillerb12d22a2016-04-23 12:50:21 -0700551 }
Craig Tiller1c51edc2016-05-07 16:18:43 -0700552 GRPC_ERROR_UNREF(op->disconnect_with_error);
Craig Tillera82950e2015-09-22 12:33:20 -0700553 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800554 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "start_transport_op");
555
556 grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
Craig Tillerbefafe62017-02-09 11:30:54 -0800557}
558
559static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
560 grpc_channel_element *elem,
561 grpc_transport_op *op) {
562 channel_data *chand = elem->channel_data;
563
Craig Tillerbefafe62017-02-09 11:30:54 -0800564 GPR_ASSERT(op->set_accept_stream == false);
565 if (op->bind_pollset != NULL) {
566 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
567 op->bind_pollset);
568 }
569
570 op->transport_private.args[0] = elem;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800571 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "start_transport_op");
Craig Tillerbefafe62017-02-09 11:30:54 -0800572 grpc_closure_sched(
Craig Tillera8610c02017-02-14 10:05:11 -0800573 exec_ctx, grpc_closure_init(
574 &op->transport_private.closure, start_transport_op_locked,
575 op, grpc_combiner_scheduler(chand->combiner, false)),
Craig Tillerbefafe62017-02-09 11:30:54 -0800576 GRPC_ERROR_NONE);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700577}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800578
Mark D. Rothb2d24882016-10-27 15:44:07 -0700579static void cc_get_channel_info(grpc_exec_ctx *exec_ctx,
580 grpc_channel_element *elem,
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700581 const grpc_channel_info *info) {
Mark D. Rothb2d24882016-10-27 15:44:07 -0700582 channel_data *chand = elem->channel_data;
Craig Tiller613dafa2017-02-09 12:00:43 -0800583 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700584 if (info->lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800585 *info->lb_policy_name = chand->info_lb_policy_name == NULL
Mark D. Roth78afd772016-11-04 12:49:49 -0700586 ? NULL
Craig Tiller613dafa2017-02-09 12:00:43 -0800587 : gpr_strdup(chand->info_lb_policy_name);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700588 }
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800589 if (info->service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800590 *info->service_config_json =
591 chand->info_service_config_json == NULL
592 ? NULL
593 : gpr_strdup(chand->info_service_config_json);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800594 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800595 gpr_mu_unlock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700596}
597
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700598/* Constructor for channel_data */
Mark D. Rothc1087882016-11-18 10:54:45 -0800599static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800600 grpc_channel_element *elem,
601 grpc_channel_element_args *args) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700602 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700603 memset(chand, 0, sizeof(*chand));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700604 GPR_ASSERT(args->is_last);
605 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800606 // Initialize data members.
Craig Tillerbefafe62017-02-09 11:30:54 -0800607 chand->combiner = grpc_combiner_create(NULL);
Craig Tillerd85477512017-02-09 12:02:39 -0800608 gpr_mu_init(&chand->info_mu);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800609 chand->owning_stack = args->channel_stack;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700610 grpc_closure_init(&chand->on_resolver_result_changed,
Craig Tillerbefafe62017-02-09 11:30:54 -0800611 on_resolver_result_changed_locked, chand,
612 grpc_combiner_scheduler(chand->combiner, false));
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800613 chand->interested_parties = grpc_pollset_set_create();
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700614 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
615 "client_channel");
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800616 // Record client channel factory.
617 const grpc_arg *arg = grpc_channel_args_find(args->channel_args,
618 GRPC_ARG_CLIENT_CHANNEL_FACTORY);
619 GPR_ASSERT(arg != NULL);
620 GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
621 grpc_client_channel_factory_ref(arg->value.pointer.p);
622 chand->client_channel_factory = arg->value.pointer.p;
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800623 // Get server name to resolve, using proxy mapper if needed.
Mark D. Roth86e90592016-11-18 09:56:40 -0800624 arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800625 GPR_ASSERT(arg != NULL);
626 GPR_ASSERT(arg->type == GRPC_ARG_STRING);
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800627 char *proxy_name = NULL;
628 grpc_channel_args *new_args = NULL;
629 grpc_proxy_mappers_map_name(exec_ctx, arg->value.string, args->channel_args,
630 &proxy_name, &new_args);
631 // Instantiate resolver.
Mark D. Roth45ccec52017-01-18 14:04:01 -0800632 chand->resolver = grpc_resolver_create(
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800633 exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string,
634 new_args != NULL ? new_args : args->channel_args,
Craig Tiller972470b2017-02-09 15:05:36 -0800635 chand->interested_parties, chand->combiner);
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800636 if (proxy_name != NULL) gpr_free(proxy_name);
637 if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args);
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800638 if (chand->resolver == NULL) {
639 return GRPC_ERROR_CREATE("resolver creation failed");
640 }
641 return GRPC_ERROR_NONE;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700642}
643
Craig Tiller972470b2017-02-09 15:05:36 -0800644static void shutdown_resolver_locked(grpc_exec_ctx *exec_ctx, void *arg,
645 grpc_error *error) {
646 grpc_resolver *resolver = arg;
647 grpc_resolver_shutdown_locked(exec_ctx, resolver);
648 GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel");
649}
650
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700651/* Destructor for channel_data */
652static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
653 grpc_channel_element *elem) {
654 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700655 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800656 grpc_closure_sched(
657 exec_ctx,
658 grpc_closure_create(shutdown_resolver_locked, chand->resolver,
659 grpc_combiner_scheduler(chand->combiner, false)),
660 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700661 }
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700662 if (chand->client_channel_factory != NULL) {
663 grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
664 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700665 if (chand->lb_policy != NULL) {
666 grpc_pollset_set_del_pollset_set(exec_ctx,
667 chand->lb_policy->interested_parties,
668 chand->interested_parties);
669 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
670 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800671 gpr_free(chand->info_lb_policy_name);
672 gpr_free(chand->info_service_config_json);
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800673 if (chand->retry_throttle_data != NULL) {
674 grpc_server_retry_throttle_data_unref(chand->retry_throttle_data);
675 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700676 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800677 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700678 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700679 grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
Craig Tiller9e5ac1b2017-02-14 22:25:50 -0800680 grpc_pollset_set_destroy(exec_ctx, chand->interested_parties);
Craig Tillerf1021672017-02-09 21:29:50 -0800681 GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel");
Craig Tillerd85477512017-02-09 12:02:39 -0800682 gpr_mu_destroy(&chand->info_mu);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700683}
684
685/*************************************************************************
686 * PER-CALL FUNCTIONS
687 */
688
689#define GET_CALL(call_data) \
690 ((grpc_subchannel_call *)(gpr_atm_acq_load(&(call_data)->subchannel_call)))
691
692#define CANCELLED_CALL ((grpc_subchannel_call *)1)
693
694typedef enum {
695 GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING,
696 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL
697} subchannel_creation_phase;
698
699/** Call data. Holds a pointer to grpc_subchannel_call and the
700 associated machinery to create such a pointer.
701 Handles queueing of stream ops until a call object is ready, waiting
702 for initial metadata before trying to create a call object,
703 and handling cancellation gracefully. */
704typedef struct client_channel_call_data {
Mark D. Roth72f6da82016-09-02 13:42:38 -0700705 // State for handling deadlines.
706 // The code in deadline_filter.c requires this to be the first field.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700707 // TODO(roth): This is slightly sub-optimal in that grpc_deadline_state
708 // and this struct both independently store a pointer to the call
709 // stack and each has its own mutex. If/when we have time, find a way
Mark D. Roth6ad99172016-09-09 07:52:48 -0700710 // to avoid this without breaking the grpc_deadline_state abstraction.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700711 grpc_deadline_state deadline_state;
Mark D. Rothf28763c2016-09-14 15:18:40 -0700712
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800713 grpc_slice path; // Request path.
Mark D. Rothe40dd292016-10-05 14:58:37 -0700714 gpr_timespec call_start_time;
715 gpr_timespec deadline;
Mark D. Roth9d480942016-10-19 14:18:05 -0700716 wait_for_ready_value wait_for_ready_from_service_config;
Mark D. Rothe40dd292016-10-05 14:58:37 -0700717 grpc_closure read_service_config;
Mark D. Rothaa850a72016-09-26 13:38:02 -0700718
Mark D. Rothf28763c2016-09-14 15:18:40 -0700719 grpc_error *cancel_error;
Mark D. Roth72f6da82016-09-02 13:42:38 -0700720
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700721 /** either 0 for no call, 1 for cancelled, or a pointer to a
722 grpc_subchannel_call */
723 gpr_atm subchannel_call;
724
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700725 subchannel_creation_phase creation_phase;
726 grpc_connected_subchannel *connected_subchannel;
727 grpc_polling_entity *pollent;
728
Craig Tiller57726ca2016-09-12 11:59:45 -0700729 grpc_transport_stream_op **waiting_ops;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700730 size_t waiting_ops_count;
731 size_t waiting_ops_capacity;
732
733 grpc_closure next_step;
734
735 grpc_call_stack *owning_call;
David Garcia Quintasd1a47f12016-09-02 12:46:44 +0200736
737 grpc_linked_mdelem lb_token_mdelem;
Mark D. Rothd6d192d2017-02-23 08:58:42 -0800738
739 grpc_closure on_complete;
740 grpc_closure *original_on_complete;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700741} call_data;
742
Craig Tiller8b1d59c2016-12-27 15:15:30 -0800743grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
744 grpc_call_element *call_elem) {
745 grpc_subchannel_call *scc = GET_CALL((call_data *)call_elem->call_data);
746 return scc == CANCELLED_CALL ? NULL : scc;
747}
748
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700749static void add_waiting_locked(call_data *calld, grpc_transport_stream_op *op) {
750 GPR_TIMER_BEGIN("add_waiting_locked", 0);
751 if (calld->waiting_ops_count == calld->waiting_ops_capacity) {
752 calld->waiting_ops_capacity = GPR_MAX(3, 2 * calld->waiting_ops_capacity);
753 calld->waiting_ops =
754 gpr_realloc(calld->waiting_ops,
755 calld->waiting_ops_capacity * sizeof(*calld->waiting_ops));
756 }
Craig Tiller57726ca2016-09-12 11:59:45 -0700757 calld->waiting_ops[calld->waiting_ops_count++] = op;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700758 GPR_TIMER_END("add_waiting_locked", 0);
759}
760
761static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld,
762 grpc_error *error) {
763 size_t i;
764 for (i = 0; i < calld->waiting_ops_count; i++) {
765 grpc_transport_stream_op_finish_with_failure(
Craig Tiller57726ca2016-09-12 11:59:45 -0700766 exec_ctx, calld->waiting_ops[i], GRPC_ERROR_REF(error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700767 }
768 calld->waiting_ops_count = 0;
769 GRPC_ERROR_UNREF(error);
770}
771
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700772static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
Craig Tiller57726ca2016-09-12 11:59:45 -0700773 if (calld->waiting_ops_count == 0) {
774 return;
775 }
776
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800777 grpc_subchannel_call *call = GET_CALL(calld);
778 grpc_transport_stream_op **ops = calld->waiting_ops;
779 size_t nops = calld->waiting_ops_count;
780 if (call == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700781 fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED);
782 return;
783 }
784 calld->waiting_ops = NULL;
785 calld->waiting_ops_count = 0;
786 calld->waiting_ops_capacity = 0;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800787 for (size_t i = 0; i < nops; i++) {
788 grpc_subchannel_call_process_op(exec_ctx, call, ops[i]);
789 }
Craig Tiller9efea882017-02-09 13:06:52 -0800790 gpr_free(ops);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700791}
792
Craig Tillerbefafe62017-02-09 11:30:54 -0800793static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
794 grpc_error *error) {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700795 grpc_call_element *elem = arg;
796 call_data *calld = elem->call_data;
797 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700798 GPR_ASSERT(calld->creation_phase ==
799 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
Yuchen Zeng19656b12016-09-01 18:00:45 -0700800 grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
801 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700802 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
803 if (calld->connected_subchannel == NULL) {
804 gpr_atm_no_barrier_store(&calld->subchannel_call, 1);
805 fail_locked(exec_ctx, calld, GRPC_ERROR_CREATE_REFERENCING(
806 "Failed to create subchannel", &error, 1));
Mark D. Roth72f6da82016-09-02 13:42:38 -0700807 } else if (GET_CALL(calld) == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700808 /* already cancelled before subchannel became ready */
David Garcia Quintas68a9e382016-12-13 10:50:40 -0800809 grpc_error *cancellation_error = GRPC_ERROR_CREATE_REFERENCING(
810 "Cancelled before creating subchannel", &error, 1);
811 /* if due to deadline, attach the deadline exceeded status to the error */
812 if (gpr_time_cmp(calld->deadline, gpr_now(GPR_CLOCK_MONOTONIC)) < 0) {
813 cancellation_error =
814 grpc_error_set_int(cancellation_error, GRPC_ERROR_INT_GRPC_STATUS,
815 GRPC_STATUS_DEADLINE_EXCEEDED);
816 }
817 fail_locked(exec_ctx, calld, cancellation_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700818 } else {
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700819 /* Create call on subchannel. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700820 grpc_subchannel_call *subchannel_call = NULL;
821 grpc_error *new_error = grpc_connected_subchannel_create_call(
Mark D. Rothaa850a72016-09-26 13:38:02 -0700822 exec_ctx, calld->connected_subchannel, calld->pollent, calld->path,
Mark D. Roth3d883412016-11-07 13:42:54 -0800823 calld->call_start_time, calld->deadline, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700824 if (new_error != GRPC_ERROR_NONE) {
825 new_error = grpc_error_add_child(new_error, error);
826 subchannel_call = CANCELLED_CALL;
827 fail_locked(exec_ctx, calld, new_error);
828 }
829 gpr_atm_rel_store(&calld->subchannel_call,
830 (gpr_atm)(uintptr_t)subchannel_call);
831 retry_waiting_locked(exec_ctx, calld);
832 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700833 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
834}
835
836static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
837 call_data *calld = elem->call_data;
838 grpc_subchannel_call *subchannel_call = GET_CALL(calld);
839 if (subchannel_call == NULL || subchannel_call == CANCELLED_CALL) {
840 return NULL;
841 } else {
842 return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
843 }
844}
845
Craig Tiller577c9b22015-11-02 14:11:15 -0800846typedef struct {
847 grpc_metadata_batch *initial_metadata;
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800848 uint32_t initial_metadata_flags;
Craig Tillerb5585d42015-11-17 07:18:31 -0800849 grpc_connected_subchannel **connected_subchannel;
Craig Tiller577c9b22015-11-02 14:11:15 -0800850 grpc_closure *on_ready;
851 grpc_call_element *elem;
852 grpc_closure closure;
853} continue_picking_args;
854
Yuchen Zeng144ce652016-09-01 18:19:34 -0700855/** Return true if subchannel is available immediately (in which case on_ready
856 should not be called), or false otherwise (in which case on_ready should be
857 called when the subchannel is available). */
Craig Tillerbefafe62017-02-09 11:30:54 -0800858static bool pick_subchannel_locked(
859 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
860 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
861 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
862 grpc_error *error);
Craig Tiller577c9b22015-11-02 14:11:15 -0800863
Craig Tillerbefafe62017-02-09 11:30:54 -0800864static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg,
865 grpc_error *error) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800866 continue_picking_args *cpa = arg;
Craig Tiller0ede5452016-04-23 12:21:45 -0700867 if (cpa->connected_subchannel == NULL) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800868 /* cancelled, do nothing */
Craig Tiller804ff712016-05-05 16:25:40 -0700869 } else if (error != GRPC_ERROR_NONE) {
Craig Tiller91031da2016-12-28 15:44:25 -0800870 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error));
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700871 } else {
Craig Tillerbefafe62017-02-09 11:30:54 -0800872 if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata,
873 cpa->initial_metadata_flags,
874 cpa->connected_subchannel, cpa->on_ready,
875 GRPC_ERROR_NONE)) {
Craig Tiller91031da2016-12-28 15:44:25 -0800876 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700877 }
Craig Tiller577c9b22015-11-02 14:11:15 -0800878 }
879 gpr_free(cpa);
880}
881
Craig Tillerbefafe62017-02-09 11:30:54 -0800882static bool pick_subchannel_locked(
883 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
884 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
885 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
886 grpc_error *error) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700887 GPR_TIMER_BEGIN("pick_subchannel", 0);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700888
Craig Tiller577c9b22015-11-02 14:11:15 -0800889 channel_data *chand = elem->channel_data;
890 call_data *calld = elem->call_data;
891 continue_picking_args *cpa;
892 grpc_closure *closure;
893
Craig Tillerb5585d42015-11-17 07:18:31 -0800894 GPR_ASSERT(connected_subchannel);
Craig Tiller577c9b22015-11-02 14:11:15 -0800895
Craig Tiller577c9b22015-11-02 14:11:15 -0800896 if (initial_metadata == NULL) {
897 if (chand->lb_policy != NULL) {
Craig Tillerab33b482015-11-21 08:11:04 -0800898 grpc_lb_policy_cancel_pick(exec_ctx, chand->lb_policy,
Mark D. Roth5f844002016-09-08 08:20:53 -0700899 connected_subchannel, GRPC_ERROR_REF(error));
Craig Tiller577c9b22015-11-02 14:11:15 -0800900 }
901 for (closure = chand->waiting_for_config_closures.head; closure != NULL;
Craig Tiller804ff712016-05-05 16:25:40 -0700902 closure = closure->next_data.next) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800903 cpa = closure->cb_arg;
Craig Tillerb5585d42015-11-17 07:18:31 -0800904 if (cpa->connected_subchannel == connected_subchannel) {
905 cpa->connected_subchannel = NULL;
Craig Tiller91031da2016-12-28 15:44:25 -0800906 grpc_closure_sched(
Mark D. Roth932b10c2016-09-09 08:44:30 -0700907 exec_ctx, cpa->on_ready,
Craig Tiller91031da2016-12-28 15:44:25 -0800908 GRPC_ERROR_CREATE_REFERENCING("Pick cancelled", &error, 1));
Craig Tiller577c9b22015-11-02 14:11:15 -0800909 }
910 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700911 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth697a1f62016-09-07 13:35:07 -0700912 GRPC_ERROR_UNREF(error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700913 return true;
Craig Tiller577c9b22015-11-02 14:11:15 -0800914 }
Mark D. Roth697a1f62016-09-07 13:35:07 -0700915 GPR_ASSERT(error == GRPC_ERROR_NONE);
Craig Tiller577c9b22015-11-02 14:11:15 -0800916 if (chand->lb_policy != NULL) {
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800917 grpc_lb_policy *lb_policy = chand->lb_policy;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700918 GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel");
Mark D. Rothe40dd292016-10-05 14:58:37 -0700919 // If the application explicitly set wait_for_ready, use that.
920 // Otherwise, if the service config specified a value for this
921 // method, use that.
Mark D. Rothc1c38582016-10-11 11:03:27 -0700922 const bool wait_for_ready_set_from_api =
923 initial_metadata_flags &
924 GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
925 const bool wait_for_ready_set_from_service_config =
926 calld->wait_for_ready_from_service_config != WAIT_FOR_READY_UNSET;
927 if (!wait_for_ready_set_from_api &&
928 wait_for_ready_set_from_service_config) {
Mark D. Rothe40dd292016-10-05 14:58:37 -0700929 if (calld->wait_for_ready_from_service_config == WAIT_FOR_READY_TRUE) {
930 initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
931 } else {
932 initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
933 }
934 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700935 const grpc_lb_policy_pick_args inputs = {
Yuchen Zengac8bc422016-10-05 14:00:02 -0700936 initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem,
937 gpr_inf_future(GPR_CLOCK_MONOTONIC)};
Mark D. Roth55f25b62016-10-12 14:55:20 -0700938 const bool result = grpc_lb_policy_pick(
939 exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, on_ready);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700940 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel");
941 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700942 return result;
Craig Tiller577c9b22015-11-02 14:11:15 -0800943 }
944 if (chand->resolver != NULL && !chand->started_resolving) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700945 chand->started_resolving = true;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800946 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -0800947 grpc_resolver_next_locked(exec_ctx, chand->resolver,
948 &chand->resolver_result,
949 &chand->on_resolver_result_changed);
Craig Tiller577c9b22015-11-02 14:11:15 -0800950 }
Craig Tiller0eab6972016-04-23 12:59:57 -0700951 if (chand->resolver != NULL) {
952 cpa = gpr_malloc(sizeof(*cpa));
953 cpa->initial_metadata = initial_metadata;
954 cpa->initial_metadata_flags = initial_metadata_flags;
955 cpa->connected_subchannel = connected_subchannel;
956 cpa->on_ready = on_ready;
957 cpa->elem = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -0800958 grpc_closure_init(&cpa->closure, continue_picking_locked, cpa,
959 grpc_combiner_scheduler(chand->combiner, true));
Craig Tiller804ff712016-05-05 16:25:40 -0700960 grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
961 GRPC_ERROR_NONE);
Craig Tiller0eab6972016-04-23 12:59:57 -0700962 } else {
Craig Tiller91031da2016-12-28 15:44:25 -0800963 grpc_closure_sched(exec_ctx, on_ready, GRPC_ERROR_CREATE("Disconnected"));
Craig Tiller0eab6972016-04-23 12:59:57 -0700964 }
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700965
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700966 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700967 return false;
Craig Tiller577c9b22015-11-02 14:11:15 -0800968}
969
Craig Tillera8610c02017-02-14 10:05:11 -0800970static void start_transport_stream_op_locked_inner(grpc_exec_ctx *exec_ctx,
971 grpc_transport_stream_op *op,
972 grpc_call_element *elem) {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700973 channel_data *chand = elem->channel_data;
Craig Tillera11bfc82017-02-14 09:56:33 -0800974 call_data *calld = elem->call_data;
Craig Tillerbefafe62017-02-09 11:30:54 -0800975 grpc_subchannel_call *call;
976
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700977 /* need to recheck that another thread hasn't set the call */
978 call = GET_CALL(calld);
979 if (call == CANCELLED_CALL) {
Mark D. Rothf28763c2016-09-14 15:18:40 -0700980 grpc_transport_stream_op_finish_with_failure(
981 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -0800982 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700983 return;
984 }
985 if (call != NULL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700986 grpc_subchannel_call_process_op(exec_ctx, call, op);
Craig Tillera11bfc82017-02-14 09:56:33 -0800987 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700988 return;
989 }
990 /* if this is a cancellation, then we can raise our cancelled flag */
991 if (op->cancel_error != GRPC_ERROR_NONE) {
992 if (!gpr_atm_rel_cas(&calld->subchannel_call, 0,
993 (gpr_atm)(uintptr_t)CANCELLED_CALL)) {
Craig Tillera11bfc82017-02-14 09:56:33 -0800994 /* recurse to retry */
Craig Tillera8610c02017-02-14 10:05:11 -0800995 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -0800996 /* early out */
997 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700998 } else {
Craig Tillerbe9691a2017-02-14 10:00:42 -0800999 /* Stash a copy of cancel_error in our call data, so that we can use
1000 it for subsequent operations. This ensures that if the call is
1001 cancelled before any ops are passed down (e.g., if the deadline
1002 is in the past when the call starts), we can return the right
1003 error to the caller when the first op does get passed down. */
Mark D. Rothf28763c2016-09-14 15:18:40 -07001004 calld->cancel_error = GRPC_ERROR_REF(op->cancel_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001005 switch (calld->creation_phase) {
1006 case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
1007 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error));
1008 break;
1009 case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
Craig Tillerbefafe62017-02-09 11:30:54 -08001010 pick_subchannel_locked(exec_ctx, elem, NULL, 0,
1011 &calld->connected_subchannel, NULL,
1012 GRPC_ERROR_REF(op->cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001013 break;
1014 }
Mark D. Roth72f6da82016-09-02 13:42:38 -07001015 grpc_transport_stream_op_finish_with_failure(
1016 exec_ctx, op, GRPC_ERROR_REF(op->cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -08001017 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001018 return;
1019 }
1020 }
1021 /* if we don't have a subchannel, try to get one */
1022 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
1023 calld->connected_subchannel == NULL &&
1024 op->send_initial_metadata != NULL) {
1025 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
Craig Tillerbefafe62017-02-09 11:30:54 -08001026 grpc_closure_init(&calld->next_step, subchannel_ready_locked, elem,
1027 grpc_combiner_scheduler(chand->combiner, true));
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001028 GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
Yuchen Zeng144ce652016-09-01 18:19:34 -07001029 /* If a subchannel is not available immediately, the polling entity from
1030 call_data should be provided to channel_data's interested_parties, so
1031 that IO of the lb_policy and resolver could be done under it. */
Craig Tillerbefafe62017-02-09 11:30:54 -08001032 if (pick_subchannel_locked(exec_ctx, elem, op->send_initial_metadata,
1033 op->send_initial_metadata_flags,
1034 &calld->connected_subchannel, &calld->next_step,
1035 GRPC_ERROR_NONE)) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001036 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
1037 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
Yuchen Zeng19656b12016-09-01 18:00:45 -07001038 } else {
Yuchen Zeng19656b12016-09-01 18:00:45 -07001039 grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
1040 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001041 }
1042 }
1043 /* if we've got a subchannel, then let's ask it to create a call */
1044 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
1045 calld->connected_subchannel != NULL) {
1046 grpc_subchannel_call *subchannel_call = NULL;
1047 grpc_error *error = grpc_connected_subchannel_create_call(
Mark D. Rothaa850a72016-09-26 13:38:02 -07001048 exec_ctx, calld->connected_subchannel, calld->pollent, calld->path,
Mark D. Roth3d883412016-11-07 13:42:54 -08001049 calld->call_start_time, calld->deadline, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001050 if (error != GRPC_ERROR_NONE) {
1051 subchannel_call = CANCELLED_CALL;
1052 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
1053 grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
1054 }
1055 gpr_atm_rel_store(&calld->subchannel_call,
1056 (gpr_atm)(uintptr_t)subchannel_call);
1057 retry_waiting_locked(exec_ctx, calld);
Craig Tillera11bfc82017-02-14 09:56:33 -08001058 /* recurse to retry */
Craig Tillera8610c02017-02-14 10:05:11 -08001059 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001060 /* early out */
1061 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001062 }
1063 /* nothing to be done but wait */
1064 add_waiting_locked(calld, op);
Craig Tillera11bfc82017-02-14 09:56:33 -08001065}
1066
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001067static void on_complete_locked(grpc_exec_ctx *exec_ctx, void *arg,
1068 grpc_error *error) {
1069 grpc_call_element *elem = arg;
1070 channel_data *chand = elem->channel_data;
1071 call_data *calld = elem->call_data;
1072 if (chand->retry_throttle_data != NULL) {
1073 if (error == GRPC_ERROR_NONE) {
1074 grpc_server_retry_throttle_data_record_success(
1075 &chand->retry_throttle_data);
1076 } else {
1077 // TODO(roth): In a subsequent PR, check the return value here and
Mark D. Rothb3322562017-02-23 14:38:02 -08001078 // decide whether or not to retry. Note that we should only
1079 // record failures whose statuses match the configured retryable
1080 // or non-fatal status codes.
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001081 grpc_server_retry_throttle_data_record_failure(
1082 &chand->retry_throttle_data);
1083 }
1084 }
1085 grpc_closure_run(exec_ctx, calld->original_on_complete, error);
1086}
1087
1088static void start_transport_stream_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
1089 grpc_error *error_ignored) {
1090 GPR_TIMER_BEGIN("start_transport_stream_op_locked", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001091
1092 grpc_transport_stream_op *op = arg;
1093 grpc_call_element *elem = op->handler_private.args[0];
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001094 channel_data *chand = elem->channel_data;
Craig Tillera11bfc82017-02-14 09:56:33 -08001095 call_data *calld = elem->call_data;
1096
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001097 if (op->recv_trailing_metadata != NULL) {
1098 GPR_ASSERT(op->on_complete != NULL);
1099 calld->original_on_complete = op->on_complete;
1100 grpc_closure_init(&calld->on_complete, on_complete_locked, elem,
1101 grpc_combiner_scheduler(chand->combiner, false));
1102 op->on_complete = &calld->on_complete;
1103 }
1104
Craig Tillera8610c02017-02-14 10:05:11 -08001105 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001106
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001107 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
1108 "start_transport_stream_op");
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001109 GPR_TIMER_END("start_transport_stream_op_locked", 0);
Craig Tillerbefafe62017-02-09 11:30:54 -08001110}
1111
Craig Tillerbe9691a2017-02-14 10:00:42 -08001112/* The logic here is fairly complicated, due to (a) the fact that we
1113 need to handle the case where we receive the send op before the
1114 initial metadata op, and (b) the need for efficiency, especially in
1115 the streaming case.
1116
1117 We use double-checked locking to initially see if initialization has been
1118 performed. If it has not, we acquire the combiner and perform initialization.
1119 If it has, we proceed on the fast path. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001120static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
1121 grpc_call_element *elem,
1122 grpc_transport_stream_op *op) {
1123 call_data *calld = elem->call_data;
1124 channel_data *chand = elem->channel_data;
1125 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
1126 grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op);
1127 /* try to (atomically) get the call */
1128 grpc_subchannel_call *call = GET_CALL(calld);
1129 GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
1130 if (call == CANCELLED_CALL) {
1131 grpc_transport_stream_op_finish_with_failure(
1132 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
1133 GPR_TIMER_END("cc_start_transport_stream_op", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001134 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001135 return;
1136 }
1137 if (call != NULL) {
1138 grpc_subchannel_call_process_op(exec_ctx, call, op);
1139 GPR_TIMER_END("cc_start_transport_stream_op", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001140 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001141 return;
1142 }
1143 /* we failed; lock and figure out what to do */
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001144 GRPC_CALL_STACK_REF(calld->owning_call, "start_transport_stream_op");
Craig Tiller4a84bdd2017-02-14 09:48:41 -08001145 op->handler_private.args[0] = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -08001146 grpc_closure_sched(
1147 exec_ctx,
Craig Tiller4a84bdd2017-02-14 09:48:41 -08001148 grpc_closure_init(&op->handler_private.closure,
Mark D. Rothd6d192d2017-02-23 08:58:42 -08001149 start_transport_stream_op_locked, op,
Craig Tillerbefafe62017-02-09 11:30:54 -08001150 grpc_combiner_scheduler(chand->combiner, false)),
1151 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001152 GPR_TIMER_END("cc_start_transport_stream_op", 0);
1153}
1154
Mark D. Rothe40dd292016-10-05 14:58:37 -07001155// Gets data from the service config. Invoked when the resolver returns
1156// its initial result.
Craig Tillerbefafe62017-02-09 11:30:54 -08001157static void read_service_config_locked(grpc_exec_ctx *exec_ctx, void *arg,
1158 grpc_error *error) {
Mark D. Rothe40dd292016-10-05 14:58:37 -07001159 grpc_call_element *elem = arg;
1160 channel_data *chand = elem->channel_data;
1161 call_data *calld = elem->call_data;
1162 // If this is an error, there's no point in looking at the service config.
Mark D. Roth196387a2016-10-12 14:53:36 -07001163 if (error == GRPC_ERROR_NONE) {
1164 // Get the method config table from channel data.
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001165 grpc_slice_hash_table *method_params_table = NULL;
Mark D. Roth9d480942016-10-19 14:18:05 -07001166 if (chand->method_params_table != NULL) {
1167 method_params_table =
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001168 grpc_slice_hash_table_ref(chand->method_params_table);
Mark D. Rothe40dd292016-10-05 14:58:37 -07001169 }
Mark D. Roth196387a2016-10-12 14:53:36 -07001170 // If the method config table was present, use it.
Mark D. Roth9d480942016-10-19 14:18:05 -07001171 if (method_params_table != NULL) {
Craig Tiller87a7e1f2016-11-09 09:42:19 -08001172 const method_parameters *method_params = grpc_method_config_table_get(
1173 exec_ctx, method_params_table, calld->path);
Mark D. Roth9d480942016-10-19 14:18:05 -07001174 if (method_params != NULL) {
1175 const bool have_method_timeout =
1176 gpr_time_cmp(method_params->timeout, gpr_time_0(GPR_TIMESPAN)) != 0;
1177 if (have_method_timeout ||
1178 method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
Mark D. Roth9d480942016-10-19 14:18:05 -07001179 if (have_method_timeout) {
1180 const gpr_timespec per_method_deadline =
1181 gpr_time_add(calld->call_start_time, method_params->timeout);
Mark D. Roth196387a2016-10-12 14:53:36 -07001182 if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
1183 calld->deadline = per_method_deadline;
1184 // Reset deadline timer.
1185 grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
1186 }
1187 }
Mark D. Roth9d480942016-10-19 14:18:05 -07001188 if (method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
Mark D. Roth196387a2016-10-12 14:53:36 -07001189 calld->wait_for_ready_from_service_config =
Mark D. Roth9d480942016-10-19 14:18:05 -07001190 method_params->wait_for_ready;
Mark D. Roth196387a2016-10-12 14:53:36 -07001191 }
Mark D. Roth196387a2016-10-12 14:53:36 -07001192 }
1193 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001194 grpc_slice_hash_table_unref(exec_ctx, method_params_table);
Mark D. Roth196387a2016-10-12 14:53:36 -07001195 }
Mark D. Rothe40dd292016-10-05 14:58:37 -07001196 }
Mark D. Roth31292f22016-10-12 13:14:07 -07001197 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "read_service_config");
Mark D. Rothe40dd292016-10-05 14:58:37 -07001198}
1199
Craig Tillerbefafe62017-02-09 11:30:54 -08001200static void initial_read_service_config_locked(grpc_exec_ctx *exec_ctx,
1201 void *arg,
1202 grpc_error *error_ignored) {
1203 grpc_call_element *elem = arg;
1204 channel_data *chand = elem->channel_data;
1205 call_data *calld = elem->call_data;
1206 // If the resolver has already returned results, then we can access
1207 // the service config parameters immediately. Otherwise, we need to
1208 // defer that work until the resolver returns an initial result.
1209 // TODO(roth): This code is almost but not quite identical to the code
1210 // in read_service_config() above. It would be nice to find a way to
1211 // combine them, to avoid having to maintain it twice.
1212 if (chand->lb_policy != NULL) {
1213 // We already have a resolver result, so check for service config.
1214 if (chand->method_params_table != NULL) {
1215 grpc_slice_hash_table *method_params_table =
1216 grpc_slice_hash_table_ref(chand->method_params_table);
1217 method_parameters *method_params = grpc_method_config_table_get(
1218 exec_ctx, method_params_table, calld->path);
1219 if (method_params != NULL) {
1220 if (gpr_time_cmp(method_params->timeout,
1221 gpr_time_0(GPR_CLOCK_MONOTONIC)) != 0) {
1222 gpr_timespec per_method_deadline =
1223 gpr_time_add(calld->call_start_time, method_params->timeout);
1224 calld->deadline = gpr_time_min(calld->deadline, per_method_deadline);
1225 }
1226 if (method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
1227 calld->wait_for_ready_from_service_config =
1228 method_params->wait_for_ready;
1229 }
1230 }
1231 grpc_slice_hash_table_unref(exec_ctx, method_params_table);
1232 }
1233 } else {
1234 // We don't yet have a resolver result, so register a callback to
1235 // get the service config data once the resolver returns.
1236 // Take a reference to the call stack to be owned by the callback.
1237 GRPC_CALL_STACK_REF(calld->owning_call, "read_service_config");
1238 grpc_closure_init(&calld->read_service_config, read_service_config_locked,
1239 elem, grpc_combiner_scheduler(chand->combiner, false));
1240 grpc_closure_list_append(&chand->waiting_for_config_closures,
1241 &calld->read_service_config, GRPC_ERROR_NONE);
1242 }
1243 // Start the deadline timer with the current deadline value. If we
1244 // do not yet have service config data, then the timer may be reset
1245 // later.
1246 grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001247 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
1248 "initial_read_service_config");
Craig Tillerbefafe62017-02-09 11:30:54 -08001249}
1250
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001251/* Constructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001252static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
1253 grpc_call_element *elem,
Craig Tillerc52ba3a2017-02-15 22:57:43 -08001254 const grpc_call_element_args *args) {
Mark D. Rothaa850a72016-09-26 13:38:02 -07001255 channel_data *chand = elem->channel_data;
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001256 call_data *calld = elem->call_data;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001257 // Initialize data members.
1258 grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001259 calld->path = grpc_slice_ref_internal(args->path);
Mark D. Rothff08f332016-10-14 13:01:01 -07001260 calld->call_start_time = args->start_time;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001261 calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
1262 calld->wait_for_ready_from_service_config = WAIT_FOR_READY_UNSET;
Mark D. Rothf28763c2016-09-14 15:18:40 -07001263 calld->cancel_error = GRPC_ERROR_NONE;
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001264 gpr_atm_rel_store(&calld->subchannel_call, 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001265 calld->connected_subchannel = NULL;
1266 calld->waiting_ops = NULL;
1267 calld->waiting_ops_count = 0;
1268 calld->waiting_ops_capacity = 0;
1269 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
1270 calld->owning_call = args->call_stack;
1271 calld->pollent = NULL;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001272 GRPC_CALL_STACK_REF(calld->owning_call, "initial_read_service_config");
Craig Tillerbefafe62017-02-09 11:30:54 -08001273 grpc_closure_sched(
1274 exec_ctx,
1275 grpc_closure_init(&calld->read_service_config,
1276 initial_read_service_config_locked, elem,
1277 grpc_combiner_scheduler(chand->combiner, false)),
1278 GRPC_ERROR_NONE);
Mark D. Roth0badbe82016-06-23 10:15:12 -07001279 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001280}
1281
1282/* Destructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001283static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
1284 grpc_call_element *elem,
1285 const grpc_call_final_info *final_info,
1286 void *and_free_memory) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001287 call_data *calld = elem->call_data;
Mark D. Rothf28763c2016-09-14 15:18:40 -07001288 grpc_deadline_state_destroy(exec_ctx, elem);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001289 grpc_slice_unref_internal(exec_ctx, calld->path);
Mark D. Rothf28763c2016-09-14 15:18:40 -07001290 GRPC_ERROR_UNREF(calld->cancel_error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001291 grpc_subchannel_call *call = GET_CALL(calld);
1292 if (call != NULL && call != CANCELLED_CALL) {
1293 GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
1294 }
1295 GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001296 GPR_ASSERT(calld->waiting_ops_count == 0);
Craig Tiller693d3942016-10-27 16:51:25 -07001297 if (calld->connected_subchannel != NULL) {
1298 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel,
1299 "picked");
1300 }
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001301 gpr_free(calld->waiting_ops);
Craig Tiller2c8063c2016-03-22 22:12:15 -07001302 gpr_free(and_free_memory);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001303}
1304
David Garcia Quintasf72eb972016-05-03 18:28:09 -07001305static void cc_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
1306 grpc_call_element *elem,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001307 grpc_polling_entity *pollent) {
Craig Tiller577c9b22015-11-02 14:11:15 -08001308 call_data *calld = elem->call_data;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001309 calld->pollent = pollent;
Craig Tiller577c9b22015-11-02 14:11:15 -08001310}
1311
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001312/*************************************************************************
1313 * EXPORTED SYMBOLS
1314 */
1315
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001316const grpc_channel_filter grpc_client_channel_filter = {
Craig Tillerf40df232016-03-25 13:38:14 -07001317 cc_start_transport_stream_op,
1318 cc_start_transport_op,
1319 sizeof(call_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001320 cc_init_call_elem,
David Garcia Quintas4afce7e2016-04-18 16:25:17 -07001321 cc_set_pollset_or_pollset_set,
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001322 cc_destroy_call_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001323 sizeof(channel_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001324 cc_init_channel_elem,
1325 cc_destroy_channel_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001326 cc_get_peer,
Mark D. Rothb2d24882016-10-27 15:44:07 -07001327 cc_get_channel_info,
Craig Tillerf40df232016-03-25 13:38:14 -07001328 "client-channel",
Craig Tiller87d5b192015-04-16 14:37:57 -07001329};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001330
Craig Tiller613dafa2017-02-09 12:00:43 -08001331static void try_to_connect_locked(grpc_exec_ctx *exec_ctx, void *arg,
1332 grpc_error *error_ignored) {
1333 channel_data *chand = arg;
1334 if (chand->lb_policy != NULL) {
1335 grpc_lb_policy_exit_idle(exec_ctx, chand->lb_policy);
1336 } else {
1337 chand->exit_idle_when_lb_policy_arrives = true;
1338 if (!chand->started_resolving && chand->resolver != NULL) {
1339 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
1340 chand->started_resolving = true;
Craig Tiller972470b2017-02-09 15:05:36 -08001341 grpc_resolver_next_locked(exec_ctx, chand->resolver,
1342 &chand->resolver_result,
1343 &chand->on_resolver_result_changed);
Craig Tiller613dafa2017-02-09 12:00:43 -08001344 }
1345 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001346 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001347}
1348
Craig Tillera82950e2015-09-22 12:33:20 -07001349grpc_connectivity_state grpc_client_channel_check_connectivity_state(
1350 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001351 channel_data *chand = elem->channel_data;
Craig Tillera8610c02017-02-14 10:05:11 -08001352 grpc_connectivity_state out =
1353 grpc_connectivity_state_check(&chand->state_tracker);
Craig Tillera82950e2015-09-22 12:33:20 -07001354 if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001355 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001356 grpc_closure_sched(
1357 exec_ctx,
1358 grpc_closure_create(try_to_connect_locked, chand,
1359 grpc_combiner_scheduler(chand->combiner, false)),
1360 GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -07001361 }
Craig Tiller48cb07c2015-07-15 16:16:15 -07001362 return out;
1363}
1364
Craig Tiller86c99582015-11-25 15:22:26 -08001365typedef struct {
1366 channel_data *chand;
1367 grpc_pollset *pollset;
1368 grpc_closure *on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001369 grpc_connectivity_state *state;
Craig Tiller86c99582015-11-25 15:22:26 -08001370 grpc_closure my_closure;
1371} external_connectivity_watcher;
1372
Craig Tiller1d881fb2015-12-01 07:39:04 -08001373static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -07001374 grpc_error *error) {
Craig Tiller86c99582015-11-25 15:22:26 -08001375 external_connectivity_watcher *w = arg;
1376 grpc_closure *follow_up = w->on_complete;
Craig Tiller69b093b2016-02-25 19:04:07 -08001377 grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
Craig Tiller1d881fb2015-12-01 07:39:04 -08001378 w->pollset);
1379 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
1380 "external_connectivity_watcher");
Craig Tiller86c99582015-11-25 15:22:26 -08001381 gpr_free(w);
Craig Tiller613dafa2017-02-09 12:00:43 -08001382 grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
1383}
1384
Craig Tillera8610c02017-02-14 10:05:11 -08001385static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg,
1386 grpc_error *error_ignored) {
Craig Tiller613dafa2017-02-09 12:00:43 -08001387 external_connectivity_watcher *w = arg;
1388 grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
1389 grpc_schedule_on_exec_ctx);
1390 grpc_connectivity_state_notify_on_state_change(
1391 exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
Craig Tiller86c99582015-11-25 15:22:26 -08001392}
1393
Craig Tillera82950e2015-09-22 12:33:20 -07001394void grpc_client_channel_watch_connectivity_state(
Craig Tiller906e3bc2015-11-24 07:31:31 -08001395 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
Craig Tillera82950e2015-09-22 12:33:20 -07001396 grpc_connectivity_state *state, grpc_closure *on_complete) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001397 channel_data *chand = elem->channel_data;
Craig Tiller86c99582015-11-25 15:22:26 -08001398 external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
1399 w->chand = chand;
1400 w->pollset = pollset;
1401 w->on_complete = on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001402 w->state = state;
Craig Tiller69b093b2016-02-25 19:04:07 -08001403 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
Craig Tiller1d881fb2015-12-01 07:39:04 -08001404 GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
1405 "external_connectivity_watcher");
Craig Tiller613dafa2017-02-09 12:00:43 -08001406 grpc_closure_sched(
1407 exec_ctx,
Craig Tillera8610c02017-02-14 10:05:11 -08001408 grpc_closure_init(&w->my_closure, watch_connectivity_state_locked, w,
Craig Tiller613dafa2017-02-09 12:00:43 -08001409 grpc_combiner_scheduler(chand->combiner, true)),
1410 GRPC_ERROR_NONE);
Craig Tiller48cb07c2015-07-15 16:16:15 -07001411}