blob: c3060cd9260e06e0433afbad910eb63404902c8b [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller06059952015-02-18 08:34:56 -08003 * 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
34#include "src/core/channel/connected_channel.h"
35
36#include <stdarg.h>
37#include <stdio.h>
38#include <string.h>
39
Craig Tiller485d7762015-01-23 12:54:05 -080040#include "src/core/support/string.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080041#include "src/core/transport/transport.h"
Craig Tiller1f41b6b2015-10-09 15:07:02 -070042#include "src/core/profiling/timers.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080043#include <grpc/byte_buffer.h>
44#include <grpc/support/alloc.h>
45#include <grpc/support/log.h>
46#include <grpc/support/slice_buffer.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
Craig Tiller577c9b22015-11-02 14:11:15 -080096static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
97 grpc_pollset *pollset) {
98 call_data *calld = elem->call_data;
99 channel_data *chand = elem->channel_data;
100 grpc_transport_set_pollset(exec_ctx, chand->transport,
101 TRANSPORT_STREAM_FROM_CALL_DATA(calld), pollset);
102}
103
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800104/* Destructor for call_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700105static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
106 grpc_call_element *elem) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800107 call_data *calld = elem->call_data;
108 channel_data *chand = elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700109 grpc_transport_destroy_stream(exec_ctx, chand->transport,
110 TRANSPORT_STREAM_FROM_CALL_DATA(calld));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800111}
112
113/* Constructor for channel_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700114static void init_channel_elem(grpc_exec_ctx *exec_ctx,
Craig Tiller577c9b22015-11-02 14:11:15 -0800115 grpc_channel_element *elem,
116 grpc_channel_element_args *args) {
Craig Tillera82950e2015-09-22 12:33:20 -0700117 channel_data *cd = (channel_data *)elem->channel_data;
Craig Tiller577c9b22015-11-02 14:11:15 -0800118 GPR_ASSERT(args->is_last);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800119 cd->transport = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800120}
121
122/* Destructor for channel_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700123static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
124 grpc_channel_element *elem) {
125 channel_data *cd = (channel_data *)elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700126 grpc_transport_destroy(exec_ctx, cd->transport);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800127}
128
Craig Tillera82950e2015-09-22 12:33:20 -0700129static char *con_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700130 channel_data *chand = elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700131 return grpc_transport_get_peer(exec_ctx, chand->transport);
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700132}
133
Craig Tiller178edfa2016-02-17 20:54:46 -0800134static const grpc_channel_filter connected_channel_filter = {
Craig Tiller71a0f9d2015-09-28 17:22:01 -0700135 con_start_transport_stream_op, con_start_transport_op, sizeof(call_data),
Craig Tiller577c9b22015-11-02 14:11:15 -0800136 init_call_elem, set_pollset, destroy_call_elem, sizeof(channel_data),
137 init_channel_elem, destroy_channel_elem, con_get_peer, "connected",
Craig Tiller87d5b192015-04-16 14:37:57 -0700138};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800139
Craig Tiller178edfa2016-02-17 20:54:46 -0800140static void bind_transport(grpc_channel_stack *channel_stack,
141 grpc_channel_element *elem, void *t) {
Craig Tillera82950e2015-09-22 12:33:20 -0700142 channel_data *cd = (channel_data *)elem->channel_data;
Craig Tiller178edfa2016-02-17 20:54:46 -0800143 GPR_ASSERT(elem->filter == &connected_channel_filter);
Craig Tillera82950e2015-09-22 12:33:20 -0700144 GPR_ASSERT(cd->transport == NULL);
Craig Tiller178edfa2016-02-17 20:54:46 -0800145 cd->transport = t;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800146
147 /* HACK(ctiller): increase call stack size for the channel to make space
148 for channel data. We need a cleaner (but performant) way to do this,
149 and I'm not sure what that is yet.
150 This is only "safe" because call stacks place no additional data after
151 the last call element, and the last call element MUST be the connected
152 channel. */
Craig Tiller178edfa2016-02-17 20:54:46 -0800153 channel_stack->call_stack_size += grpc_transport_stream_size(t);
154}
155
156bool grpc_add_connected_filter(grpc_channel_stack_builder *builder,
157 void *arg_must_be_null) {
158 GPR_ASSERT(arg_must_be_null == NULL);
159 grpc_transport *t = grpc_channel_stack_builder_get_transport(builder);
160 GPR_ASSERT(t != NULL);
161 return grpc_channel_stack_builder_append_filter(
162 builder, &connected_channel_filter, bind_transport, t);
Craig Tiller190d3602015-02-18 09:23:38 -0800163}
Craig Tiller577c9b22015-11-02 14:11:15 -0800164
165grpc_stream *grpc_connected_channel_get_stream(grpc_call_element *elem) {
166 call_data *calld = elem->call_data;
167 return TRANSPORT_STREAM_FROM_CALL_DATA(calld);
168}