blob: 93994e6bdda8014a9fc8305fbd4949b70d57889e [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/surface/server.h"
35
36#include <stdlib.h>
37#include <string.h>
38
39#include "src/core/channel/census_filter.h"
40#include "src/core/channel/channel_args.h"
41#include "src/core/channel/connected_channel.h"
ctiller18b49ab2014-12-09 14:39:16 -080042#include "src/core/iomgr/iomgr.h"
Craig Tiller485d7762015-01-23 12:54:05 -080043#include "src/core/support/string.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080044#include "src/core/surface/call.h"
45#include "src/core/surface/channel.h"
46#include "src/core/surface/completion_queue.h"
Craig Tillercce17ac2015-01-20 09:29:28 -080047#include "src/core/transport/metadata.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080048#include <grpc/support/alloc.h>
49#include <grpc/support/log.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080050#include <grpc/support/useful.h>
51
52typedef enum { PENDING_START, ALL_CALLS, CALL_LIST_COUNT } call_list;
53
54typedef struct listener {
55 void *arg;
ctiller58393c22015-01-07 14:03:30 -080056 void (*start)(grpc_server *server, void *arg, grpc_pollset *pollset);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080057 void (*destroy)(grpc_server *server, void *arg);
58 struct listener *next;
59} listener;
60
61typedef struct call_data call_data;
62typedef struct channel_data channel_data;
Craig Tiller24be0f72015-02-10 14:04:22 -080063typedef struct registered_method registered_method;
64
65typedef struct {
66 call_data *next;
67 call_data *prev;
68} call_link;
69
70typedef enum { LEGACY_CALL, BATCH_CALL, REGISTERED_CALL } requested_call_type;
71
72typedef struct {
73 requested_call_type type;
74 void *tag;
75 union {
76 struct {
Craig Tiller8e8fd892015-02-10 17:02:08 -080077 grpc_completion_queue *cq_new;
78 grpc_completion_queue *cq_bind;
Craig Tiller24be0f72015-02-10 14:04:22 -080079 grpc_call **call;
80 grpc_call_details *details;
81 grpc_metadata_array *initial_metadata;
82 } batch;
83 struct {
Craig Tiller8e8fd892015-02-10 17:02:08 -080084 grpc_completion_queue *cq_new;
85 grpc_completion_queue *cq_bind;
Craig Tiller24be0f72015-02-10 14:04:22 -080086 grpc_call **call;
87 registered_method *registered_method;
88 gpr_timespec *deadline;
89 grpc_metadata_array *initial_metadata;
90 grpc_byte_buffer **optional_payload;
91 } registered;
92 } data;
93} requested_call;
94
95typedef struct {
96 requested_call *calls;
97 size_t count;
98 size_t capacity;
99} requested_call_array;
100
101struct registered_method {
102 char *method;
103 char *host;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800104 call_data *pending;
Craig Tiller24be0f72015-02-10 14:04:22 -0800105 requested_call_array requested;
106 registered_method *next;
107};
108
109typedef struct channel_registered_method {
110 registered_method *server_registered_method;
111 grpc_mdstr *method;
112 grpc_mdstr *host;
113} channel_registered_method;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800114
115struct channel_data {
116 grpc_server *server;
117 grpc_channel *channel;
Craig Tillercce17ac2015-01-20 09:29:28 -0800118 grpc_mdstr *path_key;
119 grpc_mdstr *authority_key;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800120 /* linked list of all channels on a server */
121 channel_data *next;
122 channel_data *prev;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800123 channel_registered_method *registered_methods;
124 gpr_uint32 registered_method_slots;
125 gpr_uint32 registered_method_max_probes;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800126};
127
128struct grpc_server {
129 size_t channel_filter_count;
130 const grpc_channel_filter **channel_filters;
131 grpc_channel_args *channel_args;
132 grpc_completion_queue *cq;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800133
134 gpr_mu mu;
135
Craig Tiller24be0f72015-02-10 14:04:22 -0800136 registered_method *registered_methods;
137 requested_call_array requested_calls;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800138
139 gpr_uint8 shutdown;
Craig Tiller4ffdcd52015-01-16 11:34:55 -0800140 gpr_uint8 have_shutdown_tag;
141 void *shutdown_tag;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800142
143 call_data *lists[CALL_LIST_COUNT];
144 channel_data root_channel_data;
145
146 listener *listeners;
147 gpr_refcount internal_refcount;
148};
149
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800150typedef enum {
151 /* waiting for metadata */
152 NOT_STARTED,
153 /* inital metadata read, not flow controlled in yet */
154 PENDING,
155 /* flow controlled in, on completion queue */
156 ACTIVATED,
157 /* cancelled before being queued */
158 ZOMBIED
159} call_state;
160
Craig Tillerfb189f82015-02-03 12:07:07 -0800161typedef struct legacy_data {
Craig Tiller24be0f72015-02-10 14:04:22 -0800162 grpc_metadata_array initial_metadata;
Craig Tillerfb189f82015-02-03 12:07:07 -0800163} legacy_data;
Craig Tillercce17ac2015-01-20 09:29:28 -0800164
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800165struct call_data {
166 grpc_call *call;
167
168 call_state state;
169 gpr_timespec deadline;
Craig Tillercce17ac2015-01-20 09:29:28 -0800170 grpc_mdstr *path;
171 grpc_mdstr *host;
172
173 legacy_data *legacy;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800174
Craig Tiller04cc8be2015-02-10 16:11:22 -0800175 call_data **root[CALL_LIST_COUNT];
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800176 call_link links[CALL_LIST_COUNT];
Craig Tiller8e8fd892015-02-10 17:02:08 -0800177
178 grpc_completion_queue *cq_new;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800179};
180
181#define SERVER_FROM_CALL_ELEM(elem) \
182 (((channel_data *)(elem)->channel_data)->server)
183
184static void do_nothing(void *unused, grpc_op_error ignored) {}
185
Craig Tiller24be0f72015-02-10 14:04:22 -0800186static void begin_call(grpc_server *server, call_data *calld,
187 requested_call *rc);
188static void fail_call(grpc_server *server, requested_call *rc);
189
Craig Tiller04cc8be2015-02-10 16:11:22 -0800190static int call_list_join(call_data **root, call_data *call,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800191 call_list list) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800192 GPR_ASSERT(!call->root[list]);
193 call->root[list] = root;
194 if (!*root) {
195 *root = call;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800196 call->links[list].next = call->links[list].prev = call;
197 } else {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800198 call->links[list].next = *root;
199 call->links[list].prev = (*root)->links[list].prev;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800200 call->links[list].next->links[list].prev =
201 call->links[list].prev->links[list].next = call;
202 }
203 return 1;
204}
205
Craig Tiller04cc8be2015-02-10 16:11:22 -0800206static call_data *call_list_remove_head(call_data **root, call_list list) {
207 call_data *out = *root;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800208 if (out) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800209 out->root[list] = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800210 if (out->links[list].next == out) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800211 *root = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800212 } else {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800213 *root = out->links[list].next;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800214 out->links[list].next->links[list].prev = out->links[list].prev;
215 out->links[list].prev->links[list].next = out->links[list].next;
216 }
217 }
218 return out;
219}
220
Craig Tiller04cc8be2015-02-10 16:11:22 -0800221static int call_list_remove(call_data *call, call_list list) {
222 call_data **root = call->root[list];
223 if (root == NULL) return 0;
224 call->root[list] = NULL;
225 if (*root == call) {
226 *root = call->links[list].next;
227 if (*root == call) {
228 *root = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800229 return 1;
230 }
231 }
Craig Tiller04cc8be2015-02-10 16:11:22 -0800232 GPR_ASSERT(*root != call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800233 call->links[list].next->links[list].prev = call->links[list].prev;
234 call->links[list].prev->links[list].next = call->links[list].next;
235 return 1;
236}
237
Craig Tiller24be0f72015-02-10 14:04:22 -0800238static void requested_call_array_destroy(requested_call_array *array) {
239 gpr_free(array->calls);
240}
241
242static requested_call *requested_call_array_add(requested_call_array *array) {
243 requested_call *rc;
244 if (array->count == array->capacity) {
245 array->capacity = GPR_MAX(array->capacity + 8, array->capacity * 2);
246 array->calls =
247 gpr_realloc(array->calls, sizeof(requested_call) * array->capacity);
248 }
249 rc = &array->calls[array->count++];
250 memset(rc, 0, sizeof(*rc));
251 return rc;
252}
253
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800254static void server_ref(grpc_server *server) {
255 gpr_ref(&server->internal_refcount);
256}
257
258static void server_unref(grpc_server *server) {
259 if (gpr_unref(&server->internal_refcount)) {
260 grpc_channel_args_destroy(server->channel_args);
261 gpr_mu_destroy(&server->mu);
262 gpr_free(server->channel_filters);
Craig Tiller24be0f72015-02-10 14:04:22 -0800263 requested_call_array_destroy(&server->requested_calls);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800264 gpr_free(server);
265 }
266}
267
268static int is_channel_orphaned(channel_data *chand) {
269 return chand->next == chand;
270}
271
272static void orphan_channel(channel_data *chand) {
273 chand->next->prev = chand->prev;
274 chand->prev->next = chand->next;
275 chand->next = chand->prev = chand;
276}
277
ctiller58393c22015-01-07 14:03:30 -0800278static void finish_destroy_channel(void *cd, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800279 channel_data *chand = cd;
280 grpc_server *server = chand->server;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800281 grpc_channel_destroy(chand->channel);
282 server_unref(server);
283}
284
285static void destroy_channel(channel_data *chand) {
286 if (is_channel_orphaned(chand)) return;
287 GPR_ASSERT(chand->server != NULL);
288 orphan_channel(chand);
289 server_ref(chand->server);
ctiller18b49ab2014-12-09 14:39:16 -0800290 grpc_iomgr_add_callback(finish_destroy_channel, chand);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800291}
292
Craig Tiller04cc8be2015-02-10 16:11:22 -0800293static void finish_start_new_rpc_and_unlock(grpc_server *server, grpc_call_element *elem, call_data **pending_root, requested_call_array *array) {
294 requested_call rc;
295 call_data *calld = elem->call_data;
296 if (array->count == 0) {
297 calld->state = PENDING;
298 call_list_join(pending_root, calld, PENDING_START);
299 gpr_mu_unlock(&server->mu);
300 } else {
301 rc = server->requested_calls.calls[--server->requested_calls.count];
302 calld->state = ACTIVATED;
303 gpr_mu_unlock(&server->mu);
304 begin_call(server, calld, &rc);
305 }
306}
307
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800308static void start_new_rpc(grpc_call_element *elem) {
309 channel_data *chand = elem->channel_data;
310 call_data *calld = elem->call_data;
311 grpc_server *server = chand->server;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800312 gpr_uint32 i;
313 gpr_uint32 hash;
314 channel_registered_method *rm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800315
316 gpr_mu_lock(&server->mu);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800317 if (chand->registered_methods && calld->path && calld->host) {
318 /* check for an exact match with host */
319 hash = GRPC_MDSTR_KV_HASH(calld->host->hash, calld->path->hash);
320 for (i = 0; i < chand->registered_method_max_probes; i++) {
321 rm = &chand->registered_methods[(hash + i) % chand->registered_method_slots];
322 if (!rm) break;
323 if (rm->host != calld->host) continue;
324 if (rm->method != calld->path) continue;
325 finish_start_new_rpc_and_unlock(server, elem, &rm->server_registered_method->pending, &rm->server_registered_method->requested);
326 return;
327 }
328 /* check for a wildcard method definition (no host set) */
329 hash = GRPC_MDSTR_KV_HASH(0, calld->path->hash);
330 for (i = 0; i < chand->registered_method_max_probes; i++) {
331 rm = &chand->registered_methods[(hash + i) % chand->registered_method_slots];
332 if (!rm) break;
333 if (rm->host != NULL) continue;
334 if (rm->method != calld->path) continue;
335 finish_start_new_rpc_and_unlock(server, elem, &rm->server_registered_method->pending, &rm->server_registered_method->requested);
336 return;
337 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800338 }
Craig Tiller04cc8be2015-02-10 16:11:22 -0800339 finish_start_new_rpc_and_unlock(server, elem, &server->lists[PENDING_START], &server->requested_calls);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800340}
341
ctiller58393c22015-01-07 14:03:30 -0800342static void kill_zombie(void *elem, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800343 grpc_call_destroy(grpc_call_from_top_element(elem));
344}
345
Craig Tillercce17ac2015-01-20 09:29:28 -0800346static void stream_closed(grpc_call_element *elem) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800347 call_data *calld = elem->call_data;
348 channel_data *chand = elem->channel_data;
349 gpr_mu_lock(&chand->server->mu);
350 switch (calld->state) {
351 case ACTIVATED:
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800352 break;
353 case PENDING:
Craig Tiller04cc8be2015-02-10 16:11:22 -0800354 call_list_remove(calld, PENDING_START);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800355 /* fallthrough intended */
356 case NOT_STARTED:
357 calld->state = ZOMBIED;
ctiller18b49ab2014-12-09 14:39:16 -0800358 grpc_iomgr_add_callback(kill_zombie, elem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800359 break;
360 case ZOMBIED:
361 break;
362 }
363 gpr_mu_unlock(&chand->server->mu);
Craig Tiller0a927bf2015-02-05 10:52:53 -0800364 grpc_call_stream_closed(elem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800365}
366
Craig Tillercce17ac2015-01-20 09:29:28 -0800367static void read_closed(grpc_call_element *elem) {
368 call_data *calld = elem->call_data;
369 channel_data *chand = elem->channel_data;
370 gpr_mu_lock(&chand->server->mu);
371 switch (calld->state) {
372 case ACTIVATED:
373 case PENDING:
374 grpc_call_read_closed(elem);
375 break;
376 case NOT_STARTED:
377 calld->state = ZOMBIED;
378 grpc_iomgr_add_callback(kill_zombie, elem);
379 break;
380 case ZOMBIED:
381 break;
382 }
383 gpr_mu_unlock(&chand->server->mu);
384}
385
ctillerf962f522014-12-10 15:28:27 -0800386static void call_op(grpc_call_element *elem, grpc_call_element *from_elemn,
387 grpc_call_op *op) {
Craig Tillercce17ac2015-01-20 09:29:28 -0800388 channel_data *chand = elem->channel_data;
389 call_data *calld = elem->call_data;
390 grpc_mdelem *md;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800391 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
392 switch (op->type) {
393 case GRPC_RECV_METADATA:
Craig Tillercce17ac2015-01-20 09:29:28 -0800394 md = op->data.metadata;
395 if (md->key == chand->path_key) {
396 calld->path = grpc_mdstr_ref(md->value);
397 grpc_mdelem_unref(md);
398 } else if (md->key == chand->authority_key) {
399 calld->host = grpc_mdstr_ref(md->value);
400 grpc_mdelem_unref(md);
401 } else {
402 grpc_call_recv_metadata(elem, md);
403 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800404 break;
405 case GRPC_RECV_END_OF_INITIAL_METADATA:
406 start_new_rpc(elem);
Craig Tiller4069b682015-01-29 14:01:19 -0800407 grpc_call_initial_metadata_complete(elem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800408 break;
409 case GRPC_RECV_MESSAGE:
Craig Tillercce17ac2015-01-20 09:29:28 -0800410 grpc_call_recv_message(elem, op->data.message);
411 op->done_cb(op->user_data, GRPC_OP_OK);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800412 break;
413 case GRPC_RECV_HALF_CLOSE:
Craig Tillercce17ac2015-01-20 09:29:28 -0800414 read_closed(elem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800415 break;
416 case GRPC_RECV_FINISH:
Craig Tillercce17ac2015-01-20 09:29:28 -0800417 stream_closed(elem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800418 break;
419 case GRPC_RECV_DEADLINE:
420 grpc_call_set_deadline(elem, op->data.deadline);
421 ((call_data *)elem->call_data)->deadline = op->data.deadline;
422 break;
423 default:
424 GPR_ASSERT(op->dir == GRPC_CALL_DOWN);
425 grpc_call_next_op(elem, op);
426 break;
427 }
428}
429
ctillerf962f522014-12-10 15:28:27 -0800430static void channel_op(grpc_channel_element *elem,
431 grpc_channel_element *from_elem, grpc_channel_op *op) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800432 channel_data *chand = elem->channel_data;
Craig Tiller8b976d02015-02-05 21:41:23 -0800433 grpc_server *server = chand->server;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800434
435 switch (op->type) {
436 case GRPC_ACCEPT_CALL:
437 /* create a call */
Craig Tillerfb189f82015-02-03 12:07:07 -0800438 grpc_call_create(chand->channel, NULL,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800439 op->data.accept_call.transport_server_data);
440 break;
441 case GRPC_TRANSPORT_CLOSED:
442 /* if the transport is closed for a server channel, we destroy the
443 channel */
Craig Tiller8b976d02015-02-05 21:41:23 -0800444 gpr_mu_lock(&server->mu);
445 server_ref(server);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800446 destroy_channel(chand);
Craig Tiller8b976d02015-02-05 21:41:23 -0800447 gpr_mu_unlock(&server->mu);
448 server_unref(server);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800449 break;
nnoble0c475f02014-12-05 15:37:39 -0800450 case GRPC_TRANSPORT_GOAWAY:
451 gpr_slice_unref(op->data.goaway.message);
452 break;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800453 default:
454 GPR_ASSERT(op->dir == GRPC_CALL_DOWN);
455 grpc_channel_next_op(elem, op);
456 break;
457 }
458}
459
ctiller58393c22015-01-07 14:03:30 -0800460static void finish_shutdown_channel(void *cd, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800461 channel_data *chand = cd;
462 grpc_channel_op op;
nnoble0c475f02014-12-05 15:37:39 -0800463 op.type = GRPC_CHANNEL_DISCONNECT;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800464 op.dir = GRPC_CALL_DOWN;
465 channel_op(grpc_channel_stack_element(
466 grpc_channel_get_channel_stack(chand->channel), 0),
ctillerf962f522014-12-10 15:28:27 -0800467 NULL, &op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800468 grpc_channel_internal_unref(chand->channel);
469}
470
471static void shutdown_channel(channel_data *chand) {
472 grpc_channel_internal_ref(chand->channel);
ctiller18b49ab2014-12-09 14:39:16 -0800473 grpc_iomgr_add_callback(finish_shutdown_channel, chand);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800474}
475
476static void init_call_elem(grpc_call_element *elem,
477 const void *server_transport_data) {
478 call_data *calld = elem->call_data;
479 channel_data *chand = elem->channel_data;
480 memset(calld, 0, sizeof(call_data));
481 calld->deadline = gpr_inf_future;
482 calld->call = grpc_call_from_top_element(elem);
483
484 gpr_mu_lock(&chand->server->mu);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800485 call_list_join(&chand->server->lists[ALL_CALLS], calld, ALL_CALLS);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800486 gpr_mu_unlock(&chand->server->mu);
487
488 server_ref(chand->server);
489}
490
491static void destroy_call_elem(grpc_call_element *elem) {
492 channel_data *chand = elem->channel_data;
Craig Tillerdb7db992015-01-29 11:19:01 -0800493 call_data *calld = elem->call_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800494 int i;
495
496 gpr_mu_lock(&chand->server->mu);
497 for (i = 0; i < CALL_LIST_COUNT; i++) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800498 call_list_remove(elem->call_data, i);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800499 }
Craig Tiller4ffdcd52015-01-16 11:34:55 -0800500 if (chand->server->shutdown && chand->server->have_shutdown_tag &&
501 chand->server->lists[ALL_CALLS] == NULL) {
502 grpc_cq_end_server_shutdown(chand->server->cq, chand->server->shutdown_tag);
503 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800504 gpr_mu_unlock(&chand->server->mu);
505
Craig Tiller4df31a62015-01-30 09:44:31 -0800506 if (calld->host) {
507 grpc_mdstr_unref(calld->host);
508 }
509 if (calld->path) {
510 grpc_mdstr_unref(calld->path);
511 }
512
Craig Tillerdb7db992015-01-29 11:19:01 -0800513 if (calld->legacy) {
Craig Tiller24be0f72015-02-10 14:04:22 -0800514 gpr_free(calld->legacy->initial_metadata.metadata);
Craig Tillerdb7db992015-01-29 11:19:01 -0800515 gpr_free(calld->legacy);
516 }
517
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800518 server_unref(chand->server);
519}
520
521static void init_channel_elem(grpc_channel_element *elem,
522 const grpc_channel_args *args,
523 grpc_mdctx *metadata_context, int is_first,
524 int is_last) {
525 channel_data *chand = elem->channel_data;
526 GPR_ASSERT(is_first);
527 GPR_ASSERT(!is_last);
528 chand->server = NULL;
529 chand->channel = NULL;
Craig Tillercce17ac2015-01-20 09:29:28 -0800530 chand->path_key = grpc_mdstr_from_string(metadata_context, ":path");
531 chand->authority_key = grpc_mdstr_from_string(metadata_context, ":authority");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800532 chand->next = chand->prev = chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800533 chand->registered_methods = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800534}
535
536static void destroy_channel_elem(grpc_channel_element *elem) {
537 channel_data *chand = elem->channel_data;
538 if (chand->server) {
539 gpr_mu_lock(&chand->server->mu);
540 chand->next->prev = chand->prev;
541 chand->prev->next = chand->next;
542 chand->next = chand->prev = chand;
543 gpr_mu_unlock(&chand->server->mu);
Craig Tillercce17ac2015-01-20 09:29:28 -0800544 grpc_mdstr_unref(chand->path_key);
545 grpc_mdstr_unref(chand->authority_key);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800546 server_unref(chand->server);
547 }
548}
549
550static const grpc_channel_filter server_surface_filter = {
Craig Tiller24be0f72015-02-10 14:04:22 -0800551 call_op, channel_op, sizeof(call_data), init_call_elem, destroy_call_elem,
552 sizeof(channel_data), init_channel_elem, destroy_channel_elem, "server",
Craig Tiller9f28ac22015-01-27 17:01:29 -0800553};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800554
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800555grpc_server *grpc_server_create_from_filters(grpc_completion_queue *cq,
556 grpc_channel_filter **filters,
557 size_t filter_count,
558 const grpc_channel_args *args) {
559 size_t i;
560 int census_enabled = grpc_channel_args_is_census_enabled(args);
561
562 grpc_server *server = gpr_malloc(sizeof(grpc_server));
563 memset(server, 0, sizeof(grpc_server));
564
565 gpr_mu_init(&server->mu);
566
567 server->cq = cq;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800568 /* decremented by grpc_server_destroy */
569 gpr_ref_init(&server->internal_refcount, 1);
570 server->root_channel_data.next = server->root_channel_data.prev =
571 &server->root_channel_data;
572
573 /* Server filter stack is:
574
575 server_surface_filter - for making surface API calls
576 grpc_server_census_filter (optional) - for stats collection and tracing
577 {passed in filter stack}
578 grpc_connected_channel_filter - for interfacing with transports */
579 server->channel_filter_count = filter_count + 1 + census_enabled;
580 server->channel_filters =
581 gpr_malloc(server->channel_filter_count * sizeof(grpc_channel_filter *));
582 server->channel_filters[0] = &server_surface_filter;
583 if (census_enabled) {
584 server->channel_filters[1] = &grpc_server_census_filter;
585 }
586 for (i = 0; i < filter_count; i++) {
587 server->channel_filters[i + 1 + census_enabled] = filters[i];
588 }
589
590 server->channel_args = grpc_channel_args_copy(args);
591
592 return server;
593}
594
Craig Tiller24be0f72015-02-10 14:04:22 -0800595static int streq(const char *a, const char *b) {
596 if (a == NULL && b == NULL) return 1;
597 if (a == NULL) return 0;
598 if (b == NULL) return 0;
599 return 0 == strcmp(a, b);
600}
601
602void *grpc_server_register_method(grpc_server *server, const char *method,
603 const char *host) {
604 registered_method *m;
605 if (!method) {
606 gpr_log(GPR_ERROR, "%s method string cannot be NULL", __FUNCTION__);
607 return NULL;
608 }
609 for (m = server->registered_methods; m; m = m->next) {
610 if (streq(m->method, method) && streq(m->host, host)) {
611 gpr_log(GPR_ERROR, "duplicate registration for %s@%s", method,
612 host ? host : "*");
613 return NULL;
614 }
615 }
616 m = gpr_malloc(sizeof(registered_method));
617 memset(m, 0, sizeof(*m));
618 m->method = gpr_strdup(method);
619 m->host = gpr_strdup(host);
620 m->next = server->registered_methods;
621 server->registered_methods = m;
622 return m;
623}
624
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800625void grpc_server_start(grpc_server *server) {
626 listener *l;
627
628 for (l = server->listeners; l; l = l->next) {
ctiller58393c22015-01-07 14:03:30 -0800629 l->start(server, l->arg, grpc_cq_pollset(server->cq));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800630 }
631}
632
633grpc_transport_setup_result grpc_server_setup_transport(
634 grpc_server *s, grpc_transport *transport,
635 grpc_channel_filter const **extra_filters, size_t num_extra_filters,
636 grpc_mdctx *mdctx) {
637 size_t num_filters = s->channel_filter_count + num_extra_filters + 1;
638 grpc_channel_filter const **filters =
639 gpr_malloc(sizeof(grpc_channel_filter *) * num_filters);
640 size_t i;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800641 size_t num_registered_methods;
642 size_t alloc;
643 registered_method *rm;
644 channel_registered_method *crm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800645 grpc_channel *channel;
646 channel_data *chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800647 grpc_mdstr *host;
648 grpc_mdstr *method;
649 gpr_uint32 hash;
650 gpr_uint32 slots;
651 gpr_uint32 probes;
652 gpr_uint32 max_probes = 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800653
654 for (i = 0; i < s->channel_filter_count; i++) {
655 filters[i] = s->channel_filters[i];
656 }
657 for (; i < s->channel_filter_count + num_extra_filters; i++) {
658 filters[i] = extra_filters[i - s->channel_filter_count];
659 }
660 filters[i] = &grpc_connected_channel_filter;
661
ctillerd79b4862014-12-17 16:36:59 -0800662 grpc_transport_add_to_pollset(transport, grpc_cq_pollset(s->cq));
663
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800664 channel = grpc_channel_create_from_filters(filters, num_filters,
665 s->channel_args, mdctx, 0);
666 chand = (channel_data *)grpc_channel_stack_element(
667 grpc_channel_get_channel_stack(channel), 0)->channel_data;
668 chand->server = s;
669 server_ref(s);
670 chand->channel = channel;
671
Craig Tiller04cc8be2015-02-10 16:11:22 -0800672 num_registered_methods = 0;
673 for (rm = s->registered_methods; rm; rm = rm->next) {
674 num_registered_methods++;
675 }
676 /* build a lookup table phrased in terms of mdstr's in this channels context
677 to quickly find registered methods */
678 if (num_registered_methods > 0) {
679 slots = 2 * num_registered_methods;
680 alloc = sizeof(channel_registered_method) * slots;
681 chand->registered_methods = gpr_malloc(alloc);
682 memset(chand->registered_methods, 0, alloc);
683 for (rm = s->registered_methods; rm; rm = rm->next) {
684 host = rm->host ? grpc_mdstr_from_string(mdctx, rm->host) : NULL;
685 method = grpc_mdstr_from_string(mdctx, rm->host);
686 hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash);
687 for (probes = 0; chand->registered_methods[(hash + probes) % slots].server_registered_method != NULL; probes++);
688 if (probes > max_probes) max_probes = probes;
689 crm = &chand->registered_methods[(hash + probes) % slots];
690 crm->server_registered_method = rm;
691 crm->host = host;
692 crm->method = method;
693 }
694 chand->registered_method_slots = slots;
695 chand->registered_method_max_probes = max_probes;
696 }
697
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800698 gpr_mu_lock(&s->mu);
699 chand->next = &s->root_channel_data;
700 chand->prev = chand->next->prev;
701 chand->next->prev = chand->prev->next = chand;
702 gpr_mu_unlock(&s->mu);
703
704 gpr_free(filters);
705
706 return grpc_connected_channel_bind_transport(
707 grpc_channel_get_channel_stack(channel), transport);
708}
709
Craig Tiller4ffdcd52015-01-16 11:34:55 -0800710void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag,
711 void *shutdown_tag) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800712 listener *l;
Craig Tiller24be0f72015-02-10 14:04:22 -0800713 requested_call_array requested_calls;
nnoble0c475f02014-12-05 15:37:39 -0800714 channel_data **channels;
715 channel_data *c;
716 size_t nchannels;
717 size_t i;
718 grpc_channel_op op;
719 grpc_channel_element *elem;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800720
721 /* lock, and gather up some stuff to do */
722 gpr_mu_lock(&server->mu);
723 if (server->shutdown) {
724 gpr_mu_unlock(&server->mu);
725 return;
726 }
727
nnoble0c475f02014-12-05 15:37:39 -0800728 nchannels = 0;
729 for (c = server->root_channel_data.next; c != &server->root_channel_data;
730 c = c->next) {
731 nchannels++;
732 }
733 channels = gpr_malloc(sizeof(channel_data *) * nchannels);
734 i = 0;
735 for (c = server->root_channel_data.next; c != &server->root_channel_data;
736 c = c->next) {
737 grpc_channel_internal_ref(c->channel);
738 channels[i] = c;
739 i++;
740 }
741
Craig Tillercce17ac2015-01-20 09:29:28 -0800742 requested_calls = server->requested_calls;
Craig Tiller24be0f72015-02-10 14:04:22 -0800743 memset(&server->requested_calls, 0, sizeof(server->requested_calls));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800744
745 server->shutdown = 1;
Craig Tiller4ffdcd52015-01-16 11:34:55 -0800746 server->have_shutdown_tag = have_shutdown_tag;
747 server->shutdown_tag = shutdown_tag;
748 if (have_shutdown_tag) {
749 grpc_cq_begin_op(server->cq, NULL, GRPC_SERVER_SHUTDOWN);
750 if (server->lists[ALL_CALLS] == NULL) {
751 grpc_cq_end_server_shutdown(server->cq, shutdown_tag);
752 }
753 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800754 gpr_mu_unlock(&server->mu);
755
nnoble0c475f02014-12-05 15:37:39 -0800756 for (i = 0; i < nchannels; i++) {
757 c = channels[i];
758 elem = grpc_channel_stack_element(
759 grpc_channel_get_channel_stack(c->channel), 0);
760
761 op.type = GRPC_CHANNEL_GOAWAY;
762 op.dir = GRPC_CALL_DOWN;
763 op.data.goaway.status = GRPC_STATUS_OK;
764 op.data.goaway.message = gpr_slice_from_copied_string("Server shutdown");
ctillerf962f522014-12-10 15:28:27 -0800765 elem->filter->channel_op(elem, NULL, &op);
nnoble0c475f02014-12-05 15:37:39 -0800766
767 grpc_channel_internal_unref(c->channel);
768 }
769 gpr_free(channels);
770
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800771 /* terminate all the requested calls */
Craig Tiller24be0f72015-02-10 14:04:22 -0800772 for (i = 0; i < requested_calls.count; i++) {
773 fail_call(server, &requested_calls.calls[i]);
Craig Tillercce17ac2015-01-20 09:29:28 -0800774 }
Craig Tiller24be0f72015-02-10 14:04:22 -0800775 gpr_free(requested_calls.calls);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800776
777 /* Shutdown listeners */
778 for (l = server->listeners; l; l = l->next) {
779 l->destroy(server, l->arg);
780 }
781 while (server->listeners) {
782 l = server->listeners;
783 server->listeners = l->next;
784 gpr_free(l);
785 }
786}
787
Craig Tiller4ffdcd52015-01-16 11:34:55 -0800788void grpc_server_shutdown(grpc_server *server) {
789 shutdown_internal(server, 0, NULL);
790}
791
792void grpc_server_shutdown_and_notify(grpc_server *server, void *tag) {
793 shutdown_internal(server, 1, tag);
794}
795
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800796void grpc_server_destroy(grpc_server *server) {
797 channel_data *c;
798 gpr_mu_lock(&server->mu);
799 for (c = server->root_channel_data.next; c != &server->root_channel_data;
800 c = c->next) {
801 shutdown_channel(c);
802 }
803 gpr_mu_unlock(&server->mu);
804
805 server_unref(server);
806}
807
808void grpc_server_add_listener(grpc_server *server, void *arg,
ctiller58393c22015-01-07 14:03:30 -0800809 void (*start)(grpc_server *server, void *arg,
810 grpc_pollset *pollset),
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800811 void (*destroy)(grpc_server *server, void *arg)) {
812 listener *l = gpr_malloc(sizeof(listener));
813 l->arg = arg;
814 l->start = start;
815 l->destroy = destroy;
816 l->next = server->listeners;
817 server->listeners = l;
818}
819
Craig Tiller9f28ac22015-01-27 17:01:29 -0800820static grpc_call_error queue_call_request(grpc_server *server,
Craig Tiller24be0f72015-02-10 14:04:22 -0800821 requested_call *rc) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -0800822 call_data *calld = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800823 gpr_mu_lock(&server->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800824 if (server->shutdown) {
825 gpr_mu_unlock(&server->mu);
Craig Tiller24be0f72015-02-10 14:04:22 -0800826 fail_call(server, rc);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800827 return GRPC_CALL_OK;
828 }
Craig Tiller04cc8be2015-02-10 16:11:22 -0800829 switch (rc->type) {
830 case LEGACY_CALL:
831 case BATCH_CALL:
832 calld = call_list_remove_head(&server->lists[PENDING_START], PENDING_START);
833 break;
834 case REGISTERED_CALL:
835 calld = call_list_remove_head(&rc->data.registered.registered_method->pending, PENDING_START);
836 break;
837 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800838 if (calld) {
Craig Tillercce17ac2015-01-20 09:29:28 -0800839 GPR_ASSERT(calld->state == PENDING);
Craig Tillerbb3f22f2015-01-29 16:40:56 -0800840 calld->state = ACTIVATED;
Craig Tillercce17ac2015-01-20 09:29:28 -0800841 gpr_mu_unlock(&server->mu);
Craig Tiller24be0f72015-02-10 14:04:22 -0800842 begin_call(server, calld, rc);
Craig Tillercce17ac2015-01-20 09:29:28 -0800843 return GRPC_CALL_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800844 } else {
Craig Tiller24be0f72015-02-10 14:04:22 -0800845 *requested_call_array_add(&server->requested_calls) = *rc;
Craig Tillercce17ac2015-01-20 09:29:28 -0800846 gpr_mu_unlock(&server->mu);
847 return GRPC_CALL_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800848 }
Craig Tillercce17ac2015-01-20 09:29:28 -0800849}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800850
Craig Tiller24be0f72015-02-10 14:04:22 -0800851grpc_call_error grpc_server_request_call(grpc_server *server, grpc_call **call,
852 grpc_call_details *details,
853 grpc_metadata_array *initial_metadata,
Craig Tiller8e8fd892015-02-10 17:02:08 -0800854 grpc_completion_queue *cq_new,
855 grpc_completion_queue *cq_bind, void *tag) {
Craig Tiller24be0f72015-02-10 14:04:22 -0800856 requested_call rc;
Craig Tiller8e8fd892015-02-10 17:02:08 -0800857 grpc_cq_begin_op(cq_new, NULL, GRPC_OP_COMPLETE);
Craig Tiller24be0f72015-02-10 14:04:22 -0800858 rc.type = BATCH_CALL;
859 rc.tag = tag;
Craig Tiller8e8fd892015-02-10 17:02:08 -0800860 rc.data.batch.cq_new = cq_new;
861 rc.data.batch.cq_bind = cq_bind;
Craig Tiller24be0f72015-02-10 14:04:22 -0800862 rc.data.batch.call = call;
863 rc.data.batch.details = details;
864 rc.data.batch.initial_metadata = initial_metadata;
865 return queue_call_request(server, &rc);
866}
867
868grpc_call_error grpc_server_request_registered_call(
869 grpc_server *server, void *registered_method, grpc_call **call,
870 gpr_timespec *deadline, grpc_metadata_array *initial_metadata,
Craig Tiller8e8fd892015-02-10 17:02:08 -0800871 grpc_byte_buffer **optional_payload, grpc_completion_queue *cq_new, grpc_completion_queue *cq_bind,
872 void *tag) {
Craig Tiller24be0f72015-02-10 14:04:22 -0800873 requested_call rc;
Craig Tiller8e8fd892015-02-10 17:02:08 -0800874 grpc_cq_begin_op(cq_new, NULL, GRPC_OP_COMPLETE);
Craig Tiller24be0f72015-02-10 14:04:22 -0800875 rc.type = REGISTERED_CALL;
876 rc.tag = tag;
Craig Tiller8e8fd892015-02-10 17:02:08 -0800877 rc.data.registered.cq_new = cq_new;
878 rc.data.registered.cq_bind = cq_bind;
Craig Tiller24be0f72015-02-10 14:04:22 -0800879 rc.data.registered.call = call;
880 rc.data.registered.registered_method = registered_method;
881 rc.data.registered.deadline = deadline;
882 rc.data.registered.initial_metadata = initial_metadata;
883 rc.data.registered.optional_payload = optional_payload;
884 return queue_call_request(server, &rc);
885}
886
887grpc_call_error grpc_server_request_call_old(grpc_server *server,
888 void *tag_new) {
889 requested_call rc;
890 grpc_cq_begin_op(server->cq, NULL, GRPC_SERVER_RPC_NEW);
891 rc.type = LEGACY_CALL;
892 rc.tag = tag_new;
893 return queue_call_request(server, &rc);
894}
895
896static void publish_legacy(grpc_call *call, grpc_op_error status, void *tag);
897static void publish_registered_or_batch(grpc_call *call, grpc_op_error status,
898 void *tag);
Yang Gaoeb8e7cd2015-02-11 11:43:40 -0800899static void publish_was_not_set(grpc_call *call, grpc_op_error status, void *tag) {
900 abort();
901}
Craig Tiller24be0f72015-02-10 14:04:22 -0800902
Craig Tiller166e2502015-02-03 20:14:41 -0800903static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
904 gpr_slice slice = value->slice;
905 size_t len = GPR_SLICE_LENGTH(slice);
906
907 if (len + 1 > *capacity) {
908 *capacity = GPR_MAX(len + 1, *capacity * 2);
909 *dest = gpr_realloc(*dest, *capacity);
910 }
911 memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
912}
913
Craig Tiller24be0f72015-02-10 14:04:22 -0800914static void begin_call(grpc_server *server, call_data *calld,
915 requested_call *rc) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -0800916 grpc_ioreq_completion_func publish = publish_was_not_set;
Craig Tiller24be0f72015-02-10 14:04:22 -0800917 grpc_ioreq req[2];
918 grpc_ioreq *r = req;
919
920 /* called once initial metadata has been read by the call, but BEFORE
921 the ioreq to fetch it out of the call has been executed.
922 This means metadata related fields can be relied on in calld, but to
923 fill in the metadata array passed by the client, we need to perform
924 an ioreq op, that should complete immediately. */
925
926 switch (rc->type) {
927 case LEGACY_CALL:
928 calld->legacy = gpr_malloc(sizeof(legacy_data));
929 memset(calld->legacy, 0, sizeof(legacy_data));
930 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
931 r->data.recv_metadata = &calld->legacy->initial_metadata;
932 r++;
933 publish = publish_legacy;
934 break;
935 case BATCH_CALL:
936 cpstr(&rc->data.batch.details->host,
937 &rc->data.batch.details->host_capacity, calld->host);
938 cpstr(&rc->data.batch.details->method,
939 &rc->data.batch.details->method_capacity, calld->path);
Craig Tiller8e8fd892015-02-10 17:02:08 -0800940 grpc_call_set_completion_queue(calld->call, rc->data.batch.cq_bind);
Craig Tiller24be0f72015-02-10 14:04:22 -0800941 *rc->data.batch.call = calld->call;
942 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
943 r->data.recv_metadata = rc->data.batch.initial_metadata;
944 r++;
Craig Tiller8e8fd892015-02-10 17:02:08 -0800945 calld->cq_new = rc->data.batch.cq_new;
Craig Tiller24be0f72015-02-10 14:04:22 -0800946 publish = publish_registered_or_batch;
947 break;
948 case REGISTERED_CALL:
949 *rc->data.registered.deadline = calld->deadline;
Craig Tiller8e8fd892015-02-10 17:02:08 -0800950 grpc_call_set_completion_queue(calld->call, rc->data.registered.cq_bind);
Craig Tiller24be0f72015-02-10 14:04:22 -0800951 *rc->data.registered.call = calld->call;
952 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
953 r->data.recv_metadata = rc->data.registered.initial_metadata;
954 r++;
955 if (rc->data.registered.optional_payload) {
956 r->op = GRPC_IOREQ_RECV_MESSAGE;
957 r->data.recv_message = rc->data.registered.optional_payload;
958 r++;
959 }
Craig Tiller8e8fd892015-02-10 17:02:08 -0800960 calld->cq_new = rc->data.registered.cq_new;
Craig Tiller24be0f72015-02-10 14:04:22 -0800961 publish = publish_registered_or_batch;
962 break;
963 }
964
965 grpc_call_internal_ref(calld->call);
966 grpc_call_start_ioreq_and_call_back(calld->call, req, r - req, publish,
967 rc->tag);
968}
969
970static void fail_call(grpc_server *server, requested_call *rc) {
971 switch (rc->type) {
972 case LEGACY_CALL:
973 grpc_cq_end_new_rpc(server->cq, rc->tag, NULL, do_nothing, NULL, NULL,
974 NULL, gpr_inf_past, 0, NULL);
975 break;
976 case BATCH_CALL:
977 *rc->data.batch.call = NULL;
978 rc->data.batch.initial_metadata->count = 0;
Craig Tiller8e8fd892015-02-10 17:02:08 -0800979 grpc_cq_end_op_complete(rc->data.batch.cq_new, rc->tag, NULL, do_nothing,
Craig Tiller24be0f72015-02-10 14:04:22 -0800980 NULL, GRPC_OP_ERROR);
981 break;
982 case REGISTERED_CALL:
983 *rc->data.registered.call = NULL;
984 rc->data.registered.initial_metadata->count = 0;
Craig Tiller8e8fd892015-02-10 17:02:08 -0800985 grpc_cq_end_op_complete(rc->data.registered.cq_new, rc->tag, NULL, do_nothing,
Craig Tiller24be0f72015-02-10 14:04:22 -0800986 NULL, GRPC_OP_ERROR);
987 break;
988 }
989}
990
991static void publish_legacy(grpc_call *call, grpc_op_error status, void *tag) {
992 grpc_call_element *elem =
993 grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
994 call_data *calld = elem->call_data;
995 channel_data *chand = elem->channel_data;
996 grpc_server *server = chand->server;
997
998 if (status == GRPC_OP_OK) {
999 grpc_cq_end_new_rpc(server->cq, tag, call, do_nothing, NULL,
1000 grpc_mdstr_as_c_string(calld->path),
1001 grpc_mdstr_as_c_string(calld->host), calld->deadline,
1002 calld->legacy->initial_metadata.count,
1003 calld->legacy->initial_metadata.metadata);
1004 } else {
1005 gpr_log(GPR_ERROR, "should never reach here");
1006 abort();
1007 }
1008}
1009
1010static void publish_registered_or_batch(grpc_call *call, grpc_op_error status,
1011 void *tag) {
Craig Tiller8e8fd892015-02-10 17:02:08 -08001012 grpc_call_element *elem =
1013 grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
1014 call_data *calld = elem->call_data;
1015 grpc_cq_end_op_complete(calld->cq_new, tag, call,
Craig Tiller24be0f72015-02-10 14:04:22 -08001016 do_nothing, NULL, status);
1017}
1018
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001019const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) {
1020 return server->channel_args;
1021}