blob: ce519f9c9291b75e9d4174989a1ea4606d287b7b [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/http_server_filter.h"
ctillerd74729d2015-01-12 13:31:36 -080035
Craig Tillerc50e3982015-01-20 16:30:54 -080036#include <grpc/support/alloc.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080037#include <grpc/support/log.h>
yang-gd88e1d82015-12-02 13:23:33 -080038#include <string.h>
Craig Tiller9533d042016-03-25 17:11:06 -070039#include "src/core/lib/profiling/timers.h"
Craig Tiller077da7f2016-11-16 14:55:44 -080040#include "src/core/lib/slice/percent_encoding.h"
Craig Tillera59c16c2016-10-31 07:25:01 -070041#include "src/core/lib/slice/slice_internal.h"
Craig Tiller7c70b6c2017-01-23 07:48:42 -080042#include "src/core/lib/slice/slice_string_helpers.h"
Craig Tiller9533d042016-03-25 17:11:06 -070043#include "src/core/lib/transport/static_metadata.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080044
Mark D. Roth640d71d2016-04-27 07:17:58 -070045#define EXPECTED_CONTENT_TYPE "application/grpc"
46#define EXPECTED_CONTENT_TYPE_LENGTH sizeof(EXPECTED_CONTENT_TYPE) - 1
47
Robbie Shade3c9728f2016-09-27 12:02:03 -040048extern int grpc_http_trace;
49
Craig Tillera82950e2015-09-22 12:33:20 -070050typedef struct call_data {
Craig Tiller6902ad22015-04-16 08:01:49 -070051 grpc_linked_mdelem status;
Craig Tillercb014172015-09-08 16:40:26 -070052 grpc_linked_mdelem content_type;
Craig Tiller83f88d92015-04-21 16:02:05 -070053
Craig Tiller7c70b6c2017-01-23 07:48:42 -080054 /* did this request come with payload-bin */
55 bool seen_payload_bin;
Makarand Dharmapurikarf44946b2016-08-29 15:47:43 -070056 /* flag to ensure payload_bin is delivered only once */
Craig Tiller7c70b6c2017-01-23 07:48:42 -080057 bool payload_bin_delivered;
Makarand Dharmapurikarf44946b2016-08-29 15:47:43 -070058
Craig Tiller577c9b22015-11-02 14:11:15 -080059 grpc_metadata_batch *recv_initial_metadata;
Craig Tiller4d40ba32016-03-09 17:48:40 -080060 bool *recv_idempotent_request;
Makarand Dharmapurikard322d4b2016-08-29 12:54:19 -070061 bool *recv_cacheable_request;
Craig Tiller98bf7e62015-06-24 08:47:07 -070062 /** Closure to call when finished with the hs_on_recv hook */
Craig Tiller33825112015-09-18 07:44:19 -070063 grpc_closure *on_done_recv;
Makdharma178f4bc2016-08-24 15:16:53 -070064 /** Closure to call when we retrieve read message from the payload-bin header
65 */
66 grpc_closure *recv_message_ready;
67 grpc_closure *on_complete;
68 grpc_byte_stream **pp_recv_message;
Craig Tillerd41a4a72016-10-26 16:16:06 -070069 grpc_slice_buffer read_slice_buffer;
Makdharma178f4bc2016-08-24 15:16:53 -070070 grpc_slice_buffer_stream read_stream;
71
Craig Tiller98bf7e62015-06-24 08:47:07 -070072 /** Receive closures are chained: we inject this closure as the on_done_recv
73 up-call on transport_op, and remember to call our on_done_recv member
74 after handling it. */
Craig Tiller33825112015-09-18 07:44:19 -070075 grpc_closure hs_on_recv;
Makdharma178f4bc2016-08-24 15:16:53 -070076 grpc_closure hs_on_complete;
77 grpc_closure hs_recv_message_ready;
ctillerd74729d2015-01-12 13:31:36 -080078} call_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080079
Craig Tiller7536af02015-12-22 13:49:30 -080080typedef struct channel_data { uint8_t unused; } channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080081
Craig Tiller7c70b6c2017-01-23 07:48:42 -080082static grpc_error *server_filter_outgoing_metadata(grpc_exec_ctx *exec_ctx,
83 grpc_call_element *elem,
84 grpc_metadata_batch *b) {
85 if (b->idx.named.grpc_message != NULL) {
Craig Tiller077da7f2016-11-16 14:55:44 -080086 grpc_slice pct_encoded_msg = grpc_percent_encode_slice(
Craig Tiller7c70b6c2017-01-23 07:48:42 -080087 GRPC_MDVALUE(b->idx.named.grpc_message->md),
88 grpc_compatible_percent_encoding_unreserved_bytes);
89 if (grpc_slice_is_equivalent(pct_encoded_msg,
90 GRPC_MDVALUE(b->idx.named.grpc_message->md))) {
Craig Tillerc5866662016-11-16 15:25:00 -080091 grpc_slice_unref_internal(exec_ctx, pct_encoded_msg);
Craig Tillerb121fc72016-11-03 15:22:59 -070092 } else {
Craig Tiller7c70b6c2017-01-23 07:48:42 -080093 grpc_metadata_batch_set_value(exec_ctx, b->idx.named.grpc_message,
94 pct_encoded_msg);
Craig Tillerb121fc72016-11-03 15:22:59 -070095 }
Craig Tillerb121fc72016-11-03 15:22:59 -070096 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -080097 return GRPC_ERROR_NONE;
Craig Tillerb121fc72016-11-03 15:22:59 -070098}
Craig Tillerd1bec032015-09-18 17:29:00 -070099
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800100static void add_error(const char *error_name, grpc_error **cumulative,
101 grpc_error *new) {
102 if (new == GRPC_ERROR_NONE) return;
103 if (*cumulative == GRPC_ERROR_NONE) {
104 *cumulative = GRPC_ERROR_CREATE(error_name);
105 }
106 *cumulative = grpc_error_add_child(*cumulative, new);
107}
Craig Tillera7d37a32016-11-22 14:37:16 -0800108
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800109static grpc_error *server_filter_incoming_metadata(grpc_exec_ctx *exec_ctx,
110 grpc_call_element *elem,
111 grpc_metadata_batch *b) {
112 call_data *calld = elem->call_data;
113 grpc_error *error = GRPC_ERROR_NONE;
114 static const char *error_name = "Failed processing incoming headers";
115
116 if (b->idx.named.method != NULL) {
117 if (grpc_mdelem_eq(b->idx.named.method->md, GRPC_MDELEM_METHOD_POST)) {
Craig Tiller4d40ba32016-03-09 17:48:40 -0800118 *calld->recv_idempotent_request = false;
Makarand Dharmapurikard322d4b2016-08-29 12:54:19 -0700119 *calld->recv_cacheable_request = false;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800120 } else if (grpc_mdelem_eq(b->idx.named.method->md,
121 GRPC_MDELEM_METHOD_PUT)) {
Craig Tiller4d40ba32016-03-09 17:48:40 -0800122 *calld->recv_idempotent_request = true;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800123 } else if (grpc_mdelem_eq(b->idx.named.method->md,
124 GRPC_MDELEM_METHOD_GET)) {
Makarand Dharmapurikard322d4b2016-08-29 12:54:19 -0700125 *calld->recv_cacheable_request = true;
Craig Tillera82950e2015-09-22 12:33:20 -0700126 } else {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800127 add_error(error_name, &error,
128 grpc_attach_md_to_error(GRPC_ERROR_CREATE("Bad header"),
129 b->idx.named.method->md));
Craig Tillera82950e2015-09-22 12:33:20 -0700130 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800131 grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.method);
132 } else {
133 add_error(error_name, &error,
134 grpc_error_set_str(GRPC_ERROR_CREATE("Missing header"),
135 GRPC_ERROR_STR_KEY, ":method"));
136 }
137
138 if (b->idx.named.te != NULL) {
139 if (!grpc_mdelem_eq(b->idx.named.te->md, GRPC_MDELEM_TE_TRAILERS)) {
140 add_error(error_name, &error,
141 grpc_attach_md_to_error(GRPC_ERROR_CREATE("Bad header"),
142 b->idx.named.te->md));
Craig Tiller6902ad22015-04-16 08:01:49 -0700143 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800144 grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.te);
145 } else {
146 add_error(error_name, &error,
147 grpc_error_set_str(GRPC_ERROR_CREATE("Missing header"),
148 GRPC_ERROR_STR_KEY, "te"));
149 }
150
151 if (b->idx.named.scheme != NULL) {
152 if (!grpc_mdelem_eq(b->idx.named.scheme->md, GRPC_MDELEM_SCHEME_HTTP) &&
153 !grpc_mdelem_eq(b->idx.named.scheme->md, GRPC_MDELEM_SCHEME_HTTPS) &&
154 !grpc_mdelem_eq(b->idx.named.scheme->md, GRPC_MDELEM_SCHEME_GRPC)) {
155 add_error(error_name, &error,
156 grpc_attach_md_to_error(GRPC_ERROR_CREATE("Bad header"),
157 b->idx.named.scheme->md));
158 }
159 grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.scheme);
160 } else {
161 add_error(error_name, &error,
162 grpc_error_set_str(GRPC_ERROR_CREATE("Missing header"),
163 GRPC_ERROR_STR_KEY, ":scheme"));
164 }
165
166 if (b->idx.named.content_type != NULL) {
167 if (!grpc_mdelem_eq(b->idx.named.content_type->md,
168 GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)) {
169 if (grpc_slice_buf_start_eq(GRPC_MDVALUE(b->idx.named.content_type->md),
170 EXPECTED_CONTENT_TYPE,
171 EXPECTED_CONTENT_TYPE_LENGTH) &&
172 (GRPC_SLICE_START_PTR(GRPC_MDVALUE(
173 b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
174 '+' ||
175 GRPC_SLICE_START_PTR(GRPC_MDVALUE(
176 b->idx.named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] ==
177 ';')) {
178 /* Although the C implementation doesn't (currently) generate them,
179 any custom +-suffix is explicitly valid. */
180 /* TODO(klempner): We should consider preallocating common values such
181 as +proto or +json, or at least stashing them if we see them. */
182 /* TODO(klempner): Should we be surfacing this to application code? */
183 } else {
184 /* TODO(klempner): We're currently allowing this, but we shouldn't
185 see it without a proxy so log for now. */
186 char *val = grpc_dump_slice(GRPC_MDVALUE(b->idx.named.content_type->md),
187 GPR_DUMP_ASCII);
188 gpr_log(GPR_INFO, "Unexpected content-type '%s'", val);
189 gpr_free(val);
190 }
191 }
192 grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.content_type);
193 }
194
195 if (b->idx.named.path == NULL) {
196 add_error(error_name, &error,
197 grpc_error_set_str(GRPC_ERROR_CREATE("Missing header"),
198 GRPC_ERROR_STR_KEY, ":path"));
199 }
200
Craig Tiller5fcc5af2017-02-08 15:22:05 -0800201 if (b->idx.named.host != NULL && b->idx.named.authority == NULL) {
Craig Tillerc15d25a2017-02-09 21:22:22 -0800202 grpc_linked_mdelem *el = b->idx.named.host;
203 grpc_mdelem md = GRPC_MDELEM_REF(el->md);
204 grpc_metadata_batch_remove(exec_ctx, b, el);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800205 add_error(
206 error_name, &error,
Craig Tiller5fcc5af2017-02-08 15:22:05 -0800207 grpc_metadata_batch_add_head(
Craig Tillerc15d25a2017-02-09 21:22:22 -0800208 exec_ctx, b, el, grpc_mdelem_from_slices(
209 exec_ctx, GRPC_MDSTR_AUTHORITY,
210 grpc_slice_ref_internal(GRPC_MDVALUE(md)))));
211 GRPC_MDELEM_UNREF(exec_ctx, md);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800212 }
213
214 if (b->idx.named.authority == NULL) {
215 add_error(error_name, &error,
216 grpc_error_set_str(GRPC_ERROR_CREATE("Missing header"),
217 GRPC_ERROR_STR_KEY, ":authority"));
218 }
219
220 if (b->idx.named.grpc_payload_bin != NULL) {
221 calld->seen_payload_bin = true;
Craig Tillerd41a4a72016-10-26 16:16:06 -0700222 grpc_slice_buffer_add(&calld->read_slice_buffer,
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800223 grpc_slice_ref_internal(
224 GRPC_MDVALUE(b->idx.named.grpc_payload_bin->md)));
Makdharma178f4bc2016-08-24 15:16:53 -0700225 grpc_slice_buffer_stream_init(&calld->read_stream,
226 &calld->read_slice_buffer, 0);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800227 grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_payload_bin);
Craig Tillera82950e2015-09-22 12:33:20 -0700228 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800229
230 return error;
Craig Tillerce6e3502015-01-19 18:04:42 -0800231}
232
Craig Tillerc027e772016-05-03 16:27:00 -0700233static void hs_on_recv(grpc_exec_ctx *exec_ctx, void *user_data,
234 grpc_error *err) {
Craig Tiller83f88d92015-04-21 16:02:05 -0700235 grpc_call_element *elem = user_data;
236 call_data *calld = elem->call_data;
Craig Tillerc027e772016-05-03 16:27:00 -0700237 if (err == GRPC_ERROR_NONE) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800238 err = server_filter_incoming_metadata(exec_ctx, elem,
239 calld->recv_initial_metadata);
Craig Tiller8e5c9342016-05-12 15:34:59 -0700240 } else {
241 GRPC_ERROR_REF(err);
Craig Tillera82950e2015-09-22 12:33:20 -0700242 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800243 grpc_closure_run(exec_ctx, calld->on_done_recv, err);
Craig Tiller83f88d92015-04-21 16:02:05 -0700244}
245
Makdharma178f4bc2016-08-24 15:16:53 -0700246static void hs_on_complete(grpc_exec_ctx *exec_ctx, void *user_data,
247 grpc_error *err) {
248 grpc_call_element *elem = user_data;
249 call_data *calld = elem->call_data;
250 /* Call recv_message_ready if we got the payload via the header field */
251 if (calld->seen_payload_bin && calld->recv_message_ready != NULL) {
Makarand Dharmapurikarf44946b2016-08-29 15:47:43 -0700252 *calld->pp_recv_message = calld->payload_bin_delivered
253 ? NULL
254 : (grpc_byte_stream *)&calld->read_stream;
Craig Tiller13792872017-02-23 15:29:55 -0800255 grpc_closure_run(exec_ctx, calld->recv_message_ready, GRPC_ERROR_REF(err));
Makdharma178f4bc2016-08-24 15:16:53 -0700256 calld->recv_message_ready = NULL;
Makarand Dharmapurikarf44946b2016-08-29 15:47:43 -0700257 calld->payload_bin_delivered = true;
Makdharma178f4bc2016-08-24 15:16:53 -0700258 }
Craig Tiller13792872017-02-23 15:29:55 -0800259 grpc_closure_run(exec_ctx, calld->on_complete, GRPC_ERROR_REF(err));
Makdharma178f4bc2016-08-24 15:16:53 -0700260}
261
262static void hs_recv_message_ready(grpc_exec_ctx *exec_ctx, void *user_data,
263 grpc_error *err) {
264 grpc_call_element *elem = user_data;
265 call_data *calld = elem->call_data;
266 if (calld->seen_payload_bin) {
267 /* do nothing. This is probably a GET request, and payload will be returned
268 in hs_on_complete callback. */
269 } else {
Craig Tiller13792872017-02-23 15:29:55 -0800270 grpc_closure_run(exec_ctx, calld->recv_message_ready, GRPC_ERROR_REF(err));
Makdharma178f4bc2016-08-24 15:16:53 -0700271 }
272}
273
Craig Tillerb121fc72016-11-03 15:22:59 -0700274static void hs_mutate_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
Craig Tillera82950e2015-09-22 12:33:20 -0700275 grpc_transport_stream_op *op) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800276 /* grab pointers to our data from the call element */
277 call_data *calld = elem->call_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800278
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800279 if (op->send_initial_metadata != NULL) {
280 grpc_error *error = GRPC_ERROR_NONE;
281 static const char *error_name = "Failed sending initial metadata";
282 add_error(error_name, &error, grpc_metadata_batch_add_head(
283 exec_ctx, op->send_initial_metadata,
284 &calld->status, GRPC_MDELEM_STATUS_200));
285 add_error(error_name, &error,
286 grpc_metadata_batch_add_tail(
287 exec_ctx, op->send_initial_metadata, &calld->content_type,
288 GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC));
289 add_error(error_name, &error,
290 server_filter_outgoing_metadata(exec_ctx, elem,
291 op->send_initial_metadata));
292 if (error != GRPC_ERROR_NONE) {
293 grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
294 return;
295 }
Craig Tillera82950e2015-09-22 12:33:20 -0700296 }
Craig Tiller83f88d92015-04-21 16:02:05 -0700297
Craig Tiller577c9b22015-11-02 14:11:15 -0800298 if (op->recv_initial_metadata) {
Craig Tillera82950e2015-09-22 12:33:20 -0700299 /* substitute our callback for the higher callback */
Craig Tillerc1b6bdd2016-03-10 07:10:38 -0800300 GPR_ASSERT(op->recv_idempotent_request != NULL);
Makarand Dharmapurikard322d4b2016-08-29 12:54:19 -0700301 GPR_ASSERT(op->recv_cacheable_request != NULL);
Craig Tiller577c9b22015-11-02 14:11:15 -0800302 calld->recv_initial_metadata = op->recv_initial_metadata;
Craig Tillerc1b6bdd2016-03-10 07:10:38 -0800303 calld->recv_idempotent_request = op->recv_idempotent_request;
Makarand Dharmapurikard322d4b2016-08-29 12:54:19 -0700304 calld->recv_cacheable_request = op->recv_cacheable_request;
Craig Tillera44cbfc2016-02-03 16:02:49 -0800305 calld->on_done_recv = op->recv_initial_metadata_ready;
306 op->recv_initial_metadata_ready = &calld->hs_on_recv;
Craig Tillera82950e2015-09-22 12:33:20 -0700307 }
Makdharma178f4bc2016-08-24 15:16:53 -0700308
309 if (op->recv_message) {
310 calld->recv_message_ready = op->recv_message_ready;
311 calld->pp_recv_message = op->recv_message;
312 if (op->recv_message_ready) {
313 op->recv_message_ready = &calld->hs_recv_message_ready;
314 }
Makdharma4e520592016-08-26 16:01:20 -0700315 if (op->on_complete) {
316 calld->on_complete = op->on_complete;
317 op->on_complete = &calld->hs_on_complete;
318 }
Makdharma178f4bc2016-08-24 15:16:53 -0700319 }
Craig Tillerb121fc72016-11-03 15:22:59 -0700320
321 if (op->send_trailing_metadata) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800322 grpc_error *error = server_filter_outgoing_metadata(
323 exec_ctx, elem, op->send_trailing_metadata);
324 if (error != GRPC_ERROR_NONE) {
325 grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
326 return;
327 }
Craig Tillerb121fc72016-11-03 15:22:59 -0700328 }
Craig Tiller50d9db52015-04-23 10:52:14 -0700329}
Craig Tiller83f88d92015-04-21 16:02:05 -0700330
Craig Tillera82950e2015-09-22 12:33:20 -0700331static void hs_start_transport_op(grpc_exec_ctx *exec_ctx,
332 grpc_call_element *elem,
333 grpc_transport_stream_op *op) {
334 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
Craig Tiller0ba432d2015-10-09 16:57:11 -0700335 GPR_TIMER_BEGIN("hs_start_transport_op", 0);
Craig Tillerb121fc72016-11-03 15:22:59 -0700336 hs_mutate_op(exec_ctx, elem, op);
Craig Tillera82950e2015-09-22 12:33:20 -0700337 grpc_call_next_op(exec_ctx, elem, op);
Craig Tiller0ba432d2015-10-09 16:57:11 -0700338 GPR_TIMER_END("hs_start_transport_op", 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800339}
340
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800341/* Constructor for call_data */
Mark D. Roth76d24422016-06-23 13:22:10 -0700342static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
Mark D. Roth0badbe82016-06-23 10:15:12 -0700343 grpc_call_element *elem,
Craig Tillerc52ba3a2017-02-15 22:57:43 -0800344 const grpc_call_element_args *args) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800345 /* grab pointers to our data from the call element */
346 call_data *calld = elem->call_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800347 /* initialize members */
Craig Tillera82950e2015-09-22 12:33:20 -0700348 memset(calld, 0, sizeof(*calld));
Craig Tiller91031da2016-12-28 15:44:25 -0800349 grpc_closure_init(&calld->hs_on_recv, hs_on_recv, elem,
350 grpc_schedule_on_exec_ctx);
351 grpc_closure_init(&calld->hs_on_complete, hs_on_complete, elem,
352 grpc_schedule_on_exec_ctx);
353 grpc_closure_init(&calld->hs_recv_message_ready, hs_recv_message_ready, elem,
354 grpc_schedule_on_exec_ctx);
Craig Tiller328cbcc2016-11-08 08:52:22 -0800355 grpc_slice_buffer_init(&calld->read_slice_buffer);
Mark D. Roth0badbe82016-06-23 10:15:12 -0700356 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800357}
358
359/* Destructor for call_data */
Craig Tiller2c8063c2016-03-22 22:12:15 -0700360static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
David Garcia Quintas5dde14c2016-07-28 17:29:27 -0700361 const grpc_call_final_info *final_info,
Craig Tiller378856b2016-10-31 07:47:08 -0700362 void *ignored) {
363 call_data *calld = elem->call_data;
Craig Tiller18b4ba32016-11-09 15:23:42 -0800364 grpc_slice_buffer_destroy_internal(exec_ctx, &calld->read_slice_buffer);
Craig Tiller378856b2016-10-31 07:47:08 -0700365}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800366
367/* Constructor for channel_data */
Mark D. Rothc1087882016-11-18 10:54:45 -0800368static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800369 grpc_channel_element *elem,
370 grpc_channel_element_args *args) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800371 GPR_ASSERT(!args->is_last);
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800372 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800373}
374
375/* Destructor for channel data */
Craig Tillera82950e2015-09-22 12:33:20 -0700376static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
Craig Tillerab33b482015-11-21 08:11:04 -0800377 grpc_channel_element *elem) {}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800378
379const grpc_channel_filter grpc_http_server_filter = {
Craig Tillerf40df232016-03-25 13:38:14 -0700380 hs_start_transport_op,
381 grpc_channel_next_op,
382 sizeof(call_data),
383 init_call_elem,
David Garcia Quintas4afce7e2016-04-18 16:25:17 -0700384 grpc_call_stack_ignore_set_pollset_or_pollset_set,
Craig Tillerf40df232016-03-25 13:38:14 -0700385 destroy_call_elem,
386 sizeof(channel_data),
387 init_channel_elem,
388 destroy_channel_elem,
389 grpc_call_next_get_peer,
Mark D. Rothb2d24882016-10-27 15:44:07 -0700390 grpc_channel_next_get_info,
Craig Tillerf40df232016-03-25 13:38:14 -0700391 "http-server"};