blob: 39db06491c5ae0a4bee4053a8129425e5f3be50d [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. Roth2137cd82016-09-14 09:04:00 -070050#include "src/core/ext/client_channel/subchannel.h"
Craig Tiller9533d042016-03-25 17:11:06 -070051#include "src/core/lib/channel/channel_args.h"
52#include "src/core/lib/channel/connected_channel.h"
Mark D. Roth72f6da82016-09-02 13:42:38 -070053#include "src/core/lib/channel/deadline_filter.h"
Craig Tillerbefafe62017-02-09 11:30:54 -080054#include "src/core/lib/iomgr/combiner.h"
Craig Tiller9533d042016-03-25 17:11:06 -070055#include "src/core/lib/iomgr/iomgr.h"
Mark D. Roth4c0fe492016-08-31 13:51:55 -070056#include "src/core/lib/iomgr/polling_entity.h"
Craig Tiller9533d042016-03-25 17:11:06 -070057#include "src/core/lib/profiling/timers.h"
Craig Tiller7c70b6c2017-01-23 07:48:42 -080058#include "src/core/lib/slice/slice_internal.h"
Craig Tiller9533d042016-03-25 17:11:06 -070059#include "src/core/lib/support/string.h"
60#include "src/core/lib/surface/channel.h"
61#include "src/core/lib/transport/connectivity_state.h"
Mark D. Roth9fe284e2016-09-12 11:22:27 -070062#include "src/core/lib/transport/metadata.h"
63#include "src/core/lib/transport/metadata_batch.h"
Mark D. Rothea846a02016-11-03 11:32:54 -070064#include "src/core/lib/transport/service_config.h"
Mark D. Roth9fe284e2016-09-12 11:22:27 -070065#include "src/core/lib/transport/static_metadata.h"
Craig Tiller8910ac62015-10-08 16:49:15 -070066
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080067/* Client channel implementation */
68
Mark D. Roth26b7be42016-10-24 10:08:07 -070069/*************************************************************************
70 * METHOD-CONFIG TABLE
71 */
72
Mark D. Roth9d480942016-10-19 14:18:05 -070073typedef enum {
74 WAIT_FOR_READY_UNSET,
75 WAIT_FOR_READY_FALSE,
76 WAIT_FOR_READY_TRUE
77} wait_for_ready_value;
78
79typedef struct method_parameters {
80 gpr_timespec timeout;
81 wait_for_ready_value wait_for_ready;
82} method_parameters;
83
84static void *method_parameters_copy(void *value) {
85 void *new_value = gpr_malloc(sizeof(method_parameters));
86 memcpy(new_value, value, sizeof(method_parameters));
87 return new_value;
88}
89
Craig Tillerb28c7e82016-11-18 10:29:04 -080090static void method_parameters_free(grpc_exec_ctx *exec_ctx, void *p) {
Craig Tiller87a7e1f2016-11-09 09:42:19 -080091 gpr_free(p);
92}
93
Craig Tiller7c70b6c2017-01-23 07:48:42 -080094static const grpc_slice_hash_table_vtable method_parameters_vtable = {
Craig Tillerb28c7e82016-11-18 10:29:04 -080095 method_parameters_free, method_parameters_copy};
Mark D. Roth9d480942016-10-19 14:18:05 -070096
Mark D. Rothe30baeb2016-11-03 08:16:19 -070097static void *method_parameters_create_from_json(const grpc_json *json) {
Mark D. Rothc968e602016-11-02 14:07:36 -070098 wait_for_ready_value wait_for_ready = WAIT_FOR_READY_UNSET;
Mark D. Roth47f10842016-11-03 08:45:27 -070099 gpr_timespec timeout = {0, 0, GPR_TIMESPAN};
100 for (grpc_json *field = json->child; field != NULL; field = field->next) {
Mark D. Rothc968e602016-11-02 14:07:36 -0700101 if (field->key == NULL) continue;
Mark D. Roth84c8a022016-11-10 09:39:34 -0800102 if (strcmp(field->key, "waitForReady") == 0) {
Mark D. Rothc968e602016-11-02 14:07:36 -0700103 if (wait_for_ready != WAIT_FOR_READY_UNSET) return NULL; // Duplicate.
104 if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) {
105 return NULL;
106 }
Mark D. Roth47f10842016-11-03 08:45:27 -0700107 wait_for_ready = field->type == GRPC_JSON_TRUE ? WAIT_FOR_READY_TRUE
108 : WAIT_FOR_READY_FALSE;
Mark D. Rothc968e602016-11-02 14:07:36 -0700109 } else if (strcmp(field->key, "timeout") == 0) {
110 if (timeout.tv_sec > 0 || timeout.tv_nsec > 0) return NULL; // Duplicate.
Mark D. Roth84c8a022016-11-10 09:39:34 -0800111 if (field->type != GRPC_JSON_STRING) return NULL;
112 size_t len = strlen(field->value);
113 if (field->value[len - 1] != 's') return NULL;
Mark D. Rothc19049c2016-11-10 09:43:06 -0800114 char *buf = gpr_strdup(field->value);
Mark D. Roth84c8a022016-11-10 09:39:34 -0800115 buf[len - 1] = '\0'; // Remove trailing 's'.
Mark D. Rothc19049c2016-11-10 09:43:06 -0800116 char *decimal_point = strchr(buf, '.');
Mark D. Roth84c8a022016-11-10 09:39:34 -0800117 if (decimal_point != NULL) {
118 *decimal_point = '\0';
119 timeout.tv_nsec = gpr_parse_nonnegative_int(decimal_point + 1);
120 if (timeout.tv_nsec == -1) {
121 gpr_free(buf);
Mark D. Rothc968e602016-11-02 14:07:36 -0700122 return NULL;
123 }
Mark D. Roth84c8a022016-11-10 09:39:34 -0800124 // There should always be exactly 3, 6, or 9 fractional digits.
125 int multiplier = 1;
126 switch (strlen(decimal_point + 1)) {
127 case 9:
128 break;
129 case 6:
130 multiplier *= 1000;
131 break;
132 case 3:
133 multiplier *= 1000000;
134 break;
135 default: // Unsupported number of digits.
136 gpr_free(buf);
137 return NULL;
138 }
139 timeout.tv_nsec *= multiplier;
Mark D. Rothc968e602016-11-02 14:07:36 -0700140 }
Mark D. Roth84c8a022016-11-10 09:39:34 -0800141 timeout.tv_sec = gpr_parse_nonnegative_int(buf);
142 if (timeout.tv_sec == -1) return NULL;
143 gpr_free(buf);
Mark D. Rothc968e602016-11-02 14:07:36 -0700144 }
145 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700146 method_parameters *value = gpr_malloc(sizeof(method_parameters));
Mark D. Rothc968e602016-11-02 14:07:36 -0700147 value->timeout = timeout;
148 value->wait_for_ready = wait_for_ready;
Mark D. Roth9d480942016-10-19 14:18:05 -0700149 return value;
150}
151
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700152/*************************************************************************
153 * CHANNEL-WIDE FUNCTIONS
154 */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800155
Craig Tiller800dacb2015-10-06 09:10:26 -0700156typedef struct client_channel_channel_data {
Craig Tillerf5f17122015-06-25 08:47:26 -0700157 /** resolver for this channel */
158 grpc_resolver *resolver;
Craig Tiller20a3c352015-08-05 08:39:50 -0700159 /** have we started resolving this channel */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700160 bool started_resolving;
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700161 /** client channel factory */
162 grpc_client_channel_factory *client_channel_factory;
Craig Tillerf5f17122015-06-25 08:47:26 -0700163
Craig Tillerbefafe62017-02-09 11:30:54 -0800164 /** combiner protecting all variables below in this data structure */
165 grpc_combiner *combiner;
Mark D. Roth046cf762016-09-26 11:13:51 -0700166 /** currently active load balancer */
Craig Tillerf5f17122015-06-25 08:47:26 -0700167 grpc_lb_policy *lb_policy;
Mark D. Roth9d480942016-10-19 14:18:05 -0700168 /** maps method names to method_parameters structs */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800169 grpc_slice_hash_table *method_params_table;
Mark D. Roth046cf762016-09-26 11:13:51 -0700170 /** incoming resolver result - set by resolver.next() */
Mark D. Rothaf842452016-10-21 15:05:15 -0700171 grpc_channel_args *resolver_result;
Craig Tiller3f475422015-06-25 10:43:05 -0700172 /** a list of closures that are all waiting for config to come in */
Craig Tillerd9ccbbf2015-09-22 09:30:00 -0700173 grpc_closure_list waiting_for_config_closures;
Craig Tiller3f475422015-06-25 10:43:05 -0700174 /** resolver callback */
Mark D. Rothff4df062016-08-22 15:02:49 -0700175 grpc_closure on_resolver_result_changed;
Craig Tiller3f475422015-06-25 10:43:05 -0700176 /** connectivity state being tracked */
Craig Tillerca3e9d32015-06-27 18:37:27 -0700177 grpc_connectivity_state_tracker state_tracker;
Craig Tiller48cb07c2015-07-15 16:16:15 -0700178 /** when an lb_policy arrives, should we try to exit idle */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700179 bool exit_idle_when_lb_policy_arrives;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800180 /** owning stack */
181 grpc_channel_stack *owning_stack;
Craig Tiller69b093b2016-02-25 19:04:07 -0800182 /** interested parties (owned) */
183 grpc_pollset_set *interested_parties;
Craig Tiller613dafa2017-02-09 12:00:43 -0800184
185 /* the following properties are guarded by a mutex since API's require them
186 to be instantaniously available */
187 gpr_mu info_mu;
188 char *info_lb_policy_name;
189 /** service config in JSON form */
190 char *info_service_config_json;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800191} channel_data;
192
Craig Tillerd6c98df2015-08-18 09:33:44 -0700193/** We create one watcher for each new lb_policy that is returned from a
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700194 resolver, to watch for state changes from the lb_policy. When a state
195 change is seen, we update the channel, and create a new watcher. */
Craig Tillera82950e2015-09-22 12:33:20 -0700196typedef struct {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700197 channel_data *chand;
Craig Tiller33825112015-09-18 07:44:19 -0700198 grpc_closure on_changed;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700199 grpc_connectivity_state state;
200 grpc_lb_policy *lb_policy;
201} lb_policy_connectivity_watcher;
202
Craig Tiller2400bf52017-02-09 16:25:19 -0800203static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
204 grpc_lb_policy *lb_policy,
205 grpc_connectivity_state current_state);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700206
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800207static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
208 channel_data *chand,
209 grpc_connectivity_state state,
Craig Tiller804ff712016-05-05 16:25:40 -0700210 grpc_error *error,
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800211 const char *reason) {
212 if ((state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
Craig Tiller48ed92e2016-06-02 11:07:12 -0700213 state == GRPC_CHANNEL_SHUTDOWN) &&
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800214 chand->lb_policy != NULL) {
Mark D. Roth59c9f902016-09-28 13:33:21 -0700215 /* cancel picks with wait_for_ready=false */
Craig Tiller2400bf52017-02-09 16:25:19 -0800216 grpc_lb_policy_cancel_picks_locked(
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800217 exec_ctx, chand->lb_policy,
Mark D. Roth59c9f902016-09-28 13:33:21 -0700218 /* mask= */ GRPC_INITIAL_METADATA_WAIT_FOR_READY,
Mark D. Roth58f52b72016-09-09 13:55:18 -0700219 /* check= */ 0, GRPC_ERROR_REF(error));
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800220 }
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700221 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, error,
222 reason);
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800223}
224
Craig Tiller804ff712016-05-05 16:25:40 -0700225static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
Craig Tillerbefafe62017-02-09 11:30:54 -0800226 void *arg, grpc_error *error) {
227 lb_policy_connectivity_watcher *w = arg;
Craig Tillercb2609f2015-11-24 17:19:19 -0800228 grpc_connectivity_state publish_state = w->state;
Craig Tillerc5de8352017-02-09 14:08:05 -0800229 /* check if the notification is for the latest policy */
230 if (w->lb_policy == w->chand->lb_policy) {
231 if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
232 publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Craig Tiller972470b2017-02-09 15:05:36 -0800233 grpc_resolver_channel_saw_error_locked(exec_ctx, w->chand->resolver);
Craig Tillerc5de8352017-02-09 14:08:05 -0800234 GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
235 w->chand->lb_policy = NULL;
236 }
237 set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
238 GRPC_ERROR_REF(error), "lb_changed");
239 if (w->state != GRPC_CHANNEL_SHUTDOWN) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800240 watch_lb_policy_locked(exec_ctx, w->chand, w->lb_policy, w->state);
Craig Tillerc5de8352017-02-09 14:08:05 -0800241 }
Craig Tillera82950e2015-09-22 12:33:20 -0700242 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700243
Craig Tiller906e3bc2015-11-24 07:31:31 -0800244 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
Craig Tillera82950e2015-09-22 12:33:20 -0700245 gpr_free(w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700246}
247
Craig Tiller2400bf52017-02-09 16:25:19 -0800248static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
249 grpc_lb_policy *lb_policy,
250 grpc_connectivity_state current_state) {
Craig Tillera82950e2015-09-22 12:33:20 -0700251 lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
Craig Tiller906e3bc2015-11-24 07:31:31 -0800252 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700253
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700254 w->chand = chand;
Craig Tillerbefafe62017-02-09 11:30:54 -0800255 grpc_closure_init(&w->on_changed, on_lb_policy_state_changed_locked, w,
256 grpc_combiner_scheduler(chand->combiner, false));
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700257 w->state = current_state;
258 w->lb_policy = lb_policy;
Craig Tiller2400bf52017-02-09 16:25:19 -0800259 grpc_lb_policy_notify_on_state_change_locked(exec_ctx, lb_policy, &w->state,
260 &w->on_changed);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700261}
262
Craig Tillerbefafe62017-02-09 11:30:54 -0800263static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
264 void *arg, grpc_error *error) {
Craig Tiller3f475422015-06-25 10:43:05 -0700265 channel_data *chand = arg;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700266 char *lb_policy_name = NULL;
Craig Tiller3f475422015-06-25 10:43:05 -0700267 grpc_lb_policy *lb_policy = NULL;
268 grpc_lb_policy *old_lb_policy;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800269 grpc_slice_hash_table *method_params_table = NULL;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700270 grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700271 bool exit_idle = false;
Craig Tiller804ff712016-05-05 16:25:40 -0700272 grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800273 char *service_config_json = NULL;
Craig Tiller3f475422015-06-25 10:43:05 -0700274
Mark D. Roth046cf762016-09-26 11:13:51 -0700275 if (chand->resolver_result != NULL) {
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700276 // Find LB policy name.
Mark D. Rothaf842452016-10-21 15:05:15 -0700277 const grpc_arg *channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700278 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_POLICY_NAME);
Mark D. Rothaf842452016-10-21 15:05:15 -0700279 if (channel_arg != NULL) {
280 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
281 lb_policy_name = channel_arg->value.string;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700282 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700283 // Special case: If all of the addresses are balancer addresses,
284 // assume that we should use the grpclb policy, regardless of what the
285 // resolver actually specified.
Mark D. Rothaf842452016-10-21 15:05:15 -0700286 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700287 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES);
Mark D. Rothaf842452016-10-21 15:05:15 -0700288 if (channel_arg != NULL) {
289 GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
Mark D. Roth557c9902016-10-24 11:12:05 -0700290 grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
Mark D. Rothaf842452016-10-21 15:05:15 -0700291 bool found_backend_address = false;
292 for (size_t i = 0; i < addresses->num_addresses; ++i) {
293 if (!addresses->addresses[i].is_balancer) {
294 found_backend_address = true;
295 break;
296 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700297 }
Mark D. Rothaf842452016-10-21 15:05:15 -0700298 if (!found_backend_address) {
299 if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) {
300 gpr_log(GPR_INFO,
301 "resolver requested LB policy %s but provided only balancer "
302 "addresses, no backend addresses -- forcing use of grpclb LB "
303 "policy",
Mark D. Roth5f40e5d2016-10-24 13:09:05 -0700304 lb_policy_name);
Mark D. Rothaf842452016-10-21 15:05:15 -0700305 }
306 lb_policy_name = "grpclb";
Mark D. Roth88405f72016-10-03 08:24:52 -0700307 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700308 }
309 // Use pick_first if nothing was specified and we didn't select grpclb
310 // above.
311 if (lb_policy_name == NULL) lb_policy_name = "pick_first";
Mark D. Roth41124992016-11-03 11:22:20 -0700312 // Instantiate LB policy.
313 grpc_lb_policy_args lb_policy_args;
314 lb_policy_args.args = chand->resolver_result;
315 lb_policy_args.client_channel_factory = chand->client_channel_factory;
Craig Tiller2400bf52017-02-09 16:25:19 -0800316 lb_policy_args.combiner = chand->combiner;
Mark D. Roth88405f72016-10-03 08:24:52 -0700317 lb_policy =
318 grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700319 if (lb_policy != NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -0700320 GRPC_LB_POLICY_REF(lb_policy, "config_change");
Craig Tillerf707d622016-05-06 14:26:12 -0700321 GRPC_ERROR_UNREF(state_error);
Craig Tiller2400bf52017-02-09 16:25:19 -0800322 state = grpc_lb_policy_check_connectivity_locked(exec_ctx, lb_policy,
323 &state_error);
Craig Tiller45724b32015-09-22 10:42:19 -0700324 }
Mark D. Roth41124992016-11-03 11:22:20 -0700325 // Find service config.
Mark D. Rothaf842452016-10-21 15:05:15 -0700326 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700327 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVICE_CONFIG);
Mark D. Roth046cf762016-09-26 11:13:51 -0700328 if (channel_arg != NULL) {
Mark D. Roth9ec28af2016-11-03 12:32:39 -0700329 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800330 service_config_json = gpr_strdup(channel_arg->value.string);
Mark D. Roth70a1abd2016-11-04 09:26:37 -0700331 grpc_service_config *service_config =
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800332 grpc_service_config_create(service_config_json);
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700333 if (service_config != NULL) {
334 method_params_table = grpc_service_config_create_method_config_table(
Craig Tillerb28c7e82016-11-18 10:29:04 -0800335 exec_ctx, service_config, method_parameters_create_from_json,
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700336 &method_parameters_vtable);
337 grpc_service_config_destroy(service_config);
338 }
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700339 }
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700340 // Before we clean up, save a copy of lb_policy_name, since it might
341 // be pointing to data inside chand->resolver_result.
342 // The copy will be saved in chand->lb_policy_name below.
343 lb_policy_name = gpr_strdup(lb_policy_name);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800344 grpc_channel_args_destroy(exec_ctx, chand->resolver_result);
Mark D. Roth046cf762016-09-26 11:13:51 -0700345 chand->resolver_result = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700346 }
347
Craig Tiller86c99582015-11-25 15:22:26 -0800348 if (lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800349 grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties,
350 chand->interested_parties);
Craig Tiller86c99582015-11-25 15:22:26 -0800351 }
352
Craig Tiller613dafa2017-02-09 12:00:43 -0800353 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700354 if (lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800355 gpr_free(chand->info_lb_policy_name);
356 chand->info_lb_policy_name = lb_policy_name;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700357 }
Craig Tiller3f475422015-06-25 10:43:05 -0700358 old_lb_policy = chand->lb_policy;
359 chand->lb_policy = lb_policy;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800360 if (service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800361 gpr_free(chand->info_service_config_json);
362 chand->info_service_config_json = service_config_json;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800363 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800364 gpr_mu_unlock(&chand->info_mu);
Mark D. Roth9d480942016-10-19 14:18:05 -0700365 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800366 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth046cf762016-09-26 11:13:51 -0700367 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700368 chand->method_params_table = method_params_table;
Craig Tiller0ede5452016-04-23 12:21:45 -0700369 if (lb_policy != NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -0800370 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller0ede5452016-04-23 12:21:45 -0700371 } else if (chand->resolver == NULL /* disconnected */) {
Craig Tiller804ff712016-05-05 16:25:40 -0700372 grpc_closure_list_fail_all(
373 &chand->waiting_for_config_closures,
374 GRPC_ERROR_CREATE_REFERENCING("Channel disconnected", &error, 1));
Craig Tiller91031da2016-12-28 15:44:25 -0800375 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tillera82950e2015-09-22 12:33:20 -0700376 }
377 if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
378 GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700379 exit_idle = true;
380 chand->exit_idle_when_lb_policy_arrives = false;
Craig Tillera82950e2015-09-22 12:33:20 -0700381 }
Craig Tiller98465032015-06-29 14:36:42 -0700382
Craig Tiller804ff712016-05-05 16:25:40 -0700383 if (error == GRPC_ERROR_NONE && chand->resolver) {
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700384 set_channel_connectivity_state_locked(
385 exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700386 if (lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800387 watch_lb_policy_locked(exec_ctx, chand, lb_policy, state);
Craig Tiller45724b32015-09-22 10:42:19 -0700388 }
Craig Tiller906e3bc2015-11-24 07:31:31 -0800389 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -0800390 grpc_resolver_next_locked(exec_ctx, chand->resolver,
391 &chand->resolver_result,
392 &chand->on_resolver_result_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700393 } else {
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800394 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800395 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800396 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
397 chand->resolver = NULL;
398 }
Craig Tiller804ff712016-05-05 16:25:40 -0700399 grpc_error *refs[] = {error, state_error};
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800400 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700401 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller804ff712016-05-05 16:25:40 -0700402 GRPC_ERROR_CREATE_REFERENCING("Got config after disconnection", refs,
403 GPR_ARRAY_SIZE(refs)),
404 "resolver_gone");
Craig Tillera82950e2015-09-22 12:33:20 -0700405 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700406
Craig Tillera82950e2015-09-22 12:33:20 -0700407 if (exit_idle) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800408 grpc_lb_policy_exit_idle_locked(exec_ctx, lb_policy);
Craig Tillera82950e2015-09-22 12:33:20 -0700409 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
410 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700411
Craig Tillera82950e2015-09-22 12:33:20 -0700412 if (old_lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800413 grpc_pollset_set_del_pollset_set(
414 exec_ctx, old_lb_policy->interested_parties, chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700415 GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
416 }
Craig Tiller000cd8f2015-09-18 07:20:29 -0700417
Craig Tillera82950e2015-09-22 12:33:20 -0700418 if (lb_policy != NULL) {
419 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
420 }
Craig Tiller45724b32015-09-22 10:42:19 -0700421
Craig Tiller906e3bc2015-11-24 07:31:31 -0800422 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700423 GRPC_ERROR_UNREF(state_error);
Craig Tiller3f475422015-06-25 10:43:05 -0700424}
425
Craig Tillerbefafe62017-02-09 11:30:54 -0800426static void cc_start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
427 grpc_error *error_ignored) {
428 grpc_transport_op *op = arg;
429 grpc_channel_element *elem = op->transport_private.args[0];
Craig Tillerca3e9d32015-06-27 18:37:27 -0700430 channel_data *chand = elem->channel_data;
Craig Tiller000cd8f2015-09-18 07:20:29 -0700431
Craig Tillera82950e2015-09-22 12:33:20 -0700432 if (op->on_connectivity_state_change != NULL) {
433 grpc_connectivity_state_notify_on_state_change(
434 exec_ctx, &chand->state_tracker, op->connectivity_state,
435 op->on_connectivity_state_change);
436 op->on_connectivity_state_change = NULL;
437 op->connectivity_state = NULL;
438 }
439
Craig Tiller26dab312015-12-07 14:43:47 -0800440 if (op->send_ping != NULL) {
Craig Tiller87b71e22015-12-07 15:14:14 -0800441 if (chand->lb_policy == NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -0800442 grpc_closure_sched(exec_ctx, op->send_ping,
443 GRPC_ERROR_CREATE("Ping with no load balancing"));
Craig Tiller26dab312015-12-07 14:43:47 -0800444 } else {
Craig Tiller2400bf52017-02-09 16:25:19 -0800445 grpc_lb_policy_ping_one_locked(exec_ctx, chand->lb_policy, op->send_ping);
Craig Tiller26dab312015-12-07 14:43:47 -0800446 op->bind_pollset = NULL;
447 }
448 op->send_ping = NULL;
449 }
450
Craig Tiller1c51edc2016-05-07 16:18:43 -0700451 if (op->disconnect_with_error != GRPC_ERROR_NONE) {
452 if (chand->resolver != NULL) {
453 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700454 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller1c51edc2016-05-07 16:18:43 -0700455 GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
Craig Tiller972470b2017-02-09 15:05:36 -0800456 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700457 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
458 chand->resolver = NULL;
459 if (!chand->started_resolving) {
460 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
461 GRPC_ERROR_REF(op->disconnect_with_error));
Craig Tiller91031da2016-12-28 15:44:25 -0800462 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700463 }
464 if (chand->lb_policy != NULL) {
465 grpc_pollset_set_del_pollset_set(exec_ctx,
466 chand->lb_policy->interested_parties,
467 chand->interested_parties);
468 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
469 chand->lb_policy = NULL;
470 }
Craig Tillerb12d22a2016-04-23 12:50:21 -0700471 }
Craig Tiller1c51edc2016-05-07 16:18:43 -0700472 GRPC_ERROR_UNREF(op->disconnect_with_error);
Craig Tillera82950e2015-09-22 12:33:20 -0700473 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800474 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "start_transport_op");
475
476 grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
Craig Tillerbefafe62017-02-09 11:30:54 -0800477}
478
479static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
480 grpc_channel_element *elem,
481 grpc_transport_op *op) {
482 channel_data *chand = elem->channel_data;
483
Craig Tillerbefafe62017-02-09 11:30:54 -0800484 GPR_ASSERT(op->set_accept_stream == false);
485 if (op->bind_pollset != NULL) {
486 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
487 op->bind_pollset);
488 }
489
490 op->transport_private.args[0] = elem;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800491 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "start_transport_op");
Craig Tillerbefafe62017-02-09 11:30:54 -0800492 grpc_closure_sched(
493 exec_ctx,
494 grpc_closure_init(&op->transport_private.closure,
495 cc_start_transport_op_locked, op,
496 grpc_combiner_scheduler(chand->combiner, false)),
497 GRPC_ERROR_NONE);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700498}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800499
Mark D. Rothb2d24882016-10-27 15:44:07 -0700500static void cc_get_channel_info(grpc_exec_ctx *exec_ctx,
501 grpc_channel_element *elem,
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700502 const grpc_channel_info *info) {
Mark D. Rothb2d24882016-10-27 15:44:07 -0700503 channel_data *chand = elem->channel_data;
Craig Tiller613dafa2017-02-09 12:00:43 -0800504 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700505 if (info->lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800506 *info->lb_policy_name = chand->info_lb_policy_name == NULL
Mark D. Roth78afd772016-11-04 12:49:49 -0700507 ? NULL
Craig Tiller613dafa2017-02-09 12:00:43 -0800508 : gpr_strdup(chand->info_lb_policy_name);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700509 }
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800510 if (info->service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800511 *info->service_config_json =
512 chand->info_service_config_json == NULL
513 ? NULL
514 : gpr_strdup(chand->info_service_config_json);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800515 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800516 gpr_mu_unlock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700517}
518
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700519/* Constructor for channel_data */
Mark D. Rothc1087882016-11-18 10:54:45 -0800520static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800521 grpc_channel_element *elem,
522 grpc_channel_element_args *args) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700523 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700524 memset(chand, 0, sizeof(*chand));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700525 GPR_ASSERT(args->is_last);
526 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800527 // Initialize data members.
Craig Tillerbefafe62017-02-09 11:30:54 -0800528 chand->combiner = grpc_combiner_create(NULL);
Craig Tillerd85477512017-02-09 12:02:39 -0800529 gpr_mu_init(&chand->info_mu);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800530 chand->owning_stack = args->channel_stack;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700531 grpc_closure_init(&chand->on_resolver_result_changed,
Craig Tillerbefafe62017-02-09 11:30:54 -0800532 on_resolver_result_changed_locked, chand,
533 grpc_combiner_scheduler(chand->combiner, false));
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800534 chand->interested_parties = grpc_pollset_set_create();
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700535 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
536 "client_channel");
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800537 // Record client channel factory.
538 const grpc_arg *arg = grpc_channel_args_find(args->channel_args,
539 GRPC_ARG_CLIENT_CHANNEL_FACTORY);
540 GPR_ASSERT(arg != NULL);
541 GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
542 grpc_client_channel_factory_ref(arg->value.pointer.p);
543 chand->client_channel_factory = arg->value.pointer.p;
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800544 // Get server name to resolve, using proxy mapper if needed.
Mark D. Roth86e90592016-11-18 09:56:40 -0800545 arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800546 GPR_ASSERT(arg != NULL);
547 GPR_ASSERT(arg->type == GRPC_ARG_STRING);
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800548 char *proxy_name = NULL;
549 grpc_channel_args *new_args = NULL;
550 grpc_proxy_mappers_map_name(exec_ctx, arg->value.string, args->channel_args,
551 &proxy_name, &new_args);
552 // Instantiate resolver.
Mark D. Roth45ccec52017-01-18 14:04:01 -0800553 chand->resolver = grpc_resolver_create(
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800554 exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string,
555 new_args != NULL ? new_args : args->channel_args,
Craig Tiller972470b2017-02-09 15:05:36 -0800556 chand->interested_parties, chand->combiner);
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800557 if (proxy_name != NULL) gpr_free(proxy_name);
558 if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args);
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800559 if (chand->resolver == NULL) {
560 return GRPC_ERROR_CREATE("resolver creation failed");
561 }
562 return GRPC_ERROR_NONE;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700563}
564
Craig Tiller972470b2017-02-09 15:05:36 -0800565static void shutdown_resolver_locked(grpc_exec_ctx *exec_ctx, void *arg,
566 grpc_error *error) {
567 grpc_resolver *resolver = arg;
568 grpc_resolver_shutdown_locked(exec_ctx, resolver);
569 GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel");
570}
571
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700572/* Destructor for channel_data */
573static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
574 grpc_channel_element *elem) {
575 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700576 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800577 grpc_closure_sched(
578 exec_ctx,
579 grpc_closure_create(shutdown_resolver_locked, chand->resolver,
580 grpc_combiner_scheduler(chand->combiner, false)),
581 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700582 }
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700583 if (chand->client_channel_factory != NULL) {
584 grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
585 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700586 if (chand->lb_policy != NULL) {
587 grpc_pollset_set_del_pollset_set(exec_ctx,
588 chand->lb_policy->interested_parties,
589 chand->interested_parties);
590 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
591 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800592 gpr_free(chand->info_lb_policy_name);
593 gpr_free(chand->info_service_config_json);
Mark D. Roth9d480942016-10-19 14:18:05 -0700594 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800595 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700596 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700597 grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
598 grpc_pollset_set_destroy(chand->interested_parties);
Craig Tiller648d6482017-02-09 15:32:39 -0800599 GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel");
Craig Tillerd85477512017-02-09 12:02:39 -0800600 gpr_mu_destroy(&chand->info_mu);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700601}
602
603/*************************************************************************
604 * PER-CALL FUNCTIONS
605 */
606
607#define GET_CALL(call_data) \
608 ((grpc_subchannel_call *)(gpr_atm_acq_load(&(call_data)->subchannel_call)))
609
610#define CANCELLED_CALL ((grpc_subchannel_call *)1)
611
612typedef enum {
613 GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING,
614 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL
615} subchannel_creation_phase;
616
617/** Call data. Holds a pointer to grpc_subchannel_call and the
618 associated machinery to create such a pointer.
619 Handles queueing of stream ops until a call object is ready, waiting
620 for initial metadata before trying to create a call object,
621 and handling cancellation gracefully. */
622typedef struct client_channel_call_data {
Mark D. Roth72f6da82016-09-02 13:42:38 -0700623 // State for handling deadlines.
624 // The code in deadline_filter.c requires this to be the first field.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700625 // TODO(roth): This is slightly sub-optimal in that grpc_deadline_state
626 // and this struct both independently store a pointer to the call
627 // stack and each has its own mutex. If/when we have time, find a way
Mark D. Roth6ad99172016-09-09 07:52:48 -0700628 // to avoid this without breaking the grpc_deadline_state abstraction.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700629 grpc_deadline_state deadline_state;
Mark D. Rothf28763c2016-09-14 15:18:40 -0700630
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800631 grpc_slice path; // Request path.
Mark D. Rothe40dd292016-10-05 14:58:37 -0700632 gpr_timespec call_start_time;
633 gpr_timespec deadline;
Mark D. Roth9d480942016-10-19 14:18:05 -0700634 wait_for_ready_value wait_for_ready_from_service_config;
Mark D. Rothe40dd292016-10-05 14:58:37 -0700635 grpc_closure read_service_config;
Mark D. Rothaa850a72016-09-26 13:38:02 -0700636
Mark D. Rothf28763c2016-09-14 15:18:40 -0700637 grpc_error *cancel_error;
Mark D. Roth72f6da82016-09-02 13:42:38 -0700638
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700639 /** either 0 for no call, 1 for cancelled, or a pointer to a
640 grpc_subchannel_call */
641 gpr_atm subchannel_call;
642
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700643 subchannel_creation_phase creation_phase;
644 grpc_connected_subchannel *connected_subchannel;
645 grpc_polling_entity *pollent;
646
Craig Tiller57726ca2016-09-12 11:59:45 -0700647 grpc_transport_stream_op **waiting_ops;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700648 size_t waiting_ops_count;
649 size_t waiting_ops_capacity;
650
651 grpc_closure next_step;
652
653 grpc_call_stack *owning_call;
David Garcia Quintasd1a47f12016-09-02 12:46:44 +0200654
655 grpc_linked_mdelem lb_token_mdelem;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700656} call_data;
657
Craig Tiller8b1d59c2016-12-27 15:15:30 -0800658grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
659 grpc_call_element *call_elem) {
660 grpc_subchannel_call *scc = GET_CALL((call_data *)call_elem->call_data);
661 return scc == CANCELLED_CALL ? NULL : scc;
662}
663
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700664static void add_waiting_locked(call_data *calld, grpc_transport_stream_op *op) {
665 GPR_TIMER_BEGIN("add_waiting_locked", 0);
666 if (calld->waiting_ops_count == calld->waiting_ops_capacity) {
667 calld->waiting_ops_capacity = GPR_MAX(3, 2 * calld->waiting_ops_capacity);
668 calld->waiting_ops =
669 gpr_realloc(calld->waiting_ops,
670 calld->waiting_ops_capacity * sizeof(*calld->waiting_ops));
671 }
Craig Tiller57726ca2016-09-12 11:59:45 -0700672 calld->waiting_ops[calld->waiting_ops_count++] = op;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700673 GPR_TIMER_END("add_waiting_locked", 0);
674}
675
676static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld,
677 grpc_error *error) {
678 size_t i;
679 for (i = 0; i < calld->waiting_ops_count; i++) {
680 grpc_transport_stream_op_finish_with_failure(
Craig Tiller57726ca2016-09-12 11:59:45 -0700681 exec_ctx, calld->waiting_ops[i], GRPC_ERROR_REF(error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700682 }
683 calld->waiting_ops_count = 0;
684 GRPC_ERROR_UNREF(error);
685}
686
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700687static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
Craig Tiller57726ca2016-09-12 11:59:45 -0700688 if (calld->waiting_ops_count == 0) {
689 return;
690 }
691
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800692 grpc_subchannel_call *call = GET_CALL(calld);
693 grpc_transport_stream_op **ops = calld->waiting_ops;
694 size_t nops = calld->waiting_ops_count;
695 if (call == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700696 fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED);
697 return;
698 }
699 calld->waiting_ops = NULL;
700 calld->waiting_ops_count = 0;
701 calld->waiting_ops_capacity = 0;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800702 for (size_t i = 0; i < nops; i++) {
703 grpc_subchannel_call_process_op(exec_ctx, call, ops[i]);
704 }
Craig Tiller9efea882017-02-09 13:06:52 -0800705 gpr_free(ops);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700706}
707
Craig Tillerbefafe62017-02-09 11:30:54 -0800708static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
709 grpc_error *error) {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700710 grpc_call_element *elem = arg;
711 call_data *calld = elem->call_data;
712 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700713 GPR_ASSERT(calld->creation_phase ==
714 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
Yuchen Zeng19656b12016-09-01 18:00:45 -0700715 grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
716 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700717 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
718 if (calld->connected_subchannel == NULL) {
719 gpr_atm_no_barrier_store(&calld->subchannel_call, 1);
720 fail_locked(exec_ctx, calld, GRPC_ERROR_CREATE_REFERENCING(
721 "Failed to create subchannel", &error, 1));
Mark D. Roth72f6da82016-09-02 13:42:38 -0700722 } else if (GET_CALL(calld) == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700723 /* already cancelled before subchannel became ready */
David Garcia Quintas68a9e382016-12-13 10:50:40 -0800724 grpc_error *cancellation_error = GRPC_ERROR_CREATE_REFERENCING(
725 "Cancelled before creating subchannel", &error, 1);
726 /* if due to deadline, attach the deadline exceeded status to the error */
727 if (gpr_time_cmp(calld->deadline, gpr_now(GPR_CLOCK_MONOTONIC)) < 0) {
728 cancellation_error =
729 grpc_error_set_int(cancellation_error, GRPC_ERROR_INT_GRPC_STATUS,
730 GRPC_STATUS_DEADLINE_EXCEEDED);
731 }
732 fail_locked(exec_ctx, calld, cancellation_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700733 } else {
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700734 /* Create call on subchannel. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700735 grpc_subchannel_call *subchannel_call = NULL;
736 grpc_error *new_error = grpc_connected_subchannel_create_call(
Mark D. Rothaa850a72016-09-26 13:38:02 -0700737 exec_ctx, calld->connected_subchannel, calld->pollent, calld->path,
Mark D. Roth3d883412016-11-07 13:42:54 -0800738 calld->call_start_time, calld->deadline, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700739 if (new_error != GRPC_ERROR_NONE) {
740 new_error = grpc_error_add_child(new_error, error);
741 subchannel_call = CANCELLED_CALL;
742 fail_locked(exec_ctx, calld, new_error);
743 }
744 gpr_atm_rel_store(&calld->subchannel_call,
745 (gpr_atm)(uintptr_t)subchannel_call);
746 retry_waiting_locked(exec_ctx, calld);
747 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700748 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
749}
750
751static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
752 call_data *calld = elem->call_data;
753 grpc_subchannel_call *subchannel_call = GET_CALL(calld);
754 if (subchannel_call == NULL || subchannel_call == CANCELLED_CALL) {
755 return NULL;
756 } else {
757 return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
758 }
759}
760
Craig Tiller577c9b22015-11-02 14:11:15 -0800761typedef struct {
762 grpc_metadata_batch *initial_metadata;
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800763 uint32_t initial_metadata_flags;
Craig Tillerb5585d42015-11-17 07:18:31 -0800764 grpc_connected_subchannel **connected_subchannel;
Craig Tiller577c9b22015-11-02 14:11:15 -0800765 grpc_closure *on_ready;
766 grpc_call_element *elem;
767 grpc_closure closure;
768} continue_picking_args;
769
Yuchen Zeng144ce652016-09-01 18:19:34 -0700770/** Return true if subchannel is available immediately (in which case on_ready
771 should not be called), or false otherwise (in which case on_ready should be
772 called when the subchannel is available). */
Craig Tillerbefafe62017-02-09 11:30:54 -0800773static bool pick_subchannel_locked(
774 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
775 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
776 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
777 grpc_error *error);
Craig Tiller577c9b22015-11-02 14:11:15 -0800778
Craig Tillerbefafe62017-02-09 11:30:54 -0800779static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg,
780 grpc_error *error) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800781 continue_picking_args *cpa = arg;
Craig Tiller0ede5452016-04-23 12:21:45 -0700782 if (cpa->connected_subchannel == NULL) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800783 /* cancelled, do nothing */
Craig Tiller804ff712016-05-05 16:25:40 -0700784 } else if (error != GRPC_ERROR_NONE) {
Craig Tiller91031da2016-12-28 15:44:25 -0800785 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error));
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700786 } else {
Craig Tillerbefafe62017-02-09 11:30:54 -0800787 if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata,
788 cpa->initial_metadata_flags,
789 cpa->connected_subchannel, cpa->on_ready,
790 GRPC_ERROR_NONE)) {
Craig Tiller91031da2016-12-28 15:44:25 -0800791 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700792 }
Craig Tiller577c9b22015-11-02 14:11:15 -0800793 }
794 gpr_free(cpa);
795}
796
Craig Tillerbefafe62017-02-09 11:30:54 -0800797static bool pick_subchannel_locked(
798 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
799 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
800 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
801 grpc_error *error) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700802 GPR_TIMER_BEGIN("pick_subchannel", 0);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700803
Craig Tiller577c9b22015-11-02 14:11:15 -0800804 channel_data *chand = elem->channel_data;
805 call_data *calld = elem->call_data;
806 continue_picking_args *cpa;
807 grpc_closure *closure;
808
Craig Tillerb5585d42015-11-17 07:18:31 -0800809 GPR_ASSERT(connected_subchannel);
Craig Tiller577c9b22015-11-02 14:11:15 -0800810
Craig Tiller577c9b22015-11-02 14:11:15 -0800811 if (initial_metadata == NULL) {
812 if (chand->lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800813 grpc_lb_policy_cancel_pick_locked(exec_ctx, chand->lb_policy,
814 connected_subchannel,
815 GRPC_ERROR_REF(error));
Craig Tiller577c9b22015-11-02 14:11:15 -0800816 }
817 for (closure = chand->waiting_for_config_closures.head; closure != NULL;
Craig Tiller804ff712016-05-05 16:25:40 -0700818 closure = closure->next_data.next) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800819 cpa = closure->cb_arg;
Craig Tillerb5585d42015-11-17 07:18:31 -0800820 if (cpa->connected_subchannel == connected_subchannel) {
821 cpa->connected_subchannel = NULL;
Craig Tiller91031da2016-12-28 15:44:25 -0800822 grpc_closure_sched(
Mark D. Roth932b10c2016-09-09 08:44:30 -0700823 exec_ctx, cpa->on_ready,
Craig Tiller91031da2016-12-28 15:44:25 -0800824 GRPC_ERROR_CREATE_REFERENCING("Pick cancelled", &error, 1));
Craig Tiller577c9b22015-11-02 14:11:15 -0800825 }
826 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700827 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth697a1f62016-09-07 13:35:07 -0700828 GRPC_ERROR_UNREF(error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700829 return true;
Craig Tiller577c9b22015-11-02 14:11:15 -0800830 }
Mark D. Roth697a1f62016-09-07 13:35:07 -0700831 GPR_ASSERT(error == GRPC_ERROR_NONE);
Craig Tiller577c9b22015-11-02 14:11:15 -0800832 if (chand->lb_policy != NULL) {
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800833 grpc_lb_policy *lb_policy = chand->lb_policy;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700834 GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel");
Mark D. Rothe40dd292016-10-05 14:58:37 -0700835 // If the application explicitly set wait_for_ready, use that.
836 // Otherwise, if the service config specified a value for this
837 // method, use that.
Mark D. Rothc1c38582016-10-11 11:03:27 -0700838 const bool wait_for_ready_set_from_api =
839 initial_metadata_flags &
840 GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
841 const bool wait_for_ready_set_from_service_config =
842 calld->wait_for_ready_from_service_config != WAIT_FOR_READY_UNSET;
843 if (!wait_for_ready_set_from_api &&
844 wait_for_ready_set_from_service_config) {
Mark D. Rothe40dd292016-10-05 14:58:37 -0700845 if (calld->wait_for_ready_from_service_config == WAIT_FOR_READY_TRUE) {
846 initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
847 } else {
848 initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
849 }
850 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700851 const grpc_lb_policy_pick_args inputs = {
Yuchen Zengac8bc422016-10-05 14:00:02 -0700852 initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem,
853 gpr_inf_future(GPR_CLOCK_MONOTONIC)};
Craig Tiller2400bf52017-02-09 16:25:19 -0800854 const bool result = grpc_lb_policy_pick_locked(
Mark D. Roth55f25b62016-10-12 14:55:20 -0700855 exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, on_ready);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700856 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel");
857 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700858 return result;
Craig Tiller577c9b22015-11-02 14:11:15 -0800859 }
860 if (chand->resolver != NULL && !chand->started_resolving) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700861 chand->started_resolving = true;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800862 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -0800863 grpc_resolver_next_locked(exec_ctx, chand->resolver,
864 &chand->resolver_result,
865 &chand->on_resolver_result_changed);
Craig Tiller577c9b22015-11-02 14:11:15 -0800866 }
Craig Tiller0eab6972016-04-23 12:59:57 -0700867 if (chand->resolver != NULL) {
868 cpa = gpr_malloc(sizeof(*cpa));
869 cpa->initial_metadata = initial_metadata;
870 cpa->initial_metadata_flags = initial_metadata_flags;
871 cpa->connected_subchannel = connected_subchannel;
872 cpa->on_ready = on_ready;
873 cpa->elem = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -0800874 grpc_closure_init(&cpa->closure, continue_picking_locked, cpa,
875 grpc_combiner_scheduler(chand->combiner, true));
Craig Tiller804ff712016-05-05 16:25:40 -0700876 grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
877 GRPC_ERROR_NONE);
Craig Tiller0eab6972016-04-23 12:59:57 -0700878 } else {
Craig Tiller91031da2016-12-28 15:44:25 -0800879 grpc_closure_sched(exec_ctx, on_ready, GRPC_ERROR_CREATE("Disconnected"));
Craig Tiller0eab6972016-04-23 12:59:57 -0700880 }
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700881
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700882 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700883 return false;
Craig Tiller577c9b22015-11-02 14:11:15 -0800884}
885
Craig Tillerbefafe62017-02-09 11:30:54 -0800886static void cc_start_transport_stream_op_locked(grpc_exec_ctx *exec_ctx,
887 void *arg,
888 grpc_error *error_ignored) {
889 grpc_transport_stream_op *op = arg;
890 grpc_call_element *elem = op->transport_private.args[0];
891 call_data *calld = elem->call_data;
892 channel_data *chand = elem->channel_data;
893 grpc_subchannel_call *call;
894
895retry:
896 /* need to recheck that another thread hasn't set the call */
897 call = GET_CALL(calld);
898 if (call == CANCELLED_CALL) {
899 grpc_transport_stream_op_finish_with_failure(
900 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
Craig Tiller2b56dcc2017-02-09 13:13:05 -0800901 goto done;
Craig Tillerbefafe62017-02-09 11:30:54 -0800902 }
903 if (call != NULL) {
904 grpc_subchannel_call_process_op(exec_ctx, call, op);
Craig Tiller2b56dcc2017-02-09 13:13:05 -0800905 goto done;
Craig Tillerbefafe62017-02-09 11:30:54 -0800906 }
907 /* if this is a cancellation, then we can raise our cancelled flag */
908 if (op->cancel_error != GRPC_ERROR_NONE) {
909 if (!gpr_atm_rel_cas(&calld->subchannel_call, 0,
910 (gpr_atm)(uintptr_t)CANCELLED_CALL)) {
911 goto retry;
912 } else {
913 // Stash a copy of cancel_error in our call data, so that we can use
914 // it for subsequent operations. This ensures that if the call is
915 // cancelled before any ops are passed down (e.g., if the deadline
916 // is in the past when the call starts), we can return the right
917 // error to the caller when the first op does get passed down.
918 calld->cancel_error = GRPC_ERROR_REF(op->cancel_error);
919 switch (calld->creation_phase) {
920 case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
921 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error));
922 break;
923 case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
924 pick_subchannel_locked(exec_ctx, elem, NULL, 0,
925 &calld->connected_subchannel, NULL,
926 GRPC_ERROR_REF(op->cancel_error));
927 break;
928 }
929 grpc_transport_stream_op_finish_with_failure(
930 exec_ctx, op, GRPC_ERROR_REF(op->cancel_error));
Craig Tiller2b56dcc2017-02-09 13:13:05 -0800931 goto done;
Craig Tillerbefafe62017-02-09 11:30:54 -0800932 }
933 }
934 /* if we don't have a subchannel, try to get one */
935 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
936 calld->connected_subchannel == NULL &&
937 op->send_initial_metadata != NULL) {
938 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
939 grpc_closure_init(&calld->next_step, subchannel_ready_locked, elem,
940 grpc_combiner_scheduler(chand->combiner, true));
941 GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
942 /* If a subchannel is not available immediately, the polling entity from
943 call_data should be provided to channel_data's interested_parties, so
944 that IO of the lb_policy and resolver could be done under it. */
945 if (pick_subchannel_locked(exec_ctx, elem, op->send_initial_metadata,
946 op->send_initial_metadata_flags,
947 &calld->connected_subchannel, &calld->next_step,
948 GRPC_ERROR_NONE)) {
949 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
950 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
951 } else {
952 grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
953 chand->interested_parties);
954 }
955 }
956 /* if we've got a subchannel, then let's ask it to create a call */
957 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
958 calld->connected_subchannel != NULL) {
959 grpc_subchannel_call *subchannel_call = NULL;
960 grpc_error *error = grpc_connected_subchannel_create_call(
961 exec_ctx, calld->connected_subchannel, calld->pollent, calld->path,
962 calld->call_start_time, calld->deadline, &subchannel_call);
963 if (error != GRPC_ERROR_NONE) {
964 subchannel_call = CANCELLED_CALL;
965 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
966 grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
967 }
968 gpr_atm_rel_store(&calld->subchannel_call,
969 (gpr_atm)(uintptr_t)subchannel_call);
970 retry_waiting_locked(exec_ctx, calld);
971 goto retry;
972 }
973 /* nothing to be done but wait */
974 add_waiting_locked(calld, op);
Craig Tiller2b56dcc2017-02-09 13:13:05 -0800975done:
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800976 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
977 "start_transport_stream_op");
Craig Tillerbefafe62017-02-09 11:30:54 -0800978 GPR_TIMER_END("cc_start_transport_stream_op", 0);
979}
980
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700981// The logic here is fairly complicated, due to (a) the fact that we
982// need to handle the case where we receive the send op before the
983// initial metadata op, and (b) the need for efficiency, especially in
984// the streaming case.
985// TODO(ctiller): Explain this more thoroughly.
986static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
987 grpc_call_element *elem,
988 grpc_transport_stream_op *op) {
989 call_data *calld = elem->call_data;
Yuchen Zeng19656b12016-09-01 18:00:45 -0700990 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700991 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
Mark D. Roth72f6da82016-09-02 13:42:38 -0700992 grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700993 /* try to (atomically) get the call */
994 grpc_subchannel_call *call = GET_CALL(calld);
995 GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
996 if (call == CANCELLED_CALL) {
Mark D. Rothf28763c2016-09-14 15:18:40 -0700997 grpc_transport_stream_op_finish_with_failure(
998 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700999 GPR_TIMER_END("cc_start_transport_stream_op", 0);
1000 return;
1001 }
1002 if (call != NULL) {
1003 grpc_subchannel_call_process_op(exec_ctx, call, op);
1004 GPR_TIMER_END("cc_start_transport_stream_op", 0);
1005 return;
1006 }
1007 /* we failed; lock and figure out what to do */
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001008 GRPC_CALL_STACK_REF(calld->owning_call, "start_transport_stream_op");
Craig Tillerbefafe62017-02-09 11:30:54 -08001009 op->transport_private.args[0] = elem;
1010 grpc_closure_sched(
1011 exec_ctx,
1012 grpc_closure_init(&op->transport_private.closure,
1013 cc_start_transport_stream_op_locked, op,
1014 grpc_combiner_scheduler(chand->combiner, false)),
1015 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001016}
1017
Mark D. Rothe40dd292016-10-05 14:58:37 -07001018// Gets data from the service config. Invoked when the resolver returns
1019// its initial result.
Craig Tillerbefafe62017-02-09 11:30:54 -08001020static void read_service_config_locked(grpc_exec_ctx *exec_ctx, void *arg,
1021 grpc_error *error) {
Mark D. Rothe40dd292016-10-05 14:58:37 -07001022 grpc_call_element *elem = arg;
1023 channel_data *chand = elem->channel_data;
1024 call_data *calld = elem->call_data;
1025 // If this is an error, there's no point in looking at the service config.
Mark D. Roth196387a2016-10-12 14:53:36 -07001026 if (error == GRPC_ERROR_NONE) {
1027 // Get the method config table from channel data.
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001028 grpc_slice_hash_table *method_params_table = NULL;
Mark D. Roth9d480942016-10-19 14:18:05 -07001029 if (chand->method_params_table != NULL) {
1030 method_params_table =
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001031 grpc_slice_hash_table_ref(chand->method_params_table);
Mark D. Rothe40dd292016-10-05 14:58:37 -07001032 }
Mark D. Roth196387a2016-10-12 14:53:36 -07001033 // If the method config table was present, use it.
Mark D. Roth9d480942016-10-19 14:18:05 -07001034 if (method_params_table != NULL) {
Craig Tiller87a7e1f2016-11-09 09:42:19 -08001035 const method_parameters *method_params = grpc_method_config_table_get(
1036 exec_ctx, method_params_table, calld->path);
Mark D. Roth9d480942016-10-19 14:18:05 -07001037 if (method_params != NULL) {
1038 const bool have_method_timeout =
1039 gpr_time_cmp(method_params->timeout, gpr_time_0(GPR_TIMESPAN)) != 0;
1040 if (have_method_timeout ||
1041 method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
Mark D. Roth9d480942016-10-19 14:18:05 -07001042 if (have_method_timeout) {
1043 const gpr_timespec per_method_deadline =
1044 gpr_time_add(calld->call_start_time, method_params->timeout);
Mark D. Roth196387a2016-10-12 14:53:36 -07001045 if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
1046 calld->deadline = per_method_deadline;
1047 // Reset deadline timer.
1048 grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
1049 }
1050 }
Mark D. Roth9d480942016-10-19 14:18:05 -07001051 if (method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
Mark D. Roth196387a2016-10-12 14:53:36 -07001052 calld->wait_for_ready_from_service_config =
Mark D. Roth9d480942016-10-19 14:18:05 -07001053 method_params->wait_for_ready;
Mark D. Roth196387a2016-10-12 14:53:36 -07001054 }
Mark D. Roth196387a2016-10-12 14:53:36 -07001055 }
1056 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001057 grpc_slice_hash_table_unref(exec_ctx, method_params_table);
Mark D. Roth196387a2016-10-12 14:53:36 -07001058 }
Mark D. Rothe40dd292016-10-05 14:58:37 -07001059 }
Mark D. Roth31292f22016-10-12 13:14:07 -07001060 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "read_service_config");
Mark D. Rothe40dd292016-10-05 14:58:37 -07001061}
1062
Craig Tillerbefafe62017-02-09 11:30:54 -08001063static void initial_read_service_config_locked(grpc_exec_ctx *exec_ctx,
1064 void *arg,
1065 grpc_error *error_ignored) {
1066 grpc_call_element *elem = arg;
1067 channel_data *chand = elem->channel_data;
1068 call_data *calld = elem->call_data;
1069 // If the resolver has already returned results, then we can access
1070 // the service config parameters immediately. Otherwise, we need to
1071 // defer that work until the resolver returns an initial result.
1072 // TODO(roth): This code is almost but not quite identical to the code
1073 // in read_service_config() above. It would be nice to find a way to
1074 // combine them, to avoid having to maintain it twice.
1075 if (chand->lb_policy != NULL) {
1076 // We already have a resolver result, so check for service config.
1077 if (chand->method_params_table != NULL) {
1078 grpc_slice_hash_table *method_params_table =
1079 grpc_slice_hash_table_ref(chand->method_params_table);
1080 method_parameters *method_params = grpc_method_config_table_get(
1081 exec_ctx, method_params_table, calld->path);
1082 if (method_params != NULL) {
1083 if (gpr_time_cmp(method_params->timeout,
1084 gpr_time_0(GPR_CLOCK_MONOTONIC)) != 0) {
1085 gpr_timespec per_method_deadline =
1086 gpr_time_add(calld->call_start_time, method_params->timeout);
1087 calld->deadline = gpr_time_min(calld->deadline, per_method_deadline);
1088 }
1089 if (method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
1090 calld->wait_for_ready_from_service_config =
1091 method_params->wait_for_ready;
1092 }
1093 }
1094 grpc_slice_hash_table_unref(exec_ctx, method_params_table);
1095 }
1096 } else {
1097 // We don't yet have a resolver result, so register a callback to
1098 // get the service config data once the resolver returns.
1099 // Take a reference to the call stack to be owned by the callback.
1100 GRPC_CALL_STACK_REF(calld->owning_call, "read_service_config");
1101 grpc_closure_init(&calld->read_service_config, read_service_config_locked,
1102 elem, grpc_combiner_scheduler(chand->combiner, false));
1103 grpc_closure_list_append(&chand->waiting_for_config_closures,
1104 &calld->read_service_config, GRPC_ERROR_NONE);
1105 }
1106 // Start the deadline timer with the current deadline value. If we
1107 // do not yet have service config data, then the timer may be reset
1108 // later.
1109 grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001110 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
1111 "initial_read_service_config");
Craig Tillerbefafe62017-02-09 11:30:54 -08001112}
1113
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001114/* Constructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001115static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
1116 grpc_call_element *elem,
1117 grpc_call_element_args *args) {
Mark D. Rothaa850a72016-09-26 13:38:02 -07001118 channel_data *chand = elem->channel_data;
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001119 call_data *calld = elem->call_data;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001120 // Initialize data members.
1121 grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001122 calld->path = grpc_slice_ref_internal(args->path);
Mark D. Rothff08f332016-10-14 13:01:01 -07001123 calld->call_start_time = args->start_time;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001124 calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
1125 calld->wait_for_ready_from_service_config = WAIT_FOR_READY_UNSET;
Mark D. Rothf28763c2016-09-14 15:18:40 -07001126 calld->cancel_error = GRPC_ERROR_NONE;
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001127 gpr_atm_rel_store(&calld->subchannel_call, 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001128 calld->connected_subchannel = NULL;
1129 calld->waiting_ops = NULL;
1130 calld->waiting_ops_count = 0;
1131 calld->waiting_ops_capacity = 0;
1132 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
1133 calld->owning_call = args->call_stack;
1134 calld->pollent = NULL;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001135 GRPC_CALL_STACK_REF(calld->owning_call, "initial_read_service_config");
Craig Tillerbefafe62017-02-09 11:30:54 -08001136 grpc_closure_sched(
1137 exec_ctx,
1138 grpc_closure_init(&calld->read_service_config,
1139 initial_read_service_config_locked, elem,
1140 grpc_combiner_scheduler(chand->combiner, false)),
1141 GRPC_ERROR_NONE);
Mark D. Roth0badbe82016-06-23 10:15:12 -07001142 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001143}
1144
1145/* Destructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001146static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
1147 grpc_call_element *elem,
1148 const grpc_call_final_info *final_info,
1149 void *and_free_memory) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001150 call_data *calld = elem->call_data;
Mark D. Rothf28763c2016-09-14 15:18:40 -07001151 grpc_deadline_state_destroy(exec_ctx, elem);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001152 grpc_slice_unref_internal(exec_ctx, calld->path);
Mark D. Rothf28763c2016-09-14 15:18:40 -07001153 GRPC_ERROR_UNREF(calld->cancel_error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001154 grpc_subchannel_call *call = GET_CALL(calld);
1155 if (call != NULL && call != CANCELLED_CALL) {
1156 GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
1157 }
1158 GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001159 GPR_ASSERT(calld->waiting_ops_count == 0);
Craig Tiller693d3942016-10-27 16:51:25 -07001160 if (calld->connected_subchannel != NULL) {
1161 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel,
1162 "picked");
1163 }
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001164 gpr_free(calld->waiting_ops);
Craig Tiller2c8063c2016-03-22 22:12:15 -07001165 gpr_free(and_free_memory);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001166}
1167
David Garcia Quintasf72eb972016-05-03 18:28:09 -07001168static void cc_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
1169 grpc_call_element *elem,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001170 grpc_polling_entity *pollent) {
Craig Tiller577c9b22015-11-02 14:11:15 -08001171 call_data *calld = elem->call_data;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001172 calld->pollent = pollent;
Craig Tiller577c9b22015-11-02 14:11:15 -08001173}
1174
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001175/*************************************************************************
1176 * EXPORTED SYMBOLS
1177 */
1178
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001179const grpc_channel_filter grpc_client_channel_filter = {
Craig Tillerf40df232016-03-25 13:38:14 -07001180 cc_start_transport_stream_op,
1181 cc_start_transport_op,
1182 sizeof(call_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001183 cc_init_call_elem,
David Garcia Quintas4afce7e2016-04-18 16:25:17 -07001184 cc_set_pollset_or_pollset_set,
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001185 cc_destroy_call_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001186 sizeof(channel_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001187 cc_init_channel_elem,
1188 cc_destroy_channel_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001189 cc_get_peer,
Mark D. Rothb2d24882016-10-27 15:44:07 -07001190 cc_get_channel_info,
Craig Tillerf40df232016-03-25 13:38:14 -07001191 "client-channel",
Craig Tiller87d5b192015-04-16 14:37:57 -07001192};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001193
Craig Tiller613dafa2017-02-09 12:00:43 -08001194static void try_to_connect_locked(grpc_exec_ctx *exec_ctx, void *arg,
1195 grpc_error *error_ignored) {
1196 channel_data *chand = arg;
1197 if (chand->lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -08001198 grpc_lb_policy_exit_idle_locked(exec_ctx, chand->lb_policy);
Craig Tiller613dafa2017-02-09 12:00:43 -08001199 } else {
1200 chand->exit_idle_when_lb_policy_arrives = true;
1201 if (!chand->started_resolving && chand->resolver != NULL) {
1202 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
1203 chand->started_resolving = true;
Craig Tiller972470b2017-02-09 15:05:36 -08001204 grpc_resolver_next_locked(exec_ctx, chand->resolver,
1205 &chand->resolver_result,
1206 &chand->on_resolver_result_changed);
Craig Tiller613dafa2017-02-09 12:00:43 -08001207 }
1208 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001209 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001210}
1211
Craig Tillera82950e2015-09-22 12:33:20 -07001212grpc_connectivity_state grpc_client_channel_check_connectivity_state(
1213 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001214 channel_data *chand = elem->channel_data;
1215 grpc_connectivity_state out;
Craig Tiller613dafa2017-02-09 12:00:43 -08001216 out = grpc_connectivity_state_check(&chand->state_tracker);
Craig Tillera82950e2015-09-22 12:33:20 -07001217 if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001218 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001219 grpc_closure_sched(
1220 exec_ctx,
1221 grpc_closure_create(try_to_connect_locked, chand,
1222 grpc_combiner_scheduler(chand->combiner, false)),
1223 GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -07001224 }
Craig Tiller48cb07c2015-07-15 16:16:15 -07001225 return out;
1226}
1227
Craig Tiller86c99582015-11-25 15:22:26 -08001228typedef struct {
1229 channel_data *chand;
1230 grpc_pollset *pollset;
1231 grpc_closure *on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001232 grpc_connectivity_state *state;
Craig Tiller86c99582015-11-25 15:22:26 -08001233 grpc_closure my_closure;
1234} external_connectivity_watcher;
1235
Craig Tiller1d881fb2015-12-01 07:39:04 -08001236static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -07001237 grpc_error *error) {
Craig Tiller86c99582015-11-25 15:22:26 -08001238 external_connectivity_watcher *w = arg;
1239 grpc_closure *follow_up = w->on_complete;
Craig Tiller69b093b2016-02-25 19:04:07 -08001240 grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
Craig Tiller1d881fb2015-12-01 07:39:04 -08001241 w->pollset);
1242 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
1243 "external_connectivity_watcher");
Craig Tiller86c99582015-11-25 15:22:26 -08001244 gpr_free(w);
Craig Tiller613dafa2017-02-09 12:00:43 -08001245 grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
1246}
1247
1248static void cc_watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
1249 void *arg,
1250 grpc_error *error_ignored) {
1251 external_connectivity_watcher *w = arg;
1252 grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
1253 grpc_schedule_on_exec_ctx);
1254 grpc_connectivity_state_notify_on_state_change(
1255 exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
Craig Tiller86c99582015-11-25 15:22:26 -08001256}
1257
Craig Tillera82950e2015-09-22 12:33:20 -07001258void grpc_client_channel_watch_connectivity_state(
Craig Tiller906e3bc2015-11-24 07:31:31 -08001259 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
Craig Tillera82950e2015-09-22 12:33:20 -07001260 grpc_connectivity_state *state, grpc_closure *on_complete) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001261 channel_data *chand = elem->channel_data;
Craig Tiller86c99582015-11-25 15:22:26 -08001262 external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
1263 w->chand = chand;
1264 w->pollset = pollset;
1265 w->on_complete = on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001266 w->state = state;
Craig Tiller69b093b2016-02-25 19:04:07 -08001267 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
Craig Tiller1d881fb2015-12-01 07:39:04 -08001268 GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
1269 "external_connectivity_watcher");
Craig Tiller613dafa2017-02-09 12:00:43 -08001270 grpc_closure_sched(
1271 exec_ctx,
1272 grpc_closure_init(&w->my_closure, cc_watch_connectivity_state_locked, w,
1273 grpc_combiner_scheduler(chand->combiner, true)),
1274 GRPC_ERROR_NONE);
Craig Tiller48cb07c2015-07-15 16:16:15 -07001275}