blob: 21b5f9162d95a4cb19ab52bf158e77b6fb196697 [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;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700125 grpc_iomgr_closure finish_shutdown_channel_closure;
126 grpc_iomgr_closure finish_destroy_channel_closure;
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 Tillerec3257c2015-02-12 15:59:43 -0800133
Craig Tiller20bc56d2015-02-12 09:02:56 -0800134 grpc_completion_queue **cqs;
135 grpc_pollset **pollsets;
136 size_t cq_count;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800137
138 gpr_mu mu;
Craig Tilleraec96aa2015-04-07 14:32:15 -0700139 gpr_cv cv;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800140
Craig Tiller24be0f72015-02-10 14:04:22 -0800141 registered_method *registered_methods;
142 requested_call_array requested_calls;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800143
144 gpr_uint8 shutdown;
Craig Tilleraea2fc02015-02-17 16:54:53 -0800145 size_t num_shutdown_tags;
146 void **shutdown_tags;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800147
148 call_data *lists[CALL_LIST_COUNT];
149 channel_data root_channel_data;
150
151 listener *listeners;
Craig Tilleraec96aa2015-04-07 14:32:15 -0700152 int listeners_destroyed;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800153 gpr_refcount internal_refcount;
154};
155
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800156typedef enum {
157 /* waiting for metadata */
158 NOT_STARTED,
159 /* inital metadata read, not flow controlled in yet */
160 PENDING,
161 /* flow controlled in, on completion queue */
162 ACTIVATED,
163 /* cancelled before being queued */
164 ZOMBIED
165} call_state;
166
167struct call_data {
168 grpc_call *call;
169
170 call_state state;
Craig Tillercce17ac2015-01-20 09:29:28 -0800171 grpc_mdstr *path;
172 grpc_mdstr *host;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700173 gpr_timespec deadline;
174 int got_initial_metadata;
Craig Tillercce17ac2015-01-20 09:29:28 -0800175
Craig Tiller20bc56d2015-02-12 09:02:56 -0800176 grpc_completion_queue *cq_new;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800177
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700178 grpc_stream_op_buffer *recv_ops;
179 grpc_stream_state *recv_state;
180 void (*on_done_recv)(void *user_data, int success);
181 void *recv_user_data;
182
David Garcia Quintas284488b2015-05-28 16:27:39 -0700183 grpc_iomgr_closure kill_zombie_closure;
184
Craig Tiller04cc8be2015-02-10 16:11:22 -0800185 call_data **root[CALL_LIST_COUNT];
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800186 call_link links[CALL_LIST_COUNT];
187};
188
189#define SERVER_FROM_CALL_ELEM(elem) \
190 (((channel_data *)(elem)->channel_data)->server)
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);
David Garcia Quintas284488b2015-05-28 16:27:39 -0700311 chand->finish_destroy_channel_closure.cb = finish_destroy_channel;
312 chand->finish_destroy_channel_closure.cb_arg = chand;
313 grpc_iomgr_add_callback(&chand->finish_destroy_channel_closure);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800314}
315
Craig Tiller3b29b562015-02-11 12:58:46 -0800316static void finish_start_new_rpc_and_unlock(grpc_server *server,
317 grpc_call_element *elem,
318 call_data **pending_root,
319 requested_call_array *array) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800320 requested_call rc;
321 call_data *calld = elem->call_data;
322 if (array->count == 0) {
323 calld->state = PENDING;
324 call_list_join(pending_root, calld, PENDING_START);
325 gpr_mu_unlock(&server->mu);
326 } else {
Craig Tiller0ef1a922015-02-11 16:23:01 -0800327 rc = array->calls[--array->count];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800328 calld->state = ACTIVATED;
329 gpr_mu_unlock(&server->mu);
330 begin_call(server, calld, &rc);
331 }
332}
333
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800334static void start_new_rpc(grpc_call_element *elem) {
335 channel_data *chand = elem->channel_data;
336 call_data *calld = elem->call_data;
337 grpc_server *server = chand->server;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800338 gpr_uint32 i;
339 gpr_uint32 hash;
340 channel_registered_method *rm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800341
342 gpr_mu_lock(&server->mu);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800343 if (chand->registered_methods && calld->path && calld->host) {
Craig Tillera94beff2015-02-17 22:02:06 -0800344 /* TODO(ctiller): unify these two searches */
Craig Tiller04cc8be2015-02-10 16:11:22 -0800345 /* check for an exact match with host */
346 hash = GRPC_MDSTR_KV_HASH(calld->host->hash, calld->path->hash);
347 for (i = 0; i < chand->registered_method_max_probes; i++) {
Craig Tiller3b29b562015-02-11 12:58:46 -0800348 rm = &chand->registered_methods[(hash + i) %
349 chand->registered_method_slots];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800350 if (!rm) break;
351 if (rm->host != calld->host) continue;
352 if (rm->method != calld->path) continue;
Craig Tiller3b29b562015-02-11 12:58:46 -0800353 finish_start_new_rpc_and_unlock(server, elem,
354 &rm->server_registered_method->pending,
355 &rm->server_registered_method->requested);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800356 return;
357 }
358 /* check for a wildcard method definition (no host set) */
359 hash = GRPC_MDSTR_KV_HASH(0, calld->path->hash);
Craig Tiller0ef1a922015-02-11 16:23:01 -0800360 for (i = 0; i <= chand->registered_method_max_probes; i++) {
Craig Tiller3b29b562015-02-11 12:58:46 -0800361 rm = &chand->registered_methods[(hash + i) %
362 chand->registered_method_slots];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800363 if (!rm) break;
364 if (rm->host != NULL) continue;
365 if (rm->method != calld->path) continue;
Craig Tiller3b29b562015-02-11 12:58:46 -0800366 finish_start_new_rpc_and_unlock(server, elem,
367 &rm->server_registered_method->pending,
368 &rm->server_registered_method->requested);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800369 return;
370 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800371 }
Craig Tiller3b29b562015-02-11 12:58:46 -0800372 finish_start_new_rpc_and_unlock(server, elem, &server->lists[PENDING_START],
373 &server->requested_calls);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800374}
375
ctiller58393c22015-01-07 14:03:30 -0800376static void kill_zombie(void *elem, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800377 grpc_call_destroy(grpc_call_from_top_element(elem));
378}
379
Craig Tiller6902ad22015-04-16 08:01:49 -0700380static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
381 grpc_call_element *elem = user_data;
Craig Tillercce17ac2015-01-20 09:29:28 -0800382 channel_data *chand = elem->channel_data;
383 call_data *calld = elem->call_data;
Craig Tiller6902ad22015-04-16 08:01:49 -0700384 if (md->key == chand->path_key) {
385 calld->path = grpc_mdstr_ref(md->value);
386 return NULL;
387 } else if (md->key == chand->authority_key) {
388 calld->host = grpc_mdstr_ref(md->value);
389 return NULL;
390 }
391 return md;
392}
393
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700394static void server_on_recv(void *ptr, int success) {
395 grpc_call_element *elem = ptr;
Craig Tiller6902ad22015-04-16 08:01:49 -0700396 call_data *calld = elem->call_data;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700397 channel_data *chand = elem->channel_data;
398
399 if (success && !calld->got_initial_metadata) {
400 size_t i;
401 size_t nops = calld->recv_ops->nops;
402 grpc_stream_op *ops = calld->recv_ops->ops;
403 for (i = 0; i < nops; i++) {
404 grpc_stream_op *op = &ops[i];
405 if (op->type != GRPC_OP_METADATA) continue;
Craig Tiller205aee12015-04-16 14:46:41 -0700406 grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700407 if (0 != gpr_time_cmp(op->data.metadata.deadline, gpr_inf_future)) {
Craig Tiller6902ad22015-04-16 08:01:49 -0700408 calld->deadline = op->data.metadata.deadline;
Craig Tillercce17ac2015-01-20 09:29:28 -0800409 }
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700410 calld->got_initial_metadata = 1;
411 start_new_rpc(elem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800412 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700413 }
414 }
415
416 switch (*calld->recv_state) {
Craig Tiller06aeea72015-04-23 10:54:45 -0700417 case GRPC_STREAM_OPEN:
418 break;
419 case GRPC_STREAM_SEND_CLOSED:
420 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700421 case GRPC_STREAM_RECV_CLOSED:
422 gpr_mu_lock(&chand->server->mu);
423 if (calld->state == NOT_STARTED) {
424 calld->state = ZOMBIED;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700425 grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
426 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700427 }
428 gpr_mu_unlock(&chand->server->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800429 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700430 case GRPC_STREAM_CLOSED:
431 gpr_mu_lock(&chand->server->mu);
432 if (calld->state == NOT_STARTED) {
433 calld->state = ZOMBIED;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700434 grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
435 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700436 } else if (calld->state == PENDING) {
437 call_list_remove(calld, PENDING_START);
Craig Tillerc9d03822015-05-20 16:08:45 -0700438 calld->state = ZOMBIED;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700439 grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
440 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
441
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700442 }
443 gpr_mu_unlock(&chand->server->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800444 break;
445 }
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700446
447 calld->on_done_recv(calld->recv_user_data, success);
448}
449
Craig Tiller50d9db52015-04-23 10:52:14 -0700450static void server_mutate_op(grpc_call_element *elem, grpc_transport_op *op) {
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700451 call_data *calld = elem->call_data;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700452
453 if (op->recv_ops) {
454 /* substitute our callback for the higher callback */
455 calld->recv_ops = op->recv_ops;
456 calld->recv_state = op->recv_state;
457 calld->on_done_recv = op->on_done_recv;
458 calld->recv_user_data = op->recv_user_data;
459 op->on_done_recv = server_on_recv;
460 op->recv_user_data = elem;
461 }
Craig Tiller50d9db52015-04-23 10:52:14 -0700462}
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700463
Craig Tiller06aeea72015-04-23 10:54:45 -0700464static void server_start_transport_op(grpc_call_element *elem,
465 grpc_transport_op *op) {
Craig Tiller50d9db52015-04-23 10:52:14 -0700466 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
467 server_mutate_op(elem, op);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700468 grpc_call_next_op(elem, op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800469}
470
ctillerf962f522014-12-10 15:28:27 -0800471static void channel_op(grpc_channel_element *elem,
472 grpc_channel_element *from_elem, grpc_channel_op *op) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800473 channel_data *chand = elem->channel_data;
Craig Tiller8b976d02015-02-05 21:41:23 -0800474 grpc_server *server = chand->server;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800475
476 switch (op->type) {
477 case GRPC_ACCEPT_CALL:
478 /* create a call */
Craig Tillerfb189f82015-02-03 12:07:07 -0800479 grpc_call_create(chand->channel, NULL,
Craig Tiller87d5b192015-04-16 14:37:57 -0700480 op->data.accept_call.transport_server_data, NULL, 0,
481 gpr_inf_future);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800482 break;
483 case GRPC_TRANSPORT_CLOSED:
484 /* if the transport is closed for a server channel, we destroy the
485 channel */
Craig Tiller8b976d02015-02-05 21:41:23 -0800486 gpr_mu_lock(&server->mu);
487 server_ref(server);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800488 destroy_channel(chand);
Craig Tiller8b976d02015-02-05 21:41:23 -0800489 gpr_mu_unlock(&server->mu);
490 server_unref(server);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800491 break;
nnoble0c475f02014-12-05 15:37:39 -0800492 case GRPC_TRANSPORT_GOAWAY:
493 gpr_slice_unref(op->data.goaway.message);
494 break;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800495 default:
496 GPR_ASSERT(op->dir == GRPC_CALL_DOWN);
497 grpc_channel_next_op(elem, op);
498 break;
499 }
500}
501
ctiller58393c22015-01-07 14:03:30 -0800502static void finish_shutdown_channel(void *cd, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800503 channel_data *chand = cd;
504 grpc_channel_op op;
nnoble0c475f02014-12-05 15:37:39 -0800505 op.type = GRPC_CHANNEL_DISCONNECT;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800506 op.dir = GRPC_CALL_DOWN;
507 channel_op(grpc_channel_stack_element(
508 grpc_channel_get_channel_stack(chand->channel), 0),
ctillerf962f522014-12-10 15:28:27 -0800509 NULL, &op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800510 grpc_channel_internal_unref(chand->channel);
511}
512
513static void shutdown_channel(channel_data *chand) {
514 grpc_channel_internal_ref(chand->channel);
David Garcia Quintas284488b2015-05-28 16:27:39 -0700515 chand->finish_shutdown_channel_closure.cb = finish_shutdown_channel;
516 chand->finish_shutdown_channel_closure.cb_arg = chand;
517 grpc_iomgr_add_callback(&chand->finish_shutdown_channel_closure);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800518}
519
520static void init_call_elem(grpc_call_element *elem,
Craig Tiller06aeea72015-04-23 10:54:45 -0700521 const void *server_transport_data,
522 grpc_transport_op *initial_op) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800523 call_data *calld = elem->call_data;
524 channel_data *chand = elem->channel_data;
525 memset(calld, 0, sizeof(call_data));
526 calld->deadline = gpr_inf_future;
527 calld->call = grpc_call_from_top_element(elem);
528
529 gpr_mu_lock(&chand->server->mu);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800530 call_list_join(&chand->server->lists[ALL_CALLS], calld, ALL_CALLS);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800531 gpr_mu_unlock(&chand->server->mu);
532
533 server_ref(chand->server);
Craig Tiller50d9db52015-04-23 10:52:14 -0700534
Craig Tiller482ef8b2015-04-23 11:38:20 -0700535 if (initial_op) server_mutate_op(elem, initial_op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800536}
537
538static void destroy_call_elem(grpc_call_element *elem) {
539 channel_data *chand = elem->channel_data;
Craig Tillerdb7db992015-01-29 11:19:01 -0800540 call_data *calld = elem->call_data;
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800541 size_t i, j;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800542
543 gpr_mu_lock(&chand->server->mu);
544 for (i = 0; i < CALL_LIST_COUNT; i++) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800545 call_list_remove(elem->call_data, i);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800546 }
Craig Tilleraea2fc02015-02-17 16:54:53 -0800547 if (chand->server->shutdown && chand->server->lists[ALL_CALLS] == NULL) {
548 for (i = 0; i < chand->server->num_shutdown_tags; i++) {
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800549 for (j = 0; j < chand->server->cq_count; j++) {
Craig Tiller64be9f72015-05-04 14:53:51 -0700550 grpc_cq_end_op(chand->server->cqs[j], chand->server->shutdown_tags[i],
551 NULL, 1);
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800552 }
Craig Tiller20bc56d2015-02-12 09:02:56 -0800553 }
Craig Tiller4ffdcd52015-01-16 11:34:55 -0800554 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800555 gpr_mu_unlock(&chand->server->mu);
556
Craig Tiller4df31a62015-01-30 09:44:31 -0800557 if (calld->host) {
558 grpc_mdstr_unref(calld->host);
559 }
560 if (calld->path) {
561 grpc_mdstr_unref(calld->path);
562 }
563
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800564 server_unref(chand->server);
565}
566
567static void init_channel_elem(grpc_channel_element *elem,
568 const grpc_channel_args *args,
569 grpc_mdctx *metadata_context, int is_first,
570 int is_last) {
571 channel_data *chand = elem->channel_data;
572 GPR_ASSERT(is_first);
573 GPR_ASSERT(!is_last);
574 chand->server = NULL;
575 chand->channel = NULL;
Craig Tillercce17ac2015-01-20 09:29:28 -0800576 chand->path_key = grpc_mdstr_from_string(metadata_context, ":path");
577 chand->authority_key = grpc_mdstr_from_string(metadata_context, ":authority");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800578 chand->next = chand->prev = chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800579 chand->registered_methods = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800580}
581
582static void destroy_channel_elem(grpc_channel_element *elem) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800583 size_t i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800584 channel_data *chand = elem->channel_data;
Craig Tillerec3257c2015-02-12 15:59:43 -0800585 if (chand->registered_methods) {
586 for (i = 0; i < chand->registered_method_slots; i++) {
587 if (chand->registered_methods[i].method) {
588 grpc_mdstr_unref(chand->registered_methods[i].method);
589 }
590 if (chand->registered_methods[i].host) {
591 grpc_mdstr_unref(chand->registered_methods[i].host);
592 }
593 }
594 gpr_free(chand->registered_methods);
595 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800596 if (chand->server) {
597 gpr_mu_lock(&chand->server->mu);
598 chand->next->prev = chand->prev;
599 chand->prev->next = chand->next;
600 chand->next = chand->prev = chand;
601 gpr_mu_unlock(&chand->server->mu);
Craig Tillercce17ac2015-01-20 09:29:28 -0800602 grpc_mdstr_unref(chand->path_key);
603 grpc_mdstr_unref(chand->authority_key);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800604 server_unref(chand->server);
605 }
606}
607
608static const grpc_channel_filter server_surface_filter = {
Craig Tiller06aeea72015-04-23 10:54:45 -0700609 server_start_transport_op, channel_op, sizeof(call_data), init_call_elem,
610 destroy_call_elem, sizeof(channel_data), init_channel_elem,
611 destroy_channel_elem, "server",
Craig Tiller9f28ac22015-01-27 17:01:29 -0800612};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800613
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700614void grpc_server_register_completion_queue(grpc_server *server,
615 grpc_completion_queue *cq) {
Craig Tiller20bc56d2015-02-12 09:02:56 -0800616 size_t i, n;
617 for (i = 0; i < server->cq_count; i++) {
618 if (server->cqs[i] == cq) return;
619 }
Craig Tiller89504612015-04-27 11:48:46 -0700620 grpc_cq_internal_ref(cq);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800621 n = server->cq_count++;
Craig Tillerec3257c2015-02-12 15:59:43 -0800622 server->cqs = gpr_realloc(server->cqs,
623 server->cq_count * sizeof(grpc_completion_queue *));
Craig Tiller20bc56d2015-02-12 09:02:56 -0800624 server->cqs[n] = cq;
625}
626
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700627grpc_server *grpc_server_create_from_filters(grpc_channel_filter **filters,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800628 size_t filter_count,
629 const grpc_channel_args *args) {
630 size_t i;
631 int census_enabled = grpc_channel_args_is_census_enabled(args);
632
633 grpc_server *server = gpr_malloc(sizeof(grpc_server));
Craig Tiller60fd3612015-03-05 16:24:22 -0800634
635 GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
636
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800637 memset(server, 0, sizeof(grpc_server));
638
639 gpr_mu_init(&server->mu);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700640 gpr_cv_init(&server->cv);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800641
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800642 /* decremented by grpc_server_destroy */
643 gpr_ref_init(&server->internal_refcount, 1);
644 server->root_channel_data.next = server->root_channel_data.prev =
645 &server->root_channel_data;
646
647 /* Server filter stack is:
648
649 server_surface_filter - for making surface API calls
650 grpc_server_census_filter (optional) - for stats collection and tracing
651 {passed in filter stack}
652 grpc_connected_channel_filter - for interfacing with transports */
653 server->channel_filter_count = filter_count + 1 + census_enabled;
654 server->channel_filters =
655 gpr_malloc(server->channel_filter_count * sizeof(grpc_channel_filter *));
656 server->channel_filters[0] = &server_surface_filter;
657 if (census_enabled) {
658 server->channel_filters[1] = &grpc_server_census_filter;
659 }
660 for (i = 0; i < filter_count; i++) {
661 server->channel_filters[i + 1 + census_enabled] = filters[i];
662 }
663
664 server->channel_args = grpc_channel_args_copy(args);
665
666 return server;
667}
668
Craig Tiller24be0f72015-02-10 14:04:22 -0800669static int streq(const char *a, const char *b) {
670 if (a == NULL && b == NULL) return 1;
671 if (a == NULL) return 0;
672 if (b == NULL) return 0;
673 return 0 == strcmp(a, b);
674}
675
676void *grpc_server_register_method(grpc_server *server, const char *method,
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700677 const char *host) {
Craig Tiller24be0f72015-02-10 14:04:22 -0800678 registered_method *m;
679 if (!method) {
Craig Tiller35696192015-05-24 15:00:37 -0700680 gpr_log(GPR_ERROR, "grpc_server_register_method method string cannot be NULL");
Craig Tiller24be0f72015-02-10 14:04:22 -0800681 return NULL;
682 }
683 for (m = server->registered_methods; m; m = m->next) {
684 if (streq(m->method, method) && streq(m->host, host)) {
685 gpr_log(GPR_ERROR, "duplicate registration for %s@%s", method,
686 host ? host : "*");
687 return NULL;
688 }
689 }
690 m = gpr_malloc(sizeof(registered_method));
691 memset(m, 0, sizeof(*m));
692 m->method = gpr_strdup(method);
693 m->host = gpr_strdup(host);
694 m->next = server->registered_methods;
695 server->registered_methods = m;
696 return m;
697}
698
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800699void grpc_server_start(grpc_server *server) {
700 listener *l;
Craig Tiller20bc56d2015-02-12 09:02:56 -0800701 size_t i;
702
Craig Tillerec3257c2015-02-12 15:59:43 -0800703 server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800704 for (i = 0; i < server->cq_count; i++) {
705 server->pollsets[i] = grpc_cq_pollset(server->cqs[i]);
706 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800707
708 for (l = server->listeners; l; l = l->next) {
Craig Tiller20bc56d2015-02-12 09:02:56 -0800709 l->start(server, l->arg, server->pollsets, server->cq_count);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800710 }
711}
712
713grpc_transport_setup_result grpc_server_setup_transport(
714 grpc_server *s, grpc_transport *transport,
715 grpc_channel_filter const **extra_filters, size_t num_extra_filters,
Julien Boeufc6f8d0a2015-05-11 22:40:02 -0700716 grpc_mdctx *mdctx, const grpc_channel_args *args) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800717 size_t num_filters = s->channel_filter_count + num_extra_filters + 1;
718 grpc_channel_filter const **filters =
719 gpr_malloc(sizeof(grpc_channel_filter *) * num_filters);
720 size_t i;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800721 size_t num_registered_methods;
722 size_t alloc;
723 registered_method *rm;
724 channel_registered_method *crm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800725 grpc_channel *channel;
726 channel_data *chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800727 grpc_mdstr *host;
728 grpc_mdstr *method;
729 gpr_uint32 hash;
730 gpr_uint32 slots;
731 gpr_uint32 probes;
732 gpr_uint32 max_probes = 0;
Craig Tiller5d6bd442015-02-12 22:50:38 -0800733 grpc_transport_setup_result result;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800734
735 for (i = 0; i < s->channel_filter_count; i++) {
736 filters[i] = s->channel_filters[i];
737 }
738 for (; i < s->channel_filter_count + num_extra_filters; i++) {
739 filters[i] = extra_filters[i - s->channel_filter_count];
740 }
741 filters[i] = &grpc_connected_channel_filter;
742
Craig Tiller20bc56d2015-02-12 09:02:56 -0800743 for (i = 0; i < s->cq_count; i++) {
744 grpc_transport_add_to_pollset(transport, grpc_cq_pollset(s->cqs[i]));
745 }
ctillerd79b4862014-12-17 16:36:59 -0800746
Julien Boeufc6f8d0a2015-05-11 22:40:02 -0700747 channel =
748 grpc_channel_create_from_filters(filters, num_filters, args, mdctx, 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800749 chand = (channel_data *)grpc_channel_stack_element(
Craig Tillerc02c1d82015-04-07 16:21:55 -0700750 grpc_channel_get_channel_stack(channel), 0)
751 ->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800752 chand->server = s;
753 server_ref(s);
754 chand->channel = channel;
755
Craig Tiller04cc8be2015-02-10 16:11:22 -0800756 num_registered_methods = 0;
757 for (rm = s->registered_methods; rm; rm = rm->next) {
758 num_registered_methods++;
759 }
760 /* build a lookup table phrased in terms of mdstr's in this channels context
761 to quickly find registered methods */
762 if (num_registered_methods > 0) {
763 slots = 2 * num_registered_methods;
764 alloc = sizeof(channel_registered_method) * slots;
765 chand->registered_methods = gpr_malloc(alloc);
766 memset(chand->registered_methods, 0, alloc);
767 for (rm = s->registered_methods; rm; rm = rm->next) {
768 host = rm->host ? grpc_mdstr_from_string(mdctx, rm->host) : NULL;
Craig Tillere76c9662015-02-11 13:18:31 -0800769 method = grpc_mdstr_from_string(mdctx, rm->method);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800770 hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash);
Craig Tiller3b29b562015-02-11 12:58:46 -0800771 for (probes = 0; chand->registered_methods[(hash + probes) % slots]
Craig Tillerc02c1d82015-04-07 16:21:55 -0700772 .server_registered_method != NULL;
Craig Tiller3b29b562015-02-11 12:58:46 -0800773 probes++)
774 ;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800775 if (probes > max_probes) max_probes = probes;
776 crm = &chand->registered_methods[(hash + probes) % slots];
777 crm->server_registered_method = rm;
778 crm->host = host;
779 crm->method = method;
780 }
781 chand->registered_method_slots = slots;
782 chand->registered_method_max_probes = max_probes;
783 }
784
Craig Tiller5d6bd442015-02-12 22:50:38 -0800785 result = grpc_connected_channel_bind_transport(
786 grpc_channel_get_channel_stack(channel), transport);
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800787
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800788 gpr_mu_lock(&s->mu);
789 chand->next = &s->root_channel_data;
790 chand->prev = chand->next->prev;
791 chand->next->prev = chand->prev->next = chand;
792 gpr_mu_unlock(&s->mu);
793
794 gpr_free(filters);
795
Craig Tiller5d6bd442015-02-12 22:50:38 -0800796 return result;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800797}
798
Craig Tilleraec96aa2015-04-07 14:32:15 -0700799static int num_listeners(grpc_server *server) {
800 listener *l;
801 int n = 0;
802 for (l = server->listeners; l; l = l->next) {
803 n++;
804 }
805 return n;
806}
807
Craig Tillerbd217572015-02-11 18:10:56 -0800808static void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag,
Craig Tillerec3257c2015-02-12 15:59:43 -0800809 void *shutdown_tag) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800810 listener *l;
Craig Tiller24be0f72015-02-10 14:04:22 -0800811 requested_call_array requested_calls;
nnoble0c475f02014-12-05 15:37:39 -0800812 channel_data **channels;
813 channel_data *c;
814 size_t nchannels;
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800815 size_t i, j;
nnoble0c475f02014-12-05 15:37:39 -0800816 grpc_channel_op op;
817 grpc_channel_element *elem;
Craig Tillerbd217572015-02-11 18:10:56 -0800818 registered_method *rm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800819
820 /* lock, and gather up some stuff to do */
821 gpr_mu_lock(&server->mu);
Craig Tilleraea2fc02015-02-17 16:54:53 -0800822 if (have_shutdown_tag) {
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800823 for (i = 0; i < server->cq_count; i++) {
Craig Tiller64be9f72015-05-04 14:53:51 -0700824 grpc_cq_begin_op(server->cqs[i], NULL);
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800825 }
Craig Tilleraea2fc02015-02-17 16:54:53 -0800826 server->shutdown_tags =
827 gpr_realloc(server->shutdown_tags,
828 sizeof(void *) * (server->num_shutdown_tags + 1));
829 server->shutdown_tags[server->num_shutdown_tags++] = shutdown_tag;
830 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800831 if (server->shutdown) {
832 gpr_mu_unlock(&server->mu);
833 return;
834 }
835
nnoble0c475f02014-12-05 15:37:39 -0800836 nchannels = 0;
837 for (c = server->root_channel_data.next; c != &server->root_channel_data;
838 c = c->next) {
839 nchannels++;
840 }
841 channels = gpr_malloc(sizeof(channel_data *) * nchannels);
842 i = 0;
843 for (c = server->root_channel_data.next; c != &server->root_channel_data;
844 c = c->next) {
845 grpc_channel_internal_ref(c->channel);
846 channels[i] = c;
847 i++;
848 }
849
Craig Tillerbd217572015-02-11 18:10:56 -0800850 /* collect all unregistered then registered calls */
Craig Tillercce17ac2015-01-20 09:29:28 -0800851 requested_calls = server->requested_calls;
Craig Tiller24be0f72015-02-10 14:04:22 -0800852 memset(&server->requested_calls, 0, sizeof(server->requested_calls));
Craig Tillerbd217572015-02-11 18:10:56 -0800853 for (rm = server->registered_methods; rm; rm = rm->next) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800854 if (requested_calls.count + rm->requested.count >
855 requested_calls.capacity) {
856 requested_calls.capacity =
857 GPR_MAX(requested_calls.count + rm->requested.count,
858 2 * requested_calls.capacity);
859 requested_calls.calls =
860 gpr_realloc(requested_calls.calls, sizeof(*requested_calls.calls) *
861 requested_calls.capacity);
Craig Tillerbd217572015-02-11 18:10:56 -0800862 }
Craig Tillerec3257c2015-02-12 15:59:43 -0800863 memcpy(requested_calls.calls + requested_calls.count, rm->requested.calls,
864 sizeof(*requested_calls.calls) * rm->requested.count);
Craig Tillerbd217572015-02-11 18:10:56 -0800865 requested_calls.count += rm->requested.count;
Craig Tillerec3257c2015-02-12 15:59:43 -0800866 gpr_free(rm->requested.calls);
Craig Tillerbd217572015-02-11 18:10:56 -0800867 memset(&rm->requested, 0, sizeof(rm->requested));
868 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800869
870 server->shutdown = 1;
Craig Tilleraea2fc02015-02-17 16:54:53 -0800871 if (server->lists[ALL_CALLS] == NULL) {
872 for (i = 0; i < server->num_shutdown_tags; i++) {
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800873 for (j = 0; j < server->cq_count; j++) {
Craig Tiller64be9f72015-05-04 14:53:51 -0700874 grpc_cq_end_op(server->cqs[j], server->shutdown_tags[i], NULL, 1);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800875 }
Craig Tiller4ffdcd52015-01-16 11:34:55 -0800876 }
877 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800878 gpr_mu_unlock(&server->mu);
879
nnoble0c475f02014-12-05 15:37:39 -0800880 for (i = 0; i < nchannels; i++) {
881 c = channels[i];
882 elem = grpc_channel_stack_element(
883 grpc_channel_get_channel_stack(c->channel), 0);
884
885 op.type = GRPC_CHANNEL_GOAWAY;
886 op.dir = GRPC_CALL_DOWN;
887 op.data.goaway.status = GRPC_STATUS_OK;
888 op.data.goaway.message = gpr_slice_from_copied_string("Server shutdown");
ctillerf962f522014-12-10 15:28:27 -0800889 elem->filter->channel_op(elem, NULL, &op);
nnoble0c475f02014-12-05 15:37:39 -0800890
891 grpc_channel_internal_unref(c->channel);
892 }
893 gpr_free(channels);
894
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800895 /* terminate all the requested calls */
Craig Tiller24be0f72015-02-10 14:04:22 -0800896 for (i = 0; i < requested_calls.count; i++) {
897 fail_call(server, &requested_calls.calls[i]);
Craig Tillercce17ac2015-01-20 09:29:28 -0800898 }
Craig Tiller24be0f72015-02-10 14:04:22 -0800899 gpr_free(requested_calls.calls);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800900
901 /* Shutdown listeners */
902 for (l = server->listeners; l; l = l->next) {
903 l->destroy(server, l->arg);
904 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800905}
906
Craig Tiller4ffdcd52015-01-16 11:34:55 -0800907void grpc_server_shutdown(grpc_server *server) {
908 shutdown_internal(server, 0, NULL);
909}
910
911void grpc_server_shutdown_and_notify(grpc_server *server, void *tag) {
912 shutdown_internal(server, 1, tag);
913}
914
Craig Tilleraec96aa2015-04-07 14:32:15 -0700915void grpc_server_listener_destroy_done(void *s) {
916 grpc_server *server = s;
917 gpr_mu_lock(&server->mu);
918 server->listeners_destroyed++;
919 gpr_cv_signal(&server->cv);
920 gpr_mu_unlock(&server->mu);
921}
922
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800923void grpc_server_destroy(grpc_server *server) {
924 channel_data *c;
Craig Tilleraec96aa2015-04-07 14:32:15 -0700925 listener *l;
926 size_t i;
Craig Tiller872af022015-04-24 15:57:52 -0700927 call_data *calld;
928
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800929 gpr_mu_lock(&server->mu);
Craig Tilleraea2fc02015-02-17 16:54:53 -0800930 if (!server->shutdown) {
931 gpr_mu_unlock(&server->mu);
932 grpc_server_shutdown(server);
933 gpr_mu_lock(&server->mu);
934 }
935
Craig Tilleraec96aa2015-04-07 14:32:15 -0700936 while (server->listeners_destroyed != num_listeners(server)) {
937 for (i = 0; i < server->cq_count; i++) {
938 gpr_mu_unlock(&server->mu);
939 grpc_cq_hack_spin_pollset(server->cqs[i]);
940 gpr_mu_lock(&server->mu);
941 }
942
Craig Tillerc02c1d82015-04-07 16:21:55 -0700943 gpr_cv_wait(&server->cv, &server->mu,
944 gpr_time_add(gpr_now(), gpr_time_from_millis(100)));
Craig Tilleraec96aa2015-04-07 14:32:15 -0700945 }
946
947 while (server->listeners) {
948 l = server->listeners;
949 server->listeners = l->next;
950 gpr_free(l);
951 }
952
Craig Tiller872af022015-04-24 15:57:52 -0700953 while ((calld = call_list_remove_head(&server->lists[PENDING_START],
954 PENDING_START)) != NULL) {
David Garcia Quintasa30020f2015-05-27 19:21:01 -0700955 /* TODO(dgq): If we knew the size of the call list (or an upper bound), we
956 * could allocate all the memory for the closures in advance in a single
957 * chunk */
Craig Tiller872af022015-04-24 15:57:52 -0700958 gpr_log(GPR_DEBUG, "server destroys call %p", calld->call);
959 calld->state = ZOMBIED;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700960 grpc_iomgr_closure_init(
961 &calld->kill_zombie_closure, kill_zombie,
David Garcia Quintasa30020f2015-05-27 19:21:01 -0700962 grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
David Garcia Quintas284488b2015-05-28 16:27:39 -0700963 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
Craig Tiller872af022015-04-24 15:57:52 -0700964 }
965
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800966 for (c = server->root_channel_data.next; c != &server->root_channel_data;
967 c = c->next) {
968 shutdown_channel(c);
969 }
970 gpr_mu_unlock(&server->mu);
971
972 server_unref(server);
973}
974
975void grpc_server_add_listener(grpc_server *server, void *arg,
ctiller58393c22015-01-07 14:03:30 -0800976 void (*start)(grpc_server *server, void *arg,
Craig Tillerec3257c2015-02-12 15:59:43 -0800977 grpc_pollset **pollsets,
978 size_t pollset_count),
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800979 void (*destroy)(grpc_server *server, void *arg)) {
980 listener *l = gpr_malloc(sizeof(listener));
981 l->arg = arg;
982 l->start = start;
983 l->destroy = destroy;
984 l->next = server->listeners;
985 server->listeners = l;
986}
987
Craig Tiller9f28ac22015-01-27 17:01:29 -0800988static grpc_call_error queue_call_request(grpc_server *server,
Craig Tiller24be0f72015-02-10 14:04:22 -0800989 requested_call *rc) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -0800990 call_data *calld = NULL;
Craig Tiller0ef1a922015-02-11 16:23:01 -0800991 requested_call_array *requested_calls = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800992 gpr_mu_lock(&server->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800993 if (server->shutdown) {
994 gpr_mu_unlock(&server->mu);
Craig Tiller24be0f72015-02-10 14:04:22 -0800995 fail_call(server, rc);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800996 return GRPC_CALL_OK;
997 }
Craig Tiller04cc8be2015-02-10 16:11:22 -0800998 switch (rc->type) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800999 case BATCH_CALL:
Craig Tiller3b29b562015-02-11 12:58:46 -08001000 calld =
1001 call_list_remove_head(&server->lists[PENDING_START], PENDING_START);
Craig Tiller0ef1a922015-02-11 16:23:01 -08001002 requested_calls = &server->requested_calls;
Craig Tiller04cc8be2015-02-10 16:11:22 -08001003 break;
1004 case REGISTERED_CALL:
Craig Tiller3b29b562015-02-11 12:58:46 -08001005 calld = call_list_remove_head(
1006 &rc->data.registered.registered_method->pending, PENDING_START);
Craig Tiller0ef1a922015-02-11 16:23:01 -08001007 requested_calls = &rc->data.registered.registered_method->requested;
Craig Tiller04cc8be2015-02-10 16:11:22 -08001008 break;
1009 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001010 if (calld) {
Craig Tillercce17ac2015-01-20 09:29:28 -08001011 GPR_ASSERT(calld->state == PENDING);
Craig Tillerbb3f22f2015-01-29 16:40:56 -08001012 calld->state = ACTIVATED;
Craig Tillercce17ac2015-01-20 09:29:28 -08001013 gpr_mu_unlock(&server->mu);
Craig Tiller24be0f72015-02-10 14:04:22 -08001014 begin_call(server, calld, rc);
Craig Tillercce17ac2015-01-20 09:29:28 -08001015 return GRPC_CALL_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001016 } else {
Craig Tiller0ef1a922015-02-11 16:23:01 -08001017 *requested_call_array_add(requested_calls) = *rc;
Craig Tillercce17ac2015-01-20 09:29:28 -08001018 gpr_mu_unlock(&server->mu);
1019 return GRPC_CALL_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001020 }
Craig Tillercce17ac2015-01-20 09:29:28 -08001021}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001022
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001023grpc_call_error grpc_server_request_call(
1024 grpc_server *server, grpc_call **call, grpc_call_details *details,
1025 grpc_metadata_array *initial_metadata,
1026 grpc_completion_queue *cq_bound_to_call,
1027 grpc_completion_queue *cq_for_notification, void *tag) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001028 requested_call rc;
murgatroid99ad7c20c2015-05-22 14:42:29 -07001029 GRPC_SERVER_LOG_REQUEST_CALL(GPR_INFO, server, call, details,
1030 initial_metadata, cq_bound_to_call,
1031 cq_for_notification, tag);
Craig Tiller54478f82015-05-12 14:08:56 -07001032 grpc_cq_begin_op(cq_for_notification, NULL);
Craig Tiller24be0f72015-02-10 14:04:22 -08001033 rc.type = BATCH_CALL;
1034 rc.tag = tag;
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001035 rc.cq_bound_to_call = cq_bound_to_call;
1036 rc.cq_for_notification = cq_for_notification;
1037 rc.call = call;
Craig Tiller24be0f72015-02-10 14:04:22 -08001038 rc.data.batch.details = details;
1039 rc.data.batch.initial_metadata = initial_metadata;
1040 return queue_call_request(server, &rc);
1041}
1042
1043grpc_call_error grpc_server_request_registered_call(
Craig Tillerec3257c2015-02-12 15:59:43 -08001044 grpc_server *server, void *rm, grpc_call **call, gpr_timespec *deadline,
1045 grpc_metadata_array *initial_metadata, grpc_byte_buffer **optional_payload,
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001046 grpc_completion_queue *cq_bound_to_call,
1047 grpc_completion_queue *cq_for_notification, void *tag) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001048 requested_call rc;
Craig Tiller20bc56d2015-02-12 09:02:56 -08001049 registered_method *registered_method = rm;
Craig Tiller54478f82015-05-12 14:08:56 -07001050 grpc_cq_begin_op(cq_for_notification, NULL);
Craig Tiller24be0f72015-02-10 14:04:22 -08001051 rc.type = REGISTERED_CALL;
1052 rc.tag = tag;
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001053 rc.cq_bound_to_call = cq_bound_to_call;
1054 rc.cq_for_notification = cq_for_notification;
1055 rc.call = call;
Craig Tiller24be0f72015-02-10 14:04:22 -08001056 rc.data.registered.registered_method = registered_method;
1057 rc.data.registered.deadline = deadline;
1058 rc.data.registered.initial_metadata = initial_metadata;
1059 rc.data.registered.optional_payload = optional_payload;
1060 return queue_call_request(server, &rc);
1061}
1062
Craig Tiller64be9f72015-05-04 14:53:51 -07001063static void publish_registered_or_batch(grpc_call *call, int success,
Craig Tiller24be0f72015-02-10 14:04:22 -08001064 void *tag);
Craig Tiller64be9f72015-05-04 14:53:51 -07001065static void publish_was_not_set(grpc_call *call, int success, void *tag) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001066 abort();
1067}
Craig Tiller24be0f72015-02-10 14:04:22 -08001068
Craig Tiller166e2502015-02-03 20:14:41 -08001069static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
1070 gpr_slice slice = value->slice;
1071 size_t len = GPR_SLICE_LENGTH(slice);
1072
1073 if (len + 1 > *capacity) {
1074 *capacity = GPR_MAX(len + 1, *capacity * 2);
1075 *dest = gpr_realloc(*dest, *capacity);
1076 }
1077 memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
1078}
1079
Craig Tiller24be0f72015-02-10 14:04:22 -08001080static void begin_call(grpc_server *server, call_data *calld,
1081 requested_call *rc) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001082 grpc_ioreq_completion_func publish = publish_was_not_set;
Craig Tiller24be0f72015-02-10 14:04:22 -08001083 grpc_ioreq req[2];
1084 grpc_ioreq *r = req;
1085
1086 /* called once initial metadata has been read by the call, but BEFORE
1087 the ioreq to fetch it out of the call has been executed.
1088 This means metadata related fields can be relied on in calld, but to
1089 fill in the metadata array passed by the client, we need to perform
1090 an ioreq op, that should complete immediately. */
1091
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001092 grpc_call_set_completion_queue(calld->call, rc->cq_bound_to_call);
1093 *rc->call = calld->call;
1094 calld->cq_new = rc->cq_for_notification;
Craig Tiller24be0f72015-02-10 14:04:22 -08001095 switch (rc->type) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001096 case BATCH_CALL:
1097 cpstr(&rc->data.batch.details->host,
1098 &rc->data.batch.details->host_capacity, calld->host);
1099 cpstr(&rc->data.batch.details->method,
1100 &rc->data.batch.details->method_capacity, calld->path);
Masood Malekghassemibf177c82015-04-27 12:14:38 -07001101 rc->data.batch.details->deadline = calld->deadline;
Craig Tiller24be0f72015-02-10 14:04:22 -08001102 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1103 r->data.recv_metadata = rc->data.batch.initial_metadata;
1104 r++;
1105 publish = publish_registered_or_batch;
1106 break;
1107 case REGISTERED_CALL:
1108 *rc->data.registered.deadline = calld->deadline;
Craig Tiller24be0f72015-02-10 14:04:22 -08001109 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1110 r->data.recv_metadata = rc->data.registered.initial_metadata;
1111 r++;
1112 if (rc->data.registered.optional_payload) {
1113 r->op = GRPC_IOREQ_RECV_MESSAGE;
1114 r->data.recv_message = rc->data.registered.optional_payload;
1115 r++;
1116 }
1117 publish = publish_registered_or_batch;
1118 break;
1119 }
1120
Craig Tiller4df412b2015-04-28 07:57:54 -07001121 GRPC_CALL_INTERNAL_REF(calld->call, "server");
Craig Tiller24be0f72015-02-10 14:04:22 -08001122 grpc_call_start_ioreq_and_call_back(calld->call, req, r - req, publish,
1123 rc->tag);
1124}
1125
1126static void fail_call(grpc_server *server, requested_call *rc) {
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001127 *rc->call = NULL;
Craig Tiller24be0f72015-02-10 14:04:22 -08001128 switch (rc->type) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001129 case BATCH_CALL:
Craig Tiller24be0f72015-02-10 14:04:22 -08001130 rc->data.batch.initial_metadata->count = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001131 break;
1132 case REGISTERED_CALL:
Craig Tiller24be0f72015-02-10 14:04:22 -08001133 rc->data.registered.initial_metadata->count = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001134 break;
1135 }
Craig Tiller54478f82015-05-12 14:08:56 -07001136 grpc_cq_end_op(rc->cq_for_notification, rc->tag, NULL, 0);
Craig Tiller24be0f72015-02-10 14:04:22 -08001137}
1138
Craig Tiller64be9f72015-05-04 14:53:51 -07001139static void publish_registered_or_batch(grpc_call *call, int success,
Craig Tiller24be0f72015-02-10 14:04:22 -08001140 void *tag) {
Craig Tiller8e8fd892015-02-10 17:02:08 -08001141 grpc_call_element *elem =
1142 grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
Craig Tiller20bc56d2015-02-12 09:02:56 -08001143 call_data *calld = elem->call_data;
Craig Tiller64be9f72015-05-04 14:53:51 -07001144 grpc_cq_end_op(calld->cq_new, tag, call, success);
Craig Tiller24be0f72015-02-10 14:04:22 -08001145}
1146
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001147const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) {
1148 return server->channel_args;
Craig Tiller190d3602015-02-18 09:23:38 -08001149}
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001150
1151int grpc_server_has_open_connections(grpc_server *server) {
1152 int r;
1153 gpr_mu_lock(&server->mu);
1154 r = server->root_channel_data.next != &server->root_channel_data;
1155 gpr_mu_unlock(&server->mu);
1156 return r;
1157}
1158