blob: bc997b192c80574acf4c137dfedb226c09110a56 [file] [log] [blame]
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -07001/*
2 *
Craig Tillera93a25f2016-01-28 13:55:49 -08003 * Copyright 2015-2016, Google Inc.
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -07004 * 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
34#include "src/core/channel/client_uchannel.h"
35
36#include <string.h>
37
38#include "src/core/census/grpc_filter.h"
39#include "src/core/channel/channel_args.h"
40#include "src/core/channel/client_channel.h"
41#include "src/core/channel/compress_filter.h"
Craig Tiller577c9b22015-11-02 14:11:15 -080042#include "src/core/channel/subchannel_call_holder.h"
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -070043#include "src/core/iomgr/iomgr.h"
44#include "src/core/support/string.h"
45#include "src/core/surface/channel.h"
46#include "src/core/transport/connectivity_state.h"
47
48#include <grpc/support/alloc.h>
49#include <grpc/support/log.h>
50#include <grpc/support/sync.h>
51#include <grpc/support/useful.h>
52
53/** Microchannel (uchannel) implementation: a lightweight channel without any
54 * load-balancing mechanisms meant for communication from within the core. */
55
David Garcia Quintasc22adbc2015-10-13 16:59:24 -070056typedef struct client_uchannel_channel_data {
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -070057 /** master channel - the grpc_channel instance that ultimately owns
58 this channel_data via its channel stack.
59 We occasionally use this to bump the refcount on the master channel
60 to keep ourselves alive through an asynchronous operation. */
Craig Tiller906e3bc2015-11-24 07:31:31 -080061 grpc_channel_stack *owning_stack;
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -070062
63 /** connectivity state being tracked */
64 grpc_connectivity_state_tracker state_tracker;
65
66 /** the subchannel wrapped by the microchannel */
Craig Tillerb5585d42015-11-17 07:18:31 -080067 grpc_connected_subchannel *connected_subchannel;
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -070068
69 /** the callback used to stay subscribed to subchannel connectivity
70 * notifications */
71 grpc_closure connectivity_cb;
72
73 /** the current connectivity state of the wrapped subchannel */
74 grpc_connectivity_state subchannel_connectivity;
75
76 gpr_mu mu_state;
77} channel_data;
78
Craig Tiller577c9b22015-11-02 14:11:15 -080079typedef grpc_subchannel_call_holder call_data;
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -070080
81static void monitor_subchannel(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller6c396862016-01-28 13:53:40 -080082 bool iomgr_success) {
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -070083 channel_data *chand = arg;
84 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
85 chand->subchannel_connectivity,
86 "uchannel_monitor_subchannel");
Craig Tillerab33b482015-11-21 08:11:04 -080087 grpc_connected_subchannel_notify_on_state_change(
Craig Tillera6bebf42015-12-01 17:02:35 -080088 exec_ctx, chand->connected_subchannel, NULL,
89 &chand->subchannel_connectivity, &chand->connectivity_cb);
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -070090}
91
David Garcia Quintas85ccb8c2015-10-19 17:55:29 -070092static char *cuc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
Craig Tiller906e3bc2015-11-24 07:31:31 -080093 return grpc_subchannel_call_holder_get_peer(exec_ctx, elem->call_data);
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -070094}
95
David Garcia Quintas85ccb8c2015-10-19 17:55:29 -070096static void cuc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -070097 grpc_call_element *elem,
98 grpc_transport_stream_op *op) {
Craig Tiller577c9b22015-11-02 14:11:15 -080099 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
100 grpc_subchannel_call_holder_perform_op(exec_ctx, elem->call_data, op);
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700101}
102
David Garcia Quintas85ccb8c2015-10-19 17:55:29 -0700103static void cuc_start_transport_op(grpc_exec_ctx *exec_ctx,
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700104 grpc_channel_element *elem,
105 grpc_transport_op *op) {
106 channel_data *chand = elem->channel_data;
107
Craig Tiller6c396862016-01-28 13:53:40 -0800108 grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700109
110 GPR_ASSERT(op->set_accept_stream == NULL);
111 GPR_ASSERT(op->bind_pollset == NULL);
112
113 if (op->on_connectivity_state_change != NULL) {
114 grpc_connectivity_state_notify_on_state_change(
115 exec_ctx, &chand->state_tracker, op->connectivity_state,
116 op->on_connectivity_state_change);
117 op->on_connectivity_state_change = NULL;
118 op->connectivity_state = NULL;
119 }
120
121 if (op->disconnect) {
122 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
123 GRPC_CHANNEL_FATAL_FAILURE, "disconnect");
124 }
125}
126
Craig Tiller577c9b22015-11-02 14:11:15 -0800127static int cuc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *arg,
128 grpc_metadata_batch *initial_metadata,
Craig Tillerb5585d42015-11-17 07:18:31 -0800129 grpc_connected_subchannel **connected_subchannel,
Craig Tiller577c9b22015-11-02 14:11:15 -0800130 grpc_closure *on_ready) {
131 channel_data *chand = arg;
132 GPR_ASSERT(initial_metadata != NULL);
Craig Tillerb5585d42015-11-17 07:18:31 -0800133 *connected_subchannel = chand->connected_subchannel;
Craig Tiller577c9b22015-11-02 14:11:15 -0800134 return 1;
135}
136
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700137/* Constructor for call_data */
David Garcia Quintas85ccb8c2015-10-19 17:55:29 -0700138static void cuc_init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
Craig Tiller577c9b22015-11-02 14:11:15 -0800139 grpc_call_element_args *args) {
140 grpc_subchannel_call_holder_init(elem->call_data, cuc_pick_subchannel,
Craig Tiller11beb9a2015-11-24 10:29:32 -0800141 elem->channel_data, args->call_stack);
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700142}
143
144/* Destructor for call_data */
David Garcia Quintas85ccb8c2015-10-19 17:55:29 -0700145static void cuc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700146 grpc_call_element *elem) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800147 grpc_subchannel_call_holder_destroy(exec_ctx, elem->call_data);
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700148}
149
150/* Constructor for channel_data */
David Garcia Quintas85ccb8c2015-10-19 17:55:29 -0700151static void cuc_init_channel_elem(grpc_exec_ctx *exec_ctx,
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700152 grpc_channel_element *elem,
Craig Tiller577c9b22015-11-02 14:11:15 -0800153 grpc_channel_element_args *args) {
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700154 channel_data *chand = elem->channel_data;
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700155 memset(chand, 0, sizeof(*chand));
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700156 grpc_closure_init(&chand->connectivity_cb, monitor_subchannel, chand);
Craig Tiller577c9b22015-11-02 14:11:15 -0800157 GPR_ASSERT(args->is_last);
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700158 GPR_ASSERT(elem->filter == &grpc_client_uchannel_filter);
Craig Tiller906e3bc2015-11-24 07:31:31 -0800159 chand->owning_stack = args->channel_stack;
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700160 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
161 "client_uchannel");
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700162 gpr_mu_init(&chand->mu_state);
163}
164
165/* Destructor for channel_data */
David Garcia Quintas85ccb8c2015-10-19 17:55:29 -0700166static void cuc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700167 grpc_channel_element *elem) {
168 channel_data *chand = elem->channel_data;
Craig Tiller48613042015-11-29 14:45:11 -0800169 /* cancel subscription */
170 grpc_connected_subchannel_notify_on_state_change(
Craig Tillera6bebf42015-12-01 17:02:35 -0800171 exec_ctx, chand->connected_subchannel, NULL, NULL,
172 &chand->connectivity_cb);
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700173 grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
David Garcia Quintasfbb6b922015-10-23 13:46:26 -0700174 gpr_mu_destroy(&chand->mu_state);
Craig Tillera6bebf42015-12-01 17:02:35 -0800175 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, chand->connected_subchannel,
176 "uchannel");
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700177}
178
Craig Tiller577c9b22015-11-02 14:11:15 -0800179static void cuc_set_pollset(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
180 grpc_pollset *pollset) {
181 call_data *calld = elem->call_data;
182 calld->pollset = pollset;
183}
184
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700185const grpc_channel_filter grpc_client_uchannel_filter = {
Craig Tiller577c9b22015-11-02 14:11:15 -0800186 cuc_start_transport_stream_op, cuc_start_transport_op, sizeof(call_data),
187 cuc_init_call_elem, cuc_set_pollset, cuc_destroy_call_elem,
188 sizeof(channel_data), cuc_init_channel_elem, cuc_destroy_channel_elem,
189 cuc_get_peer, "client-uchannel",
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700190};
191
192grpc_connectivity_state grpc_client_uchannel_check_connectivity_state(
193 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
194 channel_data *chand = elem->channel_data;
195 grpc_connectivity_state out;
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700196 gpr_mu_lock(&chand->mu_state);
Craig Tillerf036a642015-12-01 17:00:40 -0800197 out = grpc_connectivity_state_check(&chand->state_tracker);
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700198 gpr_mu_unlock(&chand->mu_state);
199 return out;
200}
201
202void grpc_client_uchannel_watch_connectivity_state(
Craig Tiller7b435612015-11-24 08:15:05 -0800203 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700204 grpc_connectivity_state *state, grpc_closure *on_complete) {
205 channel_data *chand = elem->channel_data;
206 gpr_mu_lock(&chand->mu_state);
207 grpc_connectivity_state_notify_on_state_change(
208 exec_ctx, &chand->state_tracker, state, on_complete);
209 gpr_mu_unlock(&chand->mu_state);
210}
211
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700212grpc_channel *grpc_client_uchannel_create(grpc_subchannel *subchannel,
213 grpc_channel_args *args) {
214 grpc_channel *channel = NULL;
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700215 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700216
Craig Tillerb2b42612015-11-20 12:02:17 -0800217 channel =
Craig Tiller178edfa2016-02-17 20:54:46 -0800218 grpc_channel_create(&exec_ctx, NULL, args, GRPC_CLIENT_UCHANNEL, NULL);
David Garcia Quintas85ccb8c2015-10-19 17:55:29 -0700219
David Garcia Quintas7b1bd2c2015-10-05 18:22:10 -0700220 return channel;
221}
David Garcia Quintas85ccb8c2015-10-19 17:55:29 -0700222
Craig Tillerab33b482015-11-21 08:11:04 -0800223void grpc_client_uchannel_set_connected_subchannel(
224 grpc_channel *uchannel, grpc_connected_subchannel *connected_subchannel) {
David Garcia Quintas85ccb8c2015-10-19 17:55:29 -0700225 grpc_channel_element *elem =
226 grpc_channel_stack_last_element(grpc_channel_get_channel_stack(uchannel));
227 channel_data *chand = elem->channel_data;
228 GPR_ASSERT(elem->filter == &grpc_client_uchannel_filter);
229 gpr_mu_lock(&chand->mu_state);
Craig Tillerb5585d42015-11-17 07:18:31 -0800230 chand->connected_subchannel = connected_subchannel;
Craig Tillerf036a642015-12-01 17:00:40 -0800231 GRPC_CONNECTED_SUBCHANNEL_REF(connected_subchannel, "uchannel");
David Garcia Quintas85ccb8c2015-10-19 17:55:29 -0700232 gpr_mu_unlock(&chand->mu_state);
233}