blob: 4053b220638985eaf15fb487f725abbccfbd5459 [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
Craig Tiller092d8d12015-07-04 22:35:00 -070054typedef enum { PENDING_START, CALL_LIST_COUNT } call_list;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080055
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 Tillere039f032015-06-25 12:54:23 -0700117 grpc_connectivity_state connectivity_state;
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;
Craig Tillere039f032015-06-25 12:54:23 -0700128 grpc_iomgr_closure channel_connectivity_changed;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800129};
130
Craig Tillerbce999f2015-05-27 09:55:51 -0700131typedef struct shutdown_tag {
132 void *tag;
133 grpc_completion_queue *cq;
134} shutdown_tag;
135
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800136struct grpc_server {
137 size_t channel_filter_count;
138 const grpc_channel_filter **channel_filters;
139 grpc_channel_args *channel_args;
Craig Tillerec3257c2015-02-12 15:59:43 -0800140
Craig Tiller20bc56d2015-02-12 09:02:56 -0800141 grpc_completion_queue **cqs;
142 grpc_pollset **pollsets;
143 size_t cq_count;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800144
Vijay Paid2a82d92015-06-17 13:42:46 -0700145 /* The two following mutexes control access to server-state
146 mu_global controls access to non-call-related state (e.g., channel state)
147 mu_call controls access to call-related state (e.g., the call lists)
148
149 If they are ever required to be nested, you must lock mu_global
150 before mu_call. This is currently used in shutdown processing
151 (grpc_server_shutdown_and_notify and maybe_finish_shutdown) */
152 gpr_mu mu_global; /* mutex for server and channel state */
Craig Tiller079a11b2015-06-30 10:07:15 -0700153 gpr_mu mu_call; /* mutex for call-specific state */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800154
Craig Tiller24be0f72015-02-10 14:04:22 -0800155 registered_method *registered_methods;
156 requested_call_array requested_calls;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800157
158 gpr_uint8 shutdown;
Craig Tiller29f79dc2015-05-27 15:59:23 -0700159 gpr_uint8 shutdown_published;
Craig Tilleraea2fc02015-02-17 16:54:53 -0800160 size_t num_shutdown_tags;
Craig Tillerbce999f2015-05-27 09:55:51 -0700161 shutdown_tag *shutdown_tags;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800162
163 call_data *lists[CALL_LIST_COUNT];
164 channel_data root_channel_data;
165
166 listener *listeners;
Craig Tilleraec96aa2015-04-07 14:32:15 -0700167 int listeners_destroyed;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800168 gpr_refcount internal_refcount;
Craig Tillerab54f792015-07-08 08:34:20 -0700169
170 /** when did we print the last shutdown progress message */
171 gpr_timespec last_shutdown_message_time;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800172};
173
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800174typedef enum {
175 /* waiting for metadata */
176 NOT_STARTED,
177 /* inital metadata read, not flow controlled in yet */
178 PENDING,
179 /* flow controlled in, on completion queue */
180 ACTIVATED,
181 /* cancelled before being queued */
182 ZOMBIED
183} call_state;
184
185struct call_data {
186 grpc_call *call;
187
188 call_state state;
Craig Tillercce17ac2015-01-20 09:29:28 -0800189 grpc_mdstr *path;
190 grpc_mdstr *host;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700191 gpr_timespec deadline;
192 int got_initial_metadata;
Craig Tillercce17ac2015-01-20 09:29:28 -0800193
Craig Tiller20bc56d2015-02-12 09:02:56 -0800194 grpc_completion_queue *cq_new;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800195
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700196 grpc_stream_op_buffer *recv_ops;
197 grpc_stream_state *recv_state;
Craig Tiller1e6facb2015-06-11 22:47:11 -0700198 grpc_iomgr_closure *on_done_recv;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700199
Craig Tiller1e6facb2015-06-11 22:47:11 -0700200 grpc_iomgr_closure server_on_recv;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700201 grpc_iomgr_closure kill_zombie_closure;
202
Craig Tiller04cc8be2015-02-10 16:11:22 -0800203 call_data **root[CALL_LIST_COUNT];
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800204 call_link links[CALL_LIST_COUNT];
205};
206
Craig Tillerff3ae682015-06-29 17:44:04 -0700207typedef struct {
208 grpc_channel **channels;
209 size_t num_channels;
210} channel_broadcaster;
211
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800212#define SERVER_FROM_CALL_ELEM(elem) \
213 (((channel_data *)(elem)->channel_data)->server)
214
Craig Tiller24be0f72015-02-10 14:04:22 -0800215static void begin_call(grpc_server *server, call_data *calld,
216 requested_call *rc);
217static void fail_call(grpc_server *server, requested_call *rc);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700218/* Before calling maybe_finish_shutdown, we must hold mu_global and not
219 hold mu_call */
Craig Tiller52760dd2015-05-29 23:09:26 -0700220static void maybe_finish_shutdown(grpc_server *server);
Craig Tiller24be0f72015-02-10 14:04:22 -0800221
Craig Tillerff3ae682015-06-29 17:44:04 -0700222/* channel broadcaster */
223
224/* assumes server locked */
225static void channel_broadcaster_init(grpc_server *s, channel_broadcaster *cb) {
226 channel_data *c;
227 size_t count = 0;
Craig Tiller079a11b2015-06-30 10:07:15 -0700228 for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) {
229 count++;
Craig Tillerff3ae682015-06-29 17:44:04 -0700230 }
231 cb->num_channels = count;
232 cb->channels = gpr_malloc(sizeof(*cb->channels) * cb->num_channels);
233 count = 0;
Craig Tiller079a11b2015-06-30 10:07:15 -0700234 for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) {
Craig Tiller49924e02015-06-29 22:42:33 -0700235 cb->channels[count++] = c->channel;
Craig Tillerff3ae682015-06-29 17:44:04 -0700236 GRPC_CHANNEL_INTERNAL_REF(c->channel, "broadcast");
Craig Tillerff3ae682015-06-29 17:44:04 -0700237 }
238}
239
240struct shutdown_cleanup_args {
241 grpc_iomgr_closure closure;
242 gpr_slice slice;
243};
244
245static void shutdown_cleanup(void *arg, int iomgr_status_ignored) {
246 struct shutdown_cleanup_args *a = arg;
247 gpr_slice_unref(a->slice);
248 gpr_free(a);
249}
250
Craig Tiller079a11b2015-06-30 10:07:15 -0700251static void send_shutdown(grpc_channel *channel, int send_goaway,
252 int send_disconnect) {
Craig Tillerff3ae682015-06-29 17:44:04 -0700253 grpc_transport_op op;
254 struct shutdown_cleanup_args *sc;
255 grpc_channel_element *elem;
256
257 memset(&op, 0, sizeof(op));
Craig Tillerff3ae682015-06-29 17:44:04 -0700258 op.send_goaway = send_goaway;
259 sc = gpr_malloc(sizeof(*sc));
260 sc->slice = gpr_slice_from_copied_string("Server shutdown");
261 op.goaway_message = &sc->slice;
262 op.goaway_status = GRPC_STATUS_OK;
263 op.disconnect = send_disconnect;
264 grpc_iomgr_closure_init(&sc->closure, shutdown_cleanup, sc);
265 op.on_consumed = &sc->closure;
266
Craig Tiller079a11b2015-06-30 10:07:15 -0700267 elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
Craig Tillerff3ae682015-06-29 17:44:04 -0700268 elem->filter->start_transport_op(elem, &op);
269}
270
Craig Tiller079a11b2015-06-30 10:07:15 -0700271static void channel_broadcaster_shutdown(channel_broadcaster *cb,
Craig Tiller092d8d12015-07-04 22:35:00 -0700272 int send_goaway, int force_disconnect) {
Craig Tillerff3ae682015-06-29 17:44:04 -0700273 size_t i;
274
275 for (i = 0; i < cb->num_channels; i++) {
Craig Tiller9188d7a2015-07-05 12:44:37 -0700276 send_shutdown(cb->channels[i], send_goaway, force_disconnect);
Craig Tillerff3ae682015-06-29 17:44:04 -0700277 GRPC_CHANNEL_INTERNAL_UNREF(cb->channels[i], "broadcast");
278 }
279 gpr_free(cb->channels);
280}
281
282/* call list */
283
Craig Tiller3b29b562015-02-11 12:58:46 -0800284static int call_list_join(call_data **root, call_data *call, call_list list) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800285 GPR_ASSERT(!call->root[list]);
286 call->root[list] = root;
287 if (!*root) {
288 *root = call;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800289 call->links[list].next = call->links[list].prev = call;
290 } else {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800291 call->links[list].next = *root;
292 call->links[list].prev = (*root)->links[list].prev;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800293 call->links[list].next->links[list].prev =
294 call->links[list].prev->links[list].next = call;
295 }
296 return 1;
297}
298
Craig Tiller04cc8be2015-02-10 16:11:22 -0800299static call_data *call_list_remove_head(call_data **root, call_list list) {
300 call_data *out = *root;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800301 if (out) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800302 out->root[list] = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800303 if (out->links[list].next == out) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800304 *root = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800305 } else {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800306 *root = out->links[list].next;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800307 out->links[list].next->links[list].prev = out->links[list].prev;
308 out->links[list].prev->links[list].next = out->links[list].next;
309 }
310 }
311 return out;
312}
313
Craig Tiller04cc8be2015-02-10 16:11:22 -0800314static int call_list_remove(call_data *call, call_list list) {
315 call_data **root = call->root[list];
316 if (root == NULL) return 0;
317 call->root[list] = NULL;
318 if (*root == call) {
319 *root = call->links[list].next;
320 if (*root == call) {
321 *root = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800322 return 1;
323 }
324 }
Craig Tiller04cc8be2015-02-10 16:11:22 -0800325 GPR_ASSERT(*root != call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800326 call->links[list].next->links[list].prev = call->links[list].prev;
327 call->links[list].prev->links[list].next = call->links[list].next;
328 return 1;
329}
330
Craig Tiller24be0f72015-02-10 14:04:22 -0800331static void requested_call_array_destroy(requested_call_array *array) {
332 gpr_free(array->calls);
333}
334
335static requested_call *requested_call_array_add(requested_call_array *array) {
336 requested_call *rc;
337 if (array->count == array->capacity) {
338 array->capacity = GPR_MAX(array->capacity + 8, array->capacity * 2);
339 array->calls =
340 gpr_realloc(array->calls, sizeof(requested_call) * array->capacity);
341 }
342 rc = &array->calls[array->count++];
343 memset(rc, 0, sizeof(*rc));
344 return rc;
345}
346
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800347static void server_ref(grpc_server *server) {
348 gpr_ref(&server->internal_refcount);
349}
350
Craig Tilleree945e82015-05-26 16:15:34 -0700351static void server_delete(grpc_server *server) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800352 registered_method *rm;
Craig Tiller89504612015-04-27 11:48:46 -0700353 size_t i;
Craig Tilleree945e82015-05-26 16:15:34 -0700354 grpc_channel_args_destroy(server->channel_args);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700355 gpr_mu_destroy(&server->mu_global);
356 gpr_mu_destroy(&server->mu_call);
Craig Tilleree945e82015-05-26 16:15:34 -0700357 gpr_free(server->channel_filters);
358 requested_call_array_destroy(&server->requested_calls);
359 while ((rm = server->registered_methods) != NULL) {
360 server->registered_methods = rm->next;
361 gpr_free(rm->method);
362 gpr_free(rm->host);
363 requested_call_array_destroy(&rm->requested);
364 gpr_free(rm);
365 }
366 for (i = 0; i < server->cq_count; i++) {
Craig Tiller463f2372015-05-28 16:16:15 -0700367 GRPC_CQ_INTERNAL_UNREF(server->cqs[i], "server");
Craig Tilleree945e82015-05-26 16:15:34 -0700368 }
369 gpr_free(server->cqs);
370 gpr_free(server->pollsets);
371 gpr_free(server->shutdown_tags);
372 gpr_free(server);
373}
374
375static void server_unref(grpc_server *server) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800376 if (gpr_unref(&server->internal_refcount)) {
Craig Tilleree945e82015-05-26 16:15:34 -0700377 server_delete(server);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800378 }
379}
380
381static int is_channel_orphaned(channel_data *chand) {
382 return chand->next == chand;
383}
384
385static void orphan_channel(channel_data *chand) {
386 chand->next->prev = chand->prev;
387 chand->prev->next = chand->next;
388 chand->next = chand->prev = chand;
389}
390
ctiller58393c22015-01-07 14:03:30 -0800391static void finish_destroy_channel(void *cd, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800392 channel_data *chand = cd;
393 grpc_server *server = chand->server;
Craig Tiller9ec2a522015-05-29 22:46:54 -0700394 GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "server");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800395 server_unref(server);
396}
397
398static void destroy_channel(channel_data *chand) {
399 if (is_channel_orphaned(chand)) return;
400 GPR_ASSERT(chand->server != NULL);
401 orphan_channel(chand);
402 server_ref(chand->server);
Craig Tiller52760dd2015-05-29 23:09:26 -0700403 maybe_finish_shutdown(chand->server);
David Garcia Quintas284488b2015-05-28 16:27:39 -0700404 chand->finish_destroy_channel_closure.cb = finish_destroy_channel;
405 chand->finish_destroy_channel_closure.cb_arg = chand;
406 grpc_iomgr_add_callback(&chand->finish_destroy_channel_closure);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800407}
408
Craig Tiller3b29b562015-02-11 12:58:46 -0800409static void finish_start_new_rpc_and_unlock(grpc_server *server,
410 grpc_call_element *elem,
411 call_data **pending_root,
412 requested_call_array *array) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800413 requested_call rc;
414 call_data *calld = elem->call_data;
415 if (array->count == 0) {
416 calld->state = PENDING;
417 call_list_join(pending_root, calld, PENDING_START);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700418 gpr_mu_unlock(&server->mu_call);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800419 } else {
Craig Tiller0ef1a922015-02-11 16:23:01 -0800420 rc = array->calls[--array->count];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800421 calld->state = ACTIVATED;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700422 gpr_mu_unlock(&server->mu_call);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800423 begin_call(server, calld, &rc);
424 }
425}
426
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800427static void start_new_rpc(grpc_call_element *elem) {
428 channel_data *chand = elem->channel_data;
429 call_data *calld = elem->call_data;
430 grpc_server *server = chand->server;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800431 gpr_uint32 i;
432 gpr_uint32 hash;
433 channel_registered_method *rm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800434
Vijay Pai8931cdd2015-06-17 12:42:17 -0700435 gpr_mu_lock(&server->mu_call);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800436 if (chand->registered_methods && calld->path && calld->host) {
Craig Tillera94beff2015-02-17 22:02:06 -0800437 /* TODO(ctiller): unify these two searches */
Craig Tiller04cc8be2015-02-10 16:11:22 -0800438 /* check for an exact match with host */
439 hash = GRPC_MDSTR_KV_HASH(calld->host->hash, calld->path->hash);
440 for (i = 0; i < chand->registered_method_max_probes; i++) {
Craig Tiller3b29b562015-02-11 12:58:46 -0800441 rm = &chand->registered_methods[(hash + i) %
442 chand->registered_method_slots];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800443 if (!rm) break;
444 if (rm->host != calld->host) continue;
445 if (rm->method != calld->path) continue;
Craig Tiller3b29b562015-02-11 12:58:46 -0800446 finish_start_new_rpc_and_unlock(server, elem,
447 &rm->server_registered_method->pending,
448 &rm->server_registered_method->requested);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800449 return;
450 }
451 /* check for a wildcard method definition (no host set) */
452 hash = GRPC_MDSTR_KV_HASH(0, calld->path->hash);
Craig Tiller0ef1a922015-02-11 16:23:01 -0800453 for (i = 0; i <= chand->registered_method_max_probes; i++) {
Craig Tiller3b29b562015-02-11 12:58:46 -0800454 rm = &chand->registered_methods[(hash + i) %
455 chand->registered_method_slots];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800456 if (!rm) break;
457 if (rm->host != NULL) continue;
458 if (rm->method != calld->path) continue;
Craig Tiller3b29b562015-02-11 12:58:46 -0800459 finish_start_new_rpc_and_unlock(server, elem,
460 &rm->server_registered_method->pending,
461 &rm->server_registered_method->requested);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800462 return;
463 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800464 }
Craig Tiller3b29b562015-02-11 12:58:46 -0800465 finish_start_new_rpc_and_unlock(server, elem, &server->lists[PENDING_START],
466 &server->requested_calls);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800467}
468
ctiller58393c22015-01-07 14:03:30 -0800469static void kill_zombie(void *elem, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800470 grpc_call_destroy(grpc_call_from_top_element(elem));
471}
472
Craig Tilleree945e82015-05-26 16:15:34 -0700473static int num_listeners(grpc_server *server) {
474 listener *l;
475 int n = 0;
476 for (l = server->listeners; l; l = l->next) {
477 n++;
478 }
479 return n;
480}
481
Craig Tillerab54f792015-07-08 08:34:20 -0700482static int num_channels(grpc_server *server) {
483 channel_data *chand;
484 int n = 0;
485 for (chand = server->root_channel_data.next;
486 chand != &server->root_channel_data; chand = chand->next) {
487 n++;
488 }
489 return n;
490}
491
Craig Tillerdc627722015-05-26 15:27:02 -0700492static void maybe_finish_shutdown(grpc_server *server) {
Craig Tillerbce999f2015-05-27 09:55:51 -0700493 size_t i;
Craig Tillerc4a1f522015-05-29 22:32:04 -0700494 if (!server->shutdown || server->shutdown_published) {
495 return;
496 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700497
Craig Tillerab54f792015-07-08 08:34:20 -0700498 if (server->root_channel_data.next != &server->root_channel_data ||
499 server->listeners_destroyed < num_listeners(server)) {
500 if (gpr_time_cmp(
501 gpr_time_sub(gpr_now(), server->last_shutdown_message_time),
502 gpr_time_from_seconds(1)) >= 0) {
503 server->last_shutdown_message_time = gpr_now();
504 gpr_log(GPR_DEBUG,
505 "Waiting for %d channels and %d/%d listeners to be destroyed"
506 " before shutting down server",
507 num_channels(server),
508 num_listeners(server) - server->listeners_destroyed,
509 num_listeners(server));
510 }
Craig Tillerc4a1f522015-05-29 22:32:04 -0700511 return;
512 }
513 server->shutdown_published = 1;
514 for (i = 0; i < server->num_shutdown_tags; i++) {
515 grpc_cq_end_op(server->shutdown_tags[i].cq, server->shutdown_tags[i].tag,
516 NULL, 1);
Craig Tillerdc627722015-05-26 15:27:02 -0700517 }
518}
519
Craig Tiller6902ad22015-04-16 08:01:49 -0700520static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
521 grpc_call_element *elem = user_data;
Craig Tillercce17ac2015-01-20 09:29:28 -0800522 channel_data *chand = elem->channel_data;
523 call_data *calld = elem->call_data;
Craig Tiller6902ad22015-04-16 08:01:49 -0700524 if (md->key == chand->path_key) {
525 calld->path = grpc_mdstr_ref(md->value);
526 return NULL;
527 } else if (md->key == chand->authority_key) {
528 calld->host = grpc_mdstr_ref(md->value);
529 return NULL;
530 }
531 return md;
532}
533
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700534static void server_on_recv(void *ptr, int success) {
535 grpc_call_element *elem = ptr;
Craig Tiller6902ad22015-04-16 08:01:49 -0700536 call_data *calld = elem->call_data;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700537 channel_data *chand = elem->channel_data;
538
539 if (success && !calld->got_initial_metadata) {
540 size_t i;
541 size_t nops = calld->recv_ops->nops;
542 grpc_stream_op *ops = calld->recv_ops->ops;
543 for (i = 0; i < nops; i++) {
544 grpc_stream_op *op = &ops[i];
545 if (op->type != GRPC_OP_METADATA) continue;
Craig Tiller205aee12015-04-16 14:46:41 -0700546 grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700547 if (0 != gpr_time_cmp(op->data.metadata.deadline, gpr_inf_future)) {
Craig Tiller6902ad22015-04-16 08:01:49 -0700548 calld->deadline = op->data.metadata.deadline;
Craig Tillercce17ac2015-01-20 09:29:28 -0800549 }
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700550 calld->got_initial_metadata = 1;
551 start_new_rpc(elem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800552 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700553 }
554 }
555
556 switch (*calld->recv_state) {
Craig Tiller06aeea72015-04-23 10:54:45 -0700557 case GRPC_STREAM_OPEN:
558 break;
559 case GRPC_STREAM_SEND_CLOSED:
560 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700561 case GRPC_STREAM_RECV_CLOSED:
Vijay Pai8931cdd2015-06-17 12:42:17 -0700562 gpr_mu_lock(&chand->server->mu_call);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700563 if (calld->state == NOT_STARTED) {
564 calld->state = ZOMBIED;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700565 grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
566 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700567 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700568 gpr_mu_unlock(&chand->server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800569 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700570 case GRPC_STREAM_CLOSED:
Vijay Pai8931cdd2015-06-17 12:42:17 -0700571 gpr_mu_lock(&chand->server->mu_call);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700572 if (calld->state == NOT_STARTED) {
573 calld->state = ZOMBIED;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700574 grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
575 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700576 } else if (calld->state == PENDING) {
577 call_list_remove(calld, PENDING_START);
Craig Tillerc9d03822015-05-20 16:08:45 -0700578 calld->state = ZOMBIED;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700579 grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
580 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700581 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700582 gpr_mu_unlock(&chand->server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800583 break;
584 }
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700585
Craig Tiller1e6facb2015-06-11 22:47:11 -0700586 calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700587}
588
Craig Tillerb7959a02015-06-25 08:50:54 -0700589static void server_mutate_op(grpc_call_element *elem,
590 grpc_transport_stream_op *op) {
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700591 call_data *calld = elem->call_data;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700592
593 if (op->recv_ops) {
594 /* substitute our callback for the higher callback */
595 calld->recv_ops = op->recv_ops;
596 calld->recv_state = op->recv_state;
597 calld->on_done_recv = op->on_done_recv;
Craig Tiller1e6facb2015-06-11 22:47:11 -0700598 op->on_done_recv = &calld->server_on_recv;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700599 }
Craig Tiller50d9db52015-04-23 10:52:14 -0700600}
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700601
Craig Tillere039f032015-06-25 12:54:23 -0700602static void server_start_transport_stream_op(grpc_call_element *elem,
603 grpc_transport_stream_op *op) {
Craig Tiller50d9db52015-04-23 10:52:14 -0700604 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
605 server_mutate_op(elem, op);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700606 grpc_call_next_op(elem, op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800607}
608
Craig Tillere039f032015-06-25 12:54:23 -0700609static void accept_stream(void *cd, grpc_transport *transport,
610 const void *transport_server_data) {
611 channel_data *chand = cd;
612 /* create a call */
613 grpc_call_create(chand->channel, NULL, transport_server_data, NULL, 0,
614 gpr_inf_future);
615}
616
617static void channel_connectivity_changed(void *cd, int iomgr_status_ignored) {
618 channel_data *chand = cd;
619 grpc_server *server = chand->server;
620 if (chand->connectivity_state != GRPC_CHANNEL_FATAL_FAILURE) {
621 grpc_transport_op op;
622 memset(&op, 0, sizeof(op));
623 op.on_connectivity_state_change = &chand->channel_connectivity_changed,
624 op.connectivity_state = &chand->connectivity_state;
625 grpc_channel_next_op(grpc_channel_stack_element(
626 grpc_channel_get_channel_stack(chand->channel), 0),
627 &op);
628 } else {
629 gpr_mu_lock(&server->mu_global);
630 destroy_channel(chand);
631 gpr_mu_unlock(&server->mu_global);
632 GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "connectivity");
633 }
634}
635
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800636static void init_call_elem(grpc_call_element *elem,
Craig Tiller06aeea72015-04-23 10:54:45 -0700637 const void *server_transport_data,
Craig Tillerb7959a02015-06-25 08:50:54 -0700638 grpc_transport_stream_op *initial_op) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800639 call_data *calld = elem->call_data;
640 channel_data *chand = elem->channel_data;
641 memset(calld, 0, sizeof(call_data));
642 calld->deadline = gpr_inf_future;
643 calld->call = grpc_call_from_top_element(elem);
644
Craig Tiller1e6facb2015-06-11 22:47:11 -0700645 grpc_iomgr_closure_init(&calld->server_on_recv, server_on_recv, elem);
646
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800647 server_ref(chand->server);
Craig Tiller50d9db52015-04-23 10:52:14 -0700648
Craig Tiller482ef8b2015-04-23 11:38:20 -0700649 if (initial_op) server_mutate_op(elem, initial_op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800650}
651
652static void destroy_call_elem(grpc_call_element *elem) {
653 channel_data *chand = elem->channel_data;
Craig Tillerdb7db992015-01-29 11:19:01 -0800654 call_data *calld = elem->call_data;
Craig Tillerdc627722015-05-26 15:27:02 -0700655 size_t i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800656
Vijay Pai8931cdd2015-06-17 12:42:17 -0700657 gpr_mu_lock(&chand->server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800658 for (i = 0; i < CALL_LIST_COUNT; i++) {
Craig Tiller092d8d12015-07-04 22:35:00 -0700659 call_list_remove(elem->call_data, i);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800660 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700661 gpr_mu_unlock(&chand->server->mu_call);
Craig Tiller092d8d12015-07-04 22:35:00 -0700662
Craig Tiller4df31a62015-01-30 09:44:31 -0800663 if (calld->host) {
664 grpc_mdstr_unref(calld->host);
665 }
666 if (calld->path) {
667 grpc_mdstr_unref(calld->path);
668 }
669
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800670 server_unref(chand->server);
671}
672
Craig Tiller079a11b2015-06-30 10:07:15 -0700673static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800674 const grpc_channel_args *args,
675 grpc_mdctx *metadata_context, int is_first,
676 int is_last) {
677 channel_data *chand = elem->channel_data;
678 GPR_ASSERT(is_first);
679 GPR_ASSERT(!is_last);
680 chand->server = NULL;
681 chand->channel = NULL;
Craig Tillercce17ac2015-01-20 09:29:28 -0800682 chand->path_key = grpc_mdstr_from_string(metadata_context, ":path");
683 chand->authority_key = grpc_mdstr_from_string(metadata_context, ":authority");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800684 chand->next = chand->prev = chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800685 chand->registered_methods = NULL;
Craig Tillere039f032015-06-25 12:54:23 -0700686 chand->connectivity_state = GRPC_CHANNEL_IDLE;
687 grpc_iomgr_closure_init(&chand->channel_connectivity_changed,
688 channel_connectivity_changed, chand);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800689}
690
691static void destroy_channel_elem(grpc_channel_element *elem) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800692 size_t i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800693 channel_data *chand = elem->channel_data;
Craig Tillerec3257c2015-02-12 15:59:43 -0800694 if (chand->registered_methods) {
695 for (i = 0; i < chand->registered_method_slots; i++) {
696 if (chand->registered_methods[i].method) {
697 grpc_mdstr_unref(chand->registered_methods[i].method);
698 }
699 if (chand->registered_methods[i].host) {
700 grpc_mdstr_unref(chand->registered_methods[i].host);
701 }
702 }
703 gpr_free(chand->registered_methods);
704 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800705 if (chand->server) {
Vijay Pai8931cdd2015-06-17 12:42:17 -0700706 gpr_mu_lock(&chand->server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800707 chand->next->prev = chand->prev;
708 chand->prev->next = chand->next;
709 chand->next = chand->prev = chand;
Craig Tillerb76d05b2015-05-29 17:21:56 -0700710 maybe_finish_shutdown(chand->server);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700711 gpr_mu_unlock(&chand->server->mu_global);
Craig Tillercce17ac2015-01-20 09:29:28 -0800712 grpc_mdstr_unref(chand->path_key);
713 grpc_mdstr_unref(chand->authority_key);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800714 server_unref(chand->server);
715 }
716}
717
718static const grpc_channel_filter server_surface_filter = {
Craig Tillere039f032015-06-25 12:54:23 -0700719 server_start_transport_stream_op,
720 grpc_channel_next_op,
Craig Tillerb76d05b2015-05-29 17:21:56 -0700721 sizeof(call_data),
722 init_call_elem,
723 destroy_call_elem,
724 sizeof(channel_data),
725 init_channel_elem,
726 destroy_channel_elem,
727 "server",
Craig Tiller9f28ac22015-01-27 17:01:29 -0800728};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800729
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700730void grpc_server_register_completion_queue(grpc_server *server,
731 grpc_completion_queue *cq) {
Craig Tiller20bc56d2015-02-12 09:02:56 -0800732 size_t i, n;
733 for (i = 0; i < server->cq_count; i++) {
734 if (server->cqs[i] == cq) return;
735 }
Craig Tiller463f2372015-05-28 16:16:15 -0700736 GRPC_CQ_INTERNAL_REF(cq, "server");
Craig Tillerb56975c2015-06-15 10:11:16 -0700737 grpc_cq_mark_server_cq(cq);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800738 n = server->cq_count++;
Craig Tillerec3257c2015-02-12 15:59:43 -0800739 server->cqs = gpr_realloc(server->cqs,
740 server->cq_count * sizeof(grpc_completion_queue *));
Craig Tiller20bc56d2015-02-12 09:02:56 -0800741 server->cqs[n] = cq;
742}
743
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700744grpc_server *grpc_server_create_from_filters(grpc_channel_filter **filters,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800745 size_t filter_count,
746 const grpc_channel_args *args) {
747 size_t i;
Alistair Veitch9d48ebf2015-06-01 10:01:03 -0700748 /* TODO(census): restore this once we finalize census filter etc.
749 int census_enabled = grpc_channel_args_is_census_enabled(args); */
750 int census_enabled = 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800751
752 grpc_server *server = gpr_malloc(sizeof(grpc_server));
Craig Tiller60fd3612015-03-05 16:24:22 -0800753
754 GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
755
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800756 memset(server, 0, sizeof(grpc_server));
757
Vijay Pai8931cdd2015-06-17 12:42:17 -0700758 gpr_mu_init(&server->mu_global);
759 gpr_mu_init(&server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800760
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800761 /* decremented by grpc_server_destroy */
762 gpr_ref_init(&server->internal_refcount, 1);
763 server->root_channel_data.next = server->root_channel_data.prev =
764 &server->root_channel_data;
765
766 /* Server filter stack is:
767
768 server_surface_filter - for making surface API calls
769 grpc_server_census_filter (optional) - for stats collection and tracing
770 {passed in filter stack}
771 grpc_connected_channel_filter - for interfacing with transports */
772 server->channel_filter_count = filter_count + 1 + census_enabled;
773 server->channel_filters =
774 gpr_malloc(server->channel_filter_count * sizeof(grpc_channel_filter *));
775 server->channel_filters[0] = &server_surface_filter;
Alistair Veitch9d48ebf2015-06-01 10:01:03 -0700776 /* TODO(census): restore this once we rework census filter
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800777 if (census_enabled) {
778 server->channel_filters[1] = &grpc_server_census_filter;
Alistair Veitch9686dab2015-05-26 14:26:47 -0700779 } */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800780 for (i = 0; i < filter_count; i++) {
781 server->channel_filters[i + 1 + census_enabled] = filters[i];
782 }
783
784 server->channel_args = grpc_channel_args_copy(args);
785
786 return server;
787}
788
Craig Tiller24be0f72015-02-10 14:04:22 -0800789static int streq(const char *a, const char *b) {
790 if (a == NULL && b == NULL) return 1;
791 if (a == NULL) return 0;
792 if (b == NULL) return 0;
793 return 0 == strcmp(a, b);
794}
795
796void *grpc_server_register_method(grpc_server *server, const char *method,
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700797 const char *host) {
Craig Tiller24be0f72015-02-10 14:04:22 -0800798 registered_method *m;
799 if (!method) {
Craig Tillerb76d05b2015-05-29 17:21:56 -0700800 gpr_log(GPR_ERROR,
801 "grpc_server_register_method method string cannot be NULL");
Craig Tiller24be0f72015-02-10 14:04:22 -0800802 return NULL;
803 }
804 for (m = server->registered_methods; m; m = m->next) {
805 if (streq(m->method, method) && streq(m->host, host)) {
806 gpr_log(GPR_ERROR, "duplicate registration for %s@%s", method,
807 host ? host : "*");
808 return NULL;
809 }
810 }
811 m = gpr_malloc(sizeof(registered_method));
812 memset(m, 0, sizeof(*m));
813 m->method = gpr_strdup(method);
814 m->host = gpr_strdup(host);
815 m->next = server->registered_methods;
816 server->registered_methods = m;
817 return m;
818}
819
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800820void grpc_server_start(grpc_server *server) {
821 listener *l;
Craig Tiller20bc56d2015-02-12 09:02:56 -0800822 size_t i;
823
Craig Tillerec3257c2015-02-12 15:59:43 -0800824 server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800825 for (i = 0; i < server->cq_count; i++) {
826 server->pollsets[i] = grpc_cq_pollset(server->cqs[i]);
827 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800828
829 for (l = server->listeners; l; l = l->next) {
Craig Tiller20bc56d2015-02-12 09:02:56 -0800830 l->start(server, l->arg, server->pollsets, server->cq_count);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800831 }
832}
833
Craig Tiller1064f8b2015-06-25 13:52:57 -0700834void grpc_server_setup_transport(grpc_server *s, grpc_transport *transport,
835 grpc_channel_filter const **extra_filters,
836 size_t num_extra_filters, grpc_mdctx *mdctx,
837 const grpc_channel_args *args) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800838 size_t num_filters = s->channel_filter_count + num_extra_filters + 1;
839 grpc_channel_filter const **filters =
840 gpr_malloc(sizeof(grpc_channel_filter *) * num_filters);
841 size_t i;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800842 size_t num_registered_methods;
843 size_t alloc;
844 registered_method *rm;
845 channel_registered_method *crm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800846 grpc_channel *channel;
847 channel_data *chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800848 grpc_mdstr *host;
849 grpc_mdstr *method;
850 gpr_uint32 hash;
851 gpr_uint32 slots;
852 gpr_uint32 probes;
853 gpr_uint32 max_probes = 0;
Craig Tillere039f032015-06-25 12:54:23 -0700854 grpc_transport_op op;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800855
856 for (i = 0; i < s->channel_filter_count; i++) {
857 filters[i] = s->channel_filters[i];
858 }
859 for (; i < s->channel_filter_count + num_extra_filters; i++) {
860 filters[i] = extra_filters[i - s->channel_filter_count];
861 }
862 filters[i] = &grpc_connected_channel_filter;
863
Craig Tiller20bc56d2015-02-12 09:02:56 -0800864 for (i = 0; i < s->cq_count; i++) {
Craig Tillere039f032015-06-25 12:54:23 -0700865 memset(&op, 0, sizeof(op));
866 op.bind_pollset = grpc_cq_pollset(s->cqs[i]);
867 grpc_transport_perform_op(transport, &op);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800868 }
ctillerd79b4862014-12-17 16:36:59 -0800869
Julien Boeufc6f8d0a2015-05-11 22:40:02 -0700870 channel =
871 grpc_channel_create_from_filters(filters, num_filters, args, mdctx, 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800872 chand = (channel_data *)grpc_channel_stack_element(
Craig Tillerc02c1d82015-04-07 16:21:55 -0700873 grpc_channel_get_channel_stack(channel), 0)
874 ->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800875 chand->server = s;
876 server_ref(s);
877 chand->channel = channel;
878
Craig Tiller04cc8be2015-02-10 16:11:22 -0800879 num_registered_methods = 0;
880 for (rm = s->registered_methods; rm; rm = rm->next) {
881 num_registered_methods++;
882 }
883 /* build a lookup table phrased in terms of mdstr's in this channels context
884 to quickly find registered methods */
885 if (num_registered_methods > 0) {
886 slots = 2 * num_registered_methods;
887 alloc = sizeof(channel_registered_method) * slots;
888 chand->registered_methods = gpr_malloc(alloc);
889 memset(chand->registered_methods, 0, alloc);
890 for (rm = s->registered_methods; rm; rm = rm->next) {
891 host = rm->host ? grpc_mdstr_from_string(mdctx, rm->host) : NULL;
Craig Tillere76c9662015-02-11 13:18:31 -0800892 method = grpc_mdstr_from_string(mdctx, rm->method);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800893 hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash);
Craig Tiller3b29b562015-02-11 12:58:46 -0800894 for (probes = 0; chand->registered_methods[(hash + probes) % slots]
Craig Tillerc02c1d82015-04-07 16:21:55 -0700895 .server_registered_method != NULL;
Craig Tiller3b29b562015-02-11 12:58:46 -0800896 probes++)
897 ;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800898 if (probes > max_probes) max_probes = probes;
899 crm = &chand->registered_methods[(hash + probes) % slots];
900 crm->server_registered_method = rm;
901 crm->host = host;
902 crm->method = method;
903 }
904 chand->registered_method_slots = slots;
905 chand->registered_method_max_probes = max_probes;
906 }
907
Craig Tiller1064f8b2015-06-25 13:52:57 -0700908 grpc_connected_channel_bind_transport(grpc_channel_get_channel_stack(channel),
909 transport);
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800910
Vijay Pai8931cdd2015-06-17 12:42:17 -0700911 gpr_mu_lock(&s->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800912 chand->next = &s->root_channel_data;
913 chand->prev = chand->next->prev;
914 chand->next->prev = chand->prev->next = chand;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700915 gpr_mu_unlock(&s->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800916
917 gpr_free(filters);
Craig Tiller4b804102015-06-26 16:16:12 -0700918
919 GRPC_CHANNEL_INTERNAL_REF(channel, "connectivity");
920 memset(&op, 0, sizeof(op));
921 op.set_accept_stream = accept_stream;
922 op.set_accept_stream_user_data = chand;
923 op.on_connectivity_state_change = &chand->channel_connectivity_changed;
924 op.connectivity_state = &chand->connectivity_state;
925 grpc_transport_perform_op(transport, &op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800926}
927
Craig Tillerbce999f2015-05-27 09:55:51 -0700928void grpc_server_shutdown_and_notify(grpc_server *server,
929 grpc_completion_queue *cq, void *tag) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800930 listener *l;
Craig Tiller24be0f72015-02-10 14:04:22 -0800931 requested_call_array requested_calls;
Craig Tillerdc627722015-05-26 15:27:02 -0700932 size_t i;
Craig Tillerbd217572015-02-11 18:10:56 -0800933 registered_method *rm;
Craig Tillerbce999f2015-05-27 09:55:51 -0700934 shutdown_tag *sdt;
Craig Tillerff3ae682015-06-29 17:44:04 -0700935 channel_broadcaster broadcaster;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800936
937 /* lock, and gather up some stuff to do */
Vijay Pai8931cdd2015-06-17 12:42:17 -0700938 gpr_mu_lock(&server->mu_global);
Craig Tiller29f79dc2015-05-27 15:59:23 -0700939 grpc_cq_begin_op(cq, NULL);
Craig Tilleree945e82015-05-26 16:15:34 -0700940 server->shutdown_tags =
941 gpr_realloc(server->shutdown_tags,
Craig Tiller208d2122015-05-29 08:50:08 -0700942 sizeof(shutdown_tag) * (server->num_shutdown_tags + 1));
Craig Tillerbce999f2015-05-27 09:55:51 -0700943 sdt = &server->shutdown_tags[server->num_shutdown_tags++];
944 sdt->tag = tag;
945 sdt->cq = cq;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800946 if (server->shutdown) {
Vijay Pai8931cdd2015-06-17 12:42:17 -0700947 gpr_mu_unlock(&server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800948 return;
949 }
950
Craig Tillerab54f792015-07-08 08:34:20 -0700951 server->last_shutdown_message_time = gpr_now();
952
Craig Tillerff3ae682015-06-29 17:44:04 -0700953 channel_broadcaster_init(server, &broadcaster);
nnoble0c475f02014-12-05 15:37:39 -0800954
Craig Tillerbd217572015-02-11 18:10:56 -0800955 /* collect all unregistered then registered calls */
Vijay Pai8931cdd2015-06-17 12:42:17 -0700956 gpr_mu_lock(&server->mu_call);
Craig Tillercce17ac2015-01-20 09:29:28 -0800957 requested_calls = server->requested_calls;
Craig Tiller24be0f72015-02-10 14:04:22 -0800958 memset(&server->requested_calls, 0, sizeof(server->requested_calls));
Craig Tillerbd217572015-02-11 18:10:56 -0800959 for (rm = server->registered_methods; rm; rm = rm->next) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800960 if (requested_calls.count + rm->requested.count >
961 requested_calls.capacity) {
962 requested_calls.capacity =
963 GPR_MAX(requested_calls.count + rm->requested.count,
964 2 * requested_calls.capacity);
965 requested_calls.calls =
966 gpr_realloc(requested_calls.calls, sizeof(*requested_calls.calls) *
967 requested_calls.capacity);
Craig Tillerbd217572015-02-11 18:10:56 -0800968 }
Craig Tillerec3257c2015-02-12 15:59:43 -0800969 memcpy(requested_calls.calls + requested_calls.count, rm->requested.calls,
970 sizeof(*requested_calls.calls) * rm->requested.count);
Craig Tillerbd217572015-02-11 18:10:56 -0800971 requested_calls.count += rm->requested.count;
Craig Tillerec3257c2015-02-12 15:59:43 -0800972 gpr_free(rm->requested.calls);
Craig Tillerbd217572015-02-11 18:10:56 -0800973 memset(&rm->requested, 0, sizeof(rm->requested));
974 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700975 gpr_mu_unlock(&server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800976
977 server->shutdown = 1;
Craig Tillerdc627722015-05-26 15:27:02 -0700978 maybe_finish_shutdown(server);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700979 gpr_mu_unlock(&server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800980
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800981 /* terminate all the requested calls */
Craig Tiller24be0f72015-02-10 14:04:22 -0800982 for (i = 0; i < requested_calls.count; i++) {
983 fail_call(server, &requested_calls.calls[i]);
Craig Tillercce17ac2015-01-20 09:29:28 -0800984 }
Craig Tiller24be0f72015-02-10 14:04:22 -0800985 gpr_free(requested_calls.calls);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800986
987 /* Shutdown listeners */
988 for (l = server->listeners; l; l = l->next) {
989 l->destroy(server, l->arg);
990 }
Craig Tillerff3ae682015-06-29 17:44:04 -0700991
992 channel_broadcaster_shutdown(&broadcaster, 1, 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800993}
994
Craig Tilleraec96aa2015-04-07 14:32:15 -0700995void grpc_server_listener_destroy_done(void *s) {
996 grpc_server *server = s;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700997 gpr_mu_lock(&server->mu_global);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700998 server->listeners_destroyed++;
Craig Tilleree945e82015-05-26 16:15:34 -0700999 maybe_finish_shutdown(server);
Vijay Pai8931cdd2015-06-17 12:42:17 -07001000 gpr_mu_unlock(&server->mu_global);
Craig Tilleraec96aa2015-04-07 14:32:15 -07001001}
1002
Craig Tillerafa2d632015-05-26 16:39:13 -07001003void grpc_server_cancel_all_calls(grpc_server *server) {
Craig Tiller092d8d12015-07-04 22:35:00 -07001004 channel_broadcaster broadcaster;
Craig Tillerafa2d632015-05-26 16:39:13 -07001005
Craig Tiller092d8d12015-07-04 22:35:00 -07001006 gpr_mu_lock(&server->mu_global);
1007 channel_broadcaster_init(server, &broadcaster);
1008 gpr_mu_unlock(&server->mu_global);
Craig Tillerafa2d632015-05-26 16:39:13 -07001009
Craig Tiller092d8d12015-07-04 22:35:00 -07001010 channel_broadcaster_shutdown(&broadcaster, 0, 1);
Craig Tillerafa2d632015-05-26 16:39:13 -07001011}
1012
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001013void grpc_server_destroy(grpc_server *server) {
Craig Tilleraec96aa2015-04-07 14:32:15 -07001014 listener *l;
Craig Tiller872af022015-04-24 15:57:52 -07001015
Vijay Pai8931cdd2015-06-17 12:42:17 -07001016 gpr_mu_lock(&server->mu_global);
Masood Malekghassemi38bb18f2015-06-10 17:32:02 -07001017 GPR_ASSERT(server->shutdown || !server->listeners);
Craig Tilleree945e82015-05-26 16:15:34 -07001018 GPR_ASSERT(server->listeners_destroyed == num_listeners(server));
Craig Tilleraec96aa2015-04-07 14:32:15 -07001019
1020 while (server->listeners) {
1021 l = server->listeners;
1022 server->listeners = l->next;
1023 gpr_free(l);
1024 }
1025
Vijay Pai8931cdd2015-06-17 12:42:17 -07001026 gpr_mu_unlock(&server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001027
1028 server_unref(server);
1029}
1030
1031void grpc_server_add_listener(grpc_server *server, void *arg,
ctiller58393c22015-01-07 14:03:30 -08001032 void (*start)(grpc_server *server, void *arg,
Craig Tillerec3257c2015-02-12 15:59:43 -08001033 grpc_pollset **pollsets,
1034 size_t pollset_count),
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001035 void (*destroy)(grpc_server *server, void *arg)) {
1036 listener *l = gpr_malloc(sizeof(listener));
1037 l->arg = arg;
1038 l->start = start;
1039 l->destroy = destroy;
1040 l->next = server->listeners;
1041 server->listeners = l;
1042}
1043
Craig Tiller9f28ac22015-01-27 17:01:29 -08001044static grpc_call_error queue_call_request(grpc_server *server,
Craig Tiller24be0f72015-02-10 14:04:22 -08001045 requested_call *rc) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001046 call_data *calld = NULL;
Craig Tiller0ef1a922015-02-11 16:23:01 -08001047 requested_call_array *requested_calls = NULL;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001048 gpr_mu_lock(&server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001049 if (server->shutdown) {
Vijay Pai8931cdd2015-06-17 12:42:17 -07001050 gpr_mu_unlock(&server->mu_call);
Craig Tiller24be0f72015-02-10 14:04:22 -08001051 fail_call(server, rc);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001052 return GRPC_CALL_OK;
1053 }
Craig Tiller04cc8be2015-02-10 16:11:22 -08001054 switch (rc->type) {
Craig Tiller04cc8be2015-02-10 16:11:22 -08001055 case BATCH_CALL:
Craig Tiller3b29b562015-02-11 12:58:46 -08001056 calld =
1057 call_list_remove_head(&server->lists[PENDING_START], PENDING_START);
Craig Tiller0ef1a922015-02-11 16:23:01 -08001058 requested_calls = &server->requested_calls;
Craig Tiller04cc8be2015-02-10 16:11:22 -08001059 break;
1060 case REGISTERED_CALL:
Craig Tiller3b29b562015-02-11 12:58:46 -08001061 calld = call_list_remove_head(
1062 &rc->data.registered.registered_method->pending, PENDING_START);
Craig Tiller0ef1a922015-02-11 16:23:01 -08001063 requested_calls = &rc->data.registered.registered_method->requested;
Craig Tiller04cc8be2015-02-10 16:11:22 -08001064 break;
1065 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001066 if (calld) {
Craig Tillercce17ac2015-01-20 09:29:28 -08001067 GPR_ASSERT(calld->state == PENDING);
Craig Tillerbb3f22f2015-01-29 16:40:56 -08001068 calld->state = ACTIVATED;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001069 gpr_mu_unlock(&server->mu_call);
Craig Tiller24be0f72015-02-10 14:04:22 -08001070 begin_call(server, calld, rc);
Craig Tillercce17ac2015-01-20 09:29:28 -08001071 return GRPC_CALL_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001072 } else {
Craig Tiller0ef1a922015-02-11 16:23:01 -08001073 *requested_call_array_add(requested_calls) = *rc;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001074 gpr_mu_unlock(&server->mu_call);
Craig Tillercce17ac2015-01-20 09:29:28 -08001075 return GRPC_CALL_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001076 }
Craig Tillercce17ac2015-01-20 09:29:28 -08001077}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001078
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001079grpc_call_error grpc_server_request_call(
1080 grpc_server *server, grpc_call **call, grpc_call_details *details,
1081 grpc_metadata_array *initial_metadata,
1082 grpc_completion_queue *cq_bound_to_call,
1083 grpc_completion_queue *cq_for_notification, void *tag) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001084 requested_call rc;
murgatroid99ad7c20c2015-05-22 14:42:29 -07001085 GRPC_SERVER_LOG_REQUEST_CALL(GPR_INFO, server, call, details,
1086 initial_metadata, cq_bound_to_call,
1087 cq_for_notification, tag);
Craig Tillerb56975c2015-06-15 10:11:16 -07001088 if (!grpc_cq_is_server_cq(cq_for_notification)) {
1089 return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
1090 }
Craig Tiller54478f82015-05-12 14:08:56 -07001091 grpc_cq_begin_op(cq_for_notification, NULL);
Craig Tiller24be0f72015-02-10 14:04:22 -08001092 rc.type = BATCH_CALL;
1093 rc.tag = tag;
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001094 rc.cq_bound_to_call = cq_bound_to_call;
1095 rc.cq_for_notification = cq_for_notification;
1096 rc.call = call;
Craig Tiller24be0f72015-02-10 14:04:22 -08001097 rc.data.batch.details = details;
1098 rc.data.batch.initial_metadata = initial_metadata;
1099 return queue_call_request(server, &rc);
1100}
1101
1102grpc_call_error grpc_server_request_registered_call(
Craig Tillerec3257c2015-02-12 15:59:43 -08001103 grpc_server *server, void *rm, grpc_call **call, gpr_timespec *deadline,
1104 grpc_metadata_array *initial_metadata, grpc_byte_buffer **optional_payload,
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001105 grpc_completion_queue *cq_bound_to_call,
1106 grpc_completion_queue *cq_for_notification, void *tag) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001107 requested_call rc;
Craig Tiller20bc56d2015-02-12 09:02:56 -08001108 registered_method *registered_method = rm;
Craig Tillerb56975c2015-06-15 10:11:16 -07001109 if (!grpc_cq_is_server_cq(cq_for_notification)) {
1110 return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
1111 }
Craig Tiller54478f82015-05-12 14:08:56 -07001112 grpc_cq_begin_op(cq_for_notification, NULL);
Craig Tiller24be0f72015-02-10 14:04:22 -08001113 rc.type = REGISTERED_CALL;
1114 rc.tag = tag;
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001115 rc.cq_bound_to_call = cq_bound_to_call;
1116 rc.cq_for_notification = cq_for_notification;
1117 rc.call = call;
Craig Tiller24be0f72015-02-10 14:04:22 -08001118 rc.data.registered.registered_method = registered_method;
1119 rc.data.registered.deadline = deadline;
1120 rc.data.registered.initial_metadata = initial_metadata;
1121 rc.data.registered.optional_payload = optional_payload;
1122 return queue_call_request(server, &rc);
1123}
1124
Craig Tiller64be9f72015-05-04 14:53:51 -07001125static void publish_registered_or_batch(grpc_call *call, int success,
Craig Tiller24be0f72015-02-10 14:04:22 -08001126 void *tag);
Craig Tiller64be9f72015-05-04 14:53:51 -07001127static void publish_was_not_set(grpc_call *call, int success, void *tag) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001128 abort();
1129}
Craig Tiller24be0f72015-02-10 14:04:22 -08001130
Craig Tiller166e2502015-02-03 20:14:41 -08001131static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
1132 gpr_slice slice = value->slice;
1133 size_t len = GPR_SLICE_LENGTH(slice);
1134
1135 if (len + 1 > *capacity) {
1136 *capacity = GPR_MAX(len + 1, *capacity * 2);
1137 *dest = gpr_realloc(*dest, *capacity);
1138 }
1139 memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
1140}
1141
Craig Tiller24be0f72015-02-10 14:04:22 -08001142static void begin_call(grpc_server *server, call_data *calld,
1143 requested_call *rc) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001144 grpc_ioreq_completion_func publish = publish_was_not_set;
Craig Tiller24be0f72015-02-10 14:04:22 -08001145 grpc_ioreq req[2];
1146 grpc_ioreq *r = req;
1147
1148 /* called once initial metadata has been read by the call, but BEFORE
1149 the ioreq to fetch it out of the call has been executed.
1150 This means metadata related fields can be relied on in calld, but to
1151 fill in the metadata array passed by the client, we need to perform
1152 an ioreq op, that should complete immediately. */
1153
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001154 grpc_call_set_completion_queue(calld->call, rc->cq_bound_to_call);
1155 *rc->call = calld->call;
1156 calld->cq_new = rc->cq_for_notification;
Craig Tiller24be0f72015-02-10 14:04:22 -08001157 switch (rc->type) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001158 case BATCH_CALL:
Craig Tiller04c5d4b2015-06-26 17:21:41 -07001159 GPR_ASSERT(calld->host != NULL);
1160 GPR_ASSERT(calld->path != NULL);
Craig Tiller24be0f72015-02-10 14:04:22 -08001161 cpstr(&rc->data.batch.details->host,
1162 &rc->data.batch.details->host_capacity, calld->host);
1163 cpstr(&rc->data.batch.details->method,
1164 &rc->data.batch.details->method_capacity, calld->path);
Masood Malekghassemibf177c82015-04-27 12:14:38 -07001165 rc->data.batch.details->deadline = calld->deadline;
Craig Tiller24be0f72015-02-10 14:04:22 -08001166 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1167 r->data.recv_metadata = rc->data.batch.initial_metadata;
David Garcia Quintasb8f54502015-06-15 16:19:10 -07001168 r->flags = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001169 r++;
1170 publish = publish_registered_or_batch;
1171 break;
1172 case REGISTERED_CALL:
1173 *rc->data.registered.deadline = calld->deadline;
Craig Tiller24be0f72015-02-10 14:04:22 -08001174 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1175 r->data.recv_metadata = rc->data.registered.initial_metadata;
David Garcia Quintasb8f54502015-06-15 16:19:10 -07001176 r->flags = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001177 r++;
1178 if (rc->data.registered.optional_payload) {
1179 r->op = GRPC_IOREQ_RECV_MESSAGE;
1180 r->data.recv_message = rc->data.registered.optional_payload;
David Garcia Quintasb8f54502015-06-15 16:19:10 -07001181 r->flags = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001182 r++;
1183 }
1184 publish = publish_registered_or_batch;
1185 break;
1186 }
1187
Craig Tiller4df412b2015-04-28 07:57:54 -07001188 GRPC_CALL_INTERNAL_REF(calld->call, "server");
Craig Tiller24be0f72015-02-10 14:04:22 -08001189 grpc_call_start_ioreq_and_call_back(calld->call, req, r - req, publish,
1190 rc->tag);
1191}
1192
1193static void fail_call(grpc_server *server, requested_call *rc) {
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001194 *rc->call = NULL;
Craig Tiller24be0f72015-02-10 14:04:22 -08001195 switch (rc->type) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001196 case BATCH_CALL:
Craig Tiller24be0f72015-02-10 14:04:22 -08001197 rc->data.batch.initial_metadata->count = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001198 break;
1199 case REGISTERED_CALL:
Craig Tiller24be0f72015-02-10 14:04:22 -08001200 rc->data.registered.initial_metadata->count = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001201 break;
1202 }
Craig Tiller54478f82015-05-12 14:08:56 -07001203 grpc_cq_end_op(rc->cq_for_notification, rc->tag, NULL, 0);
Craig Tiller24be0f72015-02-10 14:04:22 -08001204}
1205
Craig Tiller64be9f72015-05-04 14:53:51 -07001206static void publish_registered_or_batch(grpc_call *call, int success,
Craig Tiller24be0f72015-02-10 14:04:22 -08001207 void *tag) {
Craig Tiller8e8fd892015-02-10 17:02:08 -08001208 grpc_call_element *elem =
1209 grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
Craig Tiller20bc56d2015-02-12 09:02:56 -08001210 call_data *calld = elem->call_data;
Craig Tiller64be9f72015-05-04 14:53:51 -07001211 grpc_cq_end_op(calld->cq_new, tag, call, success);
Craig Tiller24be0f72015-02-10 14:04:22 -08001212}
1213
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001214const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) {
1215 return server->channel_args;
Craig Tiller190d3602015-02-18 09:23:38 -08001216}
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001217
1218int grpc_server_has_open_connections(grpc_server *server) {
1219 int r;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001220 gpr_mu_lock(&server->mu_global);
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001221 r = server->root_channel_data.next != &server->root_channel_data;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001222 gpr_mu_unlock(&server->mu_global);
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001223 return r;
1224}