blob: e437340e1435b77d309a2dae39965504de83b986 [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
80typedef struct method_parameters {
81 gpr_timespec timeout;
82 wait_for_ready_value wait_for_ready;
83} method_parameters;
84
85static void *method_parameters_copy(void *value) {
86 void *new_value = gpr_malloc(sizeof(method_parameters));
87 memcpy(new_value, value, sizeof(method_parameters));
88 return new_value;
89}
90
Craig Tillerb28c7e82016-11-18 10:29:04 -080091static void method_parameters_free(grpc_exec_ctx *exec_ctx, void *p) {
Craig Tiller87a7e1f2016-11-09 09:42:19 -080092 gpr_free(p);
93}
94
Craig Tiller7c70b6c2017-01-23 07:48:42 -080095static const grpc_slice_hash_table_vtable method_parameters_vtable = {
Craig Tillerb28c7e82016-11-18 10:29:04 -080096 method_parameters_free, method_parameters_copy};
Mark D. Roth9d480942016-10-19 14:18:05 -070097
Mark D. Rothe30baeb2016-11-03 08:16:19 -070098static void *method_parameters_create_from_json(const grpc_json *json) {
Mark D. Rothc968e602016-11-02 14:07:36 -070099 wait_for_ready_value wait_for_ready = WAIT_FOR_READY_UNSET;
Mark D. Roth47f10842016-11-03 08:45:27 -0700100 gpr_timespec timeout = {0, 0, GPR_TIMESPAN};
101 for (grpc_json *field = json->child; field != NULL; field = field->next) {
Mark D. Rothc968e602016-11-02 14:07:36 -0700102 if (field->key == NULL) continue;
Mark D. Roth84c8a022016-11-10 09:39:34 -0800103 if (strcmp(field->key, "waitForReady") == 0) {
Mark D. Rothc968e602016-11-02 14:07:36 -0700104 if (wait_for_ready != WAIT_FOR_READY_UNSET) return NULL; // Duplicate.
105 if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) {
106 return NULL;
107 }
Mark D. Roth47f10842016-11-03 08:45:27 -0700108 wait_for_ready = field->type == GRPC_JSON_TRUE ? WAIT_FOR_READY_TRUE
109 : WAIT_FOR_READY_FALSE;
Mark D. Rothc968e602016-11-02 14:07:36 -0700110 } else if (strcmp(field->key, "timeout") == 0) {
111 if (timeout.tv_sec > 0 || timeout.tv_nsec > 0) return NULL; // Duplicate.
Mark D. Roth84c8a022016-11-10 09:39:34 -0800112 if (field->type != GRPC_JSON_STRING) return NULL;
113 size_t len = strlen(field->value);
114 if (field->value[len - 1] != 's') return NULL;
Mark D. Rothc19049c2016-11-10 09:43:06 -0800115 char *buf = gpr_strdup(field->value);
Mark D. Roth84c8a022016-11-10 09:39:34 -0800116 buf[len - 1] = '\0'; // Remove trailing 's'.
Mark D. Rothc19049c2016-11-10 09:43:06 -0800117 char *decimal_point = strchr(buf, '.');
Mark D. Roth84c8a022016-11-10 09:39:34 -0800118 if (decimal_point != NULL) {
119 *decimal_point = '\0';
120 timeout.tv_nsec = gpr_parse_nonnegative_int(decimal_point + 1);
121 if (timeout.tv_nsec == -1) {
122 gpr_free(buf);
Mark D. Rothc968e602016-11-02 14:07:36 -0700123 return NULL;
124 }
Mark D. Roth84c8a022016-11-10 09:39:34 -0800125 // There should always be exactly 3, 6, or 9 fractional digits.
126 int multiplier = 1;
127 switch (strlen(decimal_point + 1)) {
128 case 9:
129 break;
130 case 6:
131 multiplier *= 1000;
132 break;
133 case 3:
134 multiplier *= 1000000;
135 break;
136 default: // Unsupported number of digits.
137 gpr_free(buf);
138 return NULL;
139 }
140 timeout.tv_nsec *= multiplier;
Mark D. Rothc968e602016-11-02 14:07:36 -0700141 }
Mark D. Roth84c8a022016-11-10 09:39:34 -0800142 timeout.tv_sec = gpr_parse_nonnegative_int(buf);
143 if (timeout.tv_sec == -1) return NULL;
144 gpr_free(buf);
Mark D. Rothc968e602016-11-02 14:07:36 -0700145 }
146 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700147 method_parameters *value = gpr_malloc(sizeof(method_parameters));
Mark D. Rothc968e602016-11-02 14:07:36 -0700148 value->timeout = timeout;
149 value->wait_for_ready = wait_for_ready;
Mark D. Roth9d480942016-10-19 14:18:05 -0700150 return value;
151}
152
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700153/*************************************************************************
154 * CHANNEL-WIDE FUNCTIONS
155 */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800156
Craig Tiller800dacb2015-10-06 09:10:26 -0700157typedef struct client_channel_channel_data {
Craig Tillerf5f17122015-06-25 08:47:26 -0700158 /** resolver for this channel */
159 grpc_resolver *resolver;
Craig Tiller20a3c352015-08-05 08:39:50 -0700160 /** have we started resolving this channel */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700161 bool started_resolving;
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700162 /** client channel factory */
163 grpc_client_channel_factory *client_channel_factory;
Craig Tillerf5f17122015-06-25 08:47:26 -0700164
Craig Tillerbefafe62017-02-09 11:30:54 -0800165 /** combiner protecting all variables below in this data structure */
166 grpc_combiner *combiner;
Mark D. Roth046cf762016-09-26 11:13:51 -0700167 /** currently active load balancer */
Craig Tillerf5f17122015-06-25 08:47:26 -0700168 grpc_lb_policy *lb_policy;
Mark D. Roth9d480942016-10-19 14:18:05 -0700169 /** maps method names to method_parameters structs */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800170 grpc_slice_hash_table *method_params_table;
Mark D. Roth046cf762016-09-26 11:13:51 -0700171 /** incoming resolver result - set by resolver.next() */
Mark D. Rothaf842452016-10-21 15:05:15 -0700172 grpc_channel_args *resolver_result;
Craig Tiller3f475422015-06-25 10:43:05 -0700173 /** a list of closures that are all waiting for config to come in */
Craig Tillerd9ccbbf2015-09-22 09:30:00 -0700174 grpc_closure_list waiting_for_config_closures;
Craig Tiller3f475422015-06-25 10:43:05 -0700175 /** resolver callback */
Mark D. Rothff4df062016-08-22 15:02:49 -0700176 grpc_closure on_resolver_result_changed;
Craig Tiller3f475422015-06-25 10:43:05 -0700177 /** connectivity state being tracked */
Craig Tillerca3e9d32015-06-27 18:37:27 -0700178 grpc_connectivity_state_tracker state_tracker;
Craig Tiller48cb07c2015-07-15 16:16:15 -0700179 /** when an lb_policy arrives, should we try to exit idle */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700180 bool exit_idle_when_lb_policy_arrives;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800181 /** owning stack */
182 grpc_channel_stack *owning_stack;
Craig Tiller69b093b2016-02-25 19:04:07 -0800183 /** interested parties (owned) */
184 grpc_pollset_set *interested_parties;
Craig Tiller613dafa2017-02-09 12:00:43 -0800185
186 /* the following properties are guarded by a mutex since API's require them
Craig Tiller46dd7902017-02-23 09:42:16 -0800187 to be instantaneously available */
Craig Tiller613dafa2017-02-09 12:00:43 -0800188 gpr_mu info_mu;
189 char *info_lb_policy_name;
190 /** service config in JSON form */
191 char *info_service_config_json;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800192} channel_data;
193
Craig Tillerd6c98df2015-08-18 09:33:44 -0700194/** We create one watcher for each new lb_policy that is returned from a
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700195 resolver, to watch for state changes from the lb_policy. When a state
196 change is seen, we update the channel, and create a new watcher. */
Craig Tillera82950e2015-09-22 12:33:20 -0700197typedef struct {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700198 channel_data *chand;
Craig Tiller33825112015-09-18 07:44:19 -0700199 grpc_closure on_changed;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700200 grpc_connectivity_state state;
201 grpc_lb_policy *lb_policy;
202} lb_policy_connectivity_watcher;
203
Craig Tiller2400bf52017-02-09 16:25:19 -0800204static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
205 grpc_lb_policy *lb_policy,
206 grpc_connectivity_state current_state);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700207
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800208static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
209 channel_data *chand,
210 grpc_connectivity_state state,
Craig Tiller804ff712016-05-05 16:25:40 -0700211 grpc_error *error,
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800212 const char *reason) {
213 if ((state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
Craig Tiller48ed92e2016-06-02 11:07:12 -0700214 state == GRPC_CHANNEL_SHUTDOWN) &&
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800215 chand->lb_policy != NULL) {
Mark D. Roth59c9f902016-09-28 13:33:21 -0700216 /* cancel picks with wait_for_ready=false */
Craig Tiller2400bf52017-02-09 16:25:19 -0800217 grpc_lb_policy_cancel_picks_locked(
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800218 exec_ctx, chand->lb_policy,
Mark D. Roth59c9f902016-09-28 13:33:21 -0700219 /* mask= */ GRPC_INITIAL_METADATA_WAIT_FOR_READY,
Mark D. Roth58f52b72016-09-09 13:55:18 -0700220 /* check= */ 0, GRPC_ERROR_REF(error));
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800221 }
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700222 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, error,
223 reason);
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800224}
225
Craig Tiller804ff712016-05-05 16:25:40 -0700226static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
Craig Tillerbefafe62017-02-09 11:30:54 -0800227 void *arg, grpc_error *error) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700228 lb_policy_connectivity_watcher *w = arg;
Craig Tiller5d44c062015-07-01 08:55:28 -0700229 grpc_connectivity_state publish_state = w->state;
Craig Tillerc5de8352017-02-09 14:08:05 -0800230 /* check if the notification is for the latest policy */
231 if (w->lb_policy == w->chand->lb_policy) {
232 if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
233 publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Craig Tiller972470b2017-02-09 15:05:36 -0800234 grpc_resolver_channel_saw_error_locked(exec_ctx, w->chand->resolver);
Craig Tillerc5de8352017-02-09 14:08:05 -0800235 GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
236 w->chand->lb_policy = NULL;
237 }
238 set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
239 GRPC_ERROR_REF(error), "lb_changed");
240 if (w->state != GRPC_CHANNEL_SHUTDOWN) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800241 watch_lb_policy_locked(exec_ctx, w->chand, w->lb_policy, w->state);
Craig Tillerc5de8352017-02-09 14:08:05 -0800242 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800243 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700244
Craig Tiller906e3bc2015-11-24 07:31:31 -0800245 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
Craig Tillera82950e2015-09-22 12:33:20 -0700246 gpr_free(w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700247}
248
Craig Tiller2400bf52017-02-09 16:25:19 -0800249static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
250 grpc_lb_policy *lb_policy,
251 grpc_connectivity_state current_state) {
Craig Tillera82950e2015-09-22 12:33:20 -0700252 lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
Craig Tiller906e3bc2015-11-24 07:31:31 -0800253 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700254
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700255 w->chand = chand;
Craig Tillerbefafe62017-02-09 11:30:54 -0800256 grpc_closure_init(&w->on_changed, on_lb_policy_state_changed_locked, w,
257 grpc_combiner_scheduler(chand->combiner, false));
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700258 w->state = current_state;
259 w->lb_policy = lb_policy;
Craig Tiller2400bf52017-02-09 16:25:19 -0800260 grpc_lb_policy_notify_on_state_change_locked(exec_ctx, lb_policy, &w->state,
261 &w->on_changed);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700262}
263
Craig Tillerbefafe62017-02-09 11:30:54 -0800264static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
265 void *arg, grpc_error *error) {
Craig Tiller3f475422015-06-25 10:43:05 -0700266 channel_data *chand = arg;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700267 char *lb_policy_name = NULL;
Craig Tiller3f475422015-06-25 10:43:05 -0700268 grpc_lb_policy *lb_policy = NULL;
269 grpc_lb_policy *old_lb_policy;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800270 grpc_slice_hash_table *method_params_table = NULL;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700271 grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700272 bool exit_idle = false;
Craig Tiller804ff712016-05-05 16:25:40 -0700273 grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800274 char *service_config_json = NULL;
Craig Tiller3f475422015-06-25 10:43:05 -0700275
Mark D. Roth046cf762016-09-26 11:13:51 -0700276 if (chand->resolver_result != NULL) {
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700277 // Find LB policy name.
Mark D. Rothaf842452016-10-21 15:05:15 -0700278 const grpc_arg *channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700279 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_POLICY_NAME);
Mark D. Rothaf842452016-10-21 15:05:15 -0700280 if (channel_arg != NULL) {
281 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
282 lb_policy_name = channel_arg->value.string;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700283 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700284 // Special case: If all of the addresses are balancer addresses,
285 // assume that we should use the grpclb policy, regardless of what the
286 // resolver actually specified.
Mark D. Rothaf842452016-10-21 15:05:15 -0700287 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700288 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES);
Mark D. Rothaf842452016-10-21 15:05:15 -0700289 if (channel_arg != NULL) {
290 GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
Mark D. Roth557c9902016-10-24 11:12:05 -0700291 grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
Mark D. Rothaf842452016-10-21 15:05:15 -0700292 bool found_backend_address = false;
293 for (size_t i = 0; i < addresses->num_addresses; ++i) {
294 if (!addresses->addresses[i].is_balancer) {
295 found_backend_address = true;
296 break;
297 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700298 }
Mark D. Rothaf842452016-10-21 15:05:15 -0700299 if (!found_backend_address) {
300 if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) {
301 gpr_log(GPR_INFO,
302 "resolver requested LB policy %s but provided only balancer "
303 "addresses, no backend addresses -- forcing use of grpclb LB "
304 "policy",
Mark D. Roth5f40e5d2016-10-24 13:09:05 -0700305 lb_policy_name);
Mark D. Rothaf842452016-10-21 15:05:15 -0700306 }
307 lb_policy_name = "grpclb";
Mark D. Roth88405f72016-10-03 08:24:52 -0700308 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700309 }
310 // Use pick_first if nothing was specified and we didn't select grpclb
311 // above.
312 if (lb_policy_name == NULL) lb_policy_name = "pick_first";
Mark D. Roth41124992016-11-03 11:22:20 -0700313 // Instantiate LB policy.
314 grpc_lb_policy_args lb_policy_args;
315 lb_policy_args.args = chand->resolver_result;
316 lb_policy_args.client_channel_factory = chand->client_channel_factory;
Craig Tiller2400bf52017-02-09 16:25:19 -0800317 lb_policy_args.combiner = chand->combiner;
Mark D. Roth88405f72016-10-03 08:24:52 -0700318 lb_policy =
319 grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700320 if (lb_policy != NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -0700321 GRPC_LB_POLICY_REF(lb_policy, "config_change");
Craig Tillerf707d622016-05-06 14:26:12 -0700322 GRPC_ERROR_UNREF(state_error);
Craig Tiller2400bf52017-02-09 16:25:19 -0800323 state = grpc_lb_policy_check_connectivity_locked(exec_ctx, lb_policy,
324 &state_error);
Craig Tiller45724b32015-09-22 10:42:19 -0700325 }
Mark D. Roth41124992016-11-03 11:22:20 -0700326 // Find service config.
Mark D. Rothaf842452016-10-21 15:05:15 -0700327 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700328 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVICE_CONFIG);
Mark D. Roth046cf762016-09-26 11:13:51 -0700329 if (channel_arg != NULL) {
Mark D. Roth9ec28af2016-11-03 12:32:39 -0700330 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800331 service_config_json = gpr_strdup(channel_arg->value.string);
Mark D. Roth70a1abd2016-11-04 09:26:37 -0700332 grpc_service_config *service_config =
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800333 grpc_service_config_create(service_config_json);
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700334 if (service_config != NULL) {
335 method_params_table = grpc_service_config_create_method_config_table(
Craig Tillerb28c7e82016-11-18 10:29:04 -0800336 exec_ctx, service_config, method_parameters_create_from_json,
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700337 &method_parameters_vtable);
338 grpc_service_config_destroy(service_config);
339 }
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700340 }
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700341 // Before we clean up, save a copy of lb_policy_name, since it might
342 // be pointing to data inside chand->resolver_result.
343 // The copy will be saved in chand->lb_policy_name below.
344 lb_policy_name = gpr_strdup(lb_policy_name);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800345 grpc_channel_args_destroy(exec_ctx, chand->resolver_result);
Mark D. Roth046cf762016-09-26 11:13:51 -0700346 chand->resolver_result = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700347 }
348
Craig Tiller86c99582015-11-25 15:22:26 -0800349 if (lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800350 grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties,
351 chand->interested_parties);
Craig Tiller86c99582015-11-25 15:22:26 -0800352 }
353
Craig Tiller613dafa2017-02-09 12:00:43 -0800354 gpr_mu_lock(&chand->info_mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700355 if (lb_policy_name != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800356 gpr_free(chand->info_lb_policy_name);
357 chand->info_lb_policy_name = lb_policy_name;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700358 }
Craig Tiller3f475422015-06-25 10:43:05 -0700359 old_lb_policy = chand->lb_policy;
360 chand->lb_policy = lb_policy;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800361 if (service_config_json != NULL) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800362 gpr_free(chand->info_service_config_json);
363 chand->info_service_config_json = service_config_json;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800364 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800365 gpr_mu_unlock(&chand->info_mu);
Mark D. Roth9d480942016-10-19 14:18:05 -0700366 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800367 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth046cf762016-09-26 11:13:51 -0700368 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700369 chand->method_params_table = method_params_table;
Craig Tiller0ede5452016-04-23 12:21:45 -0700370 if (lb_policy != NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -0800371 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller0ede5452016-04-23 12:21:45 -0700372 } else if (chand->resolver == NULL /* disconnected */) {
Craig Tiller804ff712016-05-05 16:25:40 -0700373 grpc_closure_list_fail_all(
374 &chand->waiting_for_config_closures,
375 GRPC_ERROR_CREATE_REFERENCING("Channel disconnected", &error, 1));
Craig Tiller91031da2016-12-28 15:44:25 -0800376 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tillera82950e2015-09-22 12:33:20 -0700377 }
378 if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
379 GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700380 exit_idle = true;
381 chand->exit_idle_when_lb_policy_arrives = false;
Craig Tillera82950e2015-09-22 12:33:20 -0700382 }
Craig Tiller98465032015-06-29 14:36:42 -0700383
Craig Tiller804ff712016-05-05 16:25:40 -0700384 if (error == GRPC_ERROR_NONE && chand->resolver) {
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700385 set_channel_connectivity_state_locked(
386 exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700387 if (lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800388 watch_lb_policy_locked(exec_ctx, chand, lb_policy, state);
Craig Tiller45724b32015-09-22 10:42:19 -0700389 }
Craig Tiller906e3bc2015-11-24 07:31:31 -0800390 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -0800391 grpc_resolver_next_locked(exec_ctx, chand->resolver,
392 &chand->resolver_result,
393 &chand->on_resolver_result_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700394 } else {
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800395 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800396 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800397 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
398 chand->resolver = NULL;
399 }
Craig Tiller804ff712016-05-05 16:25:40 -0700400 grpc_error *refs[] = {error, state_error};
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800401 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700402 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller804ff712016-05-05 16:25:40 -0700403 GRPC_ERROR_CREATE_REFERENCING("Got config after disconnection", refs,
404 GPR_ARRAY_SIZE(refs)),
405 "resolver_gone");
Craig Tillera82950e2015-09-22 12:33:20 -0700406 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700407
Craig Tillera82950e2015-09-22 12:33:20 -0700408 if (exit_idle) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800409 grpc_lb_policy_exit_idle_locked(exec_ctx, lb_policy);
Craig Tillera82950e2015-09-22 12:33:20 -0700410 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
411 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700412
Craig Tillera82950e2015-09-22 12:33:20 -0700413 if (old_lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800414 grpc_pollset_set_del_pollset_set(
415 exec_ctx, old_lb_policy->interested_parties, chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700416 GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
417 }
Craig Tiller000cd8f2015-09-18 07:20:29 -0700418
Craig Tillera82950e2015-09-22 12:33:20 -0700419 if (lb_policy != NULL) {
420 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
421 }
Craig Tiller45724b32015-09-22 10:42:19 -0700422
Craig Tiller906e3bc2015-11-24 07:31:31 -0800423 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700424 GRPC_ERROR_UNREF(state_error);
Craig Tiller3f475422015-06-25 10:43:05 -0700425}
426
Craig Tillera8610c02017-02-14 10:05:11 -0800427static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
428 grpc_error *error_ignored) {
Craig Tillerbefafe62017-02-09 11:30:54 -0800429 grpc_transport_op *op = arg;
430 grpc_channel_element *elem = op->transport_private.args[0];
Craig Tillerca3e9d32015-06-27 18:37:27 -0700431 channel_data *chand = elem->channel_data;
Craig Tiller000cd8f2015-09-18 07:20:29 -0700432
Craig Tillera82950e2015-09-22 12:33:20 -0700433 if (op->on_connectivity_state_change != NULL) {
434 grpc_connectivity_state_notify_on_state_change(
435 exec_ctx, &chand->state_tracker, op->connectivity_state,
436 op->on_connectivity_state_change);
437 op->on_connectivity_state_change = NULL;
438 op->connectivity_state = NULL;
439 }
440
Craig Tiller26dab312015-12-07 14:43:47 -0800441 if (op->send_ping != NULL) {
Craig Tiller87b71e22015-12-07 15:14:14 -0800442 if (chand->lb_policy == NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -0800443 grpc_closure_sched(exec_ctx, op->send_ping,
444 GRPC_ERROR_CREATE("Ping with no load balancing"));
Craig Tiller26dab312015-12-07 14:43:47 -0800445 } else {
Craig Tiller2400bf52017-02-09 16:25:19 -0800446 grpc_lb_policy_ping_one_locked(exec_ctx, chand->lb_policy, op->send_ping);
Craig Tiller26dab312015-12-07 14:43:47 -0800447 op->bind_pollset = NULL;
448 }
449 op->send_ping = NULL;
450 }
451
Craig Tiller1c51edc2016-05-07 16:18:43 -0700452 if (op->disconnect_with_error != GRPC_ERROR_NONE) {
453 if (chand->resolver != NULL) {
454 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700455 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller1c51edc2016-05-07 16:18:43 -0700456 GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
Craig Tiller972470b2017-02-09 15:05:36 -0800457 grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700458 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
459 chand->resolver = NULL;
460 if (!chand->started_resolving) {
461 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
462 GRPC_ERROR_REF(op->disconnect_with_error));
Craig Tiller91031da2016-12-28 15:44:25 -0800463 grpc_closure_list_sched(exec_ctx, &chand->waiting_for_config_closures);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700464 }
465 if (chand->lb_policy != NULL) {
466 grpc_pollset_set_del_pollset_set(exec_ctx,
467 chand->lb_policy->interested_parties,
468 chand->interested_parties);
469 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
470 chand->lb_policy = NULL;
471 }
Craig Tillerb12d22a2016-04-23 12:50:21 -0700472 }
Craig Tiller1c51edc2016-05-07 16:18:43 -0700473 GRPC_ERROR_UNREF(op->disconnect_with_error);
Craig Tillera82950e2015-09-22 12:33:20 -0700474 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800475 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "start_transport_op");
476
477 grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
Craig Tillerbefafe62017-02-09 11:30:54 -0800478}
479
480static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
481 grpc_channel_element *elem,
482 grpc_transport_op *op) {
483 channel_data *chand = elem->channel_data;
484
Craig Tillerbefafe62017-02-09 11:30:54 -0800485 GPR_ASSERT(op->set_accept_stream == false);
486 if (op->bind_pollset != NULL) {
487 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
488 op->bind_pollset);
489 }
490
491 op->transport_private.args[0] = elem;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800492 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "start_transport_op");
Craig Tillerbefafe62017-02-09 11:30:54 -0800493 grpc_closure_sched(
Craig Tillera8610c02017-02-14 10:05:11 -0800494 exec_ctx, grpc_closure_init(
495 &op->transport_private.closure, start_transport_op_locked,
496 op, grpc_combiner_scheduler(chand->combiner, false)),
Craig Tillerbefafe62017-02-09 11:30:54 -0800497 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 GPR_ASSERT(args->is_last);
525 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800526 // Initialize data members.
Craig Tillerbefafe62017-02-09 11:30:54 -0800527 chand->combiner = grpc_combiner_create(NULL);
Craig Tillerd85477512017-02-09 12:02:39 -0800528 gpr_mu_init(&chand->info_mu);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800529 chand->owning_stack = args->channel_stack;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700530 grpc_closure_init(&chand->on_resolver_result_changed,
Craig Tillerbefafe62017-02-09 11:30:54 -0800531 on_resolver_result_changed_locked, chand,
532 grpc_combiner_scheduler(chand->combiner, false));
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800533 chand->interested_parties = grpc_pollset_set_create();
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700534 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
535 "client_channel");
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800536 // Record client channel factory.
537 const grpc_arg *arg = grpc_channel_args_find(args->channel_args,
538 GRPC_ARG_CLIENT_CHANNEL_FACTORY);
539 GPR_ASSERT(arg != NULL);
540 GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
541 grpc_client_channel_factory_ref(arg->value.pointer.p);
542 chand->client_channel_factory = arg->value.pointer.p;
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800543 // Get server name to resolve, using proxy mapper if needed.
Mark D. Roth86e90592016-11-18 09:56:40 -0800544 arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI);
Mark D. Roth21d4b2d2016-11-18 09:53:41 -0800545 GPR_ASSERT(arg != NULL);
546 GPR_ASSERT(arg->type == GRPC_ARG_STRING);
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800547 char *proxy_name = NULL;
548 grpc_channel_args *new_args = NULL;
549 grpc_proxy_mappers_map_name(exec_ctx, arg->value.string, args->channel_args,
550 &proxy_name, &new_args);
551 // Instantiate resolver.
Mark D. Roth45ccec52017-01-18 14:04:01 -0800552 chand->resolver = grpc_resolver_create(
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800553 exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string,
554 new_args != NULL ? new_args : args->channel_args,
Craig Tiller972470b2017-02-09 15:05:36 -0800555 chand->interested_parties, chand->combiner);
Mark D. Rothdc9bee72017-02-07 12:29:14 -0800556 if (proxy_name != NULL) gpr_free(proxy_name);
557 if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args);
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800558 if (chand->resolver == NULL) {
559 return GRPC_ERROR_CREATE("resolver creation failed");
560 }
561 return GRPC_ERROR_NONE;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700562}
563
Craig Tiller972470b2017-02-09 15:05:36 -0800564static void shutdown_resolver_locked(grpc_exec_ctx *exec_ctx, void *arg,
565 grpc_error *error) {
566 grpc_resolver *resolver = arg;
567 grpc_resolver_shutdown_locked(exec_ctx, resolver);
568 GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel");
569}
570
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700571/* Destructor for channel_data */
572static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
573 grpc_channel_element *elem) {
574 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700575 if (chand->resolver != NULL) {
Craig Tiller972470b2017-02-09 15:05:36 -0800576 grpc_closure_sched(
577 exec_ctx,
578 grpc_closure_create(shutdown_resolver_locked, chand->resolver,
579 grpc_combiner_scheduler(chand->combiner, false)),
580 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700581 }
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700582 if (chand->client_channel_factory != NULL) {
583 grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
584 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700585 if (chand->lb_policy != NULL) {
586 grpc_pollset_set_del_pollset_set(exec_ctx,
587 chand->lb_policy->interested_parties,
588 chand->interested_parties);
589 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
590 }
Craig Tiller613dafa2017-02-09 12:00:43 -0800591 gpr_free(chand->info_lb_policy_name);
592 gpr_free(chand->info_service_config_json);
Mark D. Roth9d480942016-10-19 14:18:05 -0700593 if (chand->method_params_table != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800594 grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700595 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700596 grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
Craig Tiller9e5ac1b2017-02-14 22:25:50 -0800597 grpc_pollset_set_destroy(exec_ctx, chand->interested_parties);
Craig Tillerf1021672017-02-09 21:29:50 -0800598 GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel");
Craig Tillerd85477512017-02-09 12:02:39 -0800599 gpr_mu_destroy(&chand->info_mu);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700600}
601
602/*************************************************************************
603 * PER-CALL FUNCTIONS
604 */
605
606#define GET_CALL(call_data) \
607 ((grpc_subchannel_call *)(gpr_atm_acq_load(&(call_data)->subchannel_call)))
608
609#define CANCELLED_CALL ((grpc_subchannel_call *)1)
610
611typedef enum {
Craig Tiller7acc37e2017-02-28 10:01:37 -0800612 /* zero so that it can be default-initialized */
613 GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING = 0,
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700614 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. Rothaa850a72016-09-26 13:38:02 -0700635
Mark D. Rothf28763c2016-09-14 15:18:40 -0700636 grpc_error *cancel_error;
Mark D. Roth72f6da82016-09-02 13:42:38 -0700637
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700638 /** either 0 for no call, 1 for cancelled, or a pointer to a
639 grpc_subchannel_call */
640 gpr_atm subchannel_call;
641
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700642 subchannel_creation_phase creation_phase;
643 grpc_connected_subchannel *connected_subchannel;
644 grpc_polling_entity *pollent;
645
Craig Tiller57726ca2016-09-12 11:59:45 -0700646 grpc_transport_stream_op **waiting_ops;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700647 size_t waiting_ops_count;
648 size_t waiting_ops_capacity;
649
650 grpc_closure next_step;
651
652 grpc_call_stack *owning_call;
David Garcia Quintasd1a47f12016-09-02 12:46:44 +0200653
654 grpc_linked_mdelem lb_token_mdelem;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700655} call_data;
656
Craig Tiller8b1d59c2016-12-27 15:15:30 -0800657grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
658 grpc_call_element *call_elem) {
659 grpc_subchannel_call *scc = GET_CALL((call_data *)call_elem->call_data);
660 return scc == CANCELLED_CALL ? NULL : scc;
661}
662
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700663static void add_waiting_locked(call_data *calld, grpc_transport_stream_op *op) {
664 GPR_TIMER_BEGIN("add_waiting_locked", 0);
665 if (calld->waiting_ops_count == calld->waiting_ops_capacity) {
666 calld->waiting_ops_capacity = GPR_MAX(3, 2 * calld->waiting_ops_capacity);
667 calld->waiting_ops =
668 gpr_realloc(calld->waiting_ops,
669 calld->waiting_ops_capacity * sizeof(*calld->waiting_ops));
670 }
Craig Tiller57726ca2016-09-12 11:59:45 -0700671 calld->waiting_ops[calld->waiting_ops_count++] = op;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700672 GPR_TIMER_END("add_waiting_locked", 0);
673}
674
675static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld,
676 grpc_error *error) {
677 size_t i;
678 for (i = 0; i < calld->waiting_ops_count; i++) {
679 grpc_transport_stream_op_finish_with_failure(
Craig Tiller57726ca2016-09-12 11:59:45 -0700680 exec_ctx, calld->waiting_ops[i], GRPC_ERROR_REF(error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700681 }
682 calld->waiting_ops_count = 0;
683 GRPC_ERROR_UNREF(error);
684}
685
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700686static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
Craig Tiller57726ca2016-09-12 11:59:45 -0700687 if (calld->waiting_ops_count == 0) {
688 return;
689 }
690
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800691 grpc_subchannel_call *call = GET_CALL(calld);
692 grpc_transport_stream_op **ops = calld->waiting_ops;
693 size_t nops = calld->waiting_ops_count;
694 if (call == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700695 fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED);
696 return;
697 }
698 calld->waiting_ops = NULL;
699 calld->waiting_ops_count = 0;
700 calld->waiting_ops_capacity = 0;
Craig Tillerd2e5cfc2017-02-09 13:02:20 -0800701 for (size_t i = 0; i < nops; i++) {
702 grpc_subchannel_call_process_op(exec_ctx, call, ops[i]);
703 }
Craig Tiller9efea882017-02-09 13:06:52 -0800704 gpr_free(ops);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700705}
706
Craig Tillera7ed2682017-02-28 13:26:37 -0800707static void apply_final_configuration_locked(grpc_exec_ctx *exec_ctx,
708 grpc_call_element *elem) {
709 /* apply service-config level configuration to the call (now that we're
710 * certain it exists) */
711 channel_data *chand = elem->channel_data;
712 call_data *calld = elem->call_data;
713 /* Get the method config table from channel data. */
714 grpc_slice_hash_table *method_params_table = NULL;
715 if (chand->method_params_table != NULL) {
716 method_params_table = grpc_slice_hash_table_ref(chand->method_params_table);
717 }
718 /* If the method config table was present, use it. */
719 if (method_params_table != NULL) {
720 const method_parameters *method_params = grpc_method_config_table_get(
721 exec_ctx, method_params_table, calld->path);
722 if (method_params != NULL) {
723 const bool have_method_timeout =
724 gpr_time_cmp(method_params->timeout, gpr_time_0(GPR_TIMESPAN)) != 0;
725 if (have_method_timeout ||
726 method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
727 if (have_method_timeout) {
728 const gpr_timespec per_method_deadline =
729 gpr_time_add(calld->call_start_time, method_params->timeout);
730 if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
731 calld->deadline = per_method_deadline;
732 }
733 }
734 if (method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
735 calld->wait_for_ready_from_service_config =
736 method_params->wait_for_ready;
737 }
738 }
739 }
740 grpc_slice_hash_table_unref(exec_ctx, method_params_table);
741 }
742 /* Start deadline timer. */
743 grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
744}
745
Craig Tillerbefafe62017-02-09 11:30:54 -0800746static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
747 grpc_error *error) {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700748 grpc_call_element *elem = arg;
749 call_data *calld = elem->call_data;
750 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700751 GPR_ASSERT(calld->creation_phase ==
752 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
Yuchen Zeng19656b12016-09-01 18:00:45 -0700753 grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
754 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700755 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
756 if (calld->connected_subchannel == NULL) {
757 gpr_atm_no_barrier_store(&calld->subchannel_call, 1);
758 fail_locked(exec_ctx, calld, GRPC_ERROR_CREATE_REFERENCING(
759 "Failed to create subchannel", &error, 1));
Mark D. Roth72f6da82016-09-02 13:42:38 -0700760 } else if (GET_CALL(calld) == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700761 /* already cancelled before subchannel became ready */
David Garcia Quintas68a9e382016-12-13 10:50:40 -0800762 grpc_error *cancellation_error = GRPC_ERROR_CREATE_REFERENCING(
763 "Cancelled before creating subchannel", &error, 1);
764 /* if due to deadline, attach the deadline exceeded status to the error */
765 if (gpr_time_cmp(calld->deadline, gpr_now(GPR_CLOCK_MONOTONIC)) < 0) {
766 cancellation_error =
767 grpc_error_set_int(cancellation_error, GRPC_ERROR_INT_GRPC_STATUS,
768 GRPC_STATUS_DEADLINE_EXCEEDED);
769 }
770 fail_locked(exec_ctx, calld, cancellation_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700771 } else {
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700772 /* Create call on subchannel. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700773 grpc_subchannel_call *subchannel_call = NULL;
Craig Tillera7ed2682017-02-28 13:26:37 -0800774 apply_final_configuration_locked(exec_ctx, elem);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700775 grpc_error *new_error = grpc_connected_subchannel_create_call(
Mark D. Rothaa850a72016-09-26 13:38:02 -0700776 exec_ctx, calld->connected_subchannel, calld->pollent, calld->path,
Mark D. Roth3d883412016-11-07 13:42:54 -0800777 calld->call_start_time, calld->deadline, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700778 if (new_error != GRPC_ERROR_NONE) {
779 new_error = grpc_error_add_child(new_error, error);
780 subchannel_call = CANCELLED_CALL;
781 fail_locked(exec_ctx, calld, new_error);
782 }
783 gpr_atm_rel_store(&calld->subchannel_call,
784 (gpr_atm)(uintptr_t)subchannel_call);
785 retry_waiting_locked(exec_ctx, calld);
786 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700787 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
788}
789
790static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
791 call_data *calld = elem->call_data;
792 grpc_subchannel_call *subchannel_call = GET_CALL(calld);
793 if (subchannel_call == NULL || subchannel_call == CANCELLED_CALL) {
794 return NULL;
795 } else {
796 return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
797 }
798}
799
Craig Tiller577c9b22015-11-02 14:11:15 -0800800typedef struct {
801 grpc_metadata_batch *initial_metadata;
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800802 uint32_t initial_metadata_flags;
Craig Tillerb5585d42015-11-17 07:18:31 -0800803 grpc_connected_subchannel **connected_subchannel;
Craig Tiller577c9b22015-11-02 14:11:15 -0800804 grpc_closure *on_ready;
805 grpc_call_element *elem;
806 grpc_closure closure;
807} continue_picking_args;
808
Yuchen Zeng144ce652016-09-01 18:19:34 -0700809/** Return true if subchannel is available immediately (in which case on_ready
810 should not be called), or false otherwise (in which case on_ready should be
811 called when the subchannel is available). */
Craig Tillerbefafe62017-02-09 11:30:54 -0800812static bool pick_subchannel_locked(
813 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
814 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
815 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
816 grpc_error *error);
Craig Tiller577c9b22015-11-02 14:11:15 -0800817
Craig Tillerbefafe62017-02-09 11:30:54 -0800818static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg,
819 grpc_error *error) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800820 continue_picking_args *cpa = arg;
Craig Tiller0ede5452016-04-23 12:21:45 -0700821 if (cpa->connected_subchannel == NULL) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800822 /* cancelled, do nothing */
Craig Tiller804ff712016-05-05 16:25:40 -0700823 } else if (error != GRPC_ERROR_NONE) {
Craig Tiller91031da2016-12-28 15:44:25 -0800824 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error));
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700825 } else {
Craig Tillerbefafe62017-02-09 11:30:54 -0800826 if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata,
827 cpa->initial_metadata_flags,
828 cpa->connected_subchannel, cpa->on_ready,
829 GRPC_ERROR_NONE)) {
Craig Tiller91031da2016-12-28 15:44:25 -0800830 grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700831 }
Craig Tiller577c9b22015-11-02 14:11:15 -0800832 }
833 gpr_free(cpa);
834}
835
Craig Tillerbefafe62017-02-09 11:30:54 -0800836static bool pick_subchannel_locked(
837 grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
838 grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
839 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
840 grpc_error *error) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700841 GPR_TIMER_BEGIN("pick_subchannel", 0);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700842
Craig Tiller577c9b22015-11-02 14:11:15 -0800843 channel_data *chand = elem->channel_data;
844 call_data *calld = elem->call_data;
845 continue_picking_args *cpa;
846 grpc_closure *closure;
847
Craig Tillerb5585d42015-11-17 07:18:31 -0800848 GPR_ASSERT(connected_subchannel);
Craig Tiller577c9b22015-11-02 14:11:15 -0800849
Craig Tiller577c9b22015-11-02 14:11:15 -0800850 if (initial_metadata == NULL) {
851 if (chand->lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -0800852 grpc_lb_policy_cancel_pick_locked(exec_ctx, chand->lb_policy,
853 connected_subchannel,
854 GRPC_ERROR_REF(error));
Craig Tiller577c9b22015-11-02 14:11:15 -0800855 }
856 for (closure = chand->waiting_for_config_closures.head; closure != NULL;
Craig Tiller804ff712016-05-05 16:25:40 -0700857 closure = closure->next_data.next) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800858 cpa = closure->cb_arg;
Craig Tillerb5585d42015-11-17 07:18:31 -0800859 if (cpa->connected_subchannel == connected_subchannel) {
860 cpa->connected_subchannel = NULL;
Craig Tiller91031da2016-12-28 15:44:25 -0800861 grpc_closure_sched(
Mark D. Roth932b10c2016-09-09 08:44:30 -0700862 exec_ctx, cpa->on_ready,
Craig Tiller91031da2016-12-28 15:44:25 -0800863 GRPC_ERROR_CREATE_REFERENCING("Pick cancelled", &error, 1));
Craig Tiller577c9b22015-11-02 14:11:15 -0800864 }
865 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700866 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth697a1f62016-09-07 13:35:07 -0700867 GRPC_ERROR_UNREF(error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700868 return true;
Craig Tiller577c9b22015-11-02 14:11:15 -0800869 }
Mark D. Roth697a1f62016-09-07 13:35:07 -0700870 GPR_ASSERT(error == GRPC_ERROR_NONE);
Craig Tiller577c9b22015-11-02 14:11:15 -0800871 if (chand->lb_policy != NULL) {
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800872 grpc_lb_policy *lb_policy = chand->lb_policy;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700873 GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel");
Mark D. Rothe40dd292016-10-05 14:58:37 -0700874 // If the application explicitly set wait_for_ready, use that.
875 // Otherwise, if the service config specified a value for this
876 // method, use that.
Mark D. Rothc1c38582016-10-11 11:03:27 -0700877 const bool wait_for_ready_set_from_api =
878 initial_metadata_flags &
879 GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
880 const bool wait_for_ready_set_from_service_config =
881 calld->wait_for_ready_from_service_config != WAIT_FOR_READY_UNSET;
882 if (!wait_for_ready_set_from_api &&
883 wait_for_ready_set_from_service_config) {
Mark D. Rothe40dd292016-10-05 14:58:37 -0700884 if (calld->wait_for_ready_from_service_config == WAIT_FOR_READY_TRUE) {
885 initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
886 } else {
887 initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
888 }
889 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700890 const grpc_lb_policy_pick_args inputs = {
Yuchen Zengac8bc422016-10-05 14:00:02 -0700891 initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem,
892 gpr_inf_future(GPR_CLOCK_MONOTONIC)};
Craig Tiller2400bf52017-02-09 16:25:19 -0800893 const bool result = grpc_lb_policy_pick_locked(
Mark D. Roth55f25b62016-10-12 14:55:20 -0700894 exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, on_ready);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700895 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel");
896 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700897 return result;
Craig Tiller577c9b22015-11-02 14:11:15 -0800898 }
899 if (chand->resolver != NULL && !chand->started_resolving) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700900 chand->started_resolving = true;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800901 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller972470b2017-02-09 15:05:36 -0800902 grpc_resolver_next_locked(exec_ctx, chand->resolver,
903 &chand->resolver_result,
904 &chand->on_resolver_result_changed);
Craig Tiller577c9b22015-11-02 14:11:15 -0800905 }
Craig Tiller0eab6972016-04-23 12:59:57 -0700906 if (chand->resolver != NULL) {
907 cpa = gpr_malloc(sizeof(*cpa));
908 cpa->initial_metadata = initial_metadata;
909 cpa->initial_metadata_flags = initial_metadata_flags;
910 cpa->connected_subchannel = connected_subchannel;
911 cpa->on_ready = on_ready;
912 cpa->elem = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -0800913 grpc_closure_init(&cpa->closure, continue_picking_locked, cpa,
914 grpc_combiner_scheduler(chand->combiner, true));
Craig Tiller804ff712016-05-05 16:25:40 -0700915 grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
916 GRPC_ERROR_NONE);
Craig Tiller0eab6972016-04-23 12:59:57 -0700917 } else {
Craig Tiller91031da2016-12-28 15:44:25 -0800918 grpc_closure_sched(exec_ctx, on_ready, GRPC_ERROR_CREATE("Disconnected"));
Craig Tiller0eab6972016-04-23 12:59:57 -0700919 }
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700920
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700921 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700922 return false;
Craig Tiller577c9b22015-11-02 14:11:15 -0800923}
924
Craig Tillera8610c02017-02-14 10:05:11 -0800925static void start_transport_stream_op_locked_inner(grpc_exec_ctx *exec_ctx,
926 grpc_transport_stream_op *op,
927 grpc_call_element *elem) {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700928 channel_data *chand = elem->channel_data;
Craig Tillera11bfc82017-02-14 09:56:33 -0800929 call_data *calld = elem->call_data;
Craig Tillerbefafe62017-02-09 11:30:54 -0800930 grpc_subchannel_call *call;
931
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700932 /* need to recheck that another thread hasn't set the call */
933 call = GET_CALL(calld);
934 if (call == CANCELLED_CALL) {
Mark D. Rothf28763c2016-09-14 15:18:40 -0700935 grpc_transport_stream_op_finish_with_failure(
936 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -0800937 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700938 return;
939 }
940 if (call != NULL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700941 grpc_subchannel_call_process_op(exec_ctx, call, op);
Craig Tillera11bfc82017-02-14 09:56:33 -0800942 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700943 return;
944 }
945 /* if this is a cancellation, then we can raise our cancelled flag */
946 if (op->cancel_error != GRPC_ERROR_NONE) {
947 if (!gpr_atm_rel_cas(&calld->subchannel_call, 0,
948 (gpr_atm)(uintptr_t)CANCELLED_CALL)) {
Craig Tillera11bfc82017-02-14 09:56:33 -0800949 /* recurse to retry */
Craig Tillera8610c02017-02-14 10:05:11 -0800950 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -0800951 /* early out */
952 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700953 } else {
Craig Tillerbe9691a2017-02-14 10:00:42 -0800954 /* Stash a copy of cancel_error in our call data, so that we can use
955 it for subsequent operations. This ensures that if the call is
956 cancelled before any ops are passed down (e.g., if the deadline
957 is in the past when the call starts), we can return the right
958 error to the caller when the first op does get passed down. */
Mark D. Rothf28763c2016-09-14 15:18:40 -0700959 calld->cancel_error = GRPC_ERROR_REF(op->cancel_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700960 switch (calld->creation_phase) {
961 case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
962 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error));
963 break;
964 case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
Craig Tillerbefafe62017-02-09 11:30:54 -0800965 pick_subchannel_locked(exec_ctx, elem, NULL, 0,
966 &calld->connected_subchannel, NULL,
967 GRPC_ERROR_REF(op->cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700968 break;
969 }
Mark D. Roth72f6da82016-09-02 13:42:38 -0700970 grpc_transport_stream_op_finish_with_failure(
971 exec_ctx, op, GRPC_ERROR_REF(op->cancel_error));
Craig Tillera11bfc82017-02-14 09:56:33 -0800972 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700973 return;
974 }
975 }
976 /* if we don't have a subchannel, try to get one */
977 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
978 calld->connected_subchannel == NULL &&
979 op->send_initial_metadata != NULL) {
980 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
Craig Tillerbefafe62017-02-09 11:30:54 -0800981 grpc_closure_init(&calld->next_step, subchannel_ready_locked, elem,
982 grpc_combiner_scheduler(chand->combiner, true));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700983 GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
Yuchen Zeng144ce652016-09-01 18:19:34 -0700984 /* If a subchannel is not available immediately, the polling entity from
985 call_data should be provided to channel_data's interested_parties, so
986 that IO of the lb_policy and resolver could be done under it. */
Craig Tillerbefafe62017-02-09 11:30:54 -0800987 if (pick_subchannel_locked(exec_ctx, elem, op->send_initial_metadata,
988 op->send_initial_metadata_flags,
989 &calld->connected_subchannel, &calld->next_step,
990 GRPC_ERROR_NONE)) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700991 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
992 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
Yuchen Zeng19656b12016-09-01 18:00:45 -0700993 } else {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700994 grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
995 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700996 }
997 }
998 /* if we've got a subchannel, then let's ask it to create a call */
999 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
1000 calld->connected_subchannel != NULL) {
1001 grpc_subchannel_call *subchannel_call = NULL;
Craig Tillera7ed2682017-02-28 13:26:37 -08001002 apply_final_configuration_locked(exec_ctx, elem);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001003 grpc_error *error = grpc_connected_subchannel_create_call(
Mark D. Rothaa850a72016-09-26 13:38:02 -07001004 exec_ctx, calld->connected_subchannel, calld->pollent, calld->path,
Mark D. Roth3d883412016-11-07 13:42:54 -08001005 calld->call_start_time, calld->deadline, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001006 if (error != GRPC_ERROR_NONE) {
1007 subchannel_call = CANCELLED_CALL;
1008 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
1009 grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
1010 }
1011 gpr_atm_rel_store(&calld->subchannel_call,
1012 (gpr_atm)(uintptr_t)subchannel_call);
1013 retry_waiting_locked(exec_ctx, calld);
Craig Tillera11bfc82017-02-14 09:56:33 -08001014 /* recurse to retry */
Craig Tillera8610c02017-02-14 10:05:11 -08001015 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001016 /* early out */
1017 return;
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001018 }
1019 /* nothing to be done but wait */
1020 add_waiting_locked(calld, op);
Craig Tillera11bfc82017-02-14 09:56:33 -08001021}
1022
1023static void cc_start_transport_stream_op_locked(grpc_exec_ctx *exec_ctx,
1024 void *arg,
1025 grpc_error *error_ignored) {
1026 GPR_TIMER_BEGIN("cc_start_transport_stream_op_locked", 0);
1027
1028 grpc_transport_stream_op *op = arg;
1029 grpc_call_element *elem = op->handler_private.args[0];
1030 call_data *calld = elem->call_data;
1031
Craig Tillera8610c02017-02-14 10:05:11 -08001032 start_transport_stream_op_locked_inner(exec_ctx, op, elem);
Craig Tillera11bfc82017-02-14 09:56:33 -08001033
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001034 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
1035 "start_transport_stream_op");
Craig Tillera11bfc82017-02-14 09:56:33 -08001036 GPR_TIMER_END("cc_start_transport_stream_op_locked", 0);
Craig Tillerbefafe62017-02-09 11:30:54 -08001037}
1038
Craig Tillerbe9691a2017-02-14 10:00:42 -08001039/* The logic here is fairly complicated, due to (a) the fact that we
1040 need to handle the case where we receive the send op before the
1041 initial metadata op, and (b) the need for efficiency, especially in
1042 the streaming case.
1043
1044 We use double-checked locking to initially see if initialization has been
1045 performed. If it has not, we acquire the combiner and perform initialization.
1046 If it has, we proceed on the fast path. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001047static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
1048 grpc_call_element *elem,
1049 grpc_transport_stream_op *op) {
1050 call_data *calld = elem->call_data;
1051 channel_data *chand = elem->channel_data;
1052 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
1053 grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op);
1054 /* try to (atomically) get the call */
1055 grpc_subchannel_call *call = GET_CALL(calld);
1056 GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
1057 if (call == CANCELLED_CALL) {
1058 grpc_transport_stream_op_finish_with_failure(
1059 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
1060 GPR_TIMER_END("cc_start_transport_stream_op", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001061 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001062 return;
1063 }
1064 if (call != NULL) {
1065 grpc_subchannel_call_process_op(exec_ctx, call, op);
1066 GPR_TIMER_END("cc_start_transport_stream_op", 0);
Craig Tillera11bfc82017-02-14 09:56:33 -08001067 /* early out */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001068 return;
1069 }
1070 /* we failed; lock and figure out what to do */
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001071 GRPC_CALL_STACK_REF(calld->owning_call, "start_transport_stream_op");
Craig Tiller4a84bdd2017-02-14 09:48:41 -08001072 op->handler_private.args[0] = elem;
Craig Tillerbefafe62017-02-09 11:30:54 -08001073 grpc_closure_sched(
1074 exec_ctx,
Craig Tiller4a84bdd2017-02-14 09:48:41 -08001075 grpc_closure_init(&op->handler_private.closure,
Craig Tillerbefafe62017-02-09 11:30:54 -08001076 cc_start_transport_stream_op_locked, op,
1077 grpc_combiner_scheduler(chand->combiner, false)),
1078 GRPC_ERROR_NONE);
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001079 GPR_TIMER_END("cc_start_transport_stream_op", 0);
1080}
1081
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001082/* Constructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001083static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
1084 grpc_call_element *elem,
Craig Tillerc52ba3a2017-02-15 22:57:43 -08001085 const grpc_call_element_args *args) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001086 call_data *calld = elem->call_data;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001087 // Initialize data members.
1088 grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001089 calld->path = grpc_slice_ref_internal(args->path);
Mark D. Rothff08f332016-10-14 13:01:01 -07001090 calld->call_start_time = args->start_time;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001091 calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001092 calld->owning_call = args->call_stack;
Mark D. Roth0badbe82016-06-23 10:15:12 -07001093 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001094}
1095
1096/* Destructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001097static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
1098 grpc_call_element *elem,
1099 const grpc_call_final_info *final_info,
1100 void *and_free_memory) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001101 call_data *calld = elem->call_data;
Mark D. Rothf28763c2016-09-14 15:18:40 -07001102 grpc_deadline_state_destroy(exec_ctx, elem);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001103 grpc_slice_unref_internal(exec_ctx, calld->path);
Mark D. Rothf28763c2016-09-14 15:18:40 -07001104 GRPC_ERROR_UNREF(calld->cancel_error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001105 grpc_subchannel_call *call = GET_CALL(calld);
1106 if (call != NULL && call != CANCELLED_CALL) {
1107 GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
1108 }
1109 GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001110 GPR_ASSERT(calld->waiting_ops_count == 0);
Craig Tiller693d3942016-10-27 16:51:25 -07001111 if (calld->connected_subchannel != NULL) {
1112 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel,
1113 "picked");
1114 }
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001115 gpr_free(calld->waiting_ops);
Craig Tiller2c8063c2016-03-22 22:12:15 -07001116 gpr_free(and_free_memory);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001117}
1118
David Garcia Quintasf72eb972016-05-03 18:28:09 -07001119static void cc_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
1120 grpc_call_element *elem,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001121 grpc_polling_entity *pollent) {
Craig Tiller577c9b22015-11-02 14:11:15 -08001122 call_data *calld = elem->call_data;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001123 calld->pollent = pollent;
Craig Tiller577c9b22015-11-02 14:11:15 -08001124}
1125
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001126/*************************************************************************
1127 * EXPORTED SYMBOLS
1128 */
1129
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001130const grpc_channel_filter grpc_client_channel_filter = {
Craig Tillerf40df232016-03-25 13:38:14 -07001131 cc_start_transport_stream_op,
1132 cc_start_transport_op,
1133 sizeof(call_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001134 cc_init_call_elem,
David Garcia Quintas4afce7e2016-04-18 16:25:17 -07001135 cc_set_pollset_or_pollset_set,
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001136 cc_destroy_call_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001137 sizeof(channel_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001138 cc_init_channel_elem,
1139 cc_destroy_channel_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001140 cc_get_peer,
Mark D. Rothb2d24882016-10-27 15:44:07 -07001141 cc_get_channel_info,
Craig Tillerf40df232016-03-25 13:38:14 -07001142 "client-channel",
Craig Tiller87d5b192015-04-16 14:37:57 -07001143};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001144
Craig Tiller613dafa2017-02-09 12:00:43 -08001145static void try_to_connect_locked(grpc_exec_ctx *exec_ctx, void *arg,
1146 grpc_error *error_ignored) {
1147 channel_data *chand = arg;
1148 if (chand->lb_policy != NULL) {
Craig Tiller2400bf52017-02-09 16:25:19 -08001149 grpc_lb_policy_exit_idle_locked(exec_ctx, chand->lb_policy);
Craig Tiller613dafa2017-02-09 12:00:43 -08001150 } else {
1151 chand->exit_idle_when_lb_policy_arrives = true;
1152 if (!chand->started_resolving && chand->resolver != NULL) {
1153 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
1154 chand->started_resolving = true;
Craig Tiller972470b2017-02-09 15:05:36 -08001155 grpc_resolver_next_locked(exec_ctx, chand->resolver,
1156 &chand->resolver_result,
1157 &chand->on_resolver_result_changed);
Craig Tiller613dafa2017-02-09 12:00:43 -08001158 }
1159 }
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001160 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001161}
1162
Craig Tillera82950e2015-09-22 12:33:20 -07001163grpc_connectivity_state grpc_client_channel_check_connectivity_state(
1164 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001165 channel_data *chand = elem->channel_data;
Craig Tillera8610c02017-02-14 10:05:11 -08001166 grpc_connectivity_state out =
1167 grpc_connectivity_state_check(&chand->state_tracker);
Craig Tillera82950e2015-09-22 12:33:20 -07001168 if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
Craig Tillerd2e5cfc2017-02-09 13:02:20 -08001169 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "try_to_connect");
Craig Tiller613dafa2017-02-09 12:00:43 -08001170 grpc_closure_sched(
1171 exec_ctx,
1172 grpc_closure_create(try_to_connect_locked, chand,
1173 grpc_combiner_scheduler(chand->combiner, false)),
1174 GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -07001175 }
Craig Tiller48cb07c2015-07-15 16:16:15 -07001176 return out;
1177}
1178
Craig Tiller86c99582015-11-25 15:22:26 -08001179typedef struct {
1180 channel_data *chand;
1181 grpc_pollset *pollset;
1182 grpc_closure *on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001183 grpc_connectivity_state *state;
Craig Tiller86c99582015-11-25 15:22:26 -08001184 grpc_closure my_closure;
1185} external_connectivity_watcher;
1186
Craig Tiller1d881fb2015-12-01 07:39:04 -08001187static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -07001188 grpc_error *error) {
Craig Tiller86c99582015-11-25 15:22:26 -08001189 external_connectivity_watcher *w = arg;
1190 grpc_closure *follow_up = w->on_complete;
Craig Tiller69b093b2016-02-25 19:04:07 -08001191 grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
Craig Tiller1d881fb2015-12-01 07:39:04 -08001192 w->pollset);
1193 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
1194 "external_connectivity_watcher");
Craig Tiller86c99582015-11-25 15:22:26 -08001195 gpr_free(w);
Craig Tiller613dafa2017-02-09 12:00:43 -08001196 grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
1197}
1198
Craig Tillera8610c02017-02-14 10:05:11 -08001199static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg,
1200 grpc_error *error_ignored) {
Craig Tiller613dafa2017-02-09 12:00:43 -08001201 external_connectivity_watcher *w = arg;
1202 grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
1203 grpc_schedule_on_exec_ctx);
1204 grpc_connectivity_state_notify_on_state_change(
1205 exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
Craig Tiller86c99582015-11-25 15:22:26 -08001206}
1207
Craig Tillera82950e2015-09-22 12:33:20 -07001208void grpc_client_channel_watch_connectivity_state(
Craig Tiller906e3bc2015-11-24 07:31:31 -08001209 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
Craig Tillera82950e2015-09-22 12:33:20 -07001210 grpc_connectivity_state *state, grpc_closure *on_complete) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001211 channel_data *chand = elem->channel_data;
Craig Tiller86c99582015-11-25 15:22:26 -08001212 external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
1213 w->chand = chand;
1214 w->pollset = pollset;
1215 w->on_complete = on_complete;
Craig Tiller613dafa2017-02-09 12:00:43 -08001216 w->state = state;
Craig Tiller69b093b2016-02-25 19:04:07 -08001217 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
Craig Tiller1d881fb2015-12-01 07:39:04 -08001218 GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
1219 "external_connectivity_watcher");
Craig Tiller613dafa2017-02-09 12:00:43 -08001220 grpc_closure_sched(
1221 exec_ctx,
Craig Tillera8610c02017-02-14 10:05:11 -08001222 grpc_closure_init(&w->my_closure, watch_connectivity_state_locked, w,
Craig Tiller613dafa2017-02-09 12:00:43 -08001223 grpc_combiner_scheduler(chand->combiner, true)),
1224 GRPC_ERROR_NONE);
Craig Tiller48cb07c2015-07-15 16:16:15 -07001225}