blob: dac374b7d4b35c2435e5729c518239ea8d43bb34 [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>
Masood Malekghassemi701af602015-06-03 15:01:17 -070051#include <grpc/support/string_util.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080052#include <grpc/support/useful.h>
53
54typedef enum { PENDING_START, ALL_CALLS, CALL_LIST_COUNT } call_list;
55
56typedef struct listener {
57 void *arg;
Craig Tillerec3257c2015-02-12 15:59:43 -080058 void (*start)(grpc_server *server, void *arg, grpc_pollset **pollsets,
59 size_t pollset_count);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080060 void (*destroy)(grpc_server *server, void *arg);
61 struct listener *next;
62} listener;
63
64typedef struct call_data call_data;
65typedef struct channel_data channel_data;
Craig Tiller24be0f72015-02-10 14:04:22 -080066typedef struct registered_method registered_method;
67
68typedef struct {
69 call_data *next;
70 call_data *prev;
71} call_link;
72
Craig Tiller0e919562015-04-28 14:03:47 -070073typedef enum { BATCH_CALL, REGISTERED_CALL } requested_call_type;
Craig Tiller24be0f72015-02-10 14:04:22 -080074
75typedef struct {
76 requested_call_type type;
77 void *tag;
Craig Tillerf9e6adf2015-05-06 11:45:59 -070078 grpc_completion_queue *cq_bound_to_call;
79 grpc_completion_queue *cq_for_notification;
80 grpc_call **call;
Craig Tiller24be0f72015-02-10 14:04:22 -080081 union {
82 struct {
Craig Tiller24be0f72015-02-10 14:04:22 -080083 grpc_call_details *details;
84 grpc_metadata_array *initial_metadata;
85 } batch;
86 struct {
Craig Tiller24be0f72015-02-10 14:04:22 -080087 registered_method *registered_method;
88 gpr_timespec *deadline;
89 grpc_metadata_array *initial_metadata;
90 grpc_byte_buffer **optional_payload;
91 } registered;
92 } data;
93} requested_call;
94
95typedef struct {
96 requested_call *calls;
97 size_t count;
98 size_t capacity;
99} requested_call_array;
100
101struct registered_method {
102 char *method;
103 char *host;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800104 call_data *pending;
Craig Tiller24be0f72015-02-10 14:04:22 -0800105 requested_call_array requested;
106 registered_method *next;
107};
108
109typedef struct channel_registered_method {
110 registered_method *server_registered_method;
111 grpc_mdstr *method;
112 grpc_mdstr *host;
113} channel_registered_method;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800114
115struct channel_data {
116 grpc_server *server;
Craig Tillerb76d05b2015-05-29 17:21:56 -0700117 size_t num_calls;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800118 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;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700127 grpc_iomgr_closure finish_destroy_channel_closure;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800128};
129
Craig Tillerbce999f2015-05-27 09:55:51 -0700130typedef struct shutdown_tag {
131 void *tag;
132 grpc_completion_queue *cq;
133} shutdown_tag;
134
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800135struct grpc_server {
136 size_t channel_filter_count;
137 const grpc_channel_filter **channel_filters;
138 grpc_channel_args *channel_args;
Craig Tillerec3257c2015-02-12 15:59:43 -0800139
Craig Tiller20bc56d2015-02-12 09:02:56 -0800140 grpc_completion_queue **cqs;
141 grpc_pollset **pollsets;
142 size_t cq_count;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800143
Vijay Pai8931cdd2015-06-17 12:42:17 -0700144 gpr_mu mu_global;
145 gpr_mu mu_call;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800146
Craig Tiller24be0f72015-02-10 14:04:22 -0800147 registered_method *registered_methods;
148 requested_call_array requested_calls;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800149
150 gpr_uint8 shutdown;
Craig Tiller29f79dc2015-05-27 15:59:23 -0700151 gpr_uint8 shutdown_published;
Craig Tilleraea2fc02015-02-17 16:54:53 -0800152 size_t num_shutdown_tags;
Craig Tillerbce999f2015-05-27 09:55:51 -0700153 shutdown_tag *shutdown_tags;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800154
155 call_data *lists[CALL_LIST_COUNT];
156 channel_data root_channel_data;
157
158 listener *listeners;
Craig Tilleraec96aa2015-04-07 14:32:15 -0700159 int listeners_destroyed;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800160 gpr_refcount internal_refcount;
161};
162
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800163typedef enum {
164 /* waiting for metadata */
165 NOT_STARTED,
166 /* inital metadata read, not flow controlled in yet */
167 PENDING,
168 /* flow controlled in, on completion queue */
169 ACTIVATED,
170 /* cancelled before being queued */
171 ZOMBIED
172} call_state;
173
174struct call_data {
175 grpc_call *call;
176
177 call_state state;
Craig Tillercce17ac2015-01-20 09:29:28 -0800178 grpc_mdstr *path;
179 grpc_mdstr *host;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700180 gpr_timespec deadline;
181 int got_initial_metadata;
Craig Tillercce17ac2015-01-20 09:29:28 -0800182
Craig Tiller20bc56d2015-02-12 09:02:56 -0800183 grpc_completion_queue *cq_new;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800184
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700185 grpc_stream_op_buffer *recv_ops;
186 grpc_stream_state *recv_state;
187 void (*on_done_recv)(void *user_data, int success);
188 void *recv_user_data;
189
David Garcia Quintas284488b2015-05-28 16:27:39 -0700190 grpc_iomgr_closure kill_zombie_closure;
191
Craig Tiller04cc8be2015-02-10 16:11:22 -0800192 call_data **root[CALL_LIST_COUNT];
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800193 call_link links[CALL_LIST_COUNT];
194};
195
196#define SERVER_FROM_CALL_ELEM(elem) \
197 (((channel_data *)(elem)->channel_data)->server)
198
Craig Tiller24be0f72015-02-10 14:04:22 -0800199static void begin_call(grpc_server *server, call_data *calld,
200 requested_call *rc);
201static void fail_call(grpc_server *server, requested_call *rc);
Craig Tillerc4a1f522015-05-29 22:32:04 -0700202static void shutdown_channel(channel_data *chand, int send_goaway,
203 int send_disconnect);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700204/* Before calling maybe_finish_shutdown, we must hold mu_global and not
205 hold mu_call */
Craig Tiller52760dd2015-05-29 23:09:26 -0700206static void maybe_finish_shutdown(grpc_server *server);
Craig Tiller24be0f72015-02-10 14:04:22 -0800207
Craig Tiller3b29b562015-02-11 12:58:46 -0800208static int call_list_join(call_data **root, call_data *call, call_list list) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800209 GPR_ASSERT(!call->root[list]);
210 call->root[list] = root;
211 if (!*root) {
212 *root = call;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800213 call->links[list].next = call->links[list].prev = call;
214 } else {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800215 call->links[list].next = *root;
216 call->links[list].prev = (*root)->links[list].prev;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800217 call->links[list].next->links[list].prev =
218 call->links[list].prev->links[list].next = call;
219 }
220 return 1;
221}
222
Craig Tiller04cc8be2015-02-10 16:11:22 -0800223static call_data *call_list_remove_head(call_data **root, call_list list) {
224 call_data *out = *root;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800225 if (out) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800226 out->root[list] = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800227 if (out->links[list].next == out) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800228 *root = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800229 } else {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800230 *root = out->links[list].next;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800231 out->links[list].next->links[list].prev = out->links[list].prev;
232 out->links[list].prev->links[list].next = out->links[list].next;
233 }
234 }
235 return out;
236}
237
Craig Tiller04cc8be2015-02-10 16:11:22 -0800238static int call_list_remove(call_data *call, call_list list) {
239 call_data **root = call->root[list];
240 if (root == NULL) return 0;
241 call->root[list] = NULL;
242 if (*root == call) {
243 *root = call->links[list].next;
244 if (*root == call) {
245 *root = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800246 return 1;
247 }
248 }
Craig Tiller04cc8be2015-02-10 16:11:22 -0800249 GPR_ASSERT(*root != call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800250 call->links[list].next->links[list].prev = call->links[list].prev;
251 call->links[list].prev->links[list].next = call->links[list].next;
252 return 1;
253}
254
Craig Tiller24be0f72015-02-10 14:04:22 -0800255static void requested_call_array_destroy(requested_call_array *array) {
256 gpr_free(array->calls);
257}
258
259static requested_call *requested_call_array_add(requested_call_array *array) {
260 requested_call *rc;
261 if (array->count == array->capacity) {
262 array->capacity = GPR_MAX(array->capacity + 8, array->capacity * 2);
263 array->calls =
264 gpr_realloc(array->calls, sizeof(requested_call) * array->capacity);
265 }
266 rc = &array->calls[array->count++];
267 memset(rc, 0, sizeof(*rc));
268 return rc;
269}
270
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800271static void server_ref(grpc_server *server) {
272 gpr_ref(&server->internal_refcount);
273}
274
Craig Tilleree945e82015-05-26 16:15:34 -0700275static void server_delete(grpc_server *server) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800276 registered_method *rm;
Craig Tiller89504612015-04-27 11:48:46 -0700277 size_t i;
Craig Tilleree945e82015-05-26 16:15:34 -0700278 grpc_channel_args_destroy(server->channel_args);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700279 gpr_mu_destroy(&server->mu_global);
280 gpr_mu_destroy(&server->mu_call);
Craig Tilleree945e82015-05-26 16:15:34 -0700281 gpr_free(server->channel_filters);
282 requested_call_array_destroy(&server->requested_calls);
283 while ((rm = server->registered_methods) != NULL) {
284 server->registered_methods = rm->next;
285 gpr_free(rm->method);
286 gpr_free(rm->host);
287 requested_call_array_destroy(&rm->requested);
288 gpr_free(rm);
289 }
290 for (i = 0; i < server->cq_count; i++) {
Craig Tiller463f2372015-05-28 16:16:15 -0700291 GRPC_CQ_INTERNAL_UNREF(server->cqs[i], "server");
Craig Tilleree945e82015-05-26 16:15:34 -0700292 }
293 gpr_free(server->cqs);
294 gpr_free(server->pollsets);
295 gpr_free(server->shutdown_tags);
296 gpr_free(server);
297}
298
299static void server_unref(grpc_server *server) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800300 if (gpr_unref(&server->internal_refcount)) {
Craig Tilleree945e82015-05-26 16:15:34 -0700301 server_delete(server);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800302 }
303}
304
305static int is_channel_orphaned(channel_data *chand) {
306 return chand->next == chand;
307}
308
309static void orphan_channel(channel_data *chand) {
310 chand->next->prev = chand->prev;
311 chand->prev->next = chand->next;
312 chand->next = chand->prev = chand;
313}
314
ctiller58393c22015-01-07 14:03:30 -0800315static void finish_destroy_channel(void *cd, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800316 channel_data *chand = cd;
317 grpc_server *server = chand->server;
Craig Tiller9ec2a522015-05-29 22:46:54 -0700318 GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "server");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800319 server_unref(server);
320}
321
322static void destroy_channel(channel_data *chand) {
323 if (is_channel_orphaned(chand)) return;
324 GPR_ASSERT(chand->server != NULL);
325 orphan_channel(chand);
326 server_ref(chand->server);
Craig Tiller52760dd2015-05-29 23:09:26 -0700327 maybe_finish_shutdown(chand->server);
David Garcia Quintas284488b2015-05-28 16:27:39 -0700328 chand->finish_destroy_channel_closure.cb = finish_destroy_channel;
329 chand->finish_destroy_channel_closure.cb_arg = chand;
330 grpc_iomgr_add_callback(&chand->finish_destroy_channel_closure);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800331}
332
Craig Tiller3b29b562015-02-11 12:58:46 -0800333static void finish_start_new_rpc_and_unlock(grpc_server *server,
334 grpc_call_element *elem,
335 call_data **pending_root,
336 requested_call_array *array) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800337 requested_call rc;
338 call_data *calld = elem->call_data;
339 if (array->count == 0) {
340 calld->state = PENDING;
341 call_list_join(pending_root, calld, PENDING_START);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700342 gpr_mu_unlock(&server->mu_call);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800343 } else {
Craig Tiller0ef1a922015-02-11 16:23:01 -0800344 rc = array->calls[--array->count];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800345 calld->state = ACTIVATED;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700346 gpr_mu_unlock(&server->mu_call);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800347 begin_call(server, calld, &rc);
348 }
349}
350
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800351static void start_new_rpc(grpc_call_element *elem) {
352 channel_data *chand = elem->channel_data;
353 call_data *calld = elem->call_data;
354 grpc_server *server = chand->server;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800355 gpr_uint32 i;
356 gpr_uint32 hash;
357 channel_registered_method *rm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800358
Vijay Pai8931cdd2015-06-17 12:42:17 -0700359 gpr_mu_lock(&server->mu_call);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800360 if (chand->registered_methods && calld->path && calld->host) {
Craig Tillera94beff2015-02-17 22:02:06 -0800361 /* TODO(ctiller): unify these two searches */
Craig Tiller04cc8be2015-02-10 16:11:22 -0800362 /* check for an exact match with host */
363 hash = GRPC_MDSTR_KV_HASH(calld->host->hash, calld->path->hash);
364 for (i = 0; i < chand->registered_method_max_probes; i++) {
Craig Tiller3b29b562015-02-11 12:58:46 -0800365 rm = &chand->registered_methods[(hash + i) %
366 chand->registered_method_slots];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800367 if (!rm) break;
368 if (rm->host != calld->host) continue;
369 if (rm->method != calld->path) continue;
Craig Tiller3b29b562015-02-11 12:58:46 -0800370 finish_start_new_rpc_and_unlock(server, elem,
371 &rm->server_registered_method->pending,
372 &rm->server_registered_method->requested);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800373 return;
374 }
375 /* check for a wildcard method definition (no host set) */
376 hash = GRPC_MDSTR_KV_HASH(0, calld->path->hash);
Craig Tiller0ef1a922015-02-11 16:23:01 -0800377 for (i = 0; i <= chand->registered_method_max_probes; i++) {
Craig Tiller3b29b562015-02-11 12:58:46 -0800378 rm = &chand->registered_methods[(hash + i) %
379 chand->registered_method_slots];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800380 if (!rm) break;
381 if (rm->host != NULL) continue;
382 if (rm->method != calld->path) continue;
Craig Tiller3b29b562015-02-11 12:58:46 -0800383 finish_start_new_rpc_and_unlock(server, elem,
384 &rm->server_registered_method->pending,
385 &rm->server_registered_method->requested);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800386 return;
387 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800388 }
Craig Tiller3b29b562015-02-11 12:58:46 -0800389 finish_start_new_rpc_and_unlock(server, elem, &server->lists[PENDING_START],
390 &server->requested_calls);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800391}
392
ctiller58393c22015-01-07 14:03:30 -0800393static void kill_zombie(void *elem, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800394 grpc_call_destroy(grpc_call_from_top_element(elem));
395}
396
Craig Tilleree945e82015-05-26 16:15:34 -0700397static int num_listeners(grpc_server *server) {
398 listener *l;
399 int n = 0;
400 for (l = server->listeners; l; l = l->next) {
401 n++;
402 }
403 return n;
404}
405
Craig Tillerdc627722015-05-26 15:27:02 -0700406static void maybe_finish_shutdown(grpc_server *server) {
Craig Tillerbce999f2015-05-27 09:55:51 -0700407 size_t i;
Craig Tillerc4a1f522015-05-29 22:32:04 -0700408 if (!server->shutdown || server->shutdown_published) {
409 return;
410 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700411
412 gpr_mu_lock(&server->mu_call);
Craig Tillerc4a1f522015-05-29 22:32:04 -0700413 if (server->lists[ALL_CALLS] != NULL) {
414 gpr_log(GPR_DEBUG,
415 "Waiting for all calls to finish before destroying server");
Vijay Pai8931cdd2015-06-17 12:42:17 -0700416 gpr_mu_unlock(&server->mu_call);
Craig Tillerc4a1f522015-05-29 22:32:04 -0700417 return;
418 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700419 gpr_mu_unlock(&server->mu_call);
420
Craig Tillerc4a1f522015-05-29 22:32:04 -0700421 if (server->root_channel_data.next != &server->root_channel_data) {
422 gpr_log(GPR_DEBUG,
Craig Tiller3e9ff5c2015-05-29 23:03:13 -0700423 "Waiting for all channels to close before destroying server");
Craig Tillerc4a1f522015-05-29 22:32:04 -0700424 return;
425 }
426 if (server->listeners_destroyed < num_listeners(server)) {
427 gpr_log(GPR_DEBUG, "Waiting for all listeners to be destroyed (@ %d/%d)",
428 server->listeners_destroyed, num_listeners(server));
429 return;
430 }
431 server->shutdown_published = 1;
432 for (i = 0; i < server->num_shutdown_tags; i++) {
433 grpc_cq_end_op(server->shutdown_tags[i].cq, server->shutdown_tags[i].tag,
434 NULL, 1);
Craig Tillerdc627722015-05-26 15:27:02 -0700435 }
436}
437
Craig Tiller6902ad22015-04-16 08:01:49 -0700438static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
439 grpc_call_element *elem = user_data;
Craig Tillercce17ac2015-01-20 09:29:28 -0800440 channel_data *chand = elem->channel_data;
441 call_data *calld = elem->call_data;
Craig Tiller6902ad22015-04-16 08:01:49 -0700442 if (md->key == chand->path_key) {
443 calld->path = grpc_mdstr_ref(md->value);
444 return NULL;
445 } else if (md->key == chand->authority_key) {
446 calld->host = grpc_mdstr_ref(md->value);
447 return NULL;
448 }
449 return md;
450}
451
Craig Tillerc4a1f522015-05-29 22:32:04 -0700452static void decrement_call_count(channel_data *chand) {
453 chand->num_calls--;
454 if (0 == chand->num_calls && chand->server->shutdown) {
455 shutdown_channel(chand, 0, 1);
456 }
457 maybe_finish_shutdown(chand->server);
458}
459
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700460static void server_on_recv(void *ptr, int success) {
461 grpc_call_element *elem = ptr;
Craig Tiller6902ad22015-04-16 08:01:49 -0700462 call_data *calld = elem->call_data;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700463 channel_data *chand = elem->channel_data;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700464 int remove_res;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700465
466 if (success && !calld->got_initial_metadata) {
467 size_t i;
468 size_t nops = calld->recv_ops->nops;
469 grpc_stream_op *ops = calld->recv_ops->ops;
470 for (i = 0; i < nops; i++) {
471 grpc_stream_op *op = &ops[i];
472 if (op->type != GRPC_OP_METADATA) continue;
Craig Tiller205aee12015-04-16 14:46:41 -0700473 grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700474 if (0 != gpr_time_cmp(op->data.metadata.deadline, gpr_inf_future)) {
Craig Tiller6902ad22015-04-16 08:01:49 -0700475 calld->deadline = op->data.metadata.deadline;
Craig Tillercce17ac2015-01-20 09:29:28 -0800476 }
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700477 calld->got_initial_metadata = 1;
478 start_new_rpc(elem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800479 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700480 }
481 }
482
483 switch (*calld->recv_state) {
Craig Tiller06aeea72015-04-23 10:54:45 -0700484 case GRPC_STREAM_OPEN:
485 break;
486 case GRPC_STREAM_SEND_CLOSED:
487 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700488 case GRPC_STREAM_RECV_CLOSED:
Vijay Pai8931cdd2015-06-17 12:42:17 -0700489 gpr_mu_lock(&chand->server->mu_call);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700490 if (calld->state == NOT_STARTED) {
491 calld->state = ZOMBIED;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700492 grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
493 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700494 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700495 gpr_mu_unlock(&chand->server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800496 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700497 case GRPC_STREAM_CLOSED:
Vijay Pai8931cdd2015-06-17 12:42:17 -0700498 gpr_mu_lock(&chand->server->mu_call);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700499 if (calld->state == NOT_STARTED) {
500 calld->state = ZOMBIED;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700501 grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
502 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700503 } else if (calld->state == PENDING) {
504 call_list_remove(calld, PENDING_START);
Craig Tillerc9d03822015-05-20 16:08:45 -0700505 calld->state = ZOMBIED;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700506 grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
507 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700508 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700509 remove_res = call_list_remove(calld, ALL_CALLS);
510 gpr_mu_unlock(&chand->server->mu_call);
511 gpr_mu_lock(&chand->server->mu_global);
512 if (remove_res) {
Craig Tillerc4a1f522015-05-29 22:32:04 -0700513 decrement_call_count(chand);
Craig Tiller29f79dc2015-05-27 15:59:23 -0700514 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700515 gpr_mu_unlock(&chand->server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800516 break;
517 }
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700518
519 calld->on_done_recv(calld->recv_user_data, success);
520}
521
Craig Tiller50d9db52015-04-23 10:52:14 -0700522static void server_mutate_op(grpc_call_element *elem, grpc_transport_op *op) {
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700523 call_data *calld = elem->call_data;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700524
525 if (op->recv_ops) {
526 /* substitute our callback for the higher callback */
527 calld->recv_ops = op->recv_ops;
528 calld->recv_state = op->recv_state;
529 calld->on_done_recv = op->on_done_recv;
530 calld->recv_user_data = op->recv_user_data;
531 op->on_done_recv = server_on_recv;
532 op->recv_user_data = elem;
533 }
Craig Tiller50d9db52015-04-23 10:52:14 -0700534}
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700535
Craig Tiller06aeea72015-04-23 10:54:45 -0700536static void server_start_transport_op(grpc_call_element *elem,
537 grpc_transport_op *op) {
Craig Tiller50d9db52015-04-23 10:52:14 -0700538 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
539 server_mutate_op(elem, op);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700540 grpc_call_next_op(elem, op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800541}
542
ctillerf962f522014-12-10 15:28:27 -0800543static void channel_op(grpc_channel_element *elem,
544 grpc_channel_element *from_elem, grpc_channel_op *op) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800545 channel_data *chand = elem->channel_data;
Craig Tiller8b976d02015-02-05 21:41:23 -0800546 grpc_server *server = chand->server;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800547
548 switch (op->type) {
549 case GRPC_ACCEPT_CALL:
550 /* create a call */
Craig Tillerfb189f82015-02-03 12:07:07 -0800551 grpc_call_create(chand->channel, NULL,
Craig Tiller87d5b192015-04-16 14:37:57 -0700552 op->data.accept_call.transport_server_data, NULL, 0,
553 gpr_inf_future);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800554 break;
555 case GRPC_TRANSPORT_CLOSED:
556 /* if the transport is closed for a server channel, we destroy the
557 channel */
Vijay Pai8931cdd2015-06-17 12:42:17 -0700558 gpr_mu_lock(&server->mu_global);
Craig Tiller8b976d02015-02-05 21:41:23 -0800559 server_ref(server);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800560 destroy_channel(chand);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700561 gpr_mu_unlock(&server->mu_global);
Craig Tiller8b976d02015-02-05 21:41:23 -0800562 server_unref(server);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800563 break;
nnoble0c475f02014-12-05 15:37:39 -0800564 case GRPC_TRANSPORT_GOAWAY:
565 gpr_slice_unref(op->data.goaway.message);
566 break;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800567 default:
568 GPR_ASSERT(op->dir == GRPC_CALL_DOWN);
569 grpc_channel_next_op(elem, op);
570 break;
571 }
572}
573
Craig Tillerb76d05b2015-05-29 17:21:56 -0700574typedef struct {
575 channel_data *chand;
576 int send_goaway;
577 int send_disconnect;
Craig Tiller668e3582015-06-01 21:21:42 -0700578 grpc_iomgr_closure finish_shutdown_channel_closure;
Craig Tillerb76d05b2015-05-29 17:21:56 -0700579} shutdown_channel_args;
580
581static void finish_shutdown_channel(void *p, int success) {
582 shutdown_channel_args *sca = p;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800583 grpc_channel_op op;
Craig Tillerb76d05b2015-05-29 17:21:56 -0700584
585 if (sca->send_goaway) {
586 op.type = GRPC_CHANNEL_GOAWAY;
587 op.dir = GRPC_CALL_DOWN;
588 op.data.goaway.status = GRPC_STATUS_OK;
589 op.data.goaway.message = gpr_slice_from_copied_string("Server shutdown");
590 channel_op(grpc_channel_stack_element(
591 grpc_channel_get_channel_stack(sca->chand->channel), 0),
592 NULL, &op);
593 }
594 if (sca->send_disconnect) {
595 op.type = GRPC_CHANNEL_DISCONNECT;
596 op.dir = GRPC_CALL_DOWN;
597 channel_op(grpc_channel_stack_element(
598 grpc_channel_get_channel_stack(sca->chand->channel), 0),
599 NULL, &op);
600 }
Craig Tiller9ec2a522015-05-29 22:46:54 -0700601 GRPC_CHANNEL_INTERNAL_UNREF(sca->chand->channel, "shutdown");
Craig Tillerfe020aa2015-06-01 09:18:50 -0700602
603 gpr_free(sca);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800604}
605
Craig Tiller8674cb12015-06-05 07:09:25 -0700606static void shutdown_channel(channel_data *chand, int send_goaway,
607 int send_disconnect) {
Craig Tillerb76d05b2015-05-29 17:21:56 -0700608 shutdown_channel_args *sca;
Craig Tiller9ec2a522015-05-29 22:46:54 -0700609 GRPC_CHANNEL_INTERNAL_REF(chand->channel, "shutdown");
Craig Tillerb76d05b2015-05-29 17:21:56 -0700610 sca = gpr_malloc(sizeof(shutdown_channel_args));
611 sca->chand = chand;
612 sca->send_goaway = send_goaway;
613 sca->send_disconnect = send_disconnect;
Craig Tiller668e3582015-06-01 21:21:42 -0700614 sca->finish_shutdown_channel_closure.cb = finish_shutdown_channel;
615 sca->finish_shutdown_channel_closure.cb_arg = sca;
616 grpc_iomgr_add_callback(&sca->finish_shutdown_channel_closure);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800617}
618
619static void init_call_elem(grpc_call_element *elem,
Craig Tiller06aeea72015-04-23 10:54:45 -0700620 const void *server_transport_data,
621 grpc_transport_op *initial_op) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800622 call_data *calld = elem->call_data;
623 channel_data *chand = elem->channel_data;
624 memset(calld, 0, sizeof(call_data));
625 calld->deadline = gpr_inf_future;
626 calld->call = grpc_call_from_top_element(elem);
627
Vijay Pai8931cdd2015-06-17 12:42:17 -0700628 gpr_mu_lock(&chand->server->mu_call);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800629 call_list_join(&chand->server->lists[ALL_CALLS], calld, ALL_CALLS);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700630 gpr_mu_unlock(&chand->server->mu_call);
631
632 gpr_mu_lock(&chand->server->mu_global);
Craig Tillerb76d05b2015-05-29 17:21:56 -0700633 chand->num_calls++;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700634 gpr_mu_unlock(&chand->server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800635
636 server_ref(chand->server);
Craig Tiller50d9db52015-04-23 10:52:14 -0700637
Craig Tiller482ef8b2015-04-23 11:38:20 -0700638 if (initial_op) server_mutate_op(elem, initial_op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800639}
640
641static void destroy_call_elem(grpc_call_element *elem) {
642 channel_data *chand = elem->channel_data;
Craig Tillerdb7db992015-01-29 11:19:01 -0800643 call_data *calld = elem->call_data;
Craig Tilleree945e82015-05-26 16:15:34 -0700644 int removed[CALL_LIST_COUNT];
Craig Tillerdc627722015-05-26 15:27:02 -0700645 size_t i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800646
Vijay Pai8931cdd2015-06-17 12:42:17 -0700647 gpr_mu_lock(&chand->server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800648 for (i = 0; i < CALL_LIST_COUNT; i++) {
Craig Tilleree945e82015-05-26 16:15:34 -0700649 removed[i] = call_list_remove(elem->call_data, i);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800650 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700651 gpr_mu_unlock(&chand->server->mu_call);
652 gpr_mu_lock(&chand->server->mu_global);
Craig Tilleree945e82015-05-26 16:15:34 -0700653 if (removed[ALL_CALLS]) {
Craig Tillerc4a1f522015-05-29 22:32:04 -0700654 decrement_call_count(chand);
Craig Tilleree945e82015-05-26 16:15:34 -0700655 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700656 gpr_mu_unlock(&chand->server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800657
Craig Tiller4df31a62015-01-30 09:44:31 -0800658 if (calld->host) {
659 grpc_mdstr_unref(calld->host);
660 }
661 if (calld->path) {
662 grpc_mdstr_unref(calld->path);
663 }
664
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800665 server_unref(chand->server);
666}
667
668static void init_channel_elem(grpc_channel_element *elem,
669 const grpc_channel_args *args,
670 grpc_mdctx *metadata_context, int is_first,
671 int is_last) {
672 channel_data *chand = elem->channel_data;
673 GPR_ASSERT(is_first);
674 GPR_ASSERT(!is_last);
675 chand->server = NULL;
Craig Tillerb76d05b2015-05-29 17:21:56 -0700676 chand->num_calls = 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800677 chand->channel = NULL;
Craig Tillercce17ac2015-01-20 09:29:28 -0800678 chand->path_key = grpc_mdstr_from_string(metadata_context, ":path");
679 chand->authority_key = grpc_mdstr_from_string(metadata_context, ":authority");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800680 chand->next = chand->prev = chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800681 chand->registered_methods = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800682}
683
684static void destroy_channel_elem(grpc_channel_element *elem) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800685 size_t i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800686 channel_data *chand = elem->channel_data;
Craig Tillerec3257c2015-02-12 15:59:43 -0800687 if (chand->registered_methods) {
688 for (i = 0; i < chand->registered_method_slots; i++) {
689 if (chand->registered_methods[i].method) {
690 grpc_mdstr_unref(chand->registered_methods[i].method);
691 }
692 if (chand->registered_methods[i].host) {
693 grpc_mdstr_unref(chand->registered_methods[i].host);
694 }
695 }
696 gpr_free(chand->registered_methods);
697 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800698 if (chand->server) {
Vijay Pai8931cdd2015-06-17 12:42:17 -0700699 gpr_mu_lock(&chand->server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800700 chand->next->prev = chand->prev;
701 chand->prev->next = chand->next;
702 chand->next = chand->prev = chand;
Craig Tillerb76d05b2015-05-29 17:21:56 -0700703 maybe_finish_shutdown(chand->server);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700704 gpr_mu_unlock(&chand->server->mu_global);
Craig Tillercce17ac2015-01-20 09:29:28 -0800705 grpc_mdstr_unref(chand->path_key);
706 grpc_mdstr_unref(chand->authority_key);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800707 server_unref(chand->server);
708 }
709}
710
711static const grpc_channel_filter server_surface_filter = {
Craig Tillerb76d05b2015-05-29 17:21:56 -0700712 server_start_transport_op,
713 channel_op,
714 sizeof(call_data),
715 init_call_elem,
716 destroy_call_elem,
717 sizeof(channel_data),
718 init_channel_elem,
719 destroy_channel_elem,
720 "server",
Craig Tiller9f28ac22015-01-27 17:01:29 -0800721};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800722
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700723void grpc_server_register_completion_queue(grpc_server *server,
724 grpc_completion_queue *cq) {
Craig Tiller20bc56d2015-02-12 09:02:56 -0800725 size_t i, n;
726 for (i = 0; i < server->cq_count; i++) {
727 if (server->cqs[i] == cq) return;
728 }
Craig Tiller463f2372015-05-28 16:16:15 -0700729 GRPC_CQ_INTERNAL_REF(cq, "server");
Craig Tillerb56975c2015-06-15 10:11:16 -0700730 grpc_cq_mark_server_cq(cq);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800731 n = server->cq_count++;
Craig Tillerec3257c2015-02-12 15:59:43 -0800732 server->cqs = gpr_realloc(server->cqs,
733 server->cq_count * sizeof(grpc_completion_queue *));
Craig Tiller20bc56d2015-02-12 09:02:56 -0800734 server->cqs[n] = cq;
735}
736
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700737grpc_server *grpc_server_create_from_filters(grpc_channel_filter **filters,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800738 size_t filter_count,
739 const grpc_channel_args *args) {
740 size_t i;
Alistair Veitch9d48ebf2015-06-01 10:01:03 -0700741 /* TODO(census): restore this once we finalize census filter etc.
742 int census_enabled = grpc_channel_args_is_census_enabled(args); */
743 int census_enabled = 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800744
745 grpc_server *server = gpr_malloc(sizeof(grpc_server));
Craig Tiller60fd3612015-03-05 16:24:22 -0800746
747 GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
748
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800749 memset(server, 0, sizeof(grpc_server));
750
Vijay Pai8931cdd2015-06-17 12:42:17 -0700751 gpr_mu_init(&server->mu_global);
752 gpr_mu_init(&server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800753
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800754 /* decremented by grpc_server_destroy */
755 gpr_ref_init(&server->internal_refcount, 1);
756 server->root_channel_data.next = server->root_channel_data.prev =
757 &server->root_channel_data;
758
759 /* Server filter stack is:
760
761 server_surface_filter - for making surface API calls
762 grpc_server_census_filter (optional) - for stats collection and tracing
763 {passed in filter stack}
764 grpc_connected_channel_filter - for interfacing with transports */
765 server->channel_filter_count = filter_count + 1 + census_enabled;
766 server->channel_filters =
767 gpr_malloc(server->channel_filter_count * sizeof(grpc_channel_filter *));
768 server->channel_filters[0] = &server_surface_filter;
Alistair Veitch9d48ebf2015-06-01 10:01:03 -0700769 /* TODO(census): restore this once we rework census filter
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800770 if (census_enabled) {
771 server->channel_filters[1] = &grpc_server_census_filter;
Alistair Veitch9686dab2015-05-26 14:26:47 -0700772 } */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800773 for (i = 0; i < filter_count; i++) {
774 server->channel_filters[i + 1 + census_enabled] = filters[i];
775 }
776
777 server->channel_args = grpc_channel_args_copy(args);
778
779 return server;
780}
781
Craig Tiller24be0f72015-02-10 14:04:22 -0800782static int streq(const char *a, const char *b) {
783 if (a == NULL && b == NULL) return 1;
784 if (a == NULL) return 0;
785 if (b == NULL) return 0;
786 return 0 == strcmp(a, b);
787}
788
789void *grpc_server_register_method(grpc_server *server, const char *method,
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700790 const char *host) {
Craig Tiller24be0f72015-02-10 14:04:22 -0800791 registered_method *m;
792 if (!method) {
Craig Tillerb76d05b2015-05-29 17:21:56 -0700793 gpr_log(GPR_ERROR,
794 "grpc_server_register_method method string cannot be NULL");
Craig Tiller24be0f72015-02-10 14:04:22 -0800795 return NULL;
796 }
797 for (m = server->registered_methods; m; m = m->next) {
798 if (streq(m->method, method) && streq(m->host, host)) {
799 gpr_log(GPR_ERROR, "duplicate registration for %s@%s", method,
800 host ? host : "*");
801 return NULL;
802 }
803 }
804 m = gpr_malloc(sizeof(registered_method));
805 memset(m, 0, sizeof(*m));
806 m->method = gpr_strdup(method);
807 m->host = gpr_strdup(host);
808 m->next = server->registered_methods;
809 server->registered_methods = m;
810 return m;
811}
812
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800813void grpc_server_start(grpc_server *server) {
814 listener *l;
Craig Tiller20bc56d2015-02-12 09:02:56 -0800815 size_t i;
816
Craig Tillerec3257c2015-02-12 15:59:43 -0800817 server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800818 for (i = 0; i < server->cq_count; i++) {
819 server->pollsets[i] = grpc_cq_pollset(server->cqs[i]);
820 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800821
822 for (l = server->listeners; l; l = l->next) {
Craig Tiller20bc56d2015-02-12 09:02:56 -0800823 l->start(server, l->arg, server->pollsets, server->cq_count);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800824 }
825}
826
827grpc_transport_setup_result grpc_server_setup_transport(
828 grpc_server *s, grpc_transport *transport,
829 grpc_channel_filter const **extra_filters, size_t num_extra_filters,
Julien Boeufc6f8d0a2015-05-11 22:40:02 -0700830 grpc_mdctx *mdctx, const grpc_channel_args *args) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800831 size_t num_filters = s->channel_filter_count + num_extra_filters + 1;
832 grpc_channel_filter const **filters =
833 gpr_malloc(sizeof(grpc_channel_filter *) * num_filters);
834 size_t i;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800835 size_t num_registered_methods;
836 size_t alloc;
837 registered_method *rm;
838 channel_registered_method *crm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800839 grpc_channel *channel;
840 channel_data *chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800841 grpc_mdstr *host;
842 grpc_mdstr *method;
843 gpr_uint32 hash;
844 gpr_uint32 slots;
845 gpr_uint32 probes;
846 gpr_uint32 max_probes = 0;
Craig Tiller5d6bd442015-02-12 22:50:38 -0800847 grpc_transport_setup_result result;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800848
849 for (i = 0; i < s->channel_filter_count; i++) {
850 filters[i] = s->channel_filters[i];
851 }
852 for (; i < s->channel_filter_count + num_extra_filters; i++) {
853 filters[i] = extra_filters[i - s->channel_filter_count];
854 }
855 filters[i] = &grpc_connected_channel_filter;
856
Craig Tiller20bc56d2015-02-12 09:02:56 -0800857 for (i = 0; i < s->cq_count; i++) {
858 grpc_transport_add_to_pollset(transport, grpc_cq_pollset(s->cqs[i]));
859 }
ctillerd79b4862014-12-17 16:36:59 -0800860
Julien Boeufc6f8d0a2015-05-11 22:40:02 -0700861 channel =
862 grpc_channel_create_from_filters(filters, num_filters, args, mdctx, 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800863 chand = (channel_data *)grpc_channel_stack_element(
Craig Tillerc02c1d82015-04-07 16:21:55 -0700864 grpc_channel_get_channel_stack(channel), 0)
865 ->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800866 chand->server = s;
867 server_ref(s);
868 chand->channel = channel;
869
Craig Tiller04cc8be2015-02-10 16:11:22 -0800870 num_registered_methods = 0;
871 for (rm = s->registered_methods; rm; rm = rm->next) {
872 num_registered_methods++;
873 }
874 /* build a lookup table phrased in terms of mdstr's in this channels context
875 to quickly find registered methods */
876 if (num_registered_methods > 0) {
877 slots = 2 * num_registered_methods;
878 alloc = sizeof(channel_registered_method) * slots;
879 chand->registered_methods = gpr_malloc(alloc);
880 memset(chand->registered_methods, 0, alloc);
881 for (rm = s->registered_methods; rm; rm = rm->next) {
882 host = rm->host ? grpc_mdstr_from_string(mdctx, rm->host) : NULL;
Craig Tillere76c9662015-02-11 13:18:31 -0800883 method = grpc_mdstr_from_string(mdctx, rm->method);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800884 hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash);
Craig Tiller3b29b562015-02-11 12:58:46 -0800885 for (probes = 0; chand->registered_methods[(hash + probes) % slots]
Craig Tillerc02c1d82015-04-07 16:21:55 -0700886 .server_registered_method != NULL;
Craig Tiller3b29b562015-02-11 12:58:46 -0800887 probes++)
888 ;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800889 if (probes > max_probes) max_probes = probes;
890 crm = &chand->registered_methods[(hash + probes) % slots];
891 crm->server_registered_method = rm;
892 crm->host = host;
893 crm->method = method;
894 }
895 chand->registered_method_slots = slots;
896 chand->registered_method_max_probes = max_probes;
897 }
898
Craig Tiller5d6bd442015-02-12 22:50:38 -0800899 result = grpc_connected_channel_bind_transport(
900 grpc_channel_get_channel_stack(channel), transport);
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800901
Vijay Pai8931cdd2015-06-17 12:42:17 -0700902 gpr_mu_lock(&s->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800903 chand->next = &s->root_channel_data;
904 chand->prev = chand->next->prev;
905 chand->next->prev = chand->prev->next = chand;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700906 gpr_mu_unlock(&s->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800907
908 gpr_free(filters);
909
Craig Tiller5d6bd442015-02-12 22:50:38 -0800910 return result;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800911}
912
Craig Tillerbce999f2015-05-27 09:55:51 -0700913void grpc_server_shutdown_and_notify(grpc_server *server,
914 grpc_completion_queue *cq, void *tag) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800915 listener *l;
Craig Tiller24be0f72015-02-10 14:04:22 -0800916 requested_call_array requested_calls;
nnoble0c475f02014-12-05 15:37:39 -0800917 channel_data *c;
Craig Tillerdc627722015-05-26 15:27:02 -0700918 size_t i;
Craig Tillerbd217572015-02-11 18:10:56 -0800919 registered_method *rm;
Craig Tillerbce999f2015-05-27 09:55:51 -0700920 shutdown_tag *sdt;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800921
922 /* lock, and gather up some stuff to do */
Vijay Pai8931cdd2015-06-17 12:42:17 -0700923 gpr_mu_lock(&server->mu_global);
Craig Tiller29f79dc2015-05-27 15:59:23 -0700924 grpc_cq_begin_op(cq, NULL);
Craig Tilleree945e82015-05-26 16:15:34 -0700925 server->shutdown_tags =
926 gpr_realloc(server->shutdown_tags,
Craig Tiller208d2122015-05-29 08:50:08 -0700927 sizeof(shutdown_tag) * (server->num_shutdown_tags + 1));
Craig Tillerbce999f2015-05-27 09:55:51 -0700928 sdt = &server->shutdown_tags[server->num_shutdown_tags++];
929 sdt->tag = tag;
930 sdt->cq = cq;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800931 if (server->shutdown) {
Vijay Pai8931cdd2015-06-17 12:42:17 -0700932 gpr_mu_unlock(&server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800933 return;
934 }
935
nnoble0c475f02014-12-05 15:37:39 -0800936 for (c = server->root_channel_data.next; c != &server->root_channel_data;
937 c = c->next) {
Craig Tillerb76d05b2015-05-29 17:21:56 -0700938 shutdown_channel(c, 1, c->num_calls == 0);
nnoble0c475f02014-12-05 15:37:39 -0800939 }
940
Craig Tillerbd217572015-02-11 18:10:56 -0800941 /* collect all unregistered then registered calls */
Vijay Pai8931cdd2015-06-17 12:42:17 -0700942 gpr_mu_lock(&server->mu_call);
Craig Tillercce17ac2015-01-20 09:29:28 -0800943 requested_calls = server->requested_calls;
Craig Tiller24be0f72015-02-10 14:04:22 -0800944 memset(&server->requested_calls, 0, sizeof(server->requested_calls));
Craig Tillerbd217572015-02-11 18:10:56 -0800945 for (rm = server->registered_methods; rm; rm = rm->next) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800946 if (requested_calls.count + rm->requested.count >
947 requested_calls.capacity) {
948 requested_calls.capacity =
949 GPR_MAX(requested_calls.count + rm->requested.count,
950 2 * requested_calls.capacity);
951 requested_calls.calls =
952 gpr_realloc(requested_calls.calls, sizeof(*requested_calls.calls) *
953 requested_calls.capacity);
Craig Tillerbd217572015-02-11 18:10:56 -0800954 }
Craig Tillerec3257c2015-02-12 15:59:43 -0800955 memcpy(requested_calls.calls + requested_calls.count, rm->requested.calls,
956 sizeof(*requested_calls.calls) * rm->requested.count);
Craig Tillerbd217572015-02-11 18:10:56 -0800957 requested_calls.count += rm->requested.count;
Craig Tillerec3257c2015-02-12 15:59:43 -0800958 gpr_free(rm->requested.calls);
Craig Tillerbd217572015-02-11 18:10:56 -0800959 memset(&rm->requested, 0, sizeof(rm->requested));
960 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700961 gpr_mu_unlock(&server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800962
963 server->shutdown = 1;
Craig Tillerdc627722015-05-26 15:27:02 -0700964 maybe_finish_shutdown(server);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700965 gpr_mu_unlock(&server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800966
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800967 /* terminate all the requested calls */
Craig Tiller24be0f72015-02-10 14:04:22 -0800968 for (i = 0; i < requested_calls.count; i++) {
969 fail_call(server, &requested_calls.calls[i]);
Craig Tillercce17ac2015-01-20 09:29:28 -0800970 }
Craig Tiller24be0f72015-02-10 14:04:22 -0800971 gpr_free(requested_calls.calls);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800972
973 /* Shutdown listeners */
974 for (l = server->listeners; l; l = l->next) {
975 l->destroy(server, l->arg);
976 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800977}
978
Craig Tilleraec96aa2015-04-07 14:32:15 -0700979void grpc_server_listener_destroy_done(void *s) {
980 grpc_server *server = s;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700981 gpr_mu_lock(&server->mu_global);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700982 server->listeners_destroyed++;
Craig Tilleree945e82015-05-26 16:15:34 -0700983 maybe_finish_shutdown(server);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700984 gpr_mu_unlock(&server->mu_global);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700985}
986
Craig Tillerafa2d632015-05-26 16:39:13 -0700987void grpc_server_cancel_all_calls(grpc_server *server) {
988 call_data *calld;
989 grpc_call **calls;
990 size_t call_count;
991 size_t call_capacity;
992 int is_first = 1;
993 size_t i;
994
Vijay Pai8931cdd2015-06-17 12:42:17 -0700995 gpr_mu_lock(&server->mu_call);
Craig Tillerafa2d632015-05-26 16:39:13 -0700996
997 GPR_ASSERT(server->shutdown);
998
999 if (!server->lists[ALL_CALLS]) {
Vijay Pai8931cdd2015-06-17 12:42:17 -07001000 gpr_mu_unlock(&server->mu_call);
Craig Tillerafa2d632015-05-26 16:39:13 -07001001 return;
1002 }
1003
1004 call_capacity = 8;
1005 call_count = 0;
1006 calls = gpr_malloc(sizeof(grpc_call *) * call_capacity);
1007
Craig Tillerb76d05b2015-05-29 17:21:56 -07001008 for (calld = server->lists[ALL_CALLS];
1009 calld != server->lists[ALL_CALLS] || is_first;
1010 calld = calld->links[ALL_CALLS].next) {
Craig Tillerafa2d632015-05-26 16:39:13 -07001011 if (call_count == call_capacity) {
1012 call_capacity *= 2;
1013 calls = gpr_realloc(calls, sizeof(grpc_call *) * call_capacity);
1014 }
1015 calls[call_count++] = calld->call;
1016 GRPC_CALL_INTERNAL_REF(calld->call, "cancel_all");
1017 is_first = 0;
1018 }
1019
Vijay Pai8931cdd2015-06-17 12:42:17 -07001020 gpr_mu_unlock(&server->mu_call);
Craig Tillerafa2d632015-05-26 16:39:13 -07001021
1022 for (i = 0; i < call_count; i++) {
Craig Tillerb76d05b2015-05-29 17:21:56 -07001023 grpc_call_cancel_with_status(calls[i], GRPC_STATUS_UNAVAILABLE,
1024 "Unavailable");
Craig Tillerafa2d632015-05-26 16:39:13 -07001025 GRPC_CALL_INTERNAL_UNREF(calls[i], "cancel_all", 1);
1026 }
1027
1028 gpr_free(calls);
1029}
1030
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001031void grpc_server_destroy(grpc_server *server) {
Craig Tilleraec96aa2015-04-07 14:32:15 -07001032 listener *l;
Craig Tiller872af022015-04-24 15:57:52 -07001033
Vijay Pai8931cdd2015-06-17 12:42:17 -07001034 gpr_mu_lock(&server->mu_global);
Masood Malekghassemi38bb18f2015-06-10 17:32:02 -07001035 GPR_ASSERT(server->shutdown || !server->listeners);
Craig Tilleree945e82015-05-26 16:15:34 -07001036 GPR_ASSERT(server->listeners_destroyed == num_listeners(server));
Craig Tilleraec96aa2015-04-07 14:32:15 -07001037
1038 while (server->listeners) {
1039 l = server->listeners;
1040 server->listeners = l->next;
1041 gpr_free(l);
1042 }
1043
Vijay Pai8931cdd2015-06-17 12:42:17 -07001044 gpr_mu_unlock(&server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001045
1046 server_unref(server);
1047}
1048
1049void grpc_server_add_listener(grpc_server *server, void *arg,
ctiller58393c22015-01-07 14:03:30 -08001050 void (*start)(grpc_server *server, void *arg,
Craig Tillerec3257c2015-02-12 15:59:43 -08001051 grpc_pollset **pollsets,
1052 size_t pollset_count),
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001053 void (*destroy)(grpc_server *server, void *arg)) {
1054 listener *l = gpr_malloc(sizeof(listener));
1055 l->arg = arg;
1056 l->start = start;
1057 l->destroy = destroy;
1058 l->next = server->listeners;
1059 server->listeners = l;
1060}
1061
Craig Tiller9f28ac22015-01-27 17:01:29 -08001062static grpc_call_error queue_call_request(grpc_server *server,
Craig Tiller24be0f72015-02-10 14:04:22 -08001063 requested_call *rc) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001064 call_data *calld = NULL;
Craig Tiller0ef1a922015-02-11 16:23:01 -08001065 requested_call_array *requested_calls = NULL;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001066 gpr_mu_lock(&server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001067 if (server->shutdown) {
Vijay Pai8931cdd2015-06-17 12:42:17 -07001068 gpr_mu_unlock(&server->mu_call);
Craig Tiller24be0f72015-02-10 14:04:22 -08001069 fail_call(server, rc);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001070 return GRPC_CALL_OK;
1071 }
Craig Tiller04cc8be2015-02-10 16:11:22 -08001072 switch (rc->type) {
Craig Tiller04cc8be2015-02-10 16:11:22 -08001073 case BATCH_CALL:
Craig Tiller3b29b562015-02-11 12:58:46 -08001074 calld =
1075 call_list_remove_head(&server->lists[PENDING_START], PENDING_START);
Craig Tiller0ef1a922015-02-11 16:23:01 -08001076 requested_calls = &server->requested_calls;
Craig Tiller04cc8be2015-02-10 16:11:22 -08001077 break;
1078 case REGISTERED_CALL:
Craig Tiller3b29b562015-02-11 12:58:46 -08001079 calld = call_list_remove_head(
1080 &rc->data.registered.registered_method->pending, PENDING_START);
Craig Tiller0ef1a922015-02-11 16:23:01 -08001081 requested_calls = &rc->data.registered.registered_method->requested;
Craig Tiller04cc8be2015-02-10 16:11:22 -08001082 break;
1083 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001084 if (calld) {
Craig Tillercce17ac2015-01-20 09:29:28 -08001085 GPR_ASSERT(calld->state == PENDING);
Craig Tillerbb3f22f2015-01-29 16:40:56 -08001086 calld->state = ACTIVATED;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001087 gpr_mu_unlock(&server->mu_call);
Craig Tiller24be0f72015-02-10 14:04:22 -08001088 begin_call(server, calld, rc);
Craig Tillercce17ac2015-01-20 09:29:28 -08001089 return GRPC_CALL_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001090 } else {
Craig Tiller0ef1a922015-02-11 16:23:01 -08001091 *requested_call_array_add(requested_calls) = *rc;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001092 gpr_mu_unlock(&server->mu_call);
Craig Tillercce17ac2015-01-20 09:29:28 -08001093 return GRPC_CALL_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001094 }
Craig Tillercce17ac2015-01-20 09:29:28 -08001095}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001096
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001097grpc_call_error grpc_server_request_call(
1098 grpc_server *server, grpc_call **call, grpc_call_details *details,
1099 grpc_metadata_array *initial_metadata,
1100 grpc_completion_queue *cq_bound_to_call,
1101 grpc_completion_queue *cq_for_notification, void *tag) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001102 requested_call rc;
murgatroid99ad7c20c2015-05-22 14:42:29 -07001103 GRPC_SERVER_LOG_REQUEST_CALL(GPR_INFO, server, call, details,
1104 initial_metadata, cq_bound_to_call,
1105 cq_for_notification, tag);
Craig Tillerb56975c2015-06-15 10:11:16 -07001106 if (!grpc_cq_is_server_cq(cq_for_notification)) {
1107 return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
1108 }
Craig Tiller54478f82015-05-12 14:08:56 -07001109 grpc_cq_begin_op(cq_for_notification, NULL);
Craig Tiller24be0f72015-02-10 14:04:22 -08001110 rc.type = BATCH_CALL;
1111 rc.tag = tag;
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001112 rc.cq_bound_to_call = cq_bound_to_call;
1113 rc.cq_for_notification = cq_for_notification;
1114 rc.call = call;
Craig Tiller24be0f72015-02-10 14:04:22 -08001115 rc.data.batch.details = details;
1116 rc.data.batch.initial_metadata = initial_metadata;
1117 return queue_call_request(server, &rc);
1118}
1119
1120grpc_call_error grpc_server_request_registered_call(
Craig Tillerec3257c2015-02-12 15:59:43 -08001121 grpc_server *server, void *rm, grpc_call **call, gpr_timespec *deadline,
1122 grpc_metadata_array *initial_metadata, grpc_byte_buffer **optional_payload,
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001123 grpc_completion_queue *cq_bound_to_call,
1124 grpc_completion_queue *cq_for_notification, void *tag) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001125 requested_call rc;
Craig Tiller20bc56d2015-02-12 09:02:56 -08001126 registered_method *registered_method = rm;
Craig Tillerb56975c2015-06-15 10:11:16 -07001127 if (!grpc_cq_is_server_cq(cq_for_notification)) {
1128 return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
1129 }
Craig Tiller54478f82015-05-12 14:08:56 -07001130 grpc_cq_begin_op(cq_for_notification, NULL);
Craig Tiller24be0f72015-02-10 14:04:22 -08001131 rc.type = REGISTERED_CALL;
1132 rc.tag = tag;
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001133 rc.cq_bound_to_call = cq_bound_to_call;
1134 rc.cq_for_notification = cq_for_notification;
1135 rc.call = call;
Craig Tiller24be0f72015-02-10 14:04:22 -08001136 rc.data.registered.registered_method = registered_method;
1137 rc.data.registered.deadline = deadline;
1138 rc.data.registered.initial_metadata = initial_metadata;
1139 rc.data.registered.optional_payload = optional_payload;
1140 return queue_call_request(server, &rc);
1141}
1142
Craig Tiller64be9f72015-05-04 14:53:51 -07001143static void publish_registered_or_batch(grpc_call *call, int success,
Craig Tiller24be0f72015-02-10 14:04:22 -08001144 void *tag);
Craig Tiller64be9f72015-05-04 14:53:51 -07001145static void publish_was_not_set(grpc_call *call, int success, void *tag) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001146 abort();
1147}
Craig Tiller24be0f72015-02-10 14:04:22 -08001148
Craig Tiller166e2502015-02-03 20:14:41 -08001149static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
1150 gpr_slice slice = value->slice;
1151 size_t len = GPR_SLICE_LENGTH(slice);
1152
1153 if (len + 1 > *capacity) {
1154 *capacity = GPR_MAX(len + 1, *capacity * 2);
1155 *dest = gpr_realloc(*dest, *capacity);
1156 }
1157 memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
1158}
1159
Craig Tiller24be0f72015-02-10 14:04:22 -08001160static void begin_call(grpc_server *server, call_data *calld,
1161 requested_call *rc) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001162 grpc_ioreq_completion_func publish = publish_was_not_set;
Craig Tiller24be0f72015-02-10 14:04:22 -08001163 grpc_ioreq req[2];
1164 grpc_ioreq *r = req;
1165
1166 /* called once initial metadata has been read by the call, but BEFORE
1167 the ioreq to fetch it out of the call has been executed.
1168 This means metadata related fields can be relied on in calld, but to
1169 fill in the metadata array passed by the client, we need to perform
1170 an ioreq op, that should complete immediately. */
1171
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001172 grpc_call_set_completion_queue(calld->call, rc->cq_bound_to_call);
1173 *rc->call = calld->call;
1174 calld->cq_new = rc->cq_for_notification;
Craig Tiller24be0f72015-02-10 14:04:22 -08001175 switch (rc->type) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001176 case BATCH_CALL:
1177 cpstr(&rc->data.batch.details->host,
1178 &rc->data.batch.details->host_capacity, calld->host);
1179 cpstr(&rc->data.batch.details->method,
1180 &rc->data.batch.details->method_capacity, calld->path);
Masood Malekghassemibf177c82015-04-27 12:14:38 -07001181 rc->data.batch.details->deadline = calld->deadline;
Craig Tiller24be0f72015-02-10 14:04:22 -08001182 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1183 r->data.recv_metadata = rc->data.batch.initial_metadata;
David Garcia Quintasb8f54502015-06-15 16:19:10 -07001184 r->flags = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001185 r++;
1186 publish = publish_registered_or_batch;
1187 break;
1188 case REGISTERED_CALL:
1189 *rc->data.registered.deadline = calld->deadline;
Craig Tiller24be0f72015-02-10 14:04:22 -08001190 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1191 r->data.recv_metadata = rc->data.registered.initial_metadata;
David Garcia Quintasb8f54502015-06-15 16:19:10 -07001192 r->flags = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001193 r++;
1194 if (rc->data.registered.optional_payload) {
1195 r->op = GRPC_IOREQ_RECV_MESSAGE;
1196 r->data.recv_message = rc->data.registered.optional_payload;
David Garcia Quintasb8f54502015-06-15 16:19:10 -07001197 r->flags = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001198 r++;
1199 }
1200 publish = publish_registered_or_batch;
1201 break;
1202 }
1203
Craig Tiller4df412b2015-04-28 07:57:54 -07001204 GRPC_CALL_INTERNAL_REF(calld->call, "server");
Craig Tiller24be0f72015-02-10 14:04:22 -08001205 grpc_call_start_ioreq_and_call_back(calld->call, req, r - req, publish,
1206 rc->tag);
1207}
1208
1209static void fail_call(grpc_server *server, requested_call *rc) {
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001210 *rc->call = NULL;
Craig Tiller24be0f72015-02-10 14:04:22 -08001211 switch (rc->type) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001212 case BATCH_CALL:
Craig Tiller24be0f72015-02-10 14:04:22 -08001213 rc->data.batch.initial_metadata->count = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001214 break;
1215 case REGISTERED_CALL:
Craig Tiller24be0f72015-02-10 14:04:22 -08001216 rc->data.registered.initial_metadata->count = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001217 break;
1218 }
Craig Tiller54478f82015-05-12 14:08:56 -07001219 grpc_cq_end_op(rc->cq_for_notification, rc->tag, NULL, 0);
Craig Tiller24be0f72015-02-10 14:04:22 -08001220}
1221
Craig Tiller64be9f72015-05-04 14:53:51 -07001222static void publish_registered_or_batch(grpc_call *call, int success,
Craig Tiller24be0f72015-02-10 14:04:22 -08001223 void *tag) {
Craig Tiller8e8fd892015-02-10 17:02:08 -08001224 grpc_call_element *elem =
1225 grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
Craig Tiller20bc56d2015-02-12 09:02:56 -08001226 call_data *calld = elem->call_data;
Craig Tiller64be9f72015-05-04 14:53:51 -07001227 grpc_cq_end_op(calld->cq_new, tag, call, success);
Craig Tiller24be0f72015-02-10 14:04:22 -08001228}
1229
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001230const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) {
1231 return server->channel_args;
Craig Tiller190d3602015-02-18 09:23:38 -08001232}
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001233
1234int grpc_server_has_open_connections(grpc_server *server) {
1235 int r;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001236 gpr_mu_lock(&server->mu_global);
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001237 r = server->root_channel_data.next != &server->root_channel_data;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001238 gpr_mu_unlock(&server->mu_global);
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001239 return r;
1240}