blob: d1ce186fec0551cc07dd08ac79a7f6d1c7c246ba [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 {
Craig Tiller7acc37e2017-02-28 10:01:37 -080074 /* zero so it can be default initialized */
75 WAIT_FOR_READY_UNSET = 0,
Mark D. Roth9d480942016-10-19 14:18:05 -070076 WAIT_FOR_READY_FALSE,
77 WAIT_FOR_READY_TRUE
78} wait_for_ready_value;
79
Mark D. Roth95b627b2017-02-24 11:02:58 -080080typedef struct {
81 gpr_refcount refs;
Mark D. Roth9d480942016-10-19 14:18:05 -070082 gpr_timespec timeout;
83 wait_for_ready_value wait_for_ready;
84} method_parameters;
85
Mark D. Roth722de8d2017-02-27 10:50:44 -080086static method_parameters *method_parameters_ref(
Mark D. Roth95b627b2017-02-24 11:02:58 -080087 method_parameters *method_params) {
88 gpr_ref(&method_params->refs);
89 return method_params;
Mark D. Roth9d480942016-10-19 14:18:05 -070090}
91
Mark D. Roth95b627b2017-02-24 11:02:58 -080092static void method_parameters_unref(method_parameters *method_params) {
93 if (gpr_unref(&method_params->refs)) {
94 gpr_free(method_params);
95 }
96}
97
98static void *method_parameters_copy(void *value) {
99 return method_parameters_ref(value);
100}
101
102static void method_parameters_free(grpc_exec_ctx *exec_ctx, void *value) {
103 method_parameters_unref(value);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800104}
105
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800106static const grpc_slice_hash_table_vtable method_parameters_vtable = {
Craig Tillerb28c7e82016-11-18 10:29:04 -0800107 method_parameters_free, method_parameters_copy};
Mark D. Roth9d480942016-10-19 14:18:05 -0700108
Mark D. Roth95b627b2017-02-24 11:02:58 -0800109static bool parse_wait_for_ready(grpc_json *field,
110 wait_for_ready_value *wait_for_ready) {
111 if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) {
112 return false;
113 }
114 *wait_for_ready = field->type == GRPC_JSON_TRUE ? WAIT_FOR_READY_TRUE
115 : WAIT_FOR_READY_FALSE;
116 return true;
117}
118
Mark D. Roth722de8d2017-02-27 10:50:44 -0800119static bool parse_timeout(grpc_json *field, gpr_timespec *timeout) {
Mark D. Roth95b627b2017-02-24 11:02:58 -0800120 if (field->type != GRPC_JSON_STRING) return false;
121 size_t len = strlen(field->value);
122 if (field->value[len - 1] != 's') return false;
123 char *buf = gpr_strdup(field->value);
124 buf[len - 1] = '\0'; // Remove trailing 's'.
125 char *decimal_point = strchr(buf, '.');
126 if (decimal_point != NULL) {
127 *decimal_point = '\0';
128 timeout->tv_nsec = gpr_parse_nonnegative_int(decimal_point + 1);
129 if (timeout->tv_nsec == -1) {
130 gpr_free(buf);
131 return false;
132 }
133 // There should always be exactly 3, 6, or 9 fractional digits.
134 int multiplier = 1;
135 switch (strlen(decimal_point + 1)) {
136 case 9:
137 break;
138 case 6:
139 multiplier *= 1000;
140 break;
141 case 3:
142 multiplier *= 1000000;
143 break;
144 default: // Unsupported number of digits.
145 gpr_free(buf);
146 return false;
147 }
148 timeout->tv_nsec *= multiplier;
149 }
150 timeout->tv_sec = gpr_parse_nonnegative_int(buf);
151 gpr_free(buf);
152 if (timeout->tv_sec == -1) return false;
153 return true;
154}
155
Mark D. Rothe30baeb2016-11-03 08:16:19 -0700156static void *method_parameters_create_from_json(const grpc_json *json) {
Mark D. Rothc968e602016-11-02 14:07:36 -0700157 wait_for_ready_value wait_for_ready = WAIT_FOR_READY_UNSET;
Mark D. Roth47f10842016-11-03 08:45:27 -0700158 gpr_timespec timeout = {0, 0, GPR_TIMESPAN};
159 for (grpc_json *field = json->child; field != NULL; field = field->next) {
Mark D. Rothc968e602016-11-02 14:07:36 -0700160 if (field->key == NULL) continue;
Mark D. Roth84c8a022016-11-10 09:39:34 -0800161 if (strcmp(field->key, "waitForReady") == 0) {
Mark D. Rothc968e602016-11-02 14:07:36 -0700162 if (wait_for_ready != WAIT_FOR_READY_UNSET) return NULL; // Duplicate.
Mark D. Roth95b627b2017-02-24 11:02:58 -0800163 if (!parse_wait_for_ready(field, &wait_for_ready)) return NULL;
Mark D. Rothc968e602016-11-02 14:07:36 -0700164 } else if (strcmp(field->key, "timeout") == 0) {
165 if (timeout.tv_sec > 0 || timeout.tv_nsec > 0) return NULL; // Duplicate.
Mark D. Roth95b627b2017-02-24 11:02:58 -0800166 if (!parse_timeout(field, &timeout)) return NULL;
Mark D. Rothc968e602016-11-02 14:07:36 -0700167 }
168 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700169 method_parameters *value = gpr_malloc(sizeof(method_parameters));
Mark D. Roth95b627b2017-02-24 11:02:58 -0800170 gpr_ref_init(&value->refs, 1);
Mark D. Rothc968e602016-11-02 14:07:36 -0700171 value->timeout = timeout;
172 value->wait_for_ready = wait_for_ready;
Mark D. Roth9d480942016-10-19 14:18:05 -0700173 return value;
174}
175
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700176/*************************************************************************
177 * CHANNEL-WIDE FUNCTIONS
178 */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800179
Craig Tiller800dacb2015-10-06 09:10:26 -0700180typedef struct client_channel_channel_data {
Craig Tillerf5f17122015-06-25 08:47:26 -0700181 /** resolver for this channel */
182 grpc_resolver *resolver;
Craig Tiller20a3c352015-08-05 08:39:50 -0700183 /** have we started resolving this channel */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700184 bool started_resolving;
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700185 /** client channel factory */
186 grpc_client_channel_factory *client_channel_factory;
Craig Tillerf5f17122015-06-25 08:47:26 -0700187
Craig Tillerbefafe62017-02-09 11:30:54 -0800188 /** combiner protecting all variables below in this data structure */
189 grpc_combiner *combiner;
Mark D. Roth046cf762016-09-26 11:13:51 -0700190 /** currently active load balancer */
Craig Tillerf5f17122015-06-25 08:47:26 -0700191 grpc_lb_policy *lb_policy;
Mark D. Roth9d480942016-10-19 14:18:05 -0700192 /** maps method names to method_parameters structs */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800193 grpc_slice_hash_table *method_params_table;
Mark D. Roth046cf762016-09-26 11:13:51 -0700194 /** incoming resolver result - set by resolver.next() */
Mark D. Rothaf842452016-10-21 15:05:15 -0700195 grpc_channel_args *resolver_result;
Craig Tiller3f475422015-06-25 10:43:05 -0700196 /** a list of closures that are all waiting for config to come in */
Craig Tillerd9ccbbf2015-09-22 09:30:00 -0700197 grpc_closure_list waiting_for_config_closures;
Craig Tiller3f475422015-06-25 10:43:05 -0700198 /** resolver callback */
Mark D. Rothff4df062016-08-22 15:02:49 -0700199 grpc_closure on_resolver_result_changed;
Craig Tiller3f475422015-06-25 10:43:05 -0700200 /** connectivity state being tracked */
Craig Tillerca3e9d32015-06-27 18:37:27 -0700201 grpc_connectivity_state_tracker state_tracker;
Craig Tiller48cb07c2015-07-15 16:16:15 -0700202 /** when an lb_policy arrives, should we try to exit idle */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700203 bool exit_idle_when_lb_policy_arrives;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800204 /** owning stack */
205 grpc_channel_stack *owning_stack;
Craig Tiller69b093b2016-02-25 19:04:07 -0800206 /** interested parties (owned) */
207 grpc_pollset_set *interested_parties;
Craig Tiller613dafa2017-02-09 12:00:43 -0800208
209 /* the following properties are guarded by a mutex since API's require them
Craig Tiller46dd7902017-02-23 09:42:16 -0800210 to be instantaneously available */
Craig Tiller613dafa2017-02-09 12:00:43 -0800211 gpr_mu info_mu;
212 char *info_lb_policy_name;
213 /** service config in JSON form */
214 char *info_service_config_json;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800215} channel_data;
216
Craig Tillerd6c98df2015-08-18 09:33:44 -0700217/** We create one watcher for each new lb_policy that is returned from a
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700218 resolver, to watch for state changes from the lb_policy. When a state
219 change is seen, we update the channel, and create a new watcher. */
Craig Tillera82950e2015-09-22 12:33:20 -0700220typedef struct {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700221 channel_data *chand;
Craig Tiller33825112015-09-18 07:44:19 -0700222 grpc_closure on_changed;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700223 grpc_connectivity_state state;
224 grpc_lb_policy *lb_policy;
225} lb_policy_connectivity_watcher;
226
Craig Tiller2400bf52017-02-09 16:25:19 -0800227static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
228 grpc_lb_policy *lb_policy,
229 grpc_connectivity_state current_state);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700230
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800231static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
232 channel_data *chand,
233 grpc_connectivity_state state,
Craig Tiller804ff712016-05-05 16:25:40 -0700234 grpc_error *error,
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800235 const char *reason) {
236 if ((state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
Craig Tiller48ed92e2016-06-02 11:07:12 -0700237 state == GRPC_CHANNEL_SHUTDOWN) &&
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800238 chand->lb_policy != NULL) {
Mark D. Roth59c9f902016-09-28 13:33:21 -0700239 /* cancel picks with wait_for_ready=false */
Craig Tiller2400bf52017-02-09 16:25:19 -0800240 grpc_lb_policy_cancel_picks_locked(
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800241 exec_ctx, chand->lb_policy,
Mark D. Roth59c9f902016-09-28 13:33:21 -0700242 /* mask= */ GRPC_INITIAL_METADATA_WAIT_FOR_READY,
Mark D. Roth58f52b72016-09-09 13:55:18 -0700243 /* check= */ 0, GRPC_ERROR_REF(error));
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800244 }
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700245 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, error,
246 reason);
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800247}
248
Craig Tiller804ff712016-05-05 16:25:40 -0700249static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
Craig Tillerbefafe62017-02-09 11:30:54 -0800250 void *arg, grpc_error *error) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700251 lb_policy_connectivity_watcher *w = arg;
Craig Tiller5d44c062015-07-01 08:55:28 -0700252 grpc_connectivity_state publish_state = w->state;
Craig Tillerc5de8352017-02-09 14:08:05 -0800253 /* check if the notification is for the latest policy */
254 if (w->lb_policy == w->chand->lb_policy) {
255 if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
256 publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Craig Tiller972470b2017-02-09 15:05:36 -0800257 grpc_resolver_channel_saw_error_locked(exec_ctx, w->chand->resolver);
Craig Tillerc5de8352017-02-09 14:08:05 -0800258 GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
259 w->chand->lb_policy = NULL;
260 }
261 set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
262 GRPC_ERROR_REF(error), "lb_changed");
263 if (w->state != GRPC_CHANNEL_SHUTDOWN) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800264 watch_lb_policy_locked(exec_ctx, w->chand, w->lb_policy, w->state);
Craig Tillerc5de8352017-02-09 14:08:05 -0800265 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800266 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700267
Craig Tiller906e3bc2015-11-24 07:31:31 -0800268 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
Craig Tillera82950e2015-09-22 12:33:20 -0700269 gpr_free(w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700270}
271
Craig Tiller2400bf52017-02-09 16:25:19 -0800272static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
273 grpc_lb_policy *lb_policy,
274 grpc_connectivity_state current_state) {
Craig Tillera82950e2015-09-22 12:33:20 -0700275 lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
Craig Tiller906e3bc2015-11-24 07:31:31 -0800276 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700277
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700278 w->chand = chand;
Craig Tillerbefafe62017-02-09 11:30:54 -0800279 grpc_closure_init(&w->on_changed, on_lb_policy_state_changed_locked, w,
280 grpc_combiner_scheduler(chand->combiner, false));
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700281 w->state = current_state;
282 w->lb_policy = lb_policy;
Craig Tiller2400bf52017-02-09 16:25:19 -0800283 grpc_lb_policy_notify_on_state_change_locked(exec_ctx, lb_policy, &w->state,
284 &w->on_changed);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700285}
286
Craig Tillerbefafe62017-02-09 11:30:54 -0800287static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
288 void *arg, grpc_error *error) {
Craig Tiller3f475422015-06-25 10:43:05 -0700289 channel_data *chand = arg;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700290 char *lb_policy_name = NULL;
Craig Tiller3f475422015-06-25 10:43:05 -0700291 grpc_lb_policy *lb_policy = NULL;
292 grpc_lb_policy *old_lb_policy;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800293 grpc_slice_hash_table *method_params_table = NULL;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700294 grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700295 bool exit_idle = false;
Craig Tiller804ff712016-05-05 16:25:40 -0700296 grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800297 char *service_config_json = NULL;
Craig Tiller3f475422015-06-25 10:43:05 -0700298
Mark D. Roth046cf762016-09-26 11:13:51 -0700299 if (chand->resolver_result != NULL) {
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700300 // Find LB policy name.
Mark D. Rothaf842452016-10-21 15:05:15 -0700301 const grpc_arg *channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700302 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_POLICY_NAME);
Mark D. Rothaf842452016-10-21 15:05:15 -0700303 if (channel_arg != NULL) {
304 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
305 lb_policy_name = channel_arg->value.string;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700306 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700307 // Special case: If all of the addresses are balancer addresses,
308 // assume that we should use the grpclb policy, regardless of what the
309 // resolver actually specified.
Mark D. Rothaf842452016-10-21 15:05:15 -0700310 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700311 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES);
Mark D. Rothaf842452016-10-21 15:05:15 -0700312 if (channel_arg != NULL) {
313 GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
Mark D. Roth557c9902016-10-24 11:12:05 -0700314 grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
Mark D. Rothaf842452016-10-21 15:05:15 -0700315 bool found_backend_address = false;
316 for (size_t i = 0; i < addresses->num_addresses; ++i) {
317 if (!addresses->addresses[i].is_balancer) {
318 found_backend_address = true;
319 break;
320 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700321 }
Mark D. Rothaf842452016-10-21 15:05:15 -0700322 if (!found_backend_address) {
323 if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) {
324 gpr_log(GPR_INFO,
325 "resolver requested LB policy %s but provided only balancer "
326 "addresses, no backend addresses -- forcing use of grpclb LB "
327 "policy",
Mark D. Roth5f40e5d2016-10-24 13:09:05 -0700328 lb_policy_name);
Mark D. Rothaf842452016-10-21 15:05:15 -0700329 }
330 lb_policy_name = "grpclb";
Mark D. Roth88405f72016-10-03 08:24:52 -0700331 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700332 }
333 // Use pick_first if nothing was specified and we didn't select grpclb
334 // above.
335 if (lb_policy_name == NULL) lb_policy_name = "pick_first";
Mark D. Roth41124992016-11-03 11:22:20 -0700336 // Instantiate LB policy.
337 grpc_lb_policy_args lb_policy_args;
338 lb_policy_args.args = chand->resolver_result;
339 lb_policy_args.client_channel_factory = chand->client_channel_factory;
Craig Tiller2400bf52017-02-09 16:25:19 -0800340 lb_policy_args.combiner = chand->combiner;
Mark D. Roth88405f72016-10-03 08:24:52 -0700341 lb_policy =
342 grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700343 if (lb_policy != NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -0700344 GRPC_LB_POLICY_REF(lb_policy, "config_change");
Craig Tillerf707d622016-05-06 14:26:12 -0700345 GRPC_ERROR_UNREF(state_error);
Craig Tiller2400bf52017-02-09 16:25:19 -0800346 state = grpc_lb_policy_check_connectivity_locked(exec_ctx, lb_policy,
347 &state_error);
Craig Tiller45724b32015-09-22 10:42:19 -0700348 }
Mark D. Roth41124992016-11-03 11:22:20 -0700349 // Find service config.
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_SERVICE_CONFIG);
Mark D. Roth046cf762016-09-26 11:13:51 -0700352 if (channel_arg != NULL) {
Mark D. Roth9ec28af2016-11-03 12:32:39 -0700353 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800354 service_config_json = gpr_strdup(channel_arg->value.string);
Mark D. Roth70a1abd2016-11-04 09:26:37 -0700355 grpc_service_config *service_config =
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800356 grpc_service_config_create(service_config_json);
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700357 if (service_config != NULL) {
358 method_params_table = grpc_service_config_create_method_config_table(
Craig Tillerb28c7e82016-11-18 10:29:04 -0800359 exec_ctx, service_config, method_parameters_create_from_json,
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700360 &method_parameters_vtable);
361 grpc_service_config_destroy(service_config);
362 }
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700363 }
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700364 // Before we clean up, save a copy of lb_policy_name, since it might
365 // be pointing to data inside chand->resolver_result.
366 // The copy will be saved in chand->lb_policy_name below.
367 lb_policy_name = gpr_strdup(lb_policy_name);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800368 grpc_channel_args_destroy(exec_ctx, chand->resolver_result);
Mark D. Roth046cf762016-09-26 11:13:51 -0700369 chand->resolver_result = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700370 }
371
Craig Tiller86c99582015-11-25 15:22:26 -0800372 if (lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800373 grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties,
374 chand->interested_parties);
Craig Tiller86c99582015-11-25 15:22:26 -0800375 }
376
Craig Tiller613dafa2017-02-09 12:00:43 -0800377 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700378 if (lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800379 gpr_free(chand->info_lb_policy_name);
380 chand->info_lb_policy_name = lb_policy_name;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700381 }
Craig Tiller3f475422015-06-25 10:43:05 -0700382 old_lb_policy = chand->lb_policy;
383 chand->lb_policy = lb_policy;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800384 if (service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800385 gpr_free(chand->info_service_config_json);
386 chand->info_service_config_json = service_config_json;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800387 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800388 gpr_mu_unlock(&chand->info_mu);
Mark D. Roth9d480942016-10-19 14:18:05 -0700389 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800390 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth046cf762016-09-26 11:13:51 -0700391 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700392 chand->method_params_table = method_params_table;
Craig Tiller0ede5452016-04-23 12:21:45 -0700393 if (lb_policy != NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -0800394 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller0ede5452016-04-23 12:21:45 -0700395 } else if (chand->resolver == NULL /* disconnected */) {
Craig Tiller804ff712016-05-05 16:25:40 -0700396 grpc_closure_list_fail_all(
397 &chand->waiting_for_config_closures,
398 GRPC_ERROR_CREATE_REFERENCING("Channel disconnected", &error, 1));
Craig Tiller91031da2016-12-28 15:44:25 -0800399 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tillera82950e2015-09-22 12:33:20 -0700400 }
401 if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
402 GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700403 exit_idle = true;
404 chand->exit_idle_when_lb_policy_arrives = false;
Craig Tillera82950e2015-09-22 12:33:20 -0700405 }
Craig Tiller98465032015-06-29 14:36:42 -0700406
Craig Tiller804ff712016-05-05 16:25:40 -0700407 if (error == GRPC_ERROR_NONE && chand->resolver) {
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700408 set_channel_connectivity_state_locked(
409 exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700410 if (lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800411 watch_lb_policy_locked(exec_ctx, chand, lb_policy, state);
Craig Tiller45724b32015-09-22 10:42:19 -0700412 }
Craig Tiller906e3bc2015-11-24 07:31:31 -0800413 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -0800414 grpc_resolver_next_locked(exec_ctx, chand->resolver,
415 &chand->resolver_result,
416 &chand->on_resolver_result_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700417 } else {
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800418 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800419 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800420 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
421 chand->resolver = NULL;
422 }
Craig Tiller804ff712016-05-05 16:25:40 -0700423 grpc_error *refs[] = {error, state_error};
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800424 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700425 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller804ff712016-05-05 16:25:40 -0700426 GRPC_ERROR_CREATE_REFERENCING("Got config after disconnection", refs,
427 GPR_ARRAY_SIZE(refs)),
428 "resolver_gone");
Craig Tillera82950e2015-09-22 12:33:20 -0700429 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700430
Craig Tillera82950e2015-09-22 12:33:20 -0700431 if (exit_idle) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800432 grpc_lb_policy_exit_idle_locked(exec_ctx, lb_policy);
Craig Tillera82950e2015-09-22 12:33:20 -0700433 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
434 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700435
Craig Tillera82950e2015-09-22 12:33:20 -0700436 if (old_lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800437 grpc_pollset_set_del_pollset_set(
438 exec_ctx, old_lb_policy->interested_parties, chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700439 GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
440 }
Craig Tiller000cd8f2015-09-18 07:20:29 -0700441
Craig Tillera82950e2015-09-22 12:33:20 -0700442 if (lb_policy != NULL) {
443 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
444 }
Craig Tiller45724b32015-09-22 10:42:19 -0700445
Craig Tiller906e3bc2015-11-24 07:31:31 -0800446 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700447 GRPC_ERROR_UNREF(state_error);
Craig Tiller3f475422015-06-25 10:43:05 -0700448}
449
Craig Tillera8610c02017-02-14 10:05:11 -0800450static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
451 grpc_error *error_ignored) {
Craig Tillerbefafe62017-02-09 11:30:54 -0800452 grpc_transport_op *op = arg;
453 grpc_channel_element *elem = op->transport_private.args[0];
Craig Tillerca3e9d32015-06-27 18:37:27 -0700454 channel_data *chand = elem->channel_data;
Craig Tiller000cd8f2015-09-18 07:20:29 -0700455
Craig Tillera82950e2015-09-22 12:33:20 -0700456 if (op->on_connectivity_state_change != NULL) {
457 grpc_connectivity_state_notify_on_state_change(
458 exec_ctx, &chand->state_tracker, op->connectivity_state,
459 op->on_connectivity_state_change);
460 op->on_connectivity_state_change = NULL;
461 op->connectivity_state = NULL;
462 }
463
Craig Tiller26dab312015-12-07 14:43:47 -0800464 if (op->send_ping != NULL) {
Craig Tiller87b71e22015-12-07 15:14:14 -0800465 if (chand->lb_policy == NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -0800466 grpc_closure_sched(exec_ctx, op->send_ping,
467 GRPC_ERROR_CREATE("Ping with no load balancing"));
Craig Tiller26dab312015-12-07 14:43:47 -0800468 } else {
Craig Tiller2400bf52017-02-09 16:25:19 -0800469 grpc_lb_policy_ping_one_locked(exec_ctx, chand->lb_policy, op->send_ping);
Craig Tiller26dab312015-12-07 14:43:47 -0800470 op->bind_pollset = NULL;
471 }
472 op->send_ping = NULL;
473 }
474
Craig Tiller1c51edc2016-05-07 16:18:43 -0700475 if (op->disconnect_with_error != GRPC_ERROR_NONE) {
476 if (chand->resolver != NULL) {
477 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700478 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller1c51edc2016-05-07 16:18:43 -0700479 GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
Craig Tiller972470b2017-02-09 15:05:36 -0800480 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700481 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
482 chand->resolver = NULL;
483 if (!chand->started_resolving) {
484 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
485 GRPC_ERROR_REF(op->disconnect_with_error));
Craig Tiller91031da2016-12-28 15:44:25 -0800486 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700487 }
488 if (chand->lb_policy != NULL) {
489 grpc_pollset_set_del_pollset_set(exec_ctx,
490 chand->lb_policy->interested_parties,
491 chand->interested_parties);
492 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
493 chand->lb_policy = NULL;
494 }
Craig Tillerb12d22a2016-04-23 12:50:21 -0700495 }
Craig Tiller1c51edc2016-05-07 16:18:43 -0700496 GRPC_ERROR_UNREF(op->disconnect_with_error);
Craig Tillera82950e2015-09-22 12:33:20 -0700497 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800498 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "start_transport_op");
499
500 grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
Craig Tillerbefafe62017-02-09 11:30:54 -0800501}
502
503static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
504 grpc_channel_element *elem,
505 grpc_transport_op *op) {
506 channel_data *chand = elem->channel_data;
507
Craig Tillerbefafe62017-02-09 11:30:54 -0800508 GPR_ASSERT(op->set_accept_stream == false);
509 if (op->bind_pollset != NULL) {
510 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
511 op->bind_pollset);
512 }
513
514 op->transport_private.args[0] = elem;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800515 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "start_transport_op");
Craig Tillerbefafe62017-02-09 11:30:54 -0800516 grpc_closure_sched(
Craig Tillera8610c02017-02-14 10:05:11 -0800517 exec_ctx, grpc_closure_init(
518 &op->transport_private.closure, start_transport_op_locked,
519 op, grpc_combiner_scheduler(chand->combiner, false)),
Craig Tillerbefafe62017-02-09 11:30:54 -0800520 GRPC_ERROR_NONE);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700521}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800522
Mark D. Rothb2d24882016-10-27 15:44:07 -0700523static void cc_get_channel_info(grpc_exec_ctx *exec_ctx,
524 grpc_channel_element *elem,
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700525 const grpc_channel_info *info) {
Mark D. Rothb2d24882016-10-27 15:44:07 -0700526 channel_data *chand = elem->channel_data;
Craig Tiller613dafa2017-02-09 12:00:43 -0800527 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700528 if (info->lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800529 *info->lb_policy_name = chand->info_lb_policy_name == NULL
Mark D. Roth78afd772016-11-04 12:49:49 -0700530 ? NULL
Craig Tiller613dafa2017-02-09 12:00:43 -0800531 : gpr_strdup(chand->info_lb_policy_name);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700532 }
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800533 if (info->service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800534 *info->service_config_json =
535 chand->info_service_config_json == NULL
536 ? NULL
537 : gpr_strdup(chand->info_service_config_json);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800538 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800539 gpr_mu_unlock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700540}
541
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700542/* Constructor for channel_data */
Mark D. Rothc1087882016-11-18 10:54:45 -0800543static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800544 grpc_channel_element *elem,
545 grpc_channel_element_args *args) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700546 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700547 GPR_ASSERT(args->is_last);
548 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800549 // Initialize data members.
Craig Tillerbefafe62017-02-09 11:30:54 -0800550 chand->combiner = grpc_combiner_create(NULL);
Craig Tillerd85477512017-02-09 12:02:39 -0800551 gpr_mu_init(&chand->info_mu);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800552 chand->owning_stack = args->channel_stack;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700553 grpc_closure_init(&chand->on_resolver_result_changed,
Craig Tillerbefafe62017-02-09 11:30:54 -0800554 on_resolver_result_changed_locked, chand,
555 grpc_combiner_scheduler(chand->combiner, false));
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800556 chand->interested_parties = grpc_pollset_set_create();
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700557 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
558 "client_channel");
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800559 // Record client channel factory.
560 const grpc_arg *arg = grpc_channel_args_find(args->channel_args,
561 GRPC_ARG_CLIENT_CHANNEL_FACTORY);
562 GPR_ASSERT(arg != NULL);
563 GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
564 grpc_client_channel_factory_ref(arg->value.pointer.p);
565 chand->client_channel_factory = arg->value.pointer.p;
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800566 // Get server name to resolve, using proxy mapper if needed.
Mark D. Roth86e90592016-11-18 09:56:40 -0800567 arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800568 GPR_ASSERT(arg != NULL);
569 GPR_ASSERT(arg->type == GRPC_ARG_STRING);
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800570 char *proxy_name = NULL;
571 grpc_channel_args *new_args = NULL;
572 grpc_proxy_mappers_map_name(exec_ctx, arg->value.string, args->channel_args,
573 &proxy_name, &new_args);
574 // Instantiate resolver.
Mark D. Roth45ccec52017-01-18 14:04:01 -0800575 chand->resolver = grpc_resolver_create(
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800576 exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string,
577 new_args != NULL ? new_args : args->channel_args,
Craig Tiller972470b2017-02-09 15:05:36 -0800578 chand->interested_parties, chand->combiner);
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800579 if (proxy_name != NULL) gpr_free(proxy_name);
580 if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args);
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800581 if (chand->resolver == NULL) {
582 return GRPC_ERROR_CREATE("resolver creation failed");
583 }
584 return GRPC_ERROR_NONE;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700585}
586
Craig Tiller972470b2017-02-09 15:05:36 -0800587static void shutdown_resolver_locked(grpc_exec_ctx *exec_ctx, void *arg,
588 grpc_error *error) {
589 grpc_resolver *resolver = arg;
590 grpc_resolver_shutdown_locked(exec_ctx, resolver);
591 GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel");
592}
593
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700594/* Destructor for channel_data */
595static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
596 grpc_channel_element *elem) {
597 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700598 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800599 grpc_closure_sched(
600 exec_ctx,
601 grpc_closure_create(shutdown_resolver_locked, chand->resolver,
602 grpc_combiner_scheduler(chand->combiner, false)),
603 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700604 }
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700605 if (chand->client_channel_factory != NULL) {
606 grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
607 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700608 if (chand->lb_policy != NULL) {
609 grpc_pollset_set_del_pollset_set(exec_ctx,
610 chand->lb_policy->interested_parties,
611 chand->interested_parties);
612 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
613 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800614 gpr_free(chand->info_lb_policy_name);
615 gpr_free(chand->info_service_config_json);
Mark D. Roth9d480942016-10-19 14:18:05 -0700616 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800617 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700618 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700619 grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
Craig Tiller9e5ac1b2017-02-14 22:25:50 -0800620 grpc_pollset_set_destroy(exec_ctx, chand->interested_parties);
Craig Tillerf1021672017-02-09 21:29:50 -0800621 GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel");
Craig Tillerd85477512017-02-09 12:02:39 -0800622 gpr_mu_destroy(&chand->info_mu);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700623}
624
625/*************************************************************************
626 * PER-CALL FUNCTIONS
627 */
628
629#define GET_CALL(call_data) \
630 ((grpc_subchannel_call *)(gpr_atm_acq_load(&(call_data)->subchannel_call)))
631
632#define CANCELLED_CALL ((grpc_subchannel_call *)1)
633
634typedef enum {
Craig Tiller7acc37e2017-02-28 10:01:37 -0800635 /* zero so that it can be default-initialized */
636 GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING = 0,
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700637 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL
638} subchannel_creation_phase;
639
640/** Call data. Holds a pointer to grpc_subchannel_call and the
641 associated machinery to create such a pointer.
642 Handles queueing of stream ops until a call object is ready, waiting
643 for initial metadata before trying to create a call object,
644 and handling cancellation gracefully. */
645typedef struct client_channel_call_data {
Mark D. Roth72f6da82016-09-02 13:42:38 -0700646 // State for handling deadlines.
647 // The code in deadline_filter.c requires this to be the first field.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700648 // TODO(roth): This is slightly sub-optimal in that grpc_deadline_state
649 // and this struct both independently store a pointer to the call
650 // stack and each has its own mutex. If/when we have time, find a way
Mark D. Roth6ad99172016-09-09 07:52:48 -0700651 // to avoid this without breaking the grpc_deadline_state abstraction.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700652 grpc_deadline_state deadline_state;
Mark D. Rothf28763c2016-09-14 15:18:40 -0700653
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800654 grpc_slice path; // Request path.
Mark D. Rothe40dd292016-10-05 14:58:37 -0700655 gpr_timespec call_start_time;
656 gpr_timespec deadline;
Mark D. Roth95b627b2017-02-24 11:02:58 -0800657 method_parameters *method_params;
Mark D. Rothaa850a72016-09-26 13:38:02 -0700658
Mark D. Rothf28763c2016-09-14 15:18:40 -0700659 grpc_error *cancel_error;
Mark D. Roth72f6da82016-09-02 13:42:38 -0700660
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700661 /** either 0 for no call, 1 for cancelled, or a pointer to a
662 grpc_subchannel_call */
663 gpr_atm subchannel_call;
664
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700665 subchannel_creation_phase creation_phase;
666 grpc_connected_subchannel *connected_subchannel;
667 grpc_polling_entity *pollent;
668
Craig Tiller57726ca2016-09-12 11:59:45 -0700669 grpc_transport_stream_op **waiting_ops;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700670 size_t waiting_ops_count;
671 size_t waiting_ops_capacity;
672
673 grpc_closure next_step;
674
675 grpc_call_stack *owning_call;
David Garcia Quintasd1a47f12016-09-02 12:46:44 +0200676
677 grpc_linked_mdelem lb_token_mdelem;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700678} call_data;
679
Craig Tiller8b1d59c2016-12-27 15:15:30 -0800680grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
681 grpc_call_element *call_elem) {
682 grpc_subchannel_call *scc = GET_CALL((call_data *)call_elem->call_data);
683 return scc == CANCELLED_CALL ? NULL : scc;
684}
685
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700686static void add_waiting_locked(call_data *calld, grpc_transport_stream_op *op) {
687 GPR_TIMER_BEGIN("add_waiting_locked", 0);
688 if (calld->waiting_ops_count == calld->waiting_ops_capacity) {
689 calld->waiting_ops_capacity = GPR_MAX(3, 2 * calld->waiting_ops_capacity);
690 calld->waiting_ops =
691 gpr_realloc(calld->waiting_ops,
692 calld->waiting_ops_capacity * sizeof(*calld->waiting_ops));
693 }
Craig Tiller57726ca2016-09-12 11:59:45 -0700694 calld->waiting_ops[calld->waiting_ops_count++] = op;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700695 GPR_TIMER_END("add_waiting_locked", 0);
696}
697
698static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld,
699 grpc_error *error) {
700 size_t i;
701 for (i = 0; i < calld->waiting_ops_count; i++) {
702 grpc_transport_stream_op_finish_with_failure(
Craig Tiller57726ca2016-09-12 11:59:45 -0700703 exec_ctx, calld->waiting_ops[i], GRPC_ERROR_REF(error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700704 }
705 calld->waiting_ops_count = 0;
706 GRPC_ERROR_UNREF(error);
707}
708
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700709static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
Craig Tiller57726ca2016-09-12 11:59:45 -0700710 if (calld->waiting_ops_count == 0) {
711 return;
712 }
713
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800714 grpc_subchannel_call *call = GET_CALL(calld);
715 grpc_transport_stream_op **ops = calld->waiting_ops;
716 size_t nops = calld->waiting_ops_count;
717 if (call == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700718 fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED);
719 return;
720 }
721 calld->waiting_ops = NULL;
722 calld->waiting_ops_count = 0;
723 calld->waiting_ops_capacity = 0;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800724 for (size_t i = 0; i < nops; i++) {
725 grpc_subchannel_call_process_op(exec_ctx, call, ops[i]);
726 }
Craig Tiller9efea882017-02-09 13:06:52 -0800727 gpr_free(ops);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700728}
729
Craig Tiller11c17d42017-03-13 13:36:34 -0700730// Sets calld->method_params.
731// If the method params specify a timeout, populates
732// *per_method_deadline and returns true.
733static bool set_call_method_params_from_service_config_locked(
734 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
735 gpr_timespec *per_method_deadline) {
736 channel_data *chand = elem->channel_data;
737 call_data *calld = elem->call_data;
738 if (chand->method_params_table != NULL) {
739 calld->method_params = grpc_method_config_table_get(
740 exec_ctx, chand->method_params_table, calld->path);
741 if (calld->method_params != NULL) {
742 method_parameters_ref(calld->method_params);
743 if (gpr_time_cmp(calld->method_params->timeout,
744 gpr_time_0(GPR_TIMESPAN)) != 0) {
745 *per_method_deadline =
746 gpr_time_add(calld->call_start_time, calld->method_params->timeout);
747 return true;
748 }
749 }
750 }
751 return false;
752}
Craig Tillerea4a4f12017-03-13 13:36:52 -0700753
Craig Tiller11c17d42017-03-13 13:36:34 -0700754static void apply_final_configuration_locked(grpc_exec_ctx *exec_ctx,
755 grpc_call_element *elem) {
756 /* apply service-config level configuration to the call (now that we're
757 * certain it exists) */
758 call_data *calld = elem->call_data;
759 gpr_timespec per_method_deadline;
760 if (set_call_method_params_from_service_config_locked(exec_ctx, elem,
761 &per_method_deadline)) {
762 // If the deadline from the service config is shorter than the one
763 // from the client API, reset the deadline timer.
764 if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
765 calld->deadline = per_method_deadline;
766 grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
767 }
768 }
769}
770
Craig Tillerbefafe62017-02-09 11:30:54 -0800771static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
772 grpc_error *error) {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700773 grpc_call_element *elem = arg;
774 call_data *calld = elem->call_data;
775 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700776 GPR_ASSERT(calld->creation_phase ==
777 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
Yuchen Zeng19656b12016-09-01 18:00:45 -0700778 grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
779 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700780 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
781 if (calld->connected_subchannel == NULL) {
782 gpr_atm_no_barrier_store(&calld->subchannel_call, 1);
783 fail_locked(exec_ctx, calld, GRPC_ERROR_CREATE_REFERENCING(
784 "Failed to create subchannel", &error, 1));
Mark D. Roth72f6da82016-09-02 13:42:38 -0700785 } else if (GET_CALL(calld) == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700786 /* already cancelled before subchannel became ready */
David Garcia Quintas68a9e382016-12-13 10:50:40 -0800787 grpc_error *cancellation_error = GRPC_ERROR_CREATE_REFERENCING(
788 "Cancelled before creating subchannel", &error, 1);
789 /* if due to deadline, attach the deadline exceeded status to the error */
790 if (gpr_time_cmp(calld->deadline, gpr_now(GPR_CLOCK_MONOTONIC)) < 0) {
791 cancellation_error =
792 grpc_error_set_int(cancellation_error, GRPC_ERROR_INT_GRPC_STATUS,
793 GRPC_STATUS_DEADLINE_EXCEEDED);
794 }
795 fail_locked(exec_ctx, calld, cancellation_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700796 } else {
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700797 /* Create call on subchannel. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700798 grpc_subchannel_call *subchannel_call = NULL;
Craig Tillera7ed2682017-02-28 13:26:37 -0800799 apply_final_configuration_locked(exec_ctx, elem);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700800 grpc_error *new_error = grpc_connected_subchannel_create_call(
Mark D. Rothaa850a72016-09-26 13:38:02 -0700801 exec_ctx, calld->connected_subchannel, calld->pollent, calld->path,
Mark D. Roth3d883412016-11-07 13:42:54 -0800802 calld->call_start_time, calld->deadline, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700803 if (new_error != GRPC_ERROR_NONE) {
804 new_error = grpc_error_add_child(new_error, error);
805 subchannel_call = CANCELLED_CALL;
806 fail_locked(exec_ctx, calld, new_error);
807 }
808 gpr_atm_rel_store(&calld->subchannel_call,
809 (gpr_atm)(uintptr_t)subchannel_call);
810 retry_waiting_locked(exec_ctx, calld);
811 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700812 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
813}
814
815static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
816 call_data *calld = elem->call_data;
817 grpc_subchannel_call *subchannel_call = GET_CALL(calld);
818 if (subchannel_call == NULL || subchannel_call == CANCELLED_CALL) {
819 return NULL;
820 } else {
821 return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
822 }
823}
824
Craig Tiller577c9b22015-11-02 14:11:15 -0800825typedef struct {
826 grpc_metadata_batch *initial_metadata;
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800827 uint32_t initial_metadata_flags;
Craig Tillerb5585d42015-11-17 07:18:31 -0800828 grpc_connected_subchannel **connected_subchannel;
Craig Tiller577c9b22015-11-02 14:11:15 -0800829 grpc_closure *on_ready;
830 grpc_call_element *elem;
831 grpc_closure closure;
832} continue_picking_args;
833
Yuchen Zeng144ce652016-09-01 18:19:34 -0700834/** Return true if subchannel is available immediately (in which case on_ready
835 should not be called), or false otherwise (in which case on_ready should be
836 called when the subchannel is available). */
Craig Tillerbefafe62017-02-09 11:30:54 -0800837static bool pick_subchannel_locked(
838 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
839 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
840 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
841 grpc_error *error);
Craig Tiller577c9b22015-11-02 14:11:15 -0800842
Craig Tillerbefafe62017-02-09 11:30:54 -0800843static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg,
844 grpc_error *error) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800845 continue_picking_args *cpa = arg;
Craig Tiller0ede5452016-04-23 12:21:45 -0700846 if (cpa->connected_subchannel == NULL) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800847 /* cancelled, do nothing */
Craig Tiller804ff712016-05-05 16:25:40 -0700848 } else if (error != GRPC_ERROR_NONE) {
Craig Tiller91031da2016-12-28 15:44:25 -0800849 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error));
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700850 } else {
Craig Tillerbefafe62017-02-09 11:30:54 -0800851 if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata,
852 cpa->initial_metadata_flags,
853 cpa->connected_subchannel, cpa->on_ready,
854 GRPC_ERROR_NONE)) {
Craig Tiller91031da2016-12-28 15:44:25 -0800855 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700856 }
Craig Tiller577c9b22015-11-02 14:11:15 -0800857 }
858 gpr_free(cpa);
859}
860
Craig Tillerbefafe62017-02-09 11:30:54 -0800861static bool pick_subchannel_locked(
862 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
863 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
864 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
865 grpc_error *error) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700866 GPR_TIMER_BEGIN("pick_subchannel", 0);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700867
Craig Tiller577c9b22015-11-02 14:11:15 -0800868 channel_data *chand = elem->channel_data;
869 call_data *calld = elem->call_data;
870 continue_picking_args *cpa;
871 grpc_closure *closure;
872
Craig Tillerb5585d42015-11-17 07:18:31 -0800873 GPR_ASSERT(connected_subchannel);
Craig Tiller577c9b22015-11-02 14:11:15 -0800874
Craig Tiller577c9b22015-11-02 14:11:15 -0800875 if (initial_metadata == NULL) {
876 if (chand->lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800877 grpc_lb_policy_cancel_pick_locked(exec_ctx, chand->lb_policy,
878 connected_subchannel,
879 GRPC_ERROR_REF(error));
Craig Tiller577c9b22015-11-02 14:11:15 -0800880 }
881 for (closure = chand->waiting_for_config_closures.head; closure != NULL;
Craig Tiller804ff712016-05-05 16:25:40 -0700882 closure = closure->next_data.next) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800883 cpa = closure->cb_arg;
Craig Tillerb5585d42015-11-17 07:18:31 -0800884 if (cpa->connected_subchannel == connected_subchannel) {
885 cpa->connected_subchannel = NULL;
Craig Tiller91031da2016-12-28 15:44:25 -0800886 grpc_closure_sched(
Mark D. Roth932b10c2016-09-09 08:44:30 -0700887 exec_ctx, cpa->on_ready,
Craig Tiller91031da2016-12-28 15:44:25 -0800888 GRPC_ERROR_CREATE_REFERENCING("Pick cancelled", &error, 1));
Craig Tiller577c9b22015-11-02 14:11:15 -0800889 }
890 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700891 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth697a1f62016-09-07 13:35:07 -0700892 GRPC_ERROR_UNREF(error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700893 return true;
Craig Tiller577c9b22015-11-02 14:11:15 -0800894 }
Mark D. Roth697a1f62016-09-07 13:35:07 -0700895 GPR_ASSERT(error == GRPC_ERROR_NONE);
Craig Tiller577c9b22015-11-02 14:11:15 -0800896 if (chand->lb_policy != NULL) {
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800897 grpc_lb_policy *lb_policy = chand->lb_policy;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700898 GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel");
Mark D. Rothe40dd292016-10-05 14:58:37 -0700899 // If the application explicitly set wait_for_ready, use that.
900 // Otherwise, if the service config specified a value for this
901 // method, use that.
Mark D. Rothc1c38582016-10-11 11:03:27 -0700902 const bool wait_for_ready_set_from_api =
903 initial_metadata_flags &
904 GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
905 const bool wait_for_ready_set_from_service_config =
Mark D. Roth95b627b2017-02-24 11:02:58 -0800906 calld->method_params != NULL &&
907 calld->method_params->wait_for_ready != WAIT_FOR_READY_UNSET;
Mark D. Rothc1c38582016-10-11 11:03:27 -0700908 if (!wait_for_ready_set_from_api &&
909 wait_for_ready_set_from_service_config) {
Mark D. Roth95b627b2017-02-24 11:02:58 -0800910 if (calld->method_params->wait_for_ready == WAIT_FOR_READY_TRUE) {
Mark D. Rothe40dd292016-10-05 14:58:37 -0700911 initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
912 } else {
913 initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
914 }
915 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700916 const grpc_lb_policy_pick_args inputs = {
Yuchen Zengac8bc422016-10-05 14:00:02 -0700917 initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem,
918 gpr_inf_future(GPR_CLOCK_MONOTONIC)};
Craig Tiller2400bf52017-02-09 16:25:19 -0800919 const bool result = grpc_lb_policy_pick_locked(
Mark D. Roth55f25b62016-10-12 14:55:20 -0700920 exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, on_ready);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700921 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel");
922 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700923 return result;
Craig Tiller577c9b22015-11-02 14:11:15 -0800924 }
925 if (chand->resolver != NULL && !chand->started_resolving) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700926 chand->started_resolving = true;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800927 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -0800928 grpc_resolver_next_locked(exec_ctx, chand->resolver,
929 &chand->resolver_result,
930 &chand->on_resolver_result_changed);
Craig Tiller577c9b22015-11-02 14:11:15 -0800931 }
Craig Tiller0eab6972016-04-23 12:59:57 -0700932 if (chand->resolver != NULL) {
933 cpa = gpr_malloc(sizeof(*cpa));
934 cpa->initial_metadata = initial_metadata;
935 cpa->initial_metadata_flags = initial_metadata_flags;
936 cpa->connected_subchannel = connected_subchannel;
937 cpa->on_ready = on_ready;
938 cpa->elem = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -0800939 grpc_closure_init(&cpa->closure, continue_picking_locked, cpa,
940 grpc_combiner_scheduler(chand->combiner, true));
Craig Tiller804ff712016-05-05 16:25:40 -0700941 grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
942 GRPC_ERROR_NONE);
Craig Tiller0eab6972016-04-23 12:59:57 -0700943 } else {
Craig Tiller91031da2016-12-28 15:44:25 -0800944 grpc_closure_sched(exec_ctx, on_ready, GRPC_ERROR_CREATE("Disconnected"));
Craig Tiller0eab6972016-04-23 12:59:57 -0700945 }
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700946
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700947 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700948 return false;
Craig Tiller577c9b22015-11-02 14:11:15 -0800949}
950
Craig Tillera8610c02017-02-14 10:05:11 -0800951static void start_transport_stream_op_locked_inner(grpc_exec_ctx *exec_ctx,
952 grpc_transport_stream_op *op,
953 grpc_call_element *elem) {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700954 channel_data *chand = elem->channel_data;
Craig Tillera11bfc82017-02-14 09:56:33 -0800955 call_data *calld = elem->call_data;
Craig Tillerbefafe62017-02-09 11:30:54 -0800956 grpc_subchannel_call *call;
957
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700958 /* need to recheck that another thread hasn't set the call */
959 call = GET_CALL(calld);
960 if (call == CANCELLED_CALL) {
Mark D. Rothf28763c2016-09-14 15:18:40 -0700961 grpc_transport_stream_op_finish_with_failure(
962 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -0800963 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700964 return;
965 }
966 if (call != NULL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700967 grpc_subchannel_call_process_op(exec_ctx, call, op);
Craig Tillera11bfc82017-02-14 09:56:33 -0800968 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700969 return;
970 }
971 /* if this is a cancellation, then we can raise our cancelled flag */
972 if (op->cancel_error != GRPC_ERROR_NONE) {
973 if (!gpr_atm_rel_cas(&calld->subchannel_call, 0,
974 (gpr_atm)(uintptr_t)CANCELLED_CALL)) {
Craig Tillera11bfc82017-02-14 09:56:33 -0800975 /* recurse to retry */
Craig Tillera8610c02017-02-14 10:05:11 -0800976 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -0800977 /* early out */
978 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700979 } else {
Craig Tillerbe9691a2017-02-14 10:00:42 -0800980 /* Stash a copy of cancel_error in our call data, so that we can use
981 it for subsequent operations. This ensures that if the call is
982 cancelled before any ops are passed down (e.g., if the deadline
983 is in the past when the call starts), we can return the right
984 error to the caller when the first op does get passed down. */
Mark D. Rothf28763c2016-09-14 15:18:40 -0700985 calld->cancel_error = GRPC_ERROR_REF(op->cancel_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700986 switch (calld->creation_phase) {
987 case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
988 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error));
989 break;
990 case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
Craig Tillerbefafe62017-02-09 11:30:54 -0800991 pick_subchannel_locked(exec_ctx, elem, NULL, 0,
992 &calld->connected_subchannel, NULL,
993 GRPC_ERROR_REF(op->cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700994 break;
995 }
Mark D. Roth72f6da82016-09-02 13:42:38 -0700996 grpc_transport_stream_op_finish_with_failure(
997 exec_ctx, op, GRPC_ERROR_REF(op->cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -0800998 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700999 return;
1000 }
1001 }
1002 /* if we don't have a subchannel, try to get one */
1003 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
1004 calld->connected_subchannel == NULL &&
1005 op->send_initial_metadata != NULL) {
1006 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
Craig Tillerbefafe62017-02-09 11:30:54 -08001007 grpc_closure_init(&calld->next_step, subchannel_ready_locked, elem,
1008 grpc_combiner_scheduler(chand->combiner, true));
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001009 GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
Yuchen Zeng144ce652016-09-01 18:19:34 -07001010 /* If a subchannel is not available immediately, the polling entity from
1011 call_data should be provided to channel_data's interested_parties, so
1012 that IO of the lb_policy and resolver could be done under it. */
Craig Tillerbefafe62017-02-09 11:30:54 -08001013 if (pick_subchannel_locked(exec_ctx, elem, op->send_initial_metadata,
1014 op->send_initial_metadata_flags,
1015 &calld->connected_subchannel, &calld->next_step,
1016 GRPC_ERROR_NONE)) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001017 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
1018 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
Yuchen Zeng19656b12016-09-01 18:00:45 -07001019 } else {
Yuchen Zeng19656b12016-09-01 18:00:45 -07001020 grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
1021 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001022 }
1023 }
1024 /* if we've got a subchannel, then let's ask it to create a call */
1025 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
1026 calld->connected_subchannel != NULL) {
1027 grpc_subchannel_call *subchannel_call = NULL;
Craig Tillera7ed2682017-02-28 13:26:37 -08001028 apply_final_configuration_locked(exec_ctx, elem);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001029 grpc_error *error = grpc_connected_subchannel_create_call(
Mark D. Rothaa850a72016-09-26 13:38:02 -07001030 exec_ctx, calld->connected_subchannel, calld->pollent, calld->path,
Mark D. Roth3d883412016-11-07 13:42:54 -08001031 calld->call_start_time, calld->deadline, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001032 if (error != GRPC_ERROR_NONE) {
1033 subchannel_call = CANCELLED_CALL;
1034 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
1035 grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
1036 }
1037 gpr_atm_rel_store(&calld->subchannel_call,
1038 (gpr_atm)(uintptr_t)subchannel_call);
1039 retry_waiting_locked(exec_ctx, calld);
Craig Tillera11bfc82017-02-14 09:56:33 -08001040 /* recurse to retry */
Craig Tillera8610c02017-02-14 10:05:11 -08001041 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001042 /* early out */
1043 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001044 }
1045 /* nothing to be done but wait */
1046 add_waiting_locked(calld, op);
Craig Tillera11bfc82017-02-14 09:56:33 -08001047}
1048
Mark D. Roth95b627b2017-02-24 11:02:58 -08001049static void start_transport_stream_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
Mark D. Roth722de8d2017-02-27 10:50:44 -08001050 grpc_error *error_ignored) {
Mark D. Roth95b627b2017-02-24 11:02:58 -08001051 GPR_TIMER_BEGIN("start_transport_stream_op_locked", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001052
1053 grpc_transport_stream_op *op = arg;
1054 grpc_call_element *elem = op->handler_private.args[0];
1055 call_data *calld = elem->call_data;
1056
Craig Tillera8610c02017-02-14 10:05:11 -08001057 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001058
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001059 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
1060 "start_transport_stream_op");
Mark D. Roth95b627b2017-02-24 11:02:58 -08001061 GPR_TIMER_END("start_transport_stream_op_locked", 0);
Craig Tillerbefafe62017-02-09 11:30:54 -08001062}
1063
Craig Tillerbe9691a2017-02-14 10:00:42 -08001064/* The logic here is fairly complicated, due to (a) the fact that we
1065 need to handle the case where we receive the send op before the
1066 initial metadata op, and (b) the need for efficiency, especially in
1067 the streaming case.
1068
1069 We use double-checked locking to initially see if initialization has been
1070 performed. If it has not, we acquire the combiner and perform initialization.
1071 If it has, we proceed on the fast path. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001072static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
1073 grpc_call_element *elem,
1074 grpc_transport_stream_op *op) {
1075 call_data *calld = elem->call_data;
1076 channel_data *chand = elem->channel_data;
1077 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
1078 grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op);
1079 /* try to (atomically) get the call */
1080 grpc_subchannel_call *call = GET_CALL(calld);
1081 GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
1082 if (call == CANCELLED_CALL) {
1083 grpc_transport_stream_op_finish_with_failure(
1084 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
1085 GPR_TIMER_END("cc_start_transport_stream_op", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001086 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001087 return;
1088 }
1089 if (call != NULL) {
1090 grpc_subchannel_call_process_op(exec_ctx, call, op);
1091 GPR_TIMER_END("cc_start_transport_stream_op", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001092 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001093 return;
1094 }
1095 /* we failed; lock and figure out what to do */
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001096 GRPC_CALL_STACK_REF(calld->owning_call, "start_transport_stream_op");
Craig Tiller4a84bdd2017-02-14 09:48:41 -08001097 op->handler_private.args[0] = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -08001098 grpc_closure_sched(
1099 exec_ctx,
Craig Tiller4a84bdd2017-02-14 09:48:41 -08001100 grpc_closure_init(&op->handler_private.closure,
Mark D. Roth95b627b2017-02-24 11:02:58 -08001101 start_transport_stream_op_locked, op,
Craig Tillerbefafe62017-02-09 11:30:54 -08001102 grpc_combiner_scheduler(chand->combiner, false)),
1103 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001104 GPR_TIMER_END("cc_start_transport_stream_op", 0);
1105}
1106
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001107/* Constructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001108static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
1109 grpc_call_element *elem,
Craig Tillerc52ba3a2017-02-15 22:57:43 -08001110 const grpc_call_element_args *args) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001111 call_data *calld = elem->call_data;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001112 // Initialize data members.
1113 grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001114 calld->path = grpc_slice_ref_internal(args->path);
Mark D. Rothff08f332016-10-14 13:01:01 -07001115 calld->call_start_time = args->start_time;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001116 calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001117 calld->owning_call = args->call_stack;
Craig Tiller2c3d0a92017-02-28 15:26:24 -08001118 grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
Mark D. Roth0badbe82016-06-23 10:15:12 -07001119 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001120}
1121
1122/* Destructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001123static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
1124 grpc_call_element *elem,
1125 const grpc_call_final_info *final_info,
1126 void *and_free_memory) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001127 call_data *calld = elem->call_data;
Mark D. Rothf28763c2016-09-14 15:18:40 -07001128 grpc_deadline_state_destroy(exec_ctx, elem);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001129 grpc_slice_unref_internal(exec_ctx, calld->path);
Mark D. Roth95b627b2017-02-24 11:02:58 -08001130 if (calld->method_params != NULL) {
1131 method_parameters_unref(calld->method_params);
1132 }
Mark D. Rothf28763c2016-09-14 15:18:40 -07001133 GRPC_ERROR_UNREF(calld->cancel_error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001134 grpc_subchannel_call *call = GET_CALL(calld);
1135 if (call != NULL && call != CANCELLED_CALL) {
1136 GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
1137 }
1138 GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001139 GPR_ASSERT(calld->waiting_ops_count == 0);
Craig Tiller693d3942016-10-27 16:51:25 -07001140 if (calld->connected_subchannel != NULL) {
1141 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel,
1142 "picked");
1143 }
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001144 gpr_free(calld->waiting_ops);
Craig Tiller2c8063c2016-03-22 22:12:15 -07001145 gpr_free(and_free_memory);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001146}
1147
David Garcia Quintasf72eb972016-05-03 18:28:09 -07001148static void cc_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
1149 grpc_call_element *elem,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001150 grpc_polling_entity *pollent) {
Craig Tiller577c9b22015-11-02 14:11:15 -08001151 call_data *calld = elem->call_data;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001152 calld->pollent = pollent;
Craig Tiller577c9b22015-11-02 14:11:15 -08001153}
1154
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001155/*************************************************************************
1156 * EXPORTED SYMBOLS
1157 */
1158
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001159const grpc_channel_filter grpc_client_channel_filter = {
Craig Tillerf40df232016-03-25 13:38:14 -07001160 cc_start_transport_stream_op,
1161 cc_start_transport_op,
1162 sizeof(call_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001163 cc_init_call_elem,
David Garcia Quintas4afce7e2016-04-18 16:25:17 -07001164 cc_set_pollset_or_pollset_set,
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001165 cc_destroy_call_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001166 sizeof(channel_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001167 cc_init_channel_elem,
1168 cc_destroy_channel_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001169 cc_get_peer,
Mark D. Rothb2d24882016-10-27 15:44:07 -07001170 cc_get_channel_info,
Craig Tillerf40df232016-03-25 13:38:14 -07001171 "client-channel",
Craig Tiller87d5b192015-04-16 14:37:57 -07001172};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001173
Craig Tiller613dafa2017-02-09 12:00:43 -08001174static void try_to_connect_locked(grpc_exec_ctx *exec_ctx, void *arg,
1175 grpc_error *error_ignored) {
1176 channel_data *chand = arg;
1177 if (chand->lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -08001178 grpc_lb_policy_exit_idle_locked(exec_ctx, chand->lb_policy);
Craig Tiller613dafa2017-02-09 12:00:43 -08001179 } else {
1180 chand->exit_idle_when_lb_policy_arrives = true;
1181 if (!chand->started_resolving && chand->resolver != NULL) {
1182 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
1183 chand->started_resolving = true;
Craig Tiller972470b2017-02-09 15:05:36 -08001184 grpc_resolver_next_locked(exec_ctx, chand->resolver,
1185 &chand->resolver_result,
1186 &chand->on_resolver_result_changed);
Craig Tiller613dafa2017-02-09 12:00:43 -08001187 }
1188 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001189 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001190}
1191
Craig Tillera82950e2015-09-22 12:33:20 -07001192grpc_connectivity_state grpc_client_channel_check_connectivity_state(
1193 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001194 channel_data *chand = elem->channel_data;
Craig Tillera8610c02017-02-14 10:05:11 -08001195 grpc_connectivity_state out =
1196 grpc_connectivity_state_check(&chand->state_tracker);
Craig Tillera82950e2015-09-22 12:33:20 -07001197 if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001198 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001199 grpc_closure_sched(
1200 exec_ctx,
1201 grpc_closure_create(try_to_connect_locked, chand,
1202 grpc_combiner_scheduler(chand->combiner, false)),
1203 GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -07001204 }
Craig Tiller48cb07c2015-07-15 16:16:15 -07001205 return out;
1206}
1207
Craig Tiller86c99582015-11-25 15:22:26 -08001208typedef struct {
1209 channel_data *chand;
1210 grpc_pollset *pollset;
1211 grpc_closure *on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001212 grpc_connectivity_state *state;
Craig Tiller86c99582015-11-25 15:22:26 -08001213 grpc_closure my_closure;
1214} external_connectivity_watcher;
1215
Craig Tiller1d881fb2015-12-01 07:39:04 -08001216static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -07001217 grpc_error *error) {
Craig Tiller86c99582015-11-25 15:22:26 -08001218 external_connectivity_watcher *w = arg;
1219 grpc_closure *follow_up = w->on_complete;
Craig Tiller69b093b2016-02-25 19:04:07 -08001220 grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
Craig Tiller1d881fb2015-12-01 07:39:04 -08001221 w->pollset);
1222 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
1223 "external_connectivity_watcher");
Craig Tiller86c99582015-11-25 15:22:26 -08001224 gpr_free(w);
Craig Tiller613dafa2017-02-09 12:00:43 -08001225 grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
1226}
1227
Craig Tillera8610c02017-02-14 10:05:11 -08001228static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg,
1229 grpc_error *error_ignored) {
Craig Tiller613dafa2017-02-09 12:00:43 -08001230 external_connectivity_watcher *w = arg;
1231 grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
1232 grpc_schedule_on_exec_ctx);
1233 grpc_connectivity_state_notify_on_state_change(
1234 exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
Craig Tiller86c99582015-11-25 15:22:26 -08001235}
1236
Craig Tillera82950e2015-09-22 12:33:20 -07001237void grpc_client_channel_watch_connectivity_state(
Craig Tiller906e3bc2015-11-24 07:31:31 -08001238 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
Craig Tillera82950e2015-09-22 12:33:20 -07001239 grpc_connectivity_state *state, grpc_closure *on_complete) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001240 channel_data *chand = elem->channel_data;
Craig Tiller86c99582015-11-25 15:22:26 -08001241 external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
1242 w->chand = chand;
1243 w->pollset = pollset;
1244 w->on_complete = on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001245 w->state = state;
Craig Tiller69b093b2016-02-25 19:04:07 -08001246 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
Craig Tiller1d881fb2015-12-01 07:39:04 -08001247 GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
1248 "external_connectivity_watcher");
Craig Tiller613dafa2017-02-09 12:00:43 -08001249 grpc_closure_sched(
1250 exec_ctx,
Craig Tillera8610c02017-02-14 10:05:11 -08001251 grpc_closure_init(&w->my_closure, watch_connectivity_state_locked, w,
Craig Tiller613dafa2017-02-09 12:00:43 -08001252 grpc_combiner_scheduler(chand->combiner, true)),
1253 GRPC_ERROR_NONE);
Craig Tiller48cb07c2015-07-15 16:16:15 -07001254}