blob: b1760648134d4142d8fc53455aaf6a19e3b1d0f5 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
3 * Copyright 2014, Google Inc.
4 * 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/http_server_filter.h"
35#include <grpc/support/log.h>
36
37typedef struct call_data {
38 int unused; /* C89 requires at least one struct element */
39} call_data;
40
41typedef struct channel_data { grpc_mdelem *te_trailers; } channel_data;
42
43/* used to silence 'variable not used' warnings */
44static void ignore_unused(void *ignored) {}
45
46/* Called either:
47 - in response to an API call (or similar) from above, to send something
48 - a network event (or similar) from below, to receive something
49 op contains type and call direction information, in addition to the data
50 that is being sent or received. */
51static void call_op(grpc_call_element *elem, grpc_call_op *op) {
52 /* grab pointers to our data from the call element */
53 call_data *calld = elem->call_data;
54 channel_data *channeld = elem->channel_data;
55 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
56
57 ignore_unused(calld);
58 ignore_unused(channeld);
59
60 switch (op->type) {
61 case GRPC_RECV_METADATA:
62 /* check if it's a te: trailers header */
63 if (op->data.metadata == channeld->te_trailers) {
64 /* swallow it */
65 grpc_mdelem_unref(op->data.metadata);
66 op->done_cb(op->user_data, GRPC_OP_OK);
67 } else {
68 /* pass the event up */
69 grpc_call_next_op(elem, op);
70 }
71 break;
72 default:
73 /* pass control up or down the stack depending on op->dir */
74 grpc_call_next_op(elem, op);
75 break;
76 }
77}
78
79/* Called on special channel events, such as disconnection or new incoming
80 calls on the server */
81static void channel_op(grpc_channel_element *elem, grpc_channel_op *op) {
82 /* grab pointers to our data from the channel element */
83 channel_data *channeld = elem->channel_data;
84
85 ignore_unused(channeld);
86
87 switch (op->type) {
88 default:
89 /* pass control up or down the stack depending on op->dir */
90 grpc_channel_next_op(elem, op);
91 break;
92 }
93}
94
95/* Constructor for call_data */
96static void init_call_elem(grpc_call_element *elem,
97 const void *server_transport_data) {
98 /* grab pointers to our data from the call element */
99 call_data *calld = elem->call_data;
100 channel_data *channeld = elem->channel_data;
101
102 ignore_unused(channeld);
103
104 /* initialize members */
105 calld->unused = 0;
106}
107
108/* Destructor for call_data */
109static void destroy_call_elem(grpc_call_element *elem) {
110 /* grab pointers to our data from the call element */
111 call_data *calld = elem->call_data;
112 channel_data *channeld = elem->channel_data;
113
114 ignore_unused(calld);
115 ignore_unused(channeld);
116}
117
118/* Constructor for channel_data */
119static void init_channel_elem(grpc_channel_element *elem,
120 const grpc_channel_args *args, grpc_mdctx *mdctx,
121 int is_first, int is_last) {
122 /* grab pointers to our data from the channel element */
123 channel_data *channeld = elem->channel_data;
124
125 /* The first and the last filters tend to be implemented differently to
126 handle the case that there's no 'next' filter to call on the up or down
127 path */
128 GPR_ASSERT(!is_first);
129 GPR_ASSERT(!is_last);
130
131 /* initialize members */
132 channeld->te_trailers = grpc_mdelem_from_strings(mdctx, "te", "trailers");
133}
134
135/* Destructor for channel data */
136static void destroy_channel_elem(grpc_channel_element *elem) {
137 /* grab pointers to our data from the channel element */
138 channel_data *channeld = elem->channel_data;
139
140 grpc_mdelem_unref(channeld->te_trailers);
141}
142
143const grpc_channel_filter grpc_http_server_filter = {
144 call_op, channel_op,
145
146 sizeof(call_data), init_call_elem, destroy_call_elem,
147
148 sizeof(channel_data), init_channel_elem, destroy_channel_elem,
149
150 "http-server"};