blob: ff922716e5acd196d129f7fca8a6825188239542 [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
72typedef enum { LEGACY_CALL, BATCH_CALL, REGISTERED_CALL } requested_call_type;
73
74typedef struct {
75 requested_call_type type;
76 void *tag;
77 union {
78 struct {
Craig Tiller8e8fd892015-02-10 17:02:08 -080079 grpc_completion_queue *cq_bind;
Craig Tiller24be0f72015-02-10 14:04:22 -080080 grpc_call **call;
81 grpc_call_details *details;
82 grpc_metadata_array *initial_metadata;
83 } batch;
84 struct {
Craig Tiller8e8fd892015-02-10 17:02:08 -080085 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;
Craig Tiller20bc56d2015-02-12 09:02:56 -0800106 grpc_completion_queue *cq;
Craig Tiller24be0f72015-02-10 14:04:22 -0800107 registered_method *next;
108};
109
110typedef struct channel_registered_method {
111 registered_method *server_registered_method;
112 grpc_mdstr *method;
113 grpc_mdstr *host;
114} channel_registered_method;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800115
116struct channel_data {
117 grpc_server *server;
118 grpc_channel *channel;
Craig Tillercce17ac2015-01-20 09:29:28 -0800119 grpc_mdstr *path_key;
120 grpc_mdstr *authority_key;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800121 /* linked list of all channels on a server */
122 channel_data *next;
123 channel_data *prev;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800124 channel_registered_method *registered_methods;
125 gpr_uint32 registered_method_slots;
126 gpr_uint32 registered_method_max_probes;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800127};
128
129struct grpc_server {
130 size_t channel_filter_count;
131 const grpc_channel_filter **channel_filters;
132 grpc_channel_args *channel_args;
Craig Tiller20bc56d2015-02-12 09:02:56 -0800133 grpc_completion_queue *unregistered_cq;
Craig Tillerec3257c2015-02-12 15:59:43 -0800134
Craig Tiller20bc56d2015-02-12 09:02:56 -0800135 grpc_completion_queue **cqs;
136 grpc_pollset **pollsets;
137 size_t cq_count;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800138
139 gpr_mu mu;
Craig Tilleraec96aa2015-04-07 14:32:15 -0700140 gpr_cv cv;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800141
Craig Tiller24be0f72015-02-10 14:04:22 -0800142 registered_method *registered_methods;
143 requested_call_array requested_calls;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800144
145 gpr_uint8 shutdown;
Craig Tilleraea2fc02015-02-17 16:54:53 -0800146 size_t num_shutdown_tags;
147 void **shutdown_tags;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800148
149 call_data *lists[CALL_LIST_COUNT];
150 channel_data root_channel_data;
151
152 listener *listeners;
Craig Tilleraec96aa2015-04-07 14:32:15 -0700153 int listeners_destroyed;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800154 gpr_refcount internal_refcount;
155};
156
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800157typedef enum {
158 /* waiting for metadata */
159 NOT_STARTED,
160 /* inital metadata read, not flow controlled in yet */
161 PENDING,
162 /* flow controlled in, on completion queue */
163 ACTIVATED,
164 /* cancelled before being queued */
165 ZOMBIED
166} call_state;
167
Craig Tillerfb189f82015-02-03 12:07:07 -0800168typedef struct legacy_data {
Craig Tiller24be0f72015-02-10 14:04:22 -0800169 grpc_metadata_array initial_metadata;
Craig Tillerfb189f82015-02-03 12:07:07 -0800170} legacy_data;
Craig Tillercce17ac2015-01-20 09:29:28 -0800171
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800172struct call_data {
173 grpc_call *call;
174
175 call_state state;
176 gpr_timespec deadline;
Craig Tillercce17ac2015-01-20 09:29:28 -0800177 grpc_mdstr *path;
178 grpc_mdstr *host;
179
180 legacy_data *legacy;
Craig Tiller20bc56d2015-02-12 09:02:56 -0800181 grpc_completion_queue *cq_new;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800182
Craig Tiller04cc8be2015-02-10 16:11:22 -0800183 call_data **root[CALL_LIST_COUNT];
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800184 call_link links[CALL_LIST_COUNT];
185};
186
187#define SERVER_FROM_CALL_ELEM(elem) \
188 (((channel_data *)(elem)->channel_data)->server)
189
190static void do_nothing(void *unused, grpc_op_error ignored) {}
191
Craig Tiller24be0f72015-02-10 14:04:22 -0800192static void begin_call(grpc_server *server, call_data *calld,
193 requested_call *rc);
194static void fail_call(grpc_server *server, requested_call *rc);
195
Craig Tiller3b29b562015-02-11 12:58:46 -0800196static int call_list_join(call_data **root, call_data *call, call_list list) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800197 GPR_ASSERT(!call->root[list]);
198 call->root[list] = root;
199 if (!*root) {
200 *root = call;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800201 call->links[list].next = call->links[list].prev = call;
202 } else {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800203 call->links[list].next = *root;
204 call->links[list].prev = (*root)->links[list].prev;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800205 call->links[list].next->links[list].prev =
206 call->links[list].prev->links[list].next = call;
207 }
208 return 1;
209}
210
Craig Tiller04cc8be2015-02-10 16:11:22 -0800211static call_data *call_list_remove_head(call_data **root, call_list list) {
212 call_data *out = *root;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800213 if (out) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800214 out->root[list] = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800215 if (out->links[list].next == out) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800216 *root = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800217 } else {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800218 *root = out->links[list].next;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800219 out->links[list].next->links[list].prev = out->links[list].prev;
220 out->links[list].prev->links[list].next = out->links[list].next;
221 }
222 }
223 return out;
224}
225
Craig Tiller04cc8be2015-02-10 16:11:22 -0800226static int call_list_remove(call_data *call, call_list list) {
227 call_data **root = call->root[list];
228 if (root == NULL) return 0;
229 call->root[list] = NULL;
230 if (*root == call) {
231 *root = call->links[list].next;
232 if (*root == call) {
233 *root = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800234 return 1;
235 }
236 }
Craig Tiller04cc8be2015-02-10 16:11:22 -0800237 GPR_ASSERT(*root != call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800238 call->links[list].next->links[list].prev = call->links[list].prev;
239 call->links[list].prev->links[list].next = call->links[list].next;
240 return 1;
241}
242
Craig Tiller24be0f72015-02-10 14:04:22 -0800243static void requested_call_array_destroy(requested_call_array *array) {
244 gpr_free(array->calls);
245}
246
247static requested_call *requested_call_array_add(requested_call_array *array) {
248 requested_call *rc;
249 if (array->count == array->capacity) {
250 array->capacity = GPR_MAX(array->capacity + 8, array->capacity * 2);
251 array->calls =
252 gpr_realloc(array->calls, sizeof(requested_call) * array->capacity);
253 }
254 rc = &array->calls[array->count++];
255 memset(rc, 0, sizeof(*rc));
256 return rc;
257}
258
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800259static void server_ref(grpc_server *server) {
260 gpr_ref(&server->internal_refcount);
261}
262
263static void server_unref(grpc_server *server) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800264 registered_method *rm;
Craig Tiller89504612015-04-27 11:48:46 -0700265 size_t i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800266 if (gpr_unref(&server->internal_refcount)) {
267 grpc_channel_args_destroy(server->channel_args);
268 gpr_mu_destroy(&server->mu);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700269 gpr_cv_destroy(&server->cv);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800270 gpr_free(server->channel_filters);
Craig Tiller24be0f72015-02-10 14:04:22 -0800271 requested_call_array_destroy(&server->requested_calls);
Craig Tillerec3257c2015-02-12 15:59:43 -0800272 while ((rm = server->registered_methods) != NULL) {
273 server->registered_methods = rm->next;
274 gpr_free(rm->method);
275 gpr_free(rm->host);
276 requested_call_array_destroy(&rm->requested);
277 gpr_free(rm);
278 }
Craig Tiller89504612015-04-27 11:48:46 -0700279 for (i = 0; i < server->cq_count; i++) {
280 grpc_cq_internal_unref(server->cqs[i]);
281 }
Craig Tillerec3257c2015-02-12 15:59:43 -0800282 gpr_free(server->cqs);
283 gpr_free(server->pollsets);
Craig Tilleraea2fc02015-02-17 16:54:53 -0800284 gpr_free(server->shutdown_tags);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800285 gpr_free(server);
286 }
287}
288
289static int is_channel_orphaned(channel_data *chand) {
290 return chand->next == chand;
291}
292
293static void orphan_channel(channel_data *chand) {
294 chand->next->prev = chand->prev;
295 chand->prev->next = chand->next;
296 chand->next = chand->prev = chand;
297}
298
ctiller58393c22015-01-07 14:03:30 -0800299static void finish_destroy_channel(void *cd, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800300 channel_data *chand = cd;
301 grpc_server *server = chand->server;
Craig Tillerd75fe662015-02-21 07:30:49 -0800302 grpc_channel_internal_unref(chand->channel);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800303 server_unref(server);
304}
305
306static void destroy_channel(channel_data *chand) {
307 if (is_channel_orphaned(chand)) return;
308 GPR_ASSERT(chand->server != NULL);
309 orphan_channel(chand);
310 server_ref(chand->server);
ctiller18b49ab2014-12-09 14:39:16 -0800311 grpc_iomgr_add_callback(finish_destroy_channel, chand);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800312}
313
Craig Tiller3b29b562015-02-11 12:58:46 -0800314static void finish_start_new_rpc_and_unlock(grpc_server *server,
315 grpc_call_element *elem,
316 call_data **pending_root,
317 requested_call_array *array) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800318 requested_call rc;
319 call_data *calld = elem->call_data;
320 if (array->count == 0) {
321 calld->state = PENDING;
322 call_list_join(pending_root, calld, PENDING_START);
323 gpr_mu_unlock(&server->mu);
324 } else {
Craig Tiller0ef1a922015-02-11 16:23:01 -0800325 rc = array->calls[--array->count];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800326 calld->state = ACTIVATED;
327 gpr_mu_unlock(&server->mu);
328 begin_call(server, calld, &rc);
329 }
330}
331
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800332static void start_new_rpc(grpc_call_element *elem) {
333 channel_data *chand = elem->channel_data;
334 call_data *calld = elem->call_data;
335 grpc_server *server = chand->server;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800336 gpr_uint32 i;
337 gpr_uint32 hash;
338 channel_registered_method *rm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800339
340 gpr_mu_lock(&server->mu);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800341 if (chand->registered_methods && calld->path && calld->host) {
Craig Tillera94beff2015-02-17 22:02:06 -0800342 /* TODO(ctiller): unify these two searches */
Craig Tiller04cc8be2015-02-10 16:11:22 -0800343 /* check for an exact match with host */
344 hash = GRPC_MDSTR_KV_HASH(calld->host->hash, calld->path->hash);
345 for (i = 0; i < chand->registered_method_max_probes; i++) {
Craig Tiller3b29b562015-02-11 12:58:46 -0800346 rm = &chand->registered_methods[(hash + i) %
347 chand->registered_method_slots];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800348 if (!rm) break;
349 if (rm->host != calld->host) continue;
350 if (rm->method != calld->path) continue;
Craig Tiller3b29b562015-02-11 12:58:46 -0800351 finish_start_new_rpc_and_unlock(server, elem,
352 &rm->server_registered_method->pending,
353 &rm->server_registered_method->requested);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800354 return;
355 }
356 /* check for a wildcard method definition (no host set) */
357 hash = GRPC_MDSTR_KV_HASH(0, calld->path->hash);
Craig Tiller0ef1a922015-02-11 16:23:01 -0800358 for (i = 0; i <= chand->registered_method_max_probes; i++) {
Craig Tiller3b29b562015-02-11 12:58:46 -0800359 rm = &chand->registered_methods[(hash + i) %
360 chand->registered_method_slots];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800361 if (!rm) break;
362 if (rm->host != NULL) continue;
363 if (rm->method != calld->path) continue;
Craig Tiller3b29b562015-02-11 12:58:46 -0800364 finish_start_new_rpc_and_unlock(server, elem,
365 &rm->server_registered_method->pending,
366 &rm->server_registered_method->requested);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800367 return;
368 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800369 }
Craig Tiller3b29b562015-02-11 12:58:46 -0800370 finish_start_new_rpc_and_unlock(server, elem, &server->lists[PENDING_START],
371 &server->requested_calls);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800372}
373
ctiller58393c22015-01-07 14:03:30 -0800374static void kill_zombie(void *elem, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800375 grpc_call_destroy(grpc_call_from_top_element(elem));
376}
377
Craig Tillercce17ac2015-01-20 09:29:28 -0800378static void stream_closed(grpc_call_element *elem) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800379 call_data *calld = elem->call_data;
380 channel_data *chand = elem->channel_data;
381 gpr_mu_lock(&chand->server->mu);
382 switch (calld->state) {
383 case ACTIVATED:
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800384 break;
385 case PENDING:
Craig Tiller04cc8be2015-02-10 16:11:22 -0800386 call_list_remove(calld, PENDING_START);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800387 /* fallthrough intended */
388 case NOT_STARTED:
389 calld->state = ZOMBIED;
ctiller18b49ab2014-12-09 14:39:16 -0800390 grpc_iomgr_add_callback(kill_zombie, elem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800391 break;
392 case ZOMBIED:
393 break;
394 }
395 gpr_mu_unlock(&chand->server->mu);
Craig Tiller0a927bf2015-02-05 10:52:53 -0800396 grpc_call_stream_closed(elem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800397}
398
Craig Tillercce17ac2015-01-20 09:29:28 -0800399static void read_closed(grpc_call_element *elem) {
400 call_data *calld = elem->call_data;
401 channel_data *chand = elem->channel_data;
402 gpr_mu_lock(&chand->server->mu);
403 switch (calld->state) {
404 case ACTIVATED:
405 case PENDING:
406 grpc_call_read_closed(elem);
407 break;
408 case NOT_STARTED:
409 calld->state = ZOMBIED;
410 grpc_iomgr_add_callback(kill_zombie, elem);
411 break;
412 case ZOMBIED:
413 break;
414 }
415 gpr_mu_unlock(&chand->server->mu);
416}
417
Craig Tiller6902ad22015-04-16 08:01:49 -0700418static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
419 grpc_call_element *elem = user_data;
Craig Tillercce17ac2015-01-20 09:29:28 -0800420 channel_data *chand = elem->channel_data;
421 call_data *calld = elem->call_data;
Craig Tiller6902ad22015-04-16 08:01:49 -0700422 if (md->key == chand->path_key) {
423 calld->path = grpc_mdstr_ref(md->value);
424 return NULL;
425 } else if (md->key == chand->authority_key) {
426 calld->host = grpc_mdstr_ref(md->value);
427 return NULL;
428 }
429 return md;
430}
431
432static void call_op(grpc_call_element *elem, grpc_call_element *from_elemn,
433 grpc_call_op *op) {
434 call_data *calld = elem->call_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800435 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
436 switch (op->type) {
437 case GRPC_RECV_METADATA:
Craig Tiller205aee12015-04-16 14:46:41 -0700438 grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem);
Craig Tiller6902ad22015-04-16 08:01:49 -0700439 if (grpc_call_recv_metadata(elem, &op->data.metadata)) {
440 calld->deadline = op->data.metadata.deadline;
441 start_new_rpc(elem);
Craig Tillercce17ac2015-01-20 09:29:28 -0800442 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800443 break;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800444 case GRPC_RECV_MESSAGE:
Craig Tillercce17ac2015-01-20 09:29:28 -0800445 grpc_call_recv_message(elem, op->data.message);
446 op->done_cb(op->user_data, GRPC_OP_OK);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800447 break;
448 case GRPC_RECV_HALF_CLOSE:
Craig Tillercce17ac2015-01-20 09:29:28 -0800449 read_closed(elem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800450 break;
451 case GRPC_RECV_FINISH:
Craig Tillercce17ac2015-01-20 09:29:28 -0800452 stream_closed(elem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800453 break;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800454 default:
455 GPR_ASSERT(op->dir == GRPC_CALL_DOWN);
456 grpc_call_next_op(elem, op);
457 break;
458 }
459}
460
ctillerf962f522014-12-10 15:28:27 -0800461static void channel_op(grpc_channel_element *elem,
462 grpc_channel_element *from_elem, grpc_channel_op *op) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800463 channel_data *chand = elem->channel_data;
Craig Tiller8b976d02015-02-05 21:41:23 -0800464 grpc_server *server = chand->server;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800465
466 switch (op->type) {
467 case GRPC_ACCEPT_CALL:
468 /* create a call */
Craig Tillerfb189f82015-02-03 12:07:07 -0800469 grpc_call_create(chand->channel, NULL,
Craig Tiller87d5b192015-04-16 14:37:57 -0700470 op->data.accept_call.transport_server_data, NULL, 0,
471 gpr_inf_future);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800472 break;
473 case GRPC_TRANSPORT_CLOSED:
474 /* if the transport is closed for a server channel, we destroy the
475 channel */
Craig Tiller8b976d02015-02-05 21:41:23 -0800476 gpr_mu_lock(&server->mu);
477 server_ref(server);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800478 destroy_channel(chand);
Craig Tiller8b976d02015-02-05 21:41:23 -0800479 gpr_mu_unlock(&server->mu);
480 server_unref(server);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800481 break;
nnoble0c475f02014-12-05 15:37:39 -0800482 case GRPC_TRANSPORT_GOAWAY:
483 gpr_slice_unref(op->data.goaway.message);
484 break;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800485 default:
486 GPR_ASSERT(op->dir == GRPC_CALL_DOWN);
487 grpc_channel_next_op(elem, op);
488 break;
489 }
490}
491
ctiller58393c22015-01-07 14:03:30 -0800492static void finish_shutdown_channel(void *cd, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800493 channel_data *chand = cd;
494 grpc_channel_op op;
nnoble0c475f02014-12-05 15:37:39 -0800495 op.type = GRPC_CHANNEL_DISCONNECT;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800496 op.dir = GRPC_CALL_DOWN;
497 channel_op(grpc_channel_stack_element(
498 grpc_channel_get_channel_stack(chand->channel), 0),
ctillerf962f522014-12-10 15:28:27 -0800499 NULL, &op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800500 grpc_channel_internal_unref(chand->channel);
501}
502
503static void shutdown_channel(channel_data *chand) {
504 grpc_channel_internal_ref(chand->channel);
ctiller18b49ab2014-12-09 14:39:16 -0800505 grpc_iomgr_add_callback(finish_shutdown_channel, chand);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800506}
507
508static void init_call_elem(grpc_call_element *elem,
509 const void *server_transport_data) {
510 call_data *calld = elem->call_data;
511 channel_data *chand = elem->channel_data;
512 memset(calld, 0, sizeof(call_data));
513 calld->deadline = gpr_inf_future;
514 calld->call = grpc_call_from_top_element(elem);
515
516 gpr_mu_lock(&chand->server->mu);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800517 call_list_join(&chand->server->lists[ALL_CALLS], calld, ALL_CALLS);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800518 gpr_mu_unlock(&chand->server->mu);
519
520 server_ref(chand->server);
521}
522
523static void destroy_call_elem(grpc_call_element *elem) {
524 channel_data *chand = elem->channel_data;
Craig Tillerdb7db992015-01-29 11:19:01 -0800525 call_data *calld = elem->call_data;
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800526 size_t i, j;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800527
528 gpr_mu_lock(&chand->server->mu);
529 for (i = 0; i < CALL_LIST_COUNT; i++) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800530 call_list_remove(elem->call_data, i);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800531 }
Craig Tilleraea2fc02015-02-17 16:54:53 -0800532 if (chand->server->shutdown && chand->server->lists[ALL_CALLS] == NULL) {
533 for (i = 0; i < chand->server->num_shutdown_tags; i++) {
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800534 for (j = 0; j < chand->server->cq_count; j++) {
535 grpc_cq_end_server_shutdown(chand->server->cqs[j],
536 chand->server->shutdown_tags[i]);
537 }
Craig Tiller20bc56d2015-02-12 09:02:56 -0800538 }
Craig Tiller4ffdcd52015-01-16 11:34:55 -0800539 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800540 gpr_mu_unlock(&chand->server->mu);
541
Craig Tiller4df31a62015-01-30 09:44:31 -0800542 if (calld->host) {
543 grpc_mdstr_unref(calld->host);
544 }
545 if (calld->path) {
546 grpc_mdstr_unref(calld->path);
547 }
548
Craig Tillerdb7db992015-01-29 11:19:01 -0800549 if (calld->legacy) {
Craig Tiller24be0f72015-02-10 14:04:22 -0800550 gpr_free(calld->legacy->initial_metadata.metadata);
Craig Tillerdb7db992015-01-29 11:19:01 -0800551 gpr_free(calld->legacy);
552 }
553
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800554 server_unref(chand->server);
555}
556
557static void init_channel_elem(grpc_channel_element *elem,
558 const grpc_channel_args *args,
559 grpc_mdctx *metadata_context, int is_first,
560 int is_last) {
561 channel_data *chand = elem->channel_data;
562 GPR_ASSERT(is_first);
563 GPR_ASSERT(!is_last);
564 chand->server = NULL;
565 chand->channel = NULL;
Craig Tillercce17ac2015-01-20 09:29:28 -0800566 chand->path_key = grpc_mdstr_from_string(metadata_context, ":path");
567 chand->authority_key = grpc_mdstr_from_string(metadata_context, ":authority");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800568 chand->next = chand->prev = chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800569 chand->registered_methods = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800570}
571
572static void destroy_channel_elem(grpc_channel_element *elem) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800573 size_t i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800574 channel_data *chand = elem->channel_data;
Craig Tillerec3257c2015-02-12 15:59:43 -0800575 if (chand->registered_methods) {
576 for (i = 0; i < chand->registered_method_slots; i++) {
577 if (chand->registered_methods[i].method) {
578 grpc_mdstr_unref(chand->registered_methods[i].method);
579 }
580 if (chand->registered_methods[i].host) {
581 grpc_mdstr_unref(chand->registered_methods[i].host);
582 }
583 }
584 gpr_free(chand->registered_methods);
585 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800586 if (chand->server) {
587 gpr_mu_lock(&chand->server->mu);
588 chand->next->prev = chand->prev;
589 chand->prev->next = chand->next;
590 chand->next = chand->prev = chand;
591 gpr_mu_unlock(&chand->server->mu);
Craig Tillercce17ac2015-01-20 09:29:28 -0800592 grpc_mdstr_unref(chand->path_key);
593 grpc_mdstr_unref(chand->authority_key);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800594 server_unref(chand->server);
595 }
596}
597
598static const grpc_channel_filter server_surface_filter = {
Craig Tillerc02c1d82015-04-07 16:21:55 -0700599 call_op, channel_op, sizeof(call_data), init_call_elem, destroy_call_elem,
600 sizeof(channel_data), init_channel_elem, destroy_channel_elem, "server",
Craig Tiller9f28ac22015-01-27 17:01:29 -0800601};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800602
Craig Tiller20bc56d2015-02-12 09:02:56 -0800603static void addcq(grpc_server *server, grpc_completion_queue *cq) {
604 size_t i, n;
605 for (i = 0; i < server->cq_count; i++) {
606 if (server->cqs[i] == cq) return;
607 }
Craig Tiller89504612015-04-27 11:48:46 -0700608 grpc_cq_internal_ref(cq);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800609 n = server->cq_count++;
Craig Tillerec3257c2015-02-12 15:59:43 -0800610 server->cqs = gpr_realloc(server->cqs,
611 server->cq_count * sizeof(grpc_completion_queue *));
Craig Tiller20bc56d2015-02-12 09:02:56 -0800612 server->cqs[n] = cq;
613}
614
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800615grpc_server *grpc_server_create_from_filters(grpc_completion_queue *cq,
616 grpc_channel_filter **filters,
617 size_t filter_count,
618 const grpc_channel_args *args) {
619 size_t i;
620 int census_enabled = grpc_channel_args_is_census_enabled(args);
621
622 grpc_server *server = gpr_malloc(sizeof(grpc_server));
Craig Tiller60fd3612015-03-05 16:24:22 -0800623
624 GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
625
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800626 memset(server, 0, sizeof(grpc_server));
Craig Tiller20bc56d2015-02-12 09:02:56 -0800627 if (cq) addcq(server, cq);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800628
629 gpr_mu_init(&server->mu);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700630 gpr_cv_init(&server->cv);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800631
Craig Tiller20bc56d2015-02-12 09:02:56 -0800632 server->unregistered_cq = cq;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800633 /* decremented by grpc_server_destroy */
634 gpr_ref_init(&server->internal_refcount, 1);
635 server->root_channel_data.next = server->root_channel_data.prev =
636 &server->root_channel_data;
637
638 /* Server filter stack is:
639
640 server_surface_filter - for making surface API calls
641 grpc_server_census_filter (optional) - for stats collection and tracing
642 {passed in filter stack}
643 grpc_connected_channel_filter - for interfacing with transports */
644 server->channel_filter_count = filter_count + 1 + census_enabled;
645 server->channel_filters =
646 gpr_malloc(server->channel_filter_count * sizeof(grpc_channel_filter *));
647 server->channel_filters[0] = &server_surface_filter;
648 if (census_enabled) {
649 server->channel_filters[1] = &grpc_server_census_filter;
650 }
651 for (i = 0; i < filter_count; i++) {
652 server->channel_filters[i + 1 + census_enabled] = filters[i];
653 }
654
655 server->channel_args = grpc_channel_args_copy(args);
656
657 return server;
658}
659
Craig Tiller24be0f72015-02-10 14:04:22 -0800660static int streq(const char *a, const char *b) {
661 if (a == NULL && b == NULL) return 1;
662 if (a == NULL) return 0;
663 if (b == NULL) return 0;
664 return 0 == strcmp(a, b);
665}
666
667void *grpc_server_register_method(grpc_server *server, const char *method,
Craig Tillerec3257c2015-02-12 15:59:43 -0800668 const char *host,
669 grpc_completion_queue *cq_new_rpc) {
Craig Tiller24be0f72015-02-10 14:04:22 -0800670 registered_method *m;
671 if (!method) {
672 gpr_log(GPR_ERROR, "%s method string cannot be NULL", __FUNCTION__);
673 return NULL;
674 }
675 for (m = server->registered_methods; m; m = m->next) {
676 if (streq(m->method, method) && streq(m->host, host)) {
677 gpr_log(GPR_ERROR, "duplicate registration for %s@%s", method,
678 host ? host : "*");
679 return NULL;
680 }
681 }
Craig Tiller20bc56d2015-02-12 09:02:56 -0800682 addcq(server, cq_new_rpc);
Craig Tiller24be0f72015-02-10 14:04:22 -0800683 m = gpr_malloc(sizeof(registered_method));
684 memset(m, 0, sizeof(*m));
685 m->method = gpr_strdup(method);
686 m->host = gpr_strdup(host);
687 m->next = server->registered_methods;
Craig Tiller20bc56d2015-02-12 09:02:56 -0800688 m->cq = cq_new_rpc;
Craig Tiller24be0f72015-02-10 14:04:22 -0800689 server->registered_methods = m;
690 return m;
691}
692
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800693void grpc_server_start(grpc_server *server) {
694 listener *l;
Craig Tiller20bc56d2015-02-12 09:02:56 -0800695 size_t i;
696
Craig Tillerec3257c2015-02-12 15:59:43 -0800697 server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800698 for (i = 0; i < server->cq_count; i++) {
699 server->pollsets[i] = grpc_cq_pollset(server->cqs[i]);
700 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800701
702 for (l = server->listeners; l; l = l->next) {
Craig Tiller20bc56d2015-02-12 09:02:56 -0800703 l->start(server, l->arg, server->pollsets, server->cq_count);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800704 }
705}
706
707grpc_transport_setup_result grpc_server_setup_transport(
708 grpc_server *s, grpc_transport *transport,
709 grpc_channel_filter const **extra_filters, size_t num_extra_filters,
710 grpc_mdctx *mdctx) {
711 size_t num_filters = s->channel_filter_count + num_extra_filters + 1;
712 grpc_channel_filter const **filters =
713 gpr_malloc(sizeof(grpc_channel_filter *) * num_filters);
714 size_t i;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800715 size_t num_registered_methods;
716 size_t alloc;
717 registered_method *rm;
718 channel_registered_method *crm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800719 grpc_channel *channel;
720 channel_data *chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800721 grpc_mdstr *host;
722 grpc_mdstr *method;
723 gpr_uint32 hash;
724 gpr_uint32 slots;
725 gpr_uint32 probes;
726 gpr_uint32 max_probes = 0;
Craig Tiller5d6bd442015-02-12 22:50:38 -0800727 grpc_transport_setup_result result;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800728
729 for (i = 0; i < s->channel_filter_count; i++) {
730 filters[i] = s->channel_filters[i];
731 }
732 for (; i < s->channel_filter_count + num_extra_filters; i++) {
733 filters[i] = extra_filters[i - s->channel_filter_count];
734 }
735 filters[i] = &grpc_connected_channel_filter;
736
Craig Tiller20bc56d2015-02-12 09:02:56 -0800737 for (i = 0; i < s->cq_count; i++) {
738 grpc_transport_add_to_pollset(transport, grpc_cq_pollset(s->cqs[i]));
739 }
ctillerd79b4862014-12-17 16:36:59 -0800740
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800741 channel = grpc_channel_create_from_filters(filters, num_filters,
742 s->channel_args, mdctx, 0);
743 chand = (channel_data *)grpc_channel_stack_element(
Craig Tillerc02c1d82015-04-07 16:21:55 -0700744 grpc_channel_get_channel_stack(channel), 0)
745 ->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800746 chand->server = s;
747 server_ref(s);
748 chand->channel = channel;
749
Craig Tiller04cc8be2015-02-10 16:11:22 -0800750 num_registered_methods = 0;
751 for (rm = s->registered_methods; rm; rm = rm->next) {
752 num_registered_methods++;
753 }
754 /* build a lookup table phrased in terms of mdstr's in this channels context
755 to quickly find registered methods */
756 if (num_registered_methods > 0) {
757 slots = 2 * num_registered_methods;
758 alloc = sizeof(channel_registered_method) * slots;
759 chand->registered_methods = gpr_malloc(alloc);
760 memset(chand->registered_methods, 0, alloc);
761 for (rm = s->registered_methods; rm; rm = rm->next) {
762 host = rm->host ? grpc_mdstr_from_string(mdctx, rm->host) : NULL;
Craig Tillere76c9662015-02-11 13:18:31 -0800763 method = grpc_mdstr_from_string(mdctx, rm->method);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800764 hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash);
Craig Tiller3b29b562015-02-11 12:58:46 -0800765 for (probes = 0; chand->registered_methods[(hash + probes) % slots]
Craig Tillerc02c1d82015-04-07 16:21:55 -0700766 .server_registered_method != NULL;
Craig Tiller3b29b562015-02-11 12:58:46 -0800767 probes++)
768 ;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800769 if (probes > max_probes) max_probes = probes;
770 crm = &chand->registered_methods[(hash + probes) % slots];
771 crm->server_registered_method = rm;
772 crm->host = host;
773 crm->method = method;
774 }
775 chand->registered_method_slots = slots;
776 chand->registered_method_max_probes = max_probes;
777 }
778
Craig Tiller5d6bd442015-02-12 22:50:38 -0800779 result = grpc_connected_channel_bind_transport(
780 grpc_channel_get_channel_stack(channel), transport);
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800781
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800782 gpr_mu_lock(&s->mu);
783 chand->next = &s->root_channel_data;
784 chand->prev = chand->next->prev;
785 chand->next->prev = chand->prev->next = chand;
786 gpr_mu_unlock(&s->mu);
787
788 gpr_free(filters);
789
Craig Tiller5d6bd442015-02-12 22:50:38 -0800790 return result;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800791}
792
Craig Tilleraec96aa2015-04-07 14:32:15 -0700793static int num_listeners(grpc_server *server) {
794 listener *l;
795 int n = 0;
796 for (l = server->listeners; l; l = l->next) {
797 n++;
798 }
799 return n;
800}
801
Craig Tillerbd217572015-02-11 18:10:56 -0800802static void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag,
Craig Tillerec3257c2015-02-12 15:59:43 -0800803 void *shutdown_tag) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800804 listener *l;
Craig Tiller24be0f72015-02-10 14:04:22 -0800805 requested_call_array requested_calls;
nnoble0c475f02014-12-05 15:37:39 -0800806 channel_data **channels;
807 channel_data *c;
808 size_t nchannels;
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800809 size_t i, j;
nnoble0c475f02014-12-05 15:37:39 -0800810 grpc_channel_op op;
811 grpc_channel_element *elem;
Craig Tillerbd217572015-02-11 18:10:56 -0800812 registered_method *rm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800813
814 /* lock, and gather up some stuff to do */
815 gpr_mu_lock(&server->mu);
Craig Tilleraea2fc02015-02-17 16:54:53 -0800816 if (have_shutdown_tag) {
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800817 for (i = 0; i < server->cq_count; i++) {
818 grpc_cq_begin_op(server->cqs[i], NULL, GRPC_SERVER_SHUTDOWN);
819 }
Craig Tilleraea2fc02015-02-17 16:54:53 -0800820 server->shutdown_tags =
821 gpr_realloc(server->shutdown_tags,
822 sizeof(void *) * (server->num_shutdown_tags + 1));
823 server->shutdown_tags[server->num_shutdown_tags++] = shutdown_tag;
824 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800825 if (server->shutdown) {
826 gpr_mu_unlock(&server->mu);
827 return;
828 }
829
nnoble0c475f02014-12-05 15:37:39 -0800830 nchannels = 0;
831 for (c = server->root_channel_data.next; c != &server->root_channel_data;
832 c = c->next) {
833 nchannels++;
834 }
835 channels = gpr_malloc(sizeof(channel_data *) * nchannels);
836 i = 0;
837 for (c = server->root_channel_data.next; c != &server->root_channel_data;
838 c = c->next) {
839 grpc_channel_internal_ref(c->channel);
840 channels[i] = c;
841 i++;
842 }
843
Craig Tillerbd217572015-02-11 18:10:56 -0800844 /* collect all unregistered then registered calls */
Craig Tillercce17ac2015-01-20 09:29:28 -0800845 requested_calls = server->requested_calls;
Craig Tiller24be0f72015-02-10 14:04:22 -0800846 memset(&server->requested_calls, 0, sizeof(server->requested_calls));
Craig Tillerbd217572015-02-11 18:10:56 -0800847 for (rm = server->registered_methods; rm; rm = rm->next) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800848 if (requested_calls.count + rm->requested.count >
849 requested_calls.capacity) {
850 requested_calls.capacity =
851 GPR_MAX(requested_calls.count + rm->requested.count,
852 2 * requested_calls.capacity);
853 requested_calls.calls =
854 gpr_realloc(requested_calls.calls, sizeof(*requested_calls.calls) *
855 requested_calls.capacity);
Craig Tillerbd217572015-02-11 18:10:56 -0800856 }
Craig Tillerec3257c2015-02-12 15:59:43 -0800857 memcpy(requested_calls.calls + requested_calls.count, rm->requested.calls,
858 sizeof(*requested_calls.calls) * rm->requested.count);
Craig Tillerbd217572015-02-11 18:10:56 -0800859 requested_calls.count += rm->requested.count;
Craig Tillerec3257c2015-02-12 15:59:43 -0800860 gpr_free(rm->requested.calls);
Craig Tillerbd217572015-02-11 18:10:56 -0800861 memset(&rm->requested, 0, sizeof(rm->requested));
862 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800863
864 server->shutdown = 1;
Craig Tilleraea2fc02015-02-17 16:54:53 -0800865 if (server->lists[ALL_CALLS] == NULL) {
866 for (i = 0; i < server->num_shutdown_tags; i++) {
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800867 for (j = 0; j < server->cq_count; j++) {
868 grpc_cq_end_server_shutdown(server->cqs[j], server->shutdown_tags[i]);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800869 }
Craig Tiller4ffdcd52015-01-16 11:34:55 -0800870 }
871 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800872 gpr_mu_unlock(&server->mu);
873
nnoble0c475f02014-12-05 15:37:39 -0800874 for (i = 0; i < nchannels; i++) {
875 c = channels[i];
876 elem = grpc_channel_stack_element(
877 grpc_channel_get_channel_stack(c->channel), 0);
878
879 op.type = GRPC_CHANNEL_GOAWAY;
880 op.dir = GRPC_CALL_DOWN;
881 op.data.goaway.status = GRPC_STATUS_OK;
882 op.data.goaway.message = gpr_slice_from_copied_string("Server shutdown");
ctillerf962f522014-12-10 15:28:27 -0800883 elem->filter->channel_op(elem, NULL, &op);
nnoble0c475f02014-12-05 15:37:39 -0800884
885 grpc_channel_internal_unref(c->channel);
886 }
887 gpr_free(channels);
888
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800889 /* terminate all the requested calls */
Craig Tiller24be0f72015-02-10 14:04:22 -0800890 for (i = 0; i < requested_calls.count; i++) {
891 fail_call(server, &requested_calls.calls[i]);
Craig Tillercce17ac2015-01-20 09:29:28 -0800892 }
Craig Tiller24be0f72015-02-10 14:04:22 -0800893 gpr_free(requested_calls.calls);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800894
895 /* Shutdown listeners */
896 for (l = server->listeners; l; l = l->next) {
897 l->destroy(server, l->arg);
898 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800899}
900
Craig Tiller4ffdcd52015-01-16 11:34:55 -0800901void grpc_server_shutdown(grpc_server *server) {
902 shutdown_internal(server, 0, NULL);
903}
904
905void grpc_server_shutdown_and_notify(grpc_server *server, void *tag) {
906 shutdown_internal(server, 1, tag);
907}
908
Craig Tilleraec96aa2015-04-07 14:32:15 -0700909void grpc_server_listener_destroy_done(void *s) {
910 grpc_server *server = s;
911 gpr_mu_lock(&server->mu);
912 server->listeners_destroyed++;
913 gpr_cv_signal(&server->cv);
914 gpr_mu_unlock(&server->mu);
915}
916
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800917void grpc_server_destroy(grpc_server *server) {
918 channel_data *c;
Craig Tilleraec96aa2015-04-07 14:32:15 -0700919 listener *l;
920 size_t i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800921 gpr_mu_lock(&server->mu);
Craig Tilleraea2fc02015-02-17 16:54:53 -0800922 if (!server->shutdown) {
923 gpr_mu_unlock(&server->mu);
924 grpc_server_shutdown(server);
925 gpr_mu_lock(&server->mu);
926 }
927
Craig Tilleraec96aa2015-04-07 14:32:15 -0700928 while (server->listeners_destroyed != num_listeners(server)) {
929 for (i = 0; i < server->cq_count; i++) {
930 gpr_mu_unlock(&server->mu);
931 grpc_cq_hack_spin_pollset(server->cqs[i]);
932 gpr_mu_lock(&server->mu);
933 }
934
Craig Tillerc02c1d82015-04-07 16:21:55 -0700935 gpr_cv_wait(&server->cv, &server->mu,
936 gpr_time_add(gpr_now(), gpr_time_from_millis(100)));
Craig Tilleraec96aa2015-04-07 14:32:15 -0700937 }
938
939 while (server->listeners) {
940 l = server->listeners;
941 server->listeners = l->next;
942 gpr_free(l);
943 }
944
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800945 for (c = server->root_channel_data.next; c != &server->root_channel_data;
946 c = c->next) {
947 shutdown_channel(c);
948 }
949 gpr_mu_unlock(&server->mu);
950
951 server_unref(server);
952}
953
954void grpc_server_add_listener(grpc_server *server, void *arg,
ctiller58393c22015-01-07 14:03:30 -0800955 void (*start)(grpc_server *server, void *arg,
Craig Tillerec3257c2015-02-12 15:59:43 -0800956 grpc_pollset **pollsets,
957 size_t pollset_count),
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800958 void (*destroy)(grpc_server *server, void *arg)) {
959 listener *l = gpr_malloc(sizeof(listener));
960 l->arg = arg;
961 l->start = start;
962 l->destroy = destroy;
963 l->next = server->listeners;
964 server->listeners = l;
965}
966
Craig Tiller9f28ac22015-01-27 17:01:29 -0800967static grpc_call_error queue_call_request(grpc_server *server,
Craig Tiller24be0f72015-02-10 14:04:22 -0800968 requested_call *rc) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -0800969 call_data *calld = NULL;
Craig Tiller0ef1a922015-02-11 16:23:01 -0800970 requested_call_array *requested_calls = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800971 gpr_mu_lock(&server->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800972 if (server->shutdown) {
973 gpr_mu_unlock(&server->mu);
Craig Tiller24be0f72015-02-10 14:04:22 -0800974 fail_call(server, rc);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800975 return GRPC_CALL_OK;
976 }
Craig Tiller04cc8be2015-02-10 16:11:22 -0800977 switch (rc->type) {
978 case LEGACY_CALL:
979 case BATCH_CALL:
Craig Tiller3b29b562015-02-11 12:58:46 -0800980 calld =
981 call_list_remove_head(&server->lists[PENDING_START], PENDING_START);
Craig Tiller0ef1a922015-02-11 16:23:01 -0800982 requested_calls = &server->requested_calls;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800983 break;
984 case REGISTERED_CALL:
Craig Tiller3b29b562015-02-11 12:58:46 -0800985 calld = call_list_remove_head(
986 &rc->data.registered.registered_method->pending, PENDING_START);
Craig Tiller0ef1a922015-02-11 16:23:01 -0800987 requested_calls = &rc->data.registered.registered_method->requested;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800988 break;
989 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800990 if (calld) {
Craig Tillercce17ac2015-01-20 09:29:28 -0800991 GPR_ASSERT(calld->state == PENDING);
Craig Tillerbb3f22f2015-01-29 16:40:56 -0800992 calld->state = ACTIVATED;
Craig Tillercce17ac2015-01-20 09:29:28 -0800993 gpr_mu_unlock(&server->mu);
Craig Tiller24be0f72015-02-10 14:04:22 -0800994 begin_call(server, calld, rc);
Craig Tillercce17ac2015-01-20 09:29:28 -0800995 return GRPC_CALL_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800996 } else {
Craig Tiller0ef1a922015-02-11 16:23:01 -0800997 *requested_call_array_add(requested_calls) = *rc;
Craig Tillercce17ac2015-01-20 09:29:28 -0800998 gpr_mu_unlock(&server->mu);
999 return GRPC_CALL_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001000 }
Craig Tillercce17ac2015-01-20 09:29:28 -08001001}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001002
Craig Tiller24be0f72015-02-10 14:04:22 -08001003grpc_call_error grpc_server_request_call(grpc_server *server, grpc_call **call,
1004 grpc_call_details *details,
1005 grpc_metadata_array *initial_metadata,
Craig Tiller3b29b562015-02-11 12:58:46 -08001006 grpc_completion_queue *cq_bind,
1007 void *tag) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001008 requested_call rc;
Craig Tiller20bc56d2015-02-12 09:02:56 -08001009 grpc_cq_begin_op(server->unregistered_cq, NULL, GRPC_OP_COMPLETE);
Craig Tiller24be0f72015-02-10 14:04:22 -08001010 rc.type = BATCH_CALL;
1011 rc.tag = tag;
Craig Tiller8e8fd892015-02-10 17:02:08 -08001012 rc.data.batch.cq_bind = cq_bind;
Craig Tiller24be0f72015-02-10 14:04:22 -08001013 rc.data.batch.call = call;
1014 rc.data.batch.details = details;
1015 rc.data.batch.initial_metadata = initial_metadata;
1016 return queue_call_request(server, &rc);
1017}
1018
1019grpc_call_error grpc_server_request_registered_call(
Craig Tillerec3257c2015-02-12 15:59:43 -08001020 grpc_server *server, void *rm, grpc_call **call, gpr_timespec *deadline,
1021 grpc_metadata_array *initial_metadata, grpc_byte_buffer **optional_payload,
1022 grpc_completion_queue *cq_bind, void *tag) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001023 requested_call rc;
Craig Tiller20bc56d2015-02-12 09:02:56 -08001024 registered_method *registered_method = rm;
1025 grpc_cq_begin_op(registered_method->cq, NULL, GRPC_OP_COMPLETE);
Craig Tiller24be0f72015-02-10 14:04:22 -08001026 rc.type = REGISTERED_CALL;
1027 rc.tag = tag;
Craig Tiller8e8fd892015-02-10 17:02:08 -08001028 rc.data.registered.cq_bind = cq_bind;
Craig Tiller24be0f72015-02-10 14:04:22 -08001029 rc.data.registered.call = call;
1030 rc.data.registered.registered_method = registered_method;
1031 rc.data.registered.deadline = deadline;
1032 rc.data.registered.initial_metadata = initial_metadata;
1033 rc.data.registered.optional_payload = optional_payload;
1034 return queue_call_request(server, &rc);
1035}
1036
1037grpc_call_error grpc_server_request_call_old(grpc_server *server,
1038 void *tag_new) {
1039 requested_call rc;
Craig Tiller20bc56d2015-02-12 09:02:56 -08001040 grpc_cq_begin_op(server->unregistered_cq, NULL, GRPC_SERVER_RPC_NEW);
Craig Tiller24be0f72015-02-10 14:04:22 -08001041 rc.type = LEGACY_CALL;
1042 rc.tag = tag_new;
1043 return queue_call_request(server, &rc);
1044}
1045
1046static void publish_legacy(grpc_call *call, grpc_op_error status, void *tag);
1047static void publish_registered_or_batch(grpc_call *call, grpc_op_error status,
1048 void *tag);
Craig Tiller3b29b562015-02-11 12:58:46 -08001049static void publish_was_not_set(grpc_call *call, grpc_op_error status,
1050 void *tag) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001051 abort();
1052}
Craig Tiller24be0f72015-02-10 14:04:22 -08001053
Craig Tiller166e2502015-02-03 20:14:41 -08001054static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
1055 gpr_slice slice = value->slice;
1056 size_t len = GPR_SLICE_LENGTH(slice);
1057
1058 if (len + 1 > *capacity) {
1059 *capacity = GPR_MAX(len + 1, *capacity * 2);
1060 *dest = gpr_realloc(*dest, *capacity);
1061 }
1062 memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
1063}
1064
Craig Tiller24be0f72015-02-10 14:04:22 -08001065static void begin_call(grpc_server *server, call_data *calld,
1066 requested_call *rc) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001067 grpc_ioreq_completion_func publish = publish_was_not_set;
Craig Tiller24be0f72015-02-10 14:04:22 -08001068 grpc_ioreq req[2];
1069 grpc_ioreq *r = req;
1070
1071 /* called once initial metadata has been read by the call, but BEFORE
1072 the ioreq to fetch it out of the call has been executed.
1073 This means metadata related fields can be relied on in calld, but to
1074 fill in the metadata array passed by the client, we need to perform
1075 an ioreq op, that should complete immediately. */
1076
1077 switch (rc->type) {
1078 case LEGACY_CALL:
1079 calld->legacy = gpr_malloc(sizeof(legacy_data));
1080 memset(calld->legacy, 0, sizeof(legacy_data));
1081 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1082 r->data.recv_metadata = &calld->legacy->initial_metadata;
1083 r++;
1084 publish = publish_legacy;
1085 break;
1086 case BATCH_CALL:
1087 cpstr(&rc->data.batch.details->host,
1088 &rc->data.batch.details->host_capacity, calld->host);
1089 cpstr(&rc->data.batch.details->method,
1090 &rc->data.batch.details->method_capacity, calld->path);
Craig Tiller8e8fd892015-02-10 17:02:08 -08001091 grpc_call_set_completion_queue(calld->call, rc->data.batch.cq_bind);
Craig Tiller24be0f72015-02-10 14:04:22 -08001092 *rc->data.batch.call = calld->call;
1093 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1094 r->data.recv_metadata = rc->data.batch.initial_metadata;
1095 r++;
Craig Tiller20bc56d2015-02-12 09:02:56 -08001096 calld->cq_new = server->unregistered_cq;
Craig Tiller24be0f72015-02-10 14:04:22 -08001097 publish = publish_registered_or_batch;
1098 break;
1099 case REGISTERED_CALL:
1100 *rc->data.registered.deadline = calld->deadline;
Craig Tiller8e8fd892015-02-10 17:02:08 -08001101 grpc_call_set_completion_queue(calld->call, rc->data.registered.cq_bind);
Craig Tiller24be0f72015-02-10 14:04:22 -08001102 *rc->data.registered.call = calld->call;
1103 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1104 r->data.recv_metadata = rc->data.registered.initial_metadata;
1105 r++;
1106 if (rc->data.registered.optional_payload) {
1107 r->op = GRPC_IOREQ_RECV_MESSAGE;
1108 r->data.recv_message = rc->data.registered.optional_payload;
1109 r++;
1110 }
Craig Tiller20bc56d2015-02-12 09:02:56 -08001111 calld->cq_new = rc->data.registered.registered_method->cq;
Craig Tiller24be0f72015-02-10 14:04:22 -08001112 publish = publish_registered_or_batch;
1113 break;
1114 }
1115
1116 grpc_call_internal_ref(calld->call);
1117 grpc_call_start_ioreq_and_call_back(calld->call, req, r - req, publish,
1118 rc->tag);
1119}
1120
1121static void fail_call(grpc_server *server, requested_call *rc) {
1122 switch (rc->type) {
1123 case LEGACY_CALL:
Craig Tillerec3257c2015-02-12 15:59:43 -08001124 grpc_cq_end_new_rpc(server->unregistered_cq, rc->tag, NULL, do_nothing,
1125 NULL, NULL, NULL, gpr_inf_past, 0, NULL);
Craig Tiller24be0f72015-02-10 14:04:22 -08001126 break;
1127 case BATCH_CALL:
1128 *rc->data.batch.call = NULL;
1129 rc->data.batch.initial_metadata->count = 0;
Craig Tillerec3257c2015-02-12 15:59:43 -08001130 grpc_cq_end_op_complete(server->unregistered_cq, rc->tag, NULL,
1131 do_nothing, NULL, GRPC_OP_ERROR);
Craig Tiller24be0f72015-02-10 14:04:22 -08001132 break;
1133 case REGISTERED_CALL:
1134 *rc->data.registered.call = NULL;
1135 rc->data.registered.initial_metadata->count = 0;
Craig Tillerec3257c2015-02-12 15:59:43 -08001136 grpc_cq_end_op_complete(rc->data.registered.registered_method->cq,
1137 rc->tag, NULL, do_nothing, NULL, GRPC_OP_ERROR);
Craig Tiller24be0f72015-02-10 14:04:22 -08001138 break;
1139 }
1140}
1141
1142static void publish_legacy(grpc_call *call, grpc_op_error status, void *tag) {
1143 grpc_call_element *elem =
1144 grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
1145 call_data *calld = elem->call_data;
1146 channel_data *chand = elem->channel_data;
1147 grpc_server *server = chand->server;
1148
1149 if (status == GRPC_OP_OK) {
Craig Tiller20bc56d2015-02-12 09:02:56 -08001150 grpc_cq_end_new_rpc(server->unregistered_cq, tag, call, do_nothing, NULL,
Craig Tiller24be0f72015-02-10 14:04:22 -08001151 grpc_mdstr_as_c_string(calld->path),
1152 grpc_mdstr_as_c_string(calld->host), calld->deadline,
1153 calld->legacy->initial_metadata.count,
1154 calld->legacy->initial_metadata.metadata);
1155 } else {
1156 gpr_log(GPR_ERROR, "should never reach here");
1157 abort();
1158 }
1159}
1160
1161static void publish_registered_or_batch(grpc_call *call, grpc_op_error status,
1162 void *tag) {
Craig Tiller8e8fd892015-02-10 17:02:08 -08001163 grpc_call_element *elem =
1164 grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
Craig Tiller20bc56d2015-02-12 09:02:56 -08001165 call_data *calld = elem->call_data;
1166 grpc_cq_end_op_complete(calld->cq_new, tag, call, do_nothing, NULL, status);
Craig Tiller24be0f72015-02-10 14:04:22 -08001167}
1168
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001169const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) {
1170 return server->channel_args;
Craig Tiller190d3602015-02-18 09:23:38 -08001171}