blob: 69f531fe1d3b4912c3dd6a6d32ac86f6f7ee45bb [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/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 Tiller60fd3612015-03-05 16:24:22 -080047#include "src/core/surface/init.h"
Craig Tillercce17ac2015-01-20 09:29:28 -080048#include "src/core/transport/metadata.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080049#include <grpc/support/alloc.h>
50#include <grpc/support/log.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080051#include <grpc/support/useful.h>
52
53typedef enum { PENDING_START, ALL_CALLS, CALL_LIST_COUNT } call_list;
54
55typedef struct listener {
56 void *arg;
Craig Tillerec3257c2015-02-12 15:59:43 -080057 void (*start)(grpc_server *server, void *arg, grpc_pollset **pollsets,
58 size_t pollset_count);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080059 void (*destroy)(grpc_server *server, void *arg);
60 struct listener *next;
61} listener;
62
63typedef struct call_data call_data;
64typedef struct channel_data channel_data;
Craig Tiller24be0f72015-02-10 14:04:22 -080065typedef struct registered_method registered_method;
66
67typedef struct {
68 call_data *next;
69 call_data *prev;
70} call_link;
71
Craig Tiller0e919562015-04-28 14:03:47 -070072typedef enum { BATCH_CALL, REGISTERED_CALL } requested_call_type;
Craig Tiller24be0f72015-02-10 14:04:22 -080073
74typedef struct {
75 requested_call_type type;
76 void *tag;
Craig Tillerf9e6adf2015-05-06 11:45:59 -070077 grpc_completion_queue *cq_bound_to_call;
78 grpc_completion_queue *cq_for_notification;
79 grpc_call **call;
Craig Tiller24be0f72015-02-10 14:04:22 -080080 union {
81 struct {
Craig Tiller24be0f72015-02-10 14:04:22 -080082 grpc_call_details *details;
83 grpc_metadata_array *initial_metadata;
84 } batch;
85 struct {
Craig Tiller24be0f72015-02-10 14:04:22 -080086 registered_method *registered_method;
87 gpr_timespec *deadline;
88 grpc_metadata_array *initial_metadata;
89 grpc_byte_buffer **optional_payload;
90 } registered;
91 } data;
92} requested_call;
93
94typedef struct {
95 requested_call *calls;
96 size_t count;
97 size_t capacity;
98} requested_call_array;
99
100struct registered_method {
101 char *method;
102 char *host;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800103 call_data *pending;
Craig Tiller24be0f72015-02-10 14:04:22 -0800104 requested_call_array requested;
105 registered_method *next;
106};
107
108typedef struct channel_registered_method {
109 registered_method *server_registered_method;
110 grpc_mdstr *method;
111 grpc_mdstr *host;
112} channel_registered_method;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800113
114struct channel_data {
115 grpc_server *server;
116 grpc_channel *channel;
Craig Tillercce17ac2015-01-20 09:29:28 -0800117 grpc_mdstr *path_key;
118 grpc_mdstr *authority_key;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800119 /* linked list of all channels on a server */
120 channel_data *next;
121 channel_data *prev;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800122 channel_registered_method *registered_methods;
123 gpr_uint32 registered_method_slots;
124 gpr_uint32 registered_method_max_probes;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800125};
126
127struct grpc_server {
128 size_t channel_filter_count;
129 const grpc_channel_filter **channel_filters;
130 grpc_channel_args *channel_args;
Craig Tillerec3257c2015-02-12 15:59:43 -0800131
Craig Tiller20bc56d2015-02-12 09:02:56 -0800132 grpc_completion_queue **cqs;
133 grpc_pollset **pollsets;
134 size_t cq_count;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800135
136 gpr_mu mu;
137
Craig Tiller24be0f72015-02-10 14:04:22 -0800138 registered_method *registered_methods;
139 requested_call_array requested_calls;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800140
141 gpr_uint8 shutdown;
Craig Tilleraea2fc02015-02-17 16:54:53 -0800142 size_t num_shutdown_tags;
143 void **shutdown_tags;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800144
145 call_data *lists[CALL_LIST_COUNT];
146 channel_data root_channel_data;
147
148 listener *listeners;
Craig Tilleraec96aa2015-04-07 14:32:15 -0700149 int listeners_destroyed;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800150 gpr_refcount internal_refcount;
151};
152
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800153typedef enum {
154 /* waiting for metadata */
155 NOT_STARTED,
156 /* inital metadata read, not flow controlled in yet */
157 PENDING,
158 /* flow controlled in, on completion queue */
159 ACTIVATED,
160 /* cancelled before being queued */
161 ZOMBIED
162} call_state;
163
164struct call_data {
165 grpc_call *call;
166
167 call_state state;
Craig Tillercce17ac2015-01-20 09:29:28 -0800168 grpc_mdstr *path;
169 grpc_mdstr *host;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700170 gpr_timespec deadline;
171 int got_initial_metadata;
Craig Tillercce17ac2015-01-20 09:29:28 -0800172
Craig Tiller20bc56d2015-02-12 09:02:56 -0800173 grpc_completion_queue *cq_new;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800174
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700175 grpc_stream_op_buffer *recv_ops;
176 grpc_stream_state *recv_state;
177 void (*on_done_recv)(void *user_data, int success);
178 void *recv_user_data;
179
Craig Tiller04cc8be2015-02-10 16:11:22 -0800180 call_data **root[CALL_LIST_COUNT];
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800181 call_link links[CALL_LIST_COUNT];
182};
183
184#define SERVER_FROM_CALL_ELEM(elem) \
185 (((channel_data *)(elem)->channel_data)->server)
186
Craig Tiller24be0f72015-02-10 14:04:22 -0800187static void begin_call(grpc_server *server, call_data *calld,
188 requested_call *rc);
189static void fail_call(grpc_server *server, requested_call *rc);
190
Craig Tiller3b29b562015-02-11 12:58:46 -0800191static int call_list_join(call_data **root, call_data *call, 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
Craig Tilleree945e82015-05-26 16:15:34 -0700258static void server_delete(grpc_server *server) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800259 registered_method *rm;
Craig Tiller89504612015-04-27 11:48:46 -0700260 size_t i;
Craig Tilleree945e82015-05-26 16:15:34 -0700261 grpc_channel_args_destroy(server->channel_args);
262 gpr_mu_destroy(&server->mu);
263 gpr_free(server->channel_filters);
264 requested_call_array_destroy(&server->requested_calls);
265 while ((rm = server->registered_methods) != NULL) {
266 server->registered_methods = rm->next;
267 gpr_free(rm->method);
268 gpr_free(rm->host);
269 requested_call_array_destroy(&rm->requested);
270 gpr_free(rm);
271 }
272 for (i = 0; i < server->cq_count; i++) {
273 grpc_cq_internal_unref(server->cqs[i]);
274 }
275 gpr_free(server->cqs);
276 gpr_free(server->pollsets);
277 gpr_free(server->shutdown_tags);
278 gpr_free(server);
279}
280
281static void server_unref(grpc_server *server) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800282 if (gpr_unref(&server->internal_refcount)) {
Craig Tilleree945e82015-05-26 16:15:34 -0700283 server_delete(server);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800284 }
285}
286
287static int is_channel_orphaned(channel_data *chand) {
288 return chand->next == chand;
289}
290
291static void orphan_channel(channel_data *chand) {
292 chand->next->prev = chand->prev;
293 chand->prev->next = chand->next;
294 chand->next = chand->prev = chand;
295}
296
ctiller58393c22015-01-07 14:03:30 -0800297static void finish_destroy_channel(void *cd, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800298 channel_data *chand = cd;
299 grpc_server *server = chand->server;
Craig Tillerd75fe662015-02-21 07:30:49 -0800300 grpc_channel_internal_unref(chand->channel);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800301 server_unref(server);
302}
303
304static void destroy_channel(channel_data *chand) {
305 if (is_channel_orphaned(chand)) return;
306 GPR_ASSERT(chand->server != NULL);
307 orphan_channel(chand);
308 server_ref(chand->server);
ctiller18b49ab2014-12-09 14:39:16 -0800309 grpc_iomgr_add_callback(finish_destroy_channel, chand);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800310}
311
Craig Tiller3b29b562015-02-11 12:58:46 -0800312static void finish_start_new_rpc_and_unlock(grpc_server *server,
313 grpc_call_element *elem,
314 call_data **pending_root,
315 requested_call_array *array) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800316 requested_call rc;
317 call_data *calld = elem->call_data;
318 if (array->count == 0) {
319 calld->state = PENDING;
320 call_list_join(pending_root, calld, PENDING_START);
321 gpr_mu_unlock(&server->mu);
322 } else {
Craig Tiller0ef1a922015-02-11 16:23:01 -0800323 rc = array->calls[--array->count];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800324 calld->state = ACTIVATED;
325 gpr_mu_unlock(&server->mu);
326 begin_call(server, calld, &rc);
327 }
328}
329
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800330static void start_new_rpc(grpc_call_element *elem) {
331 channel_data *chand = elem->channel_data;
332 call_data *calld = elem->call_data;
333 grpc_server *server = chand->server;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800334 gpr_uint32 i;
335 gpr_uint32 hash;
336 channel_registered_method *rm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800337
338 gpr_mu_lock(&server->mu);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800339 if (chand->registered_methods && calld->path && calld->host) {
Craig Tillera94beff2015-02-17 22:02:06 -0800340 /* TODO(ctiller): unify these two searches */
Craig Tiller04cc8be2015-02-10 16:11:22 -0800341 /* check for an exact match with host */
342 hash = GRPC_MDSTR_KV_HASH(calld->host->hash, calld->path->hash);
343 for (i = 0; i < chand->registered_method_max_probes; i++) {
Craig Tiller3b29b562015-02-11 12:58:46 -0800344 rm = &chand->registered_methods[(hash + i) %
345 chand->registered_method_slots];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800346 if (!rm) break;
347 if (rm->host != calld->host) continue;
348 if (rm->method != calld->path) continue;
Craig Tiller3b29b562015-02-11 12:58:46 -0800349 finish_start_new_rpc_and_unlock(server, elem,
350 &rm->server_registered_method->pending,
351 &rm->server_registered_method->requested);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800352 return;
353 }
354 /* check for a wildcard method definition (no host set) */
355 hash = GRPC_MDSTR_KV_HASH(0, calld->path->hash);
Craig Tiller0ef1a922015-02-11 16:23:01 -0800356 for (i = 0; i <= chand->registered_method_max_probes; i++) {
Craig Tiller3b29b562015-02-11 12:58:46 -0800357 rm = &chand->registered_methods[(hash + i) %
358 chand->registered_method_slots];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800359 if (!rm) break;
360 if (rm->host != NULL) continue;
361 if (rm->method != calld->path) continue;
Craig Tiller3b29b562015-02-11 12:58:46 -0800362 finish_start_new_rpc_and_unlock(server, elem,
363 &rm->server_registered_method->pending,
364 &rm->server_registered_method->requested);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800365 return;
366 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800367 }
Craig Tiller3b29b562015-02-11 12:58:46 -0800368 finish_start_new_rpc_and_unlock(server, elem, &server->lists[PENDING_START],
369 &server->requested_calls);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800370}
371
ctiller58393c22015-01-07 14:03:30 -0800372static void kill_zombie(void *elem, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800373 grpc_call_destroy(grpc_call_from_top_element(elem));
374}
375
Craig Tilleree945e82015-05-26 16:15:34 -0700376static int num_listeners(grpc_server *server) {
377 listener *l;
378 int n = 0;
379 for (l = server->listeners; l; l = l->next) {
380 n++;
381 }
382 return n;
383}
384
Craig Tillerdc627722015-05-26 15:27:02 -0700385static void maybe_finish_shutdown(grpc_server *server) {
386 size_t i, j;
Craig Tilleree945e82015-05-26 16:15:34 -0700387 if (server->shutdown && server->lists[ALL_CALLS] == NULL && server->listeners_destroyed == num_listeners(server)) {
388 for (i = 0; i < server->num_shutdown_tags; i++) {
389 for (j = 0; j < server->cq_count; j++) {
Craig Tillerdc627722015-05-26 15:27:02 -0700390 grpc_cq_end_op(server->cqs[j], server->shutdown_tags[i],
391 NULL, 1);
392 }
393 }
394 }
395}
396
Craig Tiller6902ad22015-04-16 08:01:49 -0700397static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
398 grpc_call_element *elem = user_data;
Craig Tillercce17ac2015-01-20 09:29:28 -0800399 channel_data *chand = elem->channel_data;
400 call_data *calld = elem->call_data;
Craig Tiller6902ad22015-04-16 08:01:49 -0700401 if (md->key == chand->path_key) {
402 calld->path = grpc_mdstr_ref(md->value);
403 return NULL;
404 } else if (md->key == chand->authority_key) {
405 calld->host = grpc_mdstr_ref(md->value);
406 return NULL;
407 }
408 return md;
409}
410
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700411static void server_on_recv(void *ptr, int success) {
412 grpc_call_element *elem = ptr;
Craig Tiller6902ad22015-04-16 08:01:49 -0700413 call_data *calld = elem->call_data;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700414 channel_data *chand = elem->channel_data;
415
416 if (success && !calld->got_initial_metadata) {
417 size_t i;
418 size_t nops = calld->recv_ops->nops;
419 grpc_stream_op *ops = calld->recv_ops->ops;
420 for (i = 0; i < nops; i++) {
421 grpc_stream_op *op = &ops[i];
422 if (op->type != GRPC_OP_METADATA) continue;
Craig Tiller205aee12015-04-16 14:46:41 -0700423 grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700424 if (0 != gpr_time_cmp(op->data.metadata.deadline, gpr_inf_future)) {
Craig Tiller6902ad22015-04-16 08:01:49 -0700425 calld->deadline = op->data.metadata.deadline;
Craig Tillercce17ac2015-01-20 09:29:28 -0800426 }
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700427 calld->got_initial_metadata = 1;
428 start_new_rpc(elem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800429 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700430 }
431 }
432
433 switch (*calld->recv_state) {
Craig Tiller06aeea72015-04-23 10:54:45 -0700434 case GRPC_STREAM_OPEN:
435 break;
436 case GRPC_STREAM_SEND_CLOSED:
437 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700438 case GRPC_STREAM_RECV_CLOSED:
439 gpr_mu_lock(&chand->server->mu);
440 if (calld->state == NOT_STARTED) {
441 calld->state = ZOMBIED;
442 grpc_iomgr_add_callback(kill_zombie, elem);
443 }
444 gpr_mu_unlock(&chand->server->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800445 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700446 case GRPC_STREAM_CLOSED:
447 gpr_mu_lock(&chand->server->mu);
448 if (calld->state == NOT_STARTED) {
449 calld->state = ZOMBIED;
450 grpc_iomgr_add_callback(kill_zombie, elem);
451 } else if (calld->state == PENDING) {
452 call_list_remove(calld, PENDING_START);
Craig Tillerc9d03822015-05-20 16:08:45 -0700453 calld->state = ZOMBIED;
454 grpc_iomgr_add_callback(kill_zombie, elem);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700455 }
Craig Tillerdc627722015-05-26 15:27:02 -0700456 call_list_remove(calld, ALL_CALLS);
457 maybe_finish_shutdown(chand->server);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700458 gpr_mu_unlock(&chand->server->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800459 break;
460 }
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700461
462 calld->on_done_recv(calld->recv_user_data, success);
463}
464
Craig Tiller50d9db52015-04-23 10:52:14 -0700465static void server_mutate_op(grpc_call_element *elem, grpc_transport_op *op) {
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700466 call_data *calld = elem->call_data;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700467
468 if (op->recv_ops) {
469 /* substitute our callback for the higher callback */
470 calld->recv_ops = op->recv_ops;
471 calld->recv_state = op->recv_state;
472 calld->on_done_recv = op->on_done_recv;
473 calld->recv_user_data = op->recv_user_data;
474 op->on_done_recv = server_on_recv;
475 op->recv_user_data = elem;
476 }
Craig Tiller50d9db52015-04-23 10:52:14 -0700477}
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700478
Craig Tiller06aeea72015-04-23 10:54:45 -0700479static void server_start_transport_op(grpc_call_element *elem,
480 grpc_transport_op *op) {
Craig Tiller50d9db52015-04-23 10:52:14 -0700481 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
482 server_mutate_op(elem, op);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700483 grpc_call_next_op(elem, op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800484}
485
ctillerf962f522014-12-10 15:28:27 -0800486static void channel_op(grpc_channel_element *elem,
487 grpc_channel_element *from_elem, grpc_channel_op *op) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800488 channel_data *chand = elem->channel_data;
Craig Tiller8b976d02015-02-05 21:41:23 -0800489 grpc_server *server = chand->server;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800490
491 switch (op->type) {
492 case GRPC_ACCEPT_CALL:
493 /* create a call */
Craig Tillerfb189f82015-02-03 12:07:07 -0800494 grpc_call_create(chand->channel, NULL,
Craig Tiller87d5b192015-04-16 14:37:57 -0700495 op->data.accept_call.transport_server_data, NULL, 0,
496 gpr_inf_future);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800497 break;
498 case GRPC_TRANSPORT_CLOSED:
499 /* if the transport is closed for a server channel, we destroy the
500 channel */
Craig Tiller8b976d02015-02-05 21:41:23 -0800501 gpr_mu_lock(&server->mu);
502 server_ref(server);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800503 destroy_channel(chand);
Craig Tiller8b976d02015-02-05 21:41:23 -0800504 gpr_mu_unlock(&server->mu);
505 server_unref(server);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800506 break;
nnoble0c475f02014-12-05 15:37:39 -0800507 case GRPC_TRANSPORT_GOAWAY:
508 gpr_slice_unref(op->data.goaway.message);
509 break;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800510 default:
511 GPR_ASSERT(op->dir == GRPC_CALL_DOWN);
512 grpc_channel_next_op(elem, op);
513 break;
514 }
515}
516
ctiller58393c22015-01-07 14:03:30 -0800517static void finish_shutdown_channel(void *cd, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800518 channel_data *chand = cd;
519 grpc_channel_op op;
nnoble0c475f02014-12-05 15:37:39 -0800520 op.type = GRPC_CHANNEL_DISCONNECT;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800521 op.dir = GRPC_CALL_DOWN;
522 channel_op(grpc_channel_stack_element(
523 grpc_channel_get_channel_stack(chand->channel), 0),
ctillerf962f522014-12-10 15:28:27 -0800524 NULL, &op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800525 grpc_channel_internal_unref(chand->channel);
526}
527
528static void shutdown_channel(channel_data *chand) {
529 grpc_channel_internal_ref(chand->channel);
ctiller18b49ab2014-12-09 14:39:16 -0800530 grpc_iomgr_add_callback(finish_shutdown_channel, chand);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800531}
532
533static void init_call_elem(grpc_call_element *elem,
Craig Tiller06aeea72015-04-23 10:54:45 -0700534 const void *server_transport_data,
535 grpc_transport_op *initial_op) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800536 call_data *calld = elem->call_data;
537 channel_data *chand = elem->channel_data;
538 memset(calld, 0, sizeof(call_data));
539 calld->deadline = gpr_inf_future;
540 calld->call = grpc_call_from_top_element(elem);
541
542 gpr_mu_lock(&chand->server->mu);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800543 call_list_join(&chand->server->lists[ALL_CALLS], calld, ALL_CALLS);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800544 gpr_mu_unlock(&chand->server->mu);
545
546 server_ref(chand->server);
Craig Tiller50d9db52015-04-23 10:52:14 -0700547
Craig Tiller482ef8b2015-04-23 11:38:20 -0700548 if (initial_op) server_mutate_op(elem, initial_op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800549}
550
551static void destroy_call_elem(grpc_call_element *elem) {
552 channel_data *chand = elem->channel_data;
Craig Tillerdb7db992015-01-29 11:19:01 -0800553 call_data *calld = elem->call_data;
Craig Tilleree945e82015-05-26 16:15:34 -0700554 int removed[CALL_LIST_COUNT];
Craig Tillerdc627722015-05-26 15:27:02 -0700555 size_t i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800556
557 gpr_mu_lock(&chand->server->mu);
558 for (i = 0; i < CALL_LIST_COUNT; i++) {
Craig Tilleree945e82015-05-26 16:15:34 -0700559 removed[i] = call_list_remove(elem->call_data, i);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800560 }
Craig Tilleree945e82015-05-26 16:15:34 -0700561 if (removed[ALL_CALLS]) {
562 maybe_finish_shutdown(chand->server);
563 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800564 gpr_mu_unlock(&chand->server->mu);
565
Craig Tiller4df31a62015-01-30 09:44:31 -0800566 if (calld->host) {
567 grpc_mdstr_unref(calld->host);
568 }
569 if (calld->path) {
570 grpc_mdstr_unref(calld->path);
571 }
572
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800573 server_unref(chand->server);
574}
575
576static void init_channel_elem(grpc_channel_element *elem,
577 const grpc_channel_args *args,
578 grpc_mdctx *metadata_context, int is_first,
579 int is_last) {
580 channel_data *chand = elem->channel_data;
581 GPR_ASSERT(is_first);
582 GPR_ASSERT(!is_last);
583 chand->server = NULL;
584 chand->channel = NULL;
Craig Tillercce17ac2015-01-20 09:29:28 -0800585 chand->path_key = grpc_mdstr_from_string(metadata_context, ":path");
586 chand->authority_key = grpc_mdstr_from_string(metadata_context, ":authority");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800587 chand->next = chand->prev = chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800588 chand->registered_methods = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800589}
590
591static void destroy_channel_elem(grpc_channel_element *elem) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800592 size_t i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800593 channel_data *chand = elem->channel_data;
Craig Tillerec3257c2015-02-12 15:59:43 -0800594 if (chand->registered_methods) {
595 for (i = 0; i < chand->registered_method_slots; i++) {
596 if (chand->registered_methods[i].method) {
597 grpc_mdstr_unref(chand->registered_methods[i].method);
598 }
599 if (chand->registered_methods[i].host) {
600 grpc_mdstr_unref(chand->registered_methods[i].host);
601 }
602 }
603 gpr_free(chand->registered_methods);
604 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800605 if (chand->server) {
606 gpr_mu_lock(&chand->server->mu);
607 chand->next->prev = chand->prev;
608 chand->prev->next = chand->next;
609 chand->next = chand->prev = chand;
610 gpr_mu_unlock(&chand->server->mu);
Craig Tillercce17ac2015-01-20 09:29:28 -0800611 grpc_mdstr_unref(chand->path_key);
612 grpc_mdstr_unref(chand->authority_key);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800613 server_unref(chand->server);
614 }
615}
616
617static const grpc_channel_filter server_surface_filter = {
Craig Tiller06aeea72015-04-23 10:54:45 -0700618 server_start_transport_op, channel_op, sizeof(call_data), init_call_elem,
619 destroy_call_elem, sizeof(channel_data), init_channel_elem,
620 destroy_channel_elem, "server",
Craig Tiller9f28ac22015-01-27 17:01:29 -0800621};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800622
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700623void grpc_server_register_completion_queue(grpc_server *server,
624 grpc_completion_queue *cq) {
Craig Tiller20bc56d2015-02-12 09:02:56 -0800625 size_t i, n;
626 for (i = 0; i < server->cq_count; i++) {
627 if (server->cqs[i] == cq) return;
628 }
Craig Tiller89504612015-04-27 11:48:46 -0700629 grpc_cq_internal_ref(cq);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800630 n = server->cq_count++;
Craig Tillerec3257c2015-02-12 15:59:43 -0800631 server->cqs = gpr_realloc(server->cqs,
632 server->cq_count * sizeof(grpc_completion_queue *));
Craig Tiller20bc56d2015-02-12 09:02:56 -0800633 server->cqs[n] = cq;
634}
635
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700636grpc_server *grpc_server_create_from_filters(grpc_channel_filter **filters,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800637 size_t filter_count,
638 const grpc_channel_args *args) {
639 size_t i;
640 int census_enabled = grpc_channel_args_is_census_enabled(args);
641
642 grpc_server *server = gpr_malloc(sizeof(grpc_server));
Craig Tiller60fd3612015-03-05 16:24:22 -0800643
644 GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
645
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800646 memset(server, 0, sizeof(grpc_server));
647
648 gpr_mu_init(&server->mu);
649
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800650 /* decremented by grpc_server_destroy */
651 gpr_ref_init(&server->internal_refcount, 1);
652 server->root_channel_data.next = server->root_channel_data.prev =
653 &server->root_channel_data;
654
655 /* Server filter stack is:
656
657 server_surface_filter - for making surface API calls
658 grpc_server_census_filter (optional) - for stats collection and tracing
659 {passed in filter stack}
660 grpc_connected_channel_filter - for interfacing with transports */
661 server->channel_filter_count = filter_count + 1 + census_enabled;
662 server->channel_filters =
663 gpr_malloc(server->channel_filter_count * sizeof(grpc_channel_filter *));
664 server->channel_filters[0] = &server_surface_filter;
665 if (census_enabled) {
666 server->channel_filters[1] = &grpc_server_census_filter;
667 }
668 for (i = 0; i < filter_count; i++) {
669 server->channel_filters[i + 1 + census_enabled] = filters[i];
670 }
671
672 server->channel_args = grpc_channel_args_copy(args);
673
674 return server;
675}
676
Craig Tiller24be0f72015-02-10 14:04:22 -0800677static int streq(const char *a, const char *b) {
678 if (a == NULL && b == NULL) return 1;
679 if (a == NULL) return 0;
680 if (b == NULL) return 0;
681 return 0 == strcmp(a, b);
682}
683
684void *grpc_server_register_method(grpc_server *server, const char *method,
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700685 const char *host) {
Craig Tiller24be0f72015-02-10 14:04:22 -0800686 registered_method *m;
687 if (!method) {
Craig Tiller35696192015-05-24 15:00:37 -0700688 gpr_log(GPR_ERROR, "grpc_server_register_method method string cannot be NULL");
Craig Tiller24be0f72015-02-10 14:04:22 -0800689 return NULL;
690 }
691 for (m = server->registered_methods; m; m = m->next) {
692 if (streq(m->method, method) && streq(m->host, host)) {
693 gpr_log(GPR_ERROR, "duplicate registration for %s@%s", method,
694 host ? host : "*");
695 return NULL;
696 }
697 }
698 m = gpr_malloc(sizeof(registered_method));
699 memset(m, 0, sizeof(*m));
700 m->method = gpr_strdup(method);
701 m->host = gpr_strdup(host);
702 m->next = server->registered_methods;
703 server->registered_methods = m;
704 return m;
705}
706
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800707void grpc_server_start(grpc_server *server) {
708 listener *l;
Craig Tiller20bc56d2015-02-12 09:02:56 -0800709 size_t i;
710
Craig Tillerec3257c2015-02-12 15:59:43 -0800711 server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800712 for (i = 0; i < server->cq_count; i++) {
713 server->pollsets[i] = grpc_cq_pollset(server->cqs[i]);
714 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800715
716 for (l = server->listeners; l; l = l->next) {
Craig Tiller20bc56d2015-02-12 09:02:56 -0800717 l->start(server, l->arg, server->pollsets, server->cq_count);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800718 }
719}
720
721grpc_transport_setup_result grpc_server_setup_transport(
722 grpc_server *s, grpc_transport *transport,
723 grpc_channel_filter const **extra_filters, size_t num_extra_filters,
724 grpc_mdctx *mdctx) {
725 size_t num_filters = s->channel_filter_count + num_extra_filters + 1;
726 grpc_channel_filter const **filters =
727 gpr_malloc(sizeof(grpc_channel_filter *) * num_filters);
728 size_t i;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800729 size_t num_registered_methods;
730 size_t alloc;
731 registered_method *rm;
732 channel_registered_method *crm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800733 grpc_channel *channel;
734 channel_data *chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800735 grpc_mdstr *host;
736 grpc_mdstr *method;
737 gpr_uint32 hash;
738 gpr_uint32 slots;
739 gpr_uint32 probes;
740 gpr_uint32 max_probes = 0;
Craig Tiller5d6bd442015-02-12 22:50:38 -0800741 grpc_transport_setup_result result;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800742
743 for (i = 0; i < s->channel_filter_count; i++) {
744 filters[i] = s->channel_filters[i];
745 }
746 for (; i < s->channel_filter_count + num_extra_filters; i++) {
747 filters[i] = extra_filters[i - s->channel_filter_count];
748 }
749 filters[i] = &grpc_connected_channel_filter;
750
Craig Tiller20bc56d2015-02-12 09:02:56 -0800751 for (i = 0; i < s->cq_count; i++) {
752 grpc_transport_add_to_pollset(transport, grpc_cq_pollset(s->cqs[i]));
753 }
ctillerd79b4862014-12-17 16:36:59 -0800754
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800755 channel = grpc_channel_create_from_filters(filters, num_filters,
756 s->channel_args, mdctx, 0);
757 chand = (channel_data *)grpc_channel_stack_element(
Craig Tillerc02c1d82015-04-07 16:21:55 -0700758 grpc_channel_get_channel_stack(channel), 0)
759 ->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800760 chand->server = s;
761 server_ref(s);
762 chand->channel = channel;
763
Craig Tiller04cc8be2015-02-10 16:11:22 -0800764 num_registered_methods = 0;
765 for (rm = s->registered_methods; rm; rm = rm->next) {
766 num_registered_methods++;
767 }
768 /* build a lookup table phrased in terms of mdstr's in this channels context
769 to quickly find registered methods */
770 if (num_registered_methods > 0) {
771 slots = 2 * num_registered_methods;
772 alloc = sizeof(channel_registered_method) * slots;
773 chand->registered_methods = gpr_malloc(alloc);
774 memset(chand->registered_methods, 0, alloc);
775 for (rm = s->registered_methods; rm; rm = rm->next) {
776 host = rm->host ? grpc_mdstr_from_string(mdctx, rm->host) : NULL;
Craig Tillere76c9662015-02-11 13:18:31 -0800777 method = grpc_mdstr_from_string(mdctx, rm->method);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800778 hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash);
Craig Tiller3b29b562015-02-11 12:58:46 -0800779 for (probes = 0; chand->registered_methods[(hash + probes) % slots]
Craig Tillerc02c1d82015-04-07 16:21:55 -0700780 .server_registered_method != NULL;
Craig Tiller3b29b562015-02-11 12:58:46 -0800781 probes++)
782 ;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800783 if (probes > max_probes) max_probes = probes;
784 crm = &chand->registered_methods[(hash + probes) % slots];
785 crm->server_registered_method = rm;
786 crm->host = host;
787 crm->method = method;
788 }
789 chand->registered_method_slots = slots;
790 chand->registered_method_max_probes = max_probes;
791 }
792
Craig Tiller5d6bd442015-02-12 22:50:38 -0800793 result = grpc_connected_channel_bind_transport(
794 grpc_channel_get_channel_stack(channel), transport);
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800795
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800796 gpr_mu_lock(&s->mu);
797 chand->next = &s->root_channel_data;
798 chand->prev = chand->next->prev;
799 chand->next->prev = chand->prev->next = chand;
800 gpr_mu_unlock(&s->mu);
801
802 gpr_free(filters);
803
Craig Tiller5d6bd442015-02-12 22:50:38 -0800804 return result;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800805}
806
Craig Tilleree945e82015-05-26 16:15:34 -0700807void grpc_server_shutdown_and_notify(grpc_server *server, void *shutdown_tag) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800808 listener *l;
Craig Tiller24be0f72015-02-10 14:04:22 -0800809 requested_call_array requested_calls;
nnoble0c475f02014-12-05 15:37:39 -0800810 channel_data **channels;
811 channel_data *c;
812 size_t nchannels;
Craig Tillerdc627722015-05-26 15:27:02 -0700813 size_t i;
nnoble0c475f02014-12-05 15:37:39 -0800814 grpc_channel_op op;
815 grpc_channel_element *elem;
Craig Tillerbd217572015-02-11 18:10:56 -0800816 registered_method *rm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800817
818 /* lock, and gather up some stuff to do */
819 gpr_mu_lock(&server->mu);
Craig Tilleree945e82015-05-26 16:15:34 -0700820 for (i = 0; i < server->cq_count; i++) {
821 grpc_cq_begin_op(server->cqs[i], NULL);
Craig Tilleraea2fc02015-02-17 16:54:53 -0800822 }
Craig Tilleree945e82015-05-26 16:15:34 -0700823 server->shutdown_tags =
824 gpr_realloc(server->shutdown_tags,
825 sizeof(void *) * (server->num_shutdown_tags + 1));
826 server->shutdown_tags[server->num_shutdown_tags++] = shutdown_tag;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800827 if (server->shutdown) {
828 gpr_mu_unlock(&server->mu);
829 return;
830 }
831
nnoble0c475f02014-12-05 15:37:39 -0800832 nchannels = 0;
833 for (c = server->root_channel_data.next; c != &server->root_channel_data;
834 c = c->next) {
835 nchannels++;
836 }
837 channels = gpr_malloc(sizeof(channel_data *) * nchannels);
838 i = 0;
839 for (c = server->root_channel_data.next; c != &server->root_channel_data;
840 c = c->next) {
841 grpc_channel_internal_ref(c->channel);
842 channels[i] = c;
843 i++;
844 }
845
Craig Tillerbd217572015-02-11 18:10:56 -0800846 /* collect all unregistered then registered calls */
Craig Tillercce17ac2015-01-20 09:29:28 -0800847 requested_calls = server->requested_calls;
Craig Tiller24be0f72015-02-10 14:04:22 -0800848 memset(&server->requested_calls, 0, sizeof(server->requested_calls));
Craig Tillerbd217572015-02-11 18:10:56 -0800849 for (rm = server->registered_methods; rm; rm = rm->next) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800850 if (requested_calls.count + rm->requested.count >
851 requested_calls.capacity) {
852 requested_calls.capacity =
853 GPR_MAX(requested_calls.count + rm->requested.count,
854 2 * requested_calls.capacity);
855 requested_calls.calls =
856 gpr_realloc(requested_calls.calls, sizeof(*requested_calls.calls) *
857 requested_calls.capacity);
Craig Tillerbd217572015-02-11 18:10:56 -0800858 }
Craig Tillerec3257c2015-02-12 15:59:43 -0800859 memcpy(requested_calls.calls + requested_calls.count, rm->requested.calls,
860 sizeof(*requested_calls.calls) * rm->requested.count);
Craig Tillerbd217572015-02-11 18:10:56 -0800861 requested_calls.count += rm->requested.count;
Craig Tillerec3257c2015-02-12 15:59:43 -0800862 gpr_free(rm->requested.calls);
Craig Tillerbd217572015-02-11 18:10:56 -0800863 memset(&rm->requested, 0, sizeof(rm->requested));
864 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800865
866 server->shutdown = 1;
Craig Tillerdc627722015-05-26 15:27:02 -0700867 maybe_finish_shutdown(server);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800868 gpr_mu_unlock(&server->mu);
869
nnoble0c475f02014-12-05 15:37:39 -0800870 for (i = 0; i < nchannels; i++) {
871 c = channels[i];
872 elem = grpc_channel_stack_element(
873 grpc_channel_get_channel_stack(c->channel), 0);
874
875 op.type = GRPC_CHANNEL_GOAWAY;
876 op.dir = GRPC_CALL_DOWN;
877 op.data.goaway.status = GRPC_STATUS_OK;
878 op.data.goaway.message = gpr_slice_from_copied_string("Server shutdown");
ctillerf962f522014-12-10 15:28:27 -0800879 elem->filter->channel_op(elem, NULL, &op);
nnoble0c475f02014-12-05 15:37:39 -0800880
881 grpc_channel_internal_unref(c->channel);
882 }
883 gpr_free(channels);
884
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800885 /* terminate all the requested calls */
Craig Tiller24be0f72015-02-10 14:04:22 -0800886 for (i = 0; i < requested_calls.count; i++) {
887 fail_call(server, &requested_calls.calls[i]);
Craig Tillercce17ac2015-01-20 09:29:28 -0800888 }
Craig Tiller24be0f72015-02-10 14:04:22 -0800889 gpr_free(requested_calls.calls);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800890
891 /* Shutdown listeners */
892 for (l = server->listeners; l; l = l->next) {
893 l->destroy(server, l->arg);
894 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800895}
896
Craig Tilleraec96aa2015-04-07 14:32:15 -0700897void grpc_server_listener_destroy_done(void *s) {
898 grpc_server *server = s;
899 gpr_mu_lock(&server->mu);
900 server->listeners_destroyed++;
Craig Tilleree945e82015-05-26 16:15:34 -0700901 maybe_finish_shutdown(server);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700902 gpr_mu_unlock(&server->mu);
903}
904
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800905void grpc_server_destroy(grpc_server *server) {
906 channel_data *c;
Craig Tilleraec96aa2015-04-07 14:32:15 -0700907 listener *l;
Craig Tiller872af022015-04-24 15:57:52 -0700908 call_data *calld;
909
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800910 gpr_mu_lock(&server->mu);
Craig Tilleree945e82015-05-26 16:15:34 -0700911 GPR_ASSERT(server->shutdown);
912 GPR_ASSERT(server->listeners_destroyed == num_listeners(server));
Craig Tilleraec96aa2015-04-07 14:32:15 -0700913
914 while (server->listeners) {
915 l = server->listeners;
916 server->listeners = l->next;
917 gpr_free(l);
918 }
919
Craig Tiller872af022015-04-24 15:57:52 -0700920 while ((calld = call_list_remove_head(&server->lists[PENDING_START],
921 PENDING_START)) != NULL) {
Craig Tiller872af022015-04-24 15:57:52 -0700922 calld->state = ZOMBIED;
923 grpc_iomgr_add_callback(
924 kill_zombie,
925 grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
926 }
927
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800928 for (c = server->root_channel_data.next; c != &server->root_channel_data;
929 c = c->next) {
930 shutdown_channel(c);
931 }
932 gpr_mu_unlock(&server->mu);
933
934 server_unref(server);
935}
936
937void grpc_server_add_listener(grpc_server *server, void *arg,
ctiller58393c22015-01-07 14:03:30 -0800938 void (*start)(grpc_server *server, void *arg,
Craig Tillerec3257c2015-02-12 15:59:43 -0800939 grpc_pollset **pollsets,
940 size_t pollset_count),
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800941 void (*destroy)(grpc_server *server, void *arg)) {
942 listener *l = gpr_malloc(sizeof(listener));
943 l->arg = arg;
944 l->start = start;
945 l->destroy = destroy;
946 l->next = server->listeners;
947 server->listeners = l;
948}
949
Craig Tiller9f28ac22015-01-27 17:01:29 -0800950static grpc_call_error queue_call_request(grpc_server *server,
Craig Tiller24be0f72015-02-10 14:04:22 -0800951 requested_call *rc) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -0800952 call_data *calld = NULL;
Craig Tiller0ef1a922015-02-11 16:23:01 -0800953 requested_call_array *requested_calls = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800954 gpr_mu_lock(&server->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800955 if (server->shutdown) {
956 gpr_mu_unlock(&server->mu);
Craig Tiller24be0f72015-02-10 14:04:22 -0800957 fail_call(server, rc);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800958 return GRPC_CALL_OK;
959 }
Craig Tiller04cc8be2015-02-10 16:11:22 -0800960 switch (rc->type) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800961 case BATCH_CALL:
Craig Tiller3b29b562015-02-11 12:58:46 -0800962 calld =
963 call_list_remove_head(&server->lists[PENDING_START], PENDING_START);
Craig Tiller0ef1a922015-02-11 16:23:01 -0800964 requested_calls = &server->requested_calls;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800965 break;
966 case REGISTERED_CALL:
Craig Tiller3b29b562015-02-11 12:58:46 -0800967 calld = call_list_remove_head(
968 &rc->data.registered.registered_method->pending, PENDING_START);
Craig Tiller0ef1a922015-02-11 16:23:01 -0800969 requested_calls = &rc->data.registered.registered_method->requested;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800970 break;
971 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800972 if (calld) {
Craig Tillercce17ac2015-01-20 09:29:28 -0800973 GPR_ASSERT(calld->state == PENDING);
Craig Tillerbb3f22f2015-01-29 16:40:56 -0800974 calld->state = ACTIVATED;
Craig Tillercce17ac2015-01-20 09:29:28 -0800975 gpr_mu_unlock(&server->mu);
Craig Tiller24be0f72015-02-10 14:04:22 -0800976 begin_call(server, calld, rc);
Craig Tillercce17ac2015-01-20 09:29:28 -0800977 return GRPC_CALL_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800978 } else {
Craig Tiller0ef1a922015-02-11 16:23:01 -0800979 *requested_call_array_add(requested_calls) = *rc;
Craig Tillercce17ac2015-01-20 09:29:28 -0800980 gpr_mu_unlock(&server->mu);
981 return GRPC_CALL_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800982 }
Craig Tillercce17ac2015-01-20 09:29:28 -0800983}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800984
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700985grpc_call_error grpc_server_request_call(
986 grpc_server *server, grpc_call **call, grpc_call_details *details,
987 grpc_metadata_array *initial_metadata,
988 grpc_completion_queue *cq_bound_to_call,
989 grpc_completion_queue *cq_for_notification, void *tag) {
Craig Tiller24be0f72015-02-10 14:04:22 -0800990 requested_call rc;
Craig Tiller54478f82015-05-12 14:08:56 -0700991 grpc_cq_begin_op(cq_for_notification, NULL);
Craig Tiller24be0f72015-02-10 14:04:22 -0800992 rc.type = BATCH_CALL;
993 rc.tag = tag;
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700994 rc.cq_bound_to_call = cq_bound_to_call;
995 rc.cq_for_notification = cq_for_notification;
996 rc.call = call;
Craig Tiller24be0f72015-02-10 14:04:22 -0800997 rc.data.batch.details = details;
998 rc.data.batch.initial_metadata = initial_metadata;
999 return queue_call_request(server, &rc);
1000}
1001
1002grpc_call_error grpc_server_request_registered_call(
Craig Tillerec3257c2015-02-12 15:59:43 -08001003 grpc_server *server, void *rm, grpc_call **call, gpr_timespec *deadline,
1004 grpc_metadata_array *initial_metadata, grpc_byte_buffer **optional_payload,
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001005 grpc_completion_queue *cq_bound_to_call,
1006 grpc_completion_queue *cq_for_notification, void *tag) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001007 requested_call rc;
Craig Tiller20bc56d2015-02-12 09:02:56 -08001008 registered_method *registered_method = rm;
Craig Tiller54478f82015-05-12 14:08:56 -07001009 grpc_cq_begin_op(cq_for_notification, NULL);
Craig Tiller24be0f72015-02-10 14:04:22 -08001010 rc.type = REGISTERED_CALL;
1011 rc.tag = tag;
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001012 rc.cq_bound_to_call = cq_bound_to_call;
1013 rc.cq_for_notification = cq_for_notification;
1014 rc.call = call;
Craig Tiller24be0f72015-02-10 14:04:22 -08001015 rc.data.registered.registered_method = registered_method;
1016 rc.data.registered.deadline = deadline;
1017 rc.data.registered.initial_metadata = initial_metadata;
1018 rc.data.registered.optional_payload = optional_payload;
1019 return queue_call_request(server, &rc);
1020}
1021
Craig Tiller64be9f72015-05-04 14:53:51 -07001022static void publish_registered_or_batch(grpc_call *call, int success,
Craig Tiller24be0f72015-02-10 14:04:22 -08001023 void *tag);
Craig Tiller64be9f72015-05-04 14:53:51 -07001024static void publish_was_not_set(grpc_call *call, int success, void *tag) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001025 abort();
1026}
Craig Tiller24be0f72015-02-10 14:04:22 -08001027
Craig Tiller166e2502015-02-03 20:14:41 -08001028static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
1029 gpr_slice slice = value->slice;
1030 size_t len = GPR_SLICE_LENGTH(slice);
1031
1032 if (len + 1 > *capacity) {
1033 *capacity = GPR_MAX(len + 1, *capacity * 2);
1034 *dest = gpr_realloc(*dest, *capacity);
1035 }
1036 memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
1037}
1038
Craig Tiller24be0f72015-02-10 14:04:22 -08001039static void begin_call(grpc_server *server, call_data *calld,
1040 requested_call *rc) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001041 grpc_ioreq_completion_func publish = publish_was_not_set;
Craig Tiller24be0f72015-02-10 14:04:22 -08001042 grpc_ioreq req[2];
1043 grpc_ioreq *r = req;
1044
1045 /* called once initial metadata has been read by the call, but BEFORE
1046 the ioreq to fetch it out of the call has been executed.
1047 This means metadata related fields can be relied on in calld, but to
1048 fill in the metadata array passed by the client, we need to perform
1049 an ioreq op, that should complete immediately. */
1050
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001051 grpc_call_set_completion_queue(calld->call, rc->cq_bound_to_call);
1052 *rc->call = calld->call;
1053 calld->cq_new = rc->cq_for_notification;
Craig Tiller24be0f72015-02-10 14:04:22 -08001054 switch (rc->type) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001055 case BATCH_CALL:
1056 cpstr(&rc->data.batch.details->host,
1057 &rc->data.batch.details->host_capacity, calld->host);
1058 cpstr(&rc->data.batch.details->method,
1059 &rc->data.batch.details->method_capacity, calld->path);
Masood Malekghassemibf177c82015-04-27 12:14:38 -07001060 rc->data.batch.details->deadline = calld->deadline;
Craig Tiller24be0f72015-02-10 14:04:22 -08001061 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1062 r->data.recv_metadata = rc->data.batch.initial_metadata;
1063 r++;
1064 publish = publish_registered_or_batch;
1065 break;
1066 case REGISTERED_CALL:
1067 *rc->data.registered.deadline = calld->deadline;
Craig Tiller24be0f72015-02-10 14:04:22 -08001068 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1069 r->data.recv_metadata = rc->data.registered.initial_metadata;
1070 r++;
1071 if (rc->data.registered.optional_payload) {
1072 r->op = GRPC_IOREQ_RECV_MESSAGE;
1073 r->data.recv_message = rc->data.registered.optional_payload;
1074 r++;
1075 }
1076 publish = publish_registered_or_batch;
1077 break;
1078 }
1079
Craig Tiller4df412b2015-04-28 07:57:54 -07001080 GRPC_CALL_INTERNAL_REF(calld->call, "server");
Craig Tiller24be0f72015-02-10 14:04:22 -08001081 grpc_call_start_ioreq_and_call_back(calld->call, req, r - req, publish,
1082 rc->tag);
1083}
1084
1085static void fail_call(grpc_server *server, requested_call *rc) {
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001086 *rc->call = NULL;
Craig Tiller24be0f72015-02-10 14:04:22 -08001087 switch (rc->type) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001088 case BATCH_CALL:
Craig Tiller24be0f72015-02-10 14:04:22 -08001089 rc->data.batch.initial_metadata->count = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001090 break;
1091 case REGISTERED_CALL:
Craig Tiller24be0f72015-02-10 14:04:22 -08001092 rc->data.registered.initial_metadata->count = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001093 break;
1094 }
Craig Tiller54478f82015-05-12 14:08:56 -07001095 grpc_cq_end_op(rc->cq_for_notification, rc->tag, NULL, 0);
Craig Tiller24be0f72015-02-10 14:04:22 -08001096}
1097
Craig Tiller64be9f72015-05-04 14:53:51 -07001098static void publish_registered_or_batch(grpc_call *call, int success,
Craig Tiller24be0f72015-02-10 14:04:22 -08001099 void *tag) {
Craig Tiller8e8fd892015-02-10 17:02:08 -08001100 grpc_call_element *elem =
1101 grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
Craig Tiller20bc56d2015-02-12 09:02:56 -08001102 call_data *calld = elem->call_data;
Craig Tiller64be9f72015-05-04 14:53:51 -07001103 grpc_cq_end_op(calld->cq_new, tag, call, success);
Craig Tiller24be0f72015-02-10 14:04:22 -08001104}
1105
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001106const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) {
1107 return server->channel_args;
Craig Tiller190d3602015-02-18 09:23:38 -08001108}