blob: 73714369cdc7d74d0205c50a1a903f428edd9113 [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
Craig Tiller9533d042016-03-25 17:11:06 -070034#include "src/core/lib/channel/connected_channel.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080035
36#include <stdarg.h>
37#include <stdio.h>
38#include <string.h>
39
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080040#include <grpc/byte_buffer.h>
41#include <grpc/support/alloc.h>
42#include <grpc/support/log.h>
43#include <grpc/support/slice_buffer.h>
Craig Tiller9533d042016-03-25 17:11:06 -070044#include "src/core/lib/profiling/timers.h"
45#include "src/core/lib/support/string.h"
46#include "src/core/lib/transport/transport.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080047
48#define MAX_BUFFER_LENGTH 8192
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080049
Craig Tillera82950e2015-09-22 12:33:20 -070050typedef struct connected_channel_channel_data {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080051 grpc_transport *transport;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080052} channel_data;
53
Craig Tillera82950e2015-09-22 12:33:20 -070054typedef struct connected_channel_call_data { void *unused; } call_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080055
56/* We perform a small hack to locate transport data alongside the connected
57 channel data in call allocations, to allow everything to be pulled in minimal
58 cache line requests */
Yang Gao5fd0d292015-01-26 00:19:48 -080059#define TRANSPORT_STREAM_FROM_CALL_DATA(calld) ((grpc_stream *)((calld) + 1))
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080060#define CALL_DATA_FROM_TRANSPORT_STREAM(transport_stream) \
61 (((call_data *)(transport_stream)) - 1)
62
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080063/* Intercept a call operation and either push it directly up or translate it
64 into transport stream operations */
Craig Tillera82950e2015-09-22 12:33:20 -070065static void con_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
66 grpc_call_element *elem,
67 grpc_transport_stream_op *op) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080068 call_data *calld = elem->call_data;
69 channel_data *chand = elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -070070 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080071
Craig Tillera82950e2015-09-22 12:33:20 -070072 grpc_transport_perform_stream_op(exec_ctx, chand->transport,
73 TRANSPORT_STREAM_FROM_CALL_DATA(calld), op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080074}
75
Craig Tillera82950e2015-09-22 12:33:20 -070076static void con_start_transport_op(grpc_exec_ctx *exec_ctx,
77 grpc_channel_element *elem,
78 grpc_transport_op *op) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080079 channel_data *chand = elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -070080 grpc_transport_perform_op(exec_ctx, chand->transport, op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080081}
82
83/* Constructor for call_data */
Craig Tillera82950e2015-09-22 12:33:20 -070084static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
Craig Tiller577c9b22015-11-02 14:11:15 -080085 grpc_call_element_args *args) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080086 call_data *calld = elem->call_data;
87 channel_data *chand = elem->channel_data;
88 int r;
89
Craig Tiller7b435612015-11-24 08:15:05 -080090 r = grpc_transport_init_stream(
91 exec_ctx, chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld),
92 &args->call_stack->refcount, args->server_transport_data);
Craig Tillera82950e2015-09-22 12:33:20 -070093 GPR_ASSERT(r == 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080094}
95
David Garcia Quintasf72eb972016-05-03 18:28:09 -070096static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
97 grpc_call_element *elem,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -070098 grpc_polling_entity *pollent) {
Craig Tiller577c9b22015-11-02 14:11:15 -080099 call_data *calld = elem->call_data;
100 channel_data *chand = elem->channel_data;
David Garcia Quintasf72eb972016-05-03 18:28:09 -0700101 grpc_transport_set_pops(exec_ctx, chand->transport,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700102 TRANSPORT_STREAM_FROM_CALL_DATA(calld), pollent);
Craig Tiller577c9b22015-11-02 14:11:15 -0800103}
104
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800105/* Destructor for call_data */
Craig Tiller2c8063c2016-03-22 22:12:15 -0700106static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
David Garcia Quintas01c4d992016-07-07 20:11:27 -0700107 const grpc_call_final_info *final_info,
Craig Tiller2c8063c2016-03-22 22:12:15 -0700108 void *and_free_memory) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800109 call_data *calld = elem->call_data;
110 channel_data *chand = elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700111 grpc_transport_destroy_stream(exec_ctx, chand->transport,
Craig Tiller2c8063c2016-03-22 22:12:15 -0700112 TRANSPORT_STREAM_FROM_CALL_DATA(calld),
113 and_free_memory);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800114}
115
116/* Constructor for channel_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700117static void init_channel_elem(grpc_exec_ctx *exec_ctx,
Craig Tiller577c9b22015-11-02 14:11:15 -0800118 grpc_channel_element *elem,
119 grpc_channel_element_args *args) {
Craig Tillera82950e2015-09-22 12:33:20 -0700120 channel_data *cd = (channel_data *)elem->channel_data;
Craig Tiller577c9b22015-11-02 14:11:15 -0800121 GPR_ASSERT(args->is_last);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800122 cd->transport = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800123}
124
125/* Destructor for channel_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700126static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
127 grpc_channel_element *elem) {
128 channel_data *cd = (channel_data *)elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700129 grpc_transport_destroy(exec_ctx, cd->transport);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800130}
131
Craig Tillera82950e2015-09-22 12:33:20 -0700132static char *con_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700133 channel_data *chand = elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700134 return grpc_transport_get_peer(exec_ctx, chand->transport);
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700135}
136
Craig Tiller178edfa2016-02-17 20:54:46 -0800137static const grpc_channel_filter connected_channel_filter = {
Craig Tillerf40df232016-03-25 13:38:14 -0700138 con_start_transport_stream_op,
139 con_start_transport_op,
140 sizeof(call_data),
141 init_call_elem,
David Garcia Quintas4afce7e2016-04-18 16:25:17 -0700142 set_pollset_or_pollset_set,
Craig Tillerf40df232016-03-25 13:38:14 -0700143 destroy_call_elem,
144 sizeof(channel_data),
145 init_channel_elem,
146 destroy_channel_elem,
147 con_get_peer,
148 "connected",
Craig Tiller87d5b192015-04-16 14:37:57 -0700149};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800150
Craig Tiller178edfa2016-02-17 20:54:46 -0800151static void bind_transport(grpc_channel_stack *channel_stack,
152 grpc_channel_element *elem, void *t) {
Craig Tillera82950e2015-09-22 12:33:20 -0700153 channel_data *cd = (channel_data *)elem->channel_data;
Craig Tiller178edfa2016-02-17 20:54:46 -0800154 GPR_ASSERT(elem->filter == &connected_channel_filter);
Craig Tillera82950e2015-09-22 12:33:20 -0700155 GPR_ASSERT(cd->transport == NULL);
Craig Tiller178edfa2016-02-17 20:54:46 -0800156 cd->transport = t;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800157
158 /* HACK(ctiller): increase call stack size for the channel to make space
159 for channel data. We need a cleaner (but performant) way to do this,
160 and I'm not sure what that is yet.
161 This is only "safe" because call stacks place no additional data after
162 the last call element, and the last call element MUST be the connected
163 channel. */
Craig Tiller178edfa2016-02-17 20:54:46 -0800164 channel_stack->call_stack_size += grpc_transport_stream_size(t);
165}
166
167bool grpc_add_connected_filter(grpc_channel_stack_builder *builder,
168 void *arg_must_be_null) {
169 GPR_ASSERT(arg_must_be_null == NULL);
170 grpc_transport *t = grpc_channel_stack_builder_get_transport(builder);
171 GPR_ASSERT(t != NULL);
172 return grpc_channel_stack_builder_append_filter(
173 builder, &connected_channel_filter, bind_transport, t);
Craig Tiller190d3602015-02-18 09:23:38 -0800174}
Craig Tiller577c9b22015-11-02 14:11:15 -0800175
176grpc_stream *grpc_connected_channel_get_stream(grpc_call_element *elem) {
177 call_data *calld = elem->call_data;
178 return TRANSPORT_STREAM_FROM_CALL_DATA(calld);
179}