blob: 32e5058b4db0040acc2af31cb008c17c4a9ddb27 [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
Craig Tiller97fc6a32015-07-08 15:31:35 -070075typedef struct requested_call {
Craig Tiller24be0f72015-02-10 14:04:22 -080076 requested_call_type type;
Craig Tiller97fc6a32015-07-08 15:31:35 -070077 struct requested_call *next;
Craig Tiller24be0f72015-02-10 14:04:22 -080078 void *tag;
Craig Tillerf9e6adf2015-05-06 11:45:59 -070079 grpc_completion_queue *cq_bound_to_call;
80 grpc_completion_queue *cq_for_notification;
81 grpc_call **call;
Craig Tiller97fc6a32015-07-08 15:31:35 -070082 grpc_cq_completion completion;
Craig Tiller24be0f72015-02-10 14:04:22 -080083 union {
84 struct {
Craig Tiller24be0f72015-02-10 14:04:22 -080085 grpc_call_details *details;
86 grpc_metadata_array *initial_metadata;
87 } batch;
88 struct {
Craig Tiller24be0f72015-02-10 14:04:22 -080089 registered_method *registered_method;
90 gpr_timespec *deadline;
91 grpc_metadata_array *initial_metadata;
92 grpc_byte_buffer **optional_payload;
93 } registered;
94 } data;
95} requested_call;
96
Craig Tiller24be0f72015-02-10 14:04:22 -080097struct registered_method {
98 char *method;
99 char *host;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800100 call_data *pending;
Craig Tiller97fc6a32015-07-08 15:31:35 -0700101 requested_call *requests;
Craig Tiller24be0f72015-02-10 14:04:22 -0800102 registered_method *next;
103};
104
105typedef struct channel_registered_method {
106 registered_method *server_registered_method;
107 grpc_mdstr *method;
108 grpc_mdstr *host;
109} channel_registered_method;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800110
111struct channel_data {
112 grpc_server *server;
Craig Tillere039f032015-06-25 12:54:23 -0700113 grpc_connectivity_state connectivity_state;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800114 grpc_channel *channel;
Craig Tillercce17ac2015-01-20 09:29:28 -0800115 grpc_mdstr *path_key;
116 grpc_mdstr *authority_key;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800117 /* linked list of all channels on a server */
118 channel_data *next;
119 channel_data *prev;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800120 channel_registered_method *registered_methods;
121 gpr_uint32 registered_method_slots;
122 gpr_uint32 registered_method_max_probes;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700123 grpc_iomgr_closure finish_destroy_channel_closure;
Craig Tillere039f032015-06-25 12:54:23 -0700124 grpc_iomgr_closure channel_connectivity_changed;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800125};
126
Craig Tillerbce999f2015-05-27 09:55:51 -0700127typedef struct shutdown_tag {
128 void *tag;
129 grpc_completion_queue *cq;
Craig Tiller97fc6a32015-07-08 15:31:35 -0700130 grpc_cq_completion completion;
Craig Tillerbce999f2015-05-27 09:55:51 -0700131} shutdown_tag;
132
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800133struct grpc_server {
134 size_t channel_filter_count;
135 const grpc_channel_filter **channel_filters;
136 grpc_channel_args *channel_args;
Craig Tillerec3257c2015-02-12 15:59:43 -0800137
Craig Tiller20bc56d2015-02-12 09:02:56 -0800138 grpc_completion_queue **cqs;
139 grpc_pollset **pollsets;
140 size_t cq_count;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800141
Vijay Paid2a82d92015-06-17 13:42:46 -0700142 /* The two following mutexes control access to server-state
143 mu_global controls access to non-call-related state (e.g., channel state)
144 mu_call controls access to call-related state (e.g., the call lists)
145
146 If they are ever required to be nested, you must lock mu_global
147 before mu_call. This is currently used in shutdown processing
148 (grpc_server_shutdown_and_notify and maybe_finish_shutdown) */
149 gpr_mu mu_global; /* mutex for server and channel state */
Craig Tiller079a11b2015-06-30 10:07:15 -0700150 gpr_mu mu_call; /* mutex for call-specific state */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800151
Craig Tiller24be0f72015-02-10 14:04:22 -0800152 registered_method *registered_methods;
Craig Tiller97fc6a32015-07-08 15:31:35 -0700153 requested_call *requests;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800154
155 gpr_uint8 shutdown;
Craig Tiller29f79dc2015-05-27 15:59:23 -0700156 gpr_uint8 shutdown_published;
Craig Tilleraea2fc02015-02-17 16:54:53 -0800157 size_t num_shutdown_tags;
Craig Tillerbce999f2015-05-27 09:55:51 -0700158 shutdown_tag *shutdown_tags;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800159
160 call_data *lists[CALL_LIST_COUNT];
161 channel_data root_channel_data;
162
163 listener *listeners;
Craig Tilleraec96aa2015-04-07 14:32:15 -0700164 int listeners_destroyed;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800165 gpr_refcount internal_refcount;
166};
167
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800168typedef enum {
169 /* waiting for metadata */
170 NOT_STARTED,
171 /* inital metadata read, not flow controlled in yet */
172 PENDING,
173 /* flow controlled in, on completion queue */
174 ACTIVATED,
175 /* cancelled before being queued */
176 ZOMBIED
177} call_state;
178
179struct call_data {
180 grpc_call *call;
181
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700182 /** protects state */
183 gpr_mu mu_state;
184 /** the current state of a call - see call_state */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800185 call_state state;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700186
Craig Tillercce17ac2015-01-20 09:29:28 -0800187 grpc_mdstr *path;
188 grpc_mdstr *host;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700189 gpr_timespec deadline;
190 int got_initial_metadata;
Craig Tillercce17ac2015-01-20 09:29:28 -0800191
Craig Tiller20bc56d2015-02-12 09:02:56 -0800192 grpc_completion_queue *cq_new;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800193
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700194 grpc_stream_op_buffer *recv_ops;
195 grpc_stream_state *recv_state;
Craig Tiller1e6facb2015-06-11 22:47:11 -0700196 grpc_iomgr_closure *on_done_recv;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700197
Craig Tiller1e6facb2015-06-11 22:47:11 -0700198 grpc_iomgr_closure server_on_recv;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700199 grpc_iomgr_closure kill_zombie_closure;
200
Craig Tiller04cc8be2015-02-10 16:11:22 -0800201 call_data **root[CALL_LIST_COUNT];
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800202 call_link links[CALL_LIST_COUNT];
203};
204
Craig Tillerff3ae682015-06-29 17:44:04 -0700205typedef struct {
206 grpc_channel **channels;
207 size_t num_channels;
208} channel_broadcaster;
209
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800210#define SERVER_FROM_CALL_ELEM(elem) \
211 (((channel_data *)(elem)->channel_data)->server)
212
Craig Tiller24be0f72015-02-10 14:04:22 -0800213static void begin_call(grpc_server *server, call_data *calld,
214 requested_call *rc);
215static void fail_call(grpc_server *server, requested_call *rc);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700216/* Before calling maybe_finish_shutdown, we must hold mu_global and not
217 hold mu_call */
Craig Tiller52760dd2015-05-29 23:09:26 -0700218static void maybe_finish_shutdown(grpc_server *server);
Craig Tiller24be0f72015-02-10 14:04:22 -0800219
Craig Tillerff3ae682015-06-29 17:44:04 -0700220/* channel broadcaster */
221
222/* assumes server locked */
223static void channel_broadcaster_init(grpc_server *s, channel_broadcaster *cb) {
224 channel_data *c;
225 size_t count = 0;
Craig Tiller079a11b2015-06-30 10:07:15 -0700226 for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) {
227 count++;
Craig Tillerff3ae682015-06-29 17:44:04 -0700228 }
229 cb->num_channels = count;
230 cb->channels = gpr_malloc(sizeof(*cb->channels) * cb->num_channels);
231 count = 0;
Craig Tiller079a11b2015-06-30 10:07:15 -0700232 for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) {
Craig Tiller49924e02015-06-29 22:42:33 -0700233 cb->channels[count++] = c->channel;
Craig Tillerff3ae682015-06-29 17:44:04 -0700234 GRPC_CHANNEL_INTERNAL_REF(c->channel, "broadcast");
Craig Tillerff3ae682015-06-29 17:44:04 -0700235 }
236}
237
238struct shutdown_cleanup_args {
239 grpc_iomgr_closure closure;
240 gpr_slice slice;
241};
242
243static void shutdown_cleanup(void *arg, int iomgr_status_ignored) {
244 struct shutdown_cleanup_args *a = arg;
245 gpr_slice_unref(a->slice);
246 gpr_free(a);
247}
248
Craig Tiller079a11b2015-06-30 10:07:15 -0700249static void send_shutdown(grpc_channel *channel, int send_goaway,
250 int send_disconnect) {
Craig Tillerff3ae682015-06-29 17:44:04 -0700251 grpc_transport_op op;
252 struct shutdown_cleanup_args *sc;
253 grpc_channel_element *elem;
254
255 memset(&op, 0, sizeof(op));
Craig Tillerff3ae682015-06-29 17:44:04 -0700256 op.send_goaway = send_goaway;
257 sc = gpr_malloc(sizeof(*sc));
258 sc->slice = gpr_slice_from_copied_string("Server shutdown");
259 op.goaway_message = &sc->slice;
260 op.goaway_status = GRPC_STATUS_OK;
261 op.disconnect = send_disconnect;
262 grpc_iomgr_closure_init(&sc->closure, shutdown_cleanup, sc);
263 op.on_consumed = &sc->closure;
264
Craig Tiller079a11b2015-06-30 10:07:15 -0700265 elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
Craig Tillerff3ae682015-06-29 17:44:04 -0700266 elem->filter->start_transport_op(elem, &op);
267}
268
Craig Tiller079a11b2015-06-30 10:07:15 -0700269static void channel_broadcaster_shutdown(channel_broadcaster *cb,
Craig Tiller12cf5372015-07-09 13:48:11 -0700270 int send_goaway,
271 int force_disconnect) {
Craig Tillerff3ae682015-06-29 17:44:04 -0700272 size_t i;
273
274 for (i = 0; i < cb->num_channels; i++) {
Craig Tiller9188d7a2015-07-05 12:44:37 -0700275 send_shutdown(cb->channels[i], send_goaway, force_disconnect);
Craig Tillerff3ae682015-06-29 17:44:04 -0700276 GRPC_CHANNEL_INTERNAL_UNREF(cb->channels[i], "broadcast");
277 }
278 gpr_free(cb->channels);
279}
280
281/* call list */
282
Craig Tiller3b29b562015-02-11 12:58:46 -0800283static int call_list_join(call_data **root, call_data *call, call_list list) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800284 GPR_ASSERT(!call->root[list]);
285 call->root[list] = root;
286 if (!*root) {
287 *root = call;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800288 call->links[list].next = call->links[list].prev = call;
289 } else {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800290 call->links[list].next = *root;
291 call->links[list].prev = (*root)->links[list].prev;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800292 call->links[list].next->links[list].prev =
293 call->links[list].prev->links[list].next = call;
294 }
295 return 1;
296}
297
Craig Tiller04cc8be2015-02-10 16:11:22 -0800298static call_data *call_list_remove_head(call_data **root, call_list list) {
299 call_data *out = *root;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800300 if (out) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800301 out->root[list] = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800302 if (out->links[list].next == out) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800303 *root = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800304 } else {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800305 *root = out->links[list].next;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800306 out->links[list].next->links[list].prev = out->links[list].prev;
307 out->links[list].prev->links[list].next = out->links[list].next;
308 }
309 }
310 return out;
311}
312
Craig Tiller04cc8be2015-02-10 16:11:22 -0800313static int call_list_remove(call_data *call, call_list list) {
314 call_data **root = call->root[list];
315 if (root == NULL) return 0;
316 call->root[list] = NULL;
317 if (*root == call) {
318 *root = call->links[list].next;
319 if (*root == call) {
320 *root = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800321 return 1;
322 }
323 }
Craig Tiller04cc8be2015-02-10 16:11:22 -0800324 GPR_ASSERT(*root != call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800325 call->links[list].next->links[list].prev = call->links[list].prev;
326 call->links[list].prev->links[list].next = call->links[list].next;
327 return 1;
328}
329
330static void server_ref(grpc_server *server) {
331 gpr_ref(&server->internal_refcount);
332}
333
Craig Tilleree945e82015-05-26 16:15:34 -0700334static void server_delete(grpc_server *server) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800335 registered_method *rm;
Craig Tiller89504612015-04-27 11:48:46 -0700336 size_t i;
Craig Tilleree945e82015-05-26 16:15:34 -0700337 grpc_channel_args_destroy(server->channel_args);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700338 gpr_mu_destroy(&server->mu_global);
339 gpr_mu_destroy(&server->mu_call);
Craig Tilleree945e82015-05-26 16:15:34 -0700340 gpr_free(server->channel_filters);
Craig Tilleree945e82015-05-26 16:15:34 -0700341 while ((rm = server->registered_methods) != NULL) {
342 server->registered_methods = rm->next;
343 gpr_free(rm->method);
344 gpr_free(rm->host);
Craig Tilleree945e82015-05-26 16:15:34 -0700345 gpr_free(rm);
346 }
347 for (i = 0; i < server->cq_count; i++) {
Craig Tiller463f2372015-05-28 16:16:15 -0700348 GRPC_CQ_INTERNAL_UNREF(server->cqs[i], "server");
Craig Tilleree945e82015-05-26 16:15:34 -0700349 }
350 gpr_free(server->cqs);
351 gpr_free(server->pollsets);
352 gpr_free(server->shutdown_tags);
353 gpr_free(server);
354}
355
356static void server_unref(grpc_server *server) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800357 if (gpr_unref(&server->internal_refcount)) {
Craig Tilleree945e82015-05-26 16:15:34 -0700358 server_delete(server);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800359 }
360}
361
362static int is_channel_orphaned(channel_data *chand) {
363 return chand->next == chand;
364}
365
366static void orphan_channel(channel_data *chand) {
367 chand->next->prev = chand->prev;
368 chand->prev->next = chand->next;
369 chand->next = chand->prev = chand;
370}
371
ctiller58393c22015-01-07 14:03:30 -0800372static void finish_destroy_channel(void *cd, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800373 channel_data *chand = cd;
374 grpc_server *server = chand->server;
Craig Tiller9ec2a522015-05-29 22:46:54 -0700375 GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "server");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800376 server_unref(server);
377}
378
379static void destroy_channel(channel_data *chand) {
380 if (is_channel_orphaned(chand)) return;
381 GPR_ASSERT(chand->server != NULL);
382 orphan_channel(chand);
383 server_ref(chand->server);
Craig Tiller52760dd2015-05-29 23:09:26 -0700384 maybe_finish_shutdown(chand->server);
David Garcia Quintas284488b2015-05-28 16:27:39 -0700385 chand->finish_destroy_channel_closure.cb = finish_destroy_channel;
386 chand->finish_destroy_channel_closure.cb_arg = chand;
387 grpc_iomgr_add_callback(&chand->finish_destroy_channel_closure);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800388}
389
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700390static void finish_start_new_rpc(grpc_server *server, grpc_call_element *elem,
391 call_data **pending_root,
Craig Tillerea0c3612015-07-08 15:43:18 -0700392 requested_call **requests) {
393 requested_call *rc;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800394 call_data *calld = elem->call_data;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700395 gpr_mu_lock(&server->mu_call);
Craig Tillerea0c3612015-07-08 15:43:18 -0700396 rc = *requests;
Craig Tiller97fc6a32015-07-08 15:31:35 -0700397 if (rc == NULL) {
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700398 gpr_mu_lock(&calld->mu_state);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800399 calld->state = PENDING;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700400 gpr_mu_unlock(&calld->mu_state);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800401 call_list_join(pending_root, calld, PENDING_START);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700402 gpr_mu_unlock(&server->mu_call);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800403 } else {
Craig Tiller97fc6a32015-07-08 15:31:35 -0700404 *requests = rc->next;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700405 gpr_mu_lock(&calld->mu_state);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800406 calld->state = ACTIVATED;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700407 gpr_mu_unlock(&calld->mu_state);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700408 gpr_mu_unlock(&server->mu_call);
Craig Tiller97fc6a32015-07-08 15:31:35 -0700409 begin_call(server, calld, rc);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800410 }
411}
412
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800413static void start_new_rpc(grpc_call_element *elem) {
414 channel_data *chand = elem->channel_data;
415 call_data *calld = elem->call_data;
416 grpc_server *server = chand->server;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800417 gpr_uint32 i;
418 gpr_uint32 hash;
419 channel_registered_method *rm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800420
Craig Tiller04cc8be2015-02-10 16:11:22 -0800421 if (chand->registered_methods && calld->path && calld->host) {
Craig Tillera94beff2015-02-17 22:02:06 -0800422 /* TODO(ctiller): unify these two searches */
Craig Tiller04cc8be2015-02-10 16:11:22 -0800423 /* check for an exact match with host */
424 hash = GRPC_MDSTR_KV_HASH(calld->host->hash, calld->path->hash);
425 for (i = 0; i < chand->registered_method_max_probes; i++) {
Craig Tiller3b29b562015-02-11 12:58:46 -0800426 rm = &chand->registered_methods[(hash + i) %
427 chand->registered_method_slots];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800428 if (!rm) break;
429 if (rm->host != calld->host) continue;
430 if (rm->method != calld->path) continue;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700431 finish_start_new_rpc(server, elem, &rm->server_registered_method->pending,
Craig Tillerea0c3612015-07-08 15:43:18 -0700432 &rm->server_registered_method->requests);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800433 return;
434 }
435 /* check for a wildcard method definition (no host set) */
436 hash = GRPC_MDSTR_KV_HASH(0, calld->path->hash);
Craig Tiller0ef1a922015-02-11 16:23:01 -0800437 for (i = 0; i <= chand->registered_method_max_probes; i++) {
Craig Tiller3b29b562015-02-11 12:58:46 -0800438 rm = &chand->registered_methods[(hash + i) %
439 chand->registered_method_slots];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800440 if (!rm) break;
441 if (rm->host != NULL) continue;
442 if (rm->method != calld->path) continue;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700443 finish_start_new_rpc(server, elem, &rm->server_registered_method->pending,
Craig Tillerea0c3612015-07-08 15:43:18 -0700444 &rm->server_registered_method->requests);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800445 return;
446 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800447 }
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700448 finish_start_new_rpc(server, elem, &server->lists[PENDING_START],
Craig Tillerea0c3612015-07-08 15:43:18 -0700449 &server->requests);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800450}
451
ctiller58393c22015-01-07 14:03:30 -0800452static void kill_zombie(void *elem, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800453 grpc_call_destroy(grpc_call_from_top_element(elem));
454}
455
Craig Tilleree945e82015-05-26 16:15:34 -0700456static int num_listeners(grpc_server *server) {
457 listener *l;
458 int n = 0;
459 for (l = server->listeners; l; l = l->next) {
460 n++;
461 }
462 return n;
463}
464
Craig Tiller97fc6a32015-07-08 15:31:35 -0700465static void done_shutdown_event(void *server, grpc_cq_completion *completion) {
466 server_unref(server);
467}
468
Craig Tillerdc627722015-05-26 15:27:02 -0700469static void maybe_finish_shutdown(grpc_server *server) {
Craig Tillerbce999f2015-05-27 09:55:51 -0700470 size_t i;
Craig Tillerc4a1f522015-05-29 22:32:04 -0700471 if (!server->shutdown || server->shutdown_published) {
472 return;
473 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700474
Craig Tillerc4a1f522015-05-29 22:32:04 -0700475 if (server->root_channel_data.next != &server->root_channel_data) {
476 gpr_log(GPR_DEBUG,
Craig Tiller3e9ff5c2015-05-29 23:03:13 -0700477 "Waiting for all channels to close before destroying server");
Craig Tillerc4a1f522015-05-29 22:32:04 -0700478 return;
479 }
480 if (server->listeners_destroyed < num_listeners(server)) {
481 gpr_log(GPR_DEBUG, "Waiting for all listeners to be destroyed (@ %d/%d)",
482 server->listeners_destroyed, num_listeners(server));
483 return;
484 }
485 server->shutdown_published = 1;
486 for (i = 0; i < server->num_shutdown_tags; i++) {
Craig Tiller97fc6a32015-07-08 15:31:35 -0700487 server_ref(server);
Craig Tiller12cf5372015-07-09 13:48:11 -0700488 grpc_cq_end_op(server->shutdown_tags[i].cq, server->shutdown_tags[i].tag, 1,
489 done_shutdown_event, server,
490 &server->shutdown_tags[i].completion);
Craig Tillerdc627722015-05-26 15:27:02 -0700491 }
492}
493
Craig Tiller6902ad22015-04-16 08:01:49 -0700494static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
495 grpc_call_element *elem = user_data;
Craig Tillercce17ac2015-01-20 09:29:28 -0800496 channel_data *chand = elem->channel_data;
497 call_data *calld = elem->call_data;
Craig Tiller6902ad22015-04-16 08:01:49 -0700498 if (md->key == chand->path_key) {
Craig Tiller1a65a232015-07-06 10:22:32 -0700499 calld->path = GRPC_MDSTR_REF(md->value);
Craig Tiller6902ad22015-04-16 08:01:49 -0700500 return NULL;
501 } else if (md->key == chand->authority_key) {
Craig Tiller1a65a232015-07-06 10:22:32 -0700502 calld->host = GRPC_MDSTR_REF(md->value);
Craig Tiller6902ad22015-04-16 08:01:49 -0700503 return NULL;
504 }
505 return md;
506}
507
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700508static void server_on_recv(void *ptr, int success) {
509 grpc_call_element *elem = ptr;
Craig Tiller6902ad22015-04-16 08:01:49 -0700510 call_data *calld = elem->call_data;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700511 channel_data *chand = elem->channel_data;
512
513 if (success && !calld->got_initial_metadata) {
514 size_t i;
515 size_t nops = calld->recv_ops->nops;
516 grpc_stream_op *ops = calld->recv_ops->ops;
517 for (i = 0; i < nops; i++) {
518 grpc_stream_op *op = &ops[i];
519 if (op->type != GRPC_OP_METADATA) continue;
Craig Tiller205aee12015-04-16 14:46:41 -0700520 grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700521 if (0 != gpr_time_cmp(op->data.metadata.deadline, gpr_inf_future)) {
Craig Tiller6902ad22015-04-16 08:01:49 -0700522 calld->deadline = op->data.metadata.deadline;
Craig Tillercce17ac2015-01-20 09:29:28 -0800523 }
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700524 calld->got_initial_metadata = 1;
525 start_new_rpc(elem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800526 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700527 }
528 }
529
530 switch (*calld->recv_state) {
Craig Tiller06aeea72015-04-23 10:54:45 -0700531 case GRPC_STREAM_OPEN:
532 break;
533 case GRPC_STREAM_SEND_CLOSED:
534 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700535 case GRPC_STREAM_RECV_CLOSED:
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700536 gpr_mu_lock(&calld->mu_state);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700537 if (calld->state == NOT_STARTED) {
538 calld->state = ZOMBIED;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700539 gpr_mu_unlock(&calld->mu_state);
David Garcia Quintas284488b2015-05-28 16:27:39 -0700540 grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
541 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700542 } else {
543 gpr_mu_unlock(&calld->mu_state);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700544 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800545 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700546 case GRPC_STREAM_CLOSED:
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700547 gpr_mu_lock(&calld->mu_state);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700548 if (calld->state == NOT_STARTED) {
549 calld->state = ZOMBIED;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700550 gpr_mu_unlock(&calld->mu_state);
David Garcia Quintas284488b2015-05-28 16:27:39 -0700551 grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
552 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700553 } else if (calld->state == PENDING) {
Craig Tillerc9d03822015-05-20 16:08:45 -0700554 calld->state = ZOMBIED;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700555 gpr_mu_unlock(&calld->mu_state);
556 gpr_mu_lock(&chand->server->mu_call);
557 call_list_remove(calld, PENDING_START);
558 gpr_mu_unlock(&chand->server->mu_call);
David Garcia Quintas284488b2015-05-28 16:27:39 -0700559 grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
560 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700561 } else {
562 gpr_mu_unlock(&calld->mu_state);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700563 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800564 break;
565 }
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700566
Craig Tiller1e6facb2015-06-11 22:47:11 -0700567 calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700568}
569
Craig Tillerb7959a02015-06-25 08:50:54 -0700570static void server_mutate_op(grpc_call_element *elem,
571 grpc_transport_stream_op *op) {
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700572 call_data *calld = elem->call_data;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700573
574 if (op->recv_ops) {
575 /* substitute our callback for the higher callback */
576 calld->recv_ops = op->recv_ops;
577 calld->recv_state = op->recv_state;
578 calld->on_done_recv = op->on_done_recv;
Craig Tiller1e6facb2015-06-11 22:47:11 -0700579 op->on_done_recv = &calld->server_on_recv;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700580 }
Craig Tiller50d9db52015-04-23 10:52:14 -0700581}
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700582
Craig Tillere039f032015-06-25 12:54:23 -0700583static void server_start_transport_stream_op(grpc_call_element *elem,
584 grpc_transport_stream_op *op) {
Craig Tiller50d9db52015-04-23 10:52:14 -0700585 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
586 server_mutate_op(elem, op);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700587 grpc_call_next_op(elem, op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800588}
589
Craig Tillere039f032015-06-25 12:54:23 -0700590static void accept_stream(void *cd, grpc_transport *transport,
591 const void *transport_server_data) {
592 channel_data *chand = cd;
593 /* create a call */
594 grpc_call_create(chand->channel, NULL, transport_server_data, NULL, 0,
595 gpr_inf_future);
596}
597
598static void channel_connectivity_changed(void *cd, int iomgr_status_ignored) {
599 channel_data *chand = cd;
600 grpc_server *server = chand->server;
601 if (chand->connectivity_state != GRPC_CHANNEL_FATAL_FAILURE) {
602 grpc_transport_op op;
603 memset(&op, 0, sizeof(op));
604 op.on_connectivity_state_change = &chand->channel_connectivity_changed,
605 op.connectivity_state = &chand->connectivity_state;
606 grpc_channel_next_op(grpc_channel_stack_element(
607 grpc_channel_get_channel_stack(chand->channel), 0),
608 &op);
609 } else {
610 gpr_mu_lock(&server->mu_global);
611 destroy_channel(chand);
612 gpr_mu_unlock(&server->mu_global);
613 GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "connectivity");
614 }
615}
616
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800617static void init_call_elem(grpc_call_element *elem,
Craig Tiller06aeea72015-04-23 10:54:45 -0700618 const void *server_transport_data,
Craig Tillerb7959a02015-06-25 08:50:54 -0700619 grpc_transport_stream_op *initial_op) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800620 call_data *calld = elem->call_data;
621 channel_data *chand = elem->channel_data;
622 memset(calld, 0, sizeof(call_data));
623 calld->deadline = gpr_inf_future;
624 calld->call = grpc_call_from_top_element(elem);
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700625 gpr_mu_init(&calld->mu_state);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800626
Craig Tiller1e6facb2015-06-11 22:47:11 -0700627 grpc_iomgr_closure_init(&calld->server_on_recv, server_on_recv, elem);
628
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800629 server_ref(chand->server);
Craig Tiller50d9db52015-04-23 10:52:14 -0700630
Craig Tiller482ef8b2015-04-23 11:38:20 -0700631 if (initial_op) server_mutate_op(elem, initial_op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800632}
633
634static void destroy_call_elem(grpc_call_element *elem) {
635 channel_data *chand = elem->channel_data;
Craig Tillerdb7db992015-01-29 11:19:01 -0800636 call_data *calld = elem->call_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800637
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700638 if (calld->state == PENDING) {
639 gpr_mu_lock(&chand->server->mu_call);
640 call_list_remove(elem->call_data, PENDING_START);
641 gpr_mu_unlock(&chand->server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800642 }
Craig Tiller092d8d12015-07-04 22:35:00 -0700643
Craig Tiller4df31a62015-01-30 09:44:31 -0800644 if (calld->host) {
Craig Tiller1a65a232015-07-06 10:22:32 -0700645 GRPC_MDSTR_UNREF(calld->host);
Craig Tiller4df31a62015-01-30 09:44:31 -0800646 }
647 if (calld->path) {
Craig Tiller1a65a232015-07-06 10:22:32 -0700648 GRPC_MDSTR_UNREF(calld->path);
Craig Tiller4df31a62015-01-30 09:44:31 -0800649 }
650
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700651 gpr_mu_destroy(&calld->mu_state);
652
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800653 server_unref(chand->server);
654}
655
Craig Tiller079a11b2015-06-30 10:07:15 -0700656static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800657 const grpc_channel_args *args,
658 grpc_mdctx *metadata_context, int is_first,
659 int is_last) {
660 channel_data *chand = elem->channel_data;
661 GPR_ASSERT(is_first);
662 GPR_ASSERT(!is_last);
663 chand->server = NULL;
664 chand->channel = NULL;
Craig Tillercce17ac2015-01-20 09:29:28 -0800665 chand->path_key = grpc_mdstr_from_string(metadata_context, ":path");
666 chand->authority_key = grpc_mdstr_from_string(metadata_context, ":authority");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800667 chand->next = chand->prev = chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800668 chand->registered_methods = NULL;
Craig Tillere039f032015-06-25 12:54:23 -0700669 chand->connectivity_state = GRPC_CHANNEL_IDLE;
670 grpc_iomgr_closure_init(&chand->channel_connectivity_changed,
671 channel_connectivity_changed, chand);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800672}
673
674static void destroy_channel_elem(grpc_channel_element *elem) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800675 size_t i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800676 channel_data *chand = elem->channel_data;
Craig Tillerec3257c2015-02-12 15:59:43 -0800677 if (chand->registered_methods) {
678 for (i = 0; i < chand->registered_method_slots; i++) {
679 if (chand->registered_methods[i].method) {
Craig Tiller1a65a232015-07-06 10:22:32 -0700680 GRPC_MDSTR_UNREF(chand->registered_methods[i].method);
Craig Tillerec3257c2015-02-12 15:59:43 -0800681 }
682 if (chand->registered_methods[i].host) {
Craig Tiller1a65a232015-07-06 10:22:32 -0700683 GRPC_MDSTR_UNREF(chand->registered_methods[i].host);
Craig Tillerec3257c2015-02-12 15:59:43 -0800684 }
685 }
686 gpr_free(chand->registered_methods);
687 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800688 if (chand->server) {
Vijay Pai8931cdd2015-06-17 12:42:17 -0700689 gpr_mu_lock(&chand->server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800690 chand->next->prev = chand->prev;
691 chand->prev->next = chand->next;
692 chand->next = chand->prev = chand;
Craig Tillerb76d05b2015-05-29 17:21:56 -0700693 maybe_finish_shutdown(chand->server);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700694 gpr_mu_unlock(&chand->server->mu_global);
Craig Tiller1a65a232015-07-06 10:22:32 -0700695 GRPC_MDSTR_UNREF(chand->path_key);
696 GRPC_MDSTR_UNREF(chand->authority_key);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800697 server_unref(chand->server);
698 }
699}
700
701static const grpc_channel_filter server_surface_filter = {
Craig Tillere039f032015-06-25 12:54:23 -0700702 server_start_transport_stream_op,
703 grpc_channel_next_op,
Craig Tillerb76d05b2015-05-29 17:21:56 -0700704 sizeof(call_data),
705 init_call_elem,
706 destroy_call_elem,
707 sizeof(channel_data),
708 init_channel_elem,
709 destroy_channel_elem,
710 "server",
Craig Tiller9f28ac22015-01-27 17:01:29 -0800711};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800712
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700713void grpc_server_register_completion_queue(grpc_server *server,
714 grpc_completion_queue *cq) {
Craig Tiller20bc56d2015-02-12 09:02:56 -0800715 size_t i, n;
716 for (i = 0; i < server->cq_count; i++) {
717 if (server->cqs[i] == cq) return;
718 }
Craig Tiller463f2372015-05-28 16:16:15 -0700719 GRPC_CQ_INTERNAL_REF(cq, "server");
Craig Tillerb56975c2015-06-15 10:11:16 -0700720 grpc_cq_mark_server_cq(cq);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800721 n = server->cq_count++;
Craig Tillerec3257c2015-02-12 15:59:43 -0800722 server->cqs = gpr_realloc(server->cqs,
723 server->cq_count * sizeof(grpc_completion_queue *));
Craig Tiller20bc56d2015-02-12 09:02:56 -0800724 server->cqs[n] = cq;
725}
726
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700727grpc_server *grpc_server_create_from_filters(grpc_channel_filter **filters,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800728 size_t filter_count,
729 const grpc_channel_args *args) {
730 size_t i;
Alistair Veitch9d48ebf2015-06-01 10:01:03 -0700731 /* TODO(census): restore this once we finalize census filter etc.
732 int census_enabled = grpc_channel_args_is_census_enabled(args); */
733 int census_enabled = 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800734
735 grpc_server *server = gpr_malloc(sizeof(grpc_server));
Craig Tiller60fd3612015-03-05 16:24:22 -0800736
737 GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
738
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800739 memset(server, 0, sizeof(grpc_server));
740
Vijay Pai8931cdd2015-06-17 12:42:17 -0700741 gpr_mu_init(&server->mu_global);
742 gpr_mu_init(&server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800743
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800744 /* decremented by grpc_server_destroy */
745 gpr_ref_init(&server->internal_refcount, 1);
746 server->root_channel_data.next = server->root_channel_data.prev =
747 &server->root_channel_data;
748
749 /* Server filter stack is:
750
751 server_surface_filter - for making surface API calls
752 grpc_server_census_filter (optional) - for stats collection and tracing
753 {passed in filter stack}
754 grpc_connected_channel_filter - for interfacing with transports */
755 server->channel_filter_count = filter_count + 1 + census_enabled;
756 server->channel_filters =
757 gpr_malloc(server->channel_filter_count * sizeof(grpc_channel_filter *));
758 server->channel_filters[0] = &server_surface_filter;
Alistair Veitch9d48ebf2015-06-01 10:01:03 -0700759 /* TODO(census): restore this once we rework census filter
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800760 if (census_enabled) {
761 server->channel_filters[1] = &grpc_server_census_filter;
Alistair Veitch9686dab2015-05-26 14:26:47 -0700762 } */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800763 for (i = 0; i < filter_count; i++) {
764 server->channel_filters[i + 1 + census_enabled] = filters[i];
765 }
766
767 server->channel_args = grpc_channel_args_copy(args);
768
769 return server;
770}
771
Craig Tiller24be0f72015-02-10 14:04:22 -0800772static int streq(const char *a, const char *b) {
773 if (a == NULL && b == NULL) return 1;
774 if (a == NULL) return 0;
775 if (b == NULL) return 0;
776 return 0 == strcmp(a, b);
777}
778
779void *grpc_server_register_method(grpc_server *server, const char *method,
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700780 const char *host) {
Craig Tiller24be0f72015-02-10 14:04:22 -0800781 registered_method *m;
782 if (!method) {
Craig Tillerb76d05b2015-05-29 17:21:56 -0700783 gpr_log(GPR_ERROR,
784 "grpc_server_register_method method string cannot be NULL");
Craig Tiller24be0f72015-02-10 14:04:22 -0800785 return NULL;
786 }
787 for (m = server->registered_methods; m; m = m->next) {
788 if (streq(m->method, method) && streq(m->host, host)) {
789 gpr_log(GPR_ERROR, "duplicate registration for %s@%s", method,
790 host ? host : "*");
791 return NULL;
792 }
793 }
794 m = gpr_malloc(sizeof(registered_method));
795 memset(m, 0, sizeof(*m));
796 m->method = gpr_strdup(method);
797 m->host = gpr_strdup(host);
798 m->next = server->registered_methods;
799 server->registered_methods = m;
800 return m;
801}
802
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800803void grpc_server_start(grpc_server *server) {
804 listener *l;
Craig Tiller20bc56d2015-02-12 09:02:56 -0800805 size_t i;
806
Craig Tillerec3257c2015-02-12 15:59:43 -0800807 server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800808 for (i = 0; i < server->cq_count; i++) {
809 server->pollsets[i] = grpc_cq_pollset(server->cqs[i]);
810 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800811
812 for (l = server->listeners; l; l = l->next) {
Craig Tiller20bc56d2015-02-12 09:02:56 -0800813 l->start(server, l->arg, server->pollsets, server->cq_count);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800814 }
815}
816
Craig Tiller1064f8b2015-06-25 13:52:57 -0700817void grpc_server_setup_transport(grpc_server *s, grpc_transport *transport,
818 grpc_channel_filter const **extra_filters,
819 size_t num_extra_filters, grpc_mdctx *mdctx,
820 const grpc_channel_args *args) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800821 size_t num_filters = s->channel_filter_count + num_extra_filters + 1;
822 grpc_channel_filter const **filters =
823 gpr_malloc(sizeof(grpc_channel_filter *) * num_filters);
824 size_t i;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800825 size_t num_registered_methods;
826 size_t alloc;
827 registered_method *rm;
828 channel_registered_method *crm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800829 grpc_channel *channel;
830 channel_data *chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800831 grpc_mdstr *host;
832 grpc_mdstr *method;
833 gpr_uint32 hash;
834 gpr_uint32 slots;
835 gpr_uint32 probes;
836 gpr_uint32 max_probes = 0;
Craig Tillere039f032015-06-25 12:54:23 -0700837 grpc_transport_op op;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800838
839 for (i = 0; i < s->channel_filter_count; i++) {
840 filters[i] = s->channel_filters[i];
841 }
842 for (; i < s->channel_filter_count + num_extra_filters; i++) {
843 filters[i] = extra_filters[i - s->channel_filter_count];
844 }
845 filters[i] = &grpc_connected_channel_filter;
846
Craig Tiller20bc56d2015-02-12 09:02:56 -0800847 for (i = 0; i < s->cq_count; i++) {
Craig Tillere039f032015-06-25 12:54:23 -0700848 memset(&op, 0, sizeof(op));
849 op.bind_pollset = grpc_cq_pollset(s->cqs[i]);
850 grpc_transport_perform_op(transport, &op);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800851 }
ctillerd79b4862014-12-17 16:36:59 -0800852
Julien Boeufc6f8d0a2015-05-11 22:40:02 -0700853 channel =
854 grpc_channel_create_from_filters(filters, num_filters, args, mdctx, 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800855 chand = (channel_data *)grpc_channel_stack_element(
Craig Tillerc02c1d82015-04-07 16:21:55 -0700856 grpc_channel_get_channel_stack(channel), 0)
857 ->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800858 chand->server = s;
859 server_ref(s);
860 chand->channel = channel;
861
Craig Tiller04cc8be2015-02-10 16:11:22 -0800862 num_registered_methods = 0;
863 for (rm = s->registered_methods; rm; rm = rm->next) {
864 num_registered_methods++;
865 }
866 /* build a lookup table phrased in terms of mdstr's in this channels context
867 to quickly find registered methods */
868 if (num_registered_methods > 0) {
869 slots = 2 * num_registered_methods;
870 alloc = sizeof(channel_registered_method) * slots;
871 chand->registered_methods = gpr_malloc(alloc);
872 memset(chand->registered_methods, 0, alloc);
873 for (rm = s->registered_methods; rm; rm = rm->next) {
874 host = rm->host ? grpc_mdstr_from_string(mdctx, rm->host) : NULL;
Craig Tillere76c9662015-02-11 13:18:31 -0800875 method = grpc_mdstr_from_string(mdctx, rm->method);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800876 hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash);
Craig Tiller3b29b562015-02-11 12:58:46 -0800877 for (probes = 0; chand->registered_methods[(hash + probes) % slots]
Craig Tillerc02c1d82015-04-07 16:21:55 -0700878 .server_registered_method != NULL;
Craig Tiller3b29b562015-02-11 12:58:46 -0800879 probes++)
880 ;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800881 if (probes > max_probes) max_probes = probes;
882 crm = &chand->registered_methods[(hash + probes) % slots];
883 crm->server_registered_method = rm;
884 crm->host = host;
885 crm->method = method;
886 }
887 chand->registered_method_slots = slots;
888 chand->registered_method_max_probes = max_probes;
889 }
890
Craig Tiller1064f8b2015-06-25 13:52:57 -0700891 grpc_connected_channel_bind_transport(grpc_channel_get_channel_stack(channel),
892 transport);
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800893
Vijay Pai8931cdd2015-06-17 12:42:17 -0700894 gpr_mu_lock(&s->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800895 chand->next = &s->root_channel_data;
896 chand->prev = chand->next->prev;
897 chand->next->prev = chand->prev->next = chand;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700898 gpr_mu_unlock(&s->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800899
900 gpr_free(filters);
Craig Tiller4b804102015-06-26 16:16:12 -0700901
902 GRPC_CHANNEL_INTERNAL_REF(channel, "connectivity");
903 memset(&op, 0, sizeof(op));
904 op.set_accept_stream = accept_stream;
905 op.set_accept_stream_user_data = chand;
906 op.on_connectivity_state_change = &chand->channel_connectivity_changed;
907 op.connectivity_state = &chand->connectivity_state;
908 grpc_transport_perform_op(transport, &op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800909}
910
Craig Tillerbce999f2015-05-27 09:55:51 -0700911void grpc_server_shutdown_and_notify(grpc_server *server,
912 grpc_completion_queue *cq, void *tag) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800913 listener *l;
Craig Tiller97fc6a32015-07-08 15:31:35 -0700914 requested_call *requests = NULL;
Craig Tillerbd217572015-02-11 18:10:56 -0800915 registered_method *rm;
Craig Tillerbce999f2015-05-27 09:55:51 -0700916 shutdown_tag *sdt;
Craig Tillerff3ae682015-06-29 17:44:04 -0700917 channel_broadcaster broadcaster;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800918
919 /* lock, and gather up some stuff to do */
Vijay Pai8931cdd2015-06-17 12:42:17 -0700920 gpr_mu_lock(&server->mu_global);
Craig Tiller97fc6a32015-07-08 15:31:35 -0700921 grpc_cq_begin_op(cq);
Craig Tilleree945e82015-05-26 16:15:34 -0700922 server->shutdown_tags =
923 gpr_realloc(server->shutdown_tags,
Craig Tiller208d2122015-05-29 08:50:08 -0700924 sizeof(shutdown_tag) * (server->num_shutdown_tags + 1));
Craig Tillerbce999f2015-05-27 09:55:51 -0700925 sdt = &server->shutdown_tags[server->num_shutdown_tags++];
926 sdt->tag = tag;
927 sdt->cq = cq;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800928 if (server->shutdown) {
Vijay Pai8931cdd2015-06-17 12:42:17 -0700929 gpr_mu_unlock(&server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800930 return;
931 }
932
Craig Tillerff3ae682015-06-29 17:44:04 -0700933 channel_broadcaster_init(server, &broadcaster);
nnoble0c475f02014-12-05 15:37:39 -0800934
Craig Tillerbd217572015-02-11 18:10:56 -0800935 /* collect all unregistered then registered calls */
Vijay Pai8931cdd2015-06-17 12:42:17 -0700936 gpr_mu_lock(&server->mu_call);
Craig Tiller97fc6a32015-07-08 15:31:35 -0700937 requests = server->requests;
938 server->requests = NULL;
Craig Tillerbd217572015-02-11 18:10:56 -0800939 for (rm = server->registered_methods; rm; rm = rm->next) {
Craig Tiller97fc6a32015-07-08 15:31:35 -0700940 while (rm->requests != NULL) {
941 requested_call *c = rm->requests;
942 rm->requests = c->next;
943 c->next = requests;
944 requests = c;
Craig Tillerbd217572015-02-11 18:10:56 -0800945 }
Craig Tillerbd217572015-02-11 18:10:56 -0800946 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700947 gpr_mu_unlock(&server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800948
949 server->shutdown = 1;
Craig Tillerdc627722015-05-26 15:27:02 -0700950 maybe_finish_shutdown(server);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700951 gpr_mu_unlock(&server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800952
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800953 /* terminate all the requested calls */
Craig Tiller97fc6a32015-07-08 15:31:35 -0700954 while (requests != NULL) {
955 requested_call *next = requests->next;
956 fail_call(server, requests);
957 requests = next;
Craig Tillercce17ac2015-01-20 09:29:28 -0800958 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800959
960 /* Shutdown listeners */
961 for (l = server->listeners; l; l = l->next) {
962 l->destroy(server, l->arg);
963 }
Craig Tillerff3ae682015-06-29 17:44:04 -0700964
965 channel_broadcaster_shutdown(&broadcaster, 1, 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800966}
967
Craig Tilleraec96aa2015-04-07 14:32:15 -0700968void grpc_server_listener_destroy_done(void *s) {
969 grpc_server *server = s;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700970 gpr_mu_lock(&server->mu_global);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700971 server->listeners_destroyed++;
Craig Tilleree945e82015-05-26 16:15:34 -0700972 maybe_finish_shutdown(server);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700973 gpr_mu_unlock(&server->mu_global);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700974}
975
Craig Tillerafa2d632015-05-26 16:39:13 -0700976void grpc_server_cancel_all_calls(grpc_server *server) {
Craig Tiller092d8d12015-07-04 22:35:00 -0700977 channel_broadcaster broadcaster;
Craig Tillerafa2d632015-05-26 16:39:13 -0700978
Craig Tiller092d8d12015-07-04 22:35:00 -0700979 gpr_mu_lock(&server->mu_global);
980 channel_broadcaster_init(server, &broadcaster);
981 gpr_mu_unlock(&server->mu_global);
Craig Tillerafa2d632015-05-26 16:39:13 -0700982
Craig Tiller092d8d12015-07-04 22:35:00 -0700983 channel_broadcaster_shutdown(&broadcaster, 0, 1);
Craig Tillerafa2d632015-05-26 16:39:13 -0700984}
985
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800986void grpc_server_destroy(grpc_server *server) {
Craig Tilleraec96aa2015-04-07 14:32:15 -0700987 listener *l;
Craig Tiller872af022015-04-24 15:57:52 -0700988
Vijay Pai8931cdd2015-06-17 12:42:17 -0700989 gpr_mu_lock(&server->mu_global);
Masood Malekghassemi38bb18f2015-06-10 17:32:02 -0700990 GPR_ASSERT(server->shutdown || !server->listeners);
Craig Tilleree945e82015-05-26 16:15:34 -0700991 GPR_ASSERT(server->listeners_destroyed == num_listeners(server));
Craig Tilleraec96aa2015-04-07 14:32:15 -0700992
993 while (server->listeners) {
994 l = server->listeners;
995 server->listeners = l->next;
996 gpr_free(l);
997 }
998
Vijay Pai8931cdd2015-06-17 12:42:17 -0700999 gpr_mu_unlock(&server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001000
1001 server_unref(server);
1002}
1003
1004void grpc_server_add_listener(grpc_server *server, void *arg,
ctiller58393c22015-01-07 14:03:30 -08001005 void (*start)(grpc_server *server, void *arg,
Craig Tillerec3257c2015-02-12 15:59:43 -08001006 grpc_pollset **pollsets,
1007 size_t pollset_count),
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001008 void (*destroy)(grpc_server *server, void *arg)) {
1009 listener *l = gpr_malloc(sizeof(listener));
1010 l->arg = arg;
1011 l->start = start;
1012 l->destroy = destroy;
1013 l->next = server->listeners;
1014 server->listeners = l;
1015}
1016
Craig Tiller9f28ac22015-01-27 17:01:29 -08001017static grpc_call_error queue_call_request(grpc_server *server,
Craig Tiller24be0f72015-02-10 14:04:22 -08001018 requested_call *rc) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001019 call_data *calld = NULL;
Craig Tillerb4c55ea2015-07-08 15:39:27 -07001020 requested_call **requests = NULL;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001021 gpr_mu_lock(&server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001022 if (server->shutdown) {
Vijay Pai8931cdd2015-06-17 12:42:17 -07001023 gpr_mu_unlock(&server->mu_call);
Craig Tiller24be0f72015-02-10 14:04:22 -08001024 fail_call(server, rc);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001025 return GRPC_CALL_OK;
1026 }
Craig Tiller04cc8be2015-02-10 16:11:22 -08001027 switch (rc->type) {
Craig Tiller04cc8be2015-02-10 16:11:22 -08001028 case BATCH_CALL:
Craig Tiller3b29b562015-02-11 12:58:46 -08001029 calld =
1030 call_list_remove_head(&server->lists[PENDING_START], PENDING_START);
Craig Tiller97fc6a32015-07-08 15:31:35 -07001031 requests = &server->requests;
Craig Tiller04cc8be2015-02-10 16:11:22 -08001032 break;
1033 case REGISTERED_CALL:
Craig Tiller3b29b562015-02-11 12:58:46 -08001034 calld = call_list_remove_head(
1035 &rc->data.registered.registered_method->pending, PENDING_START);
Craig Tiller97fc6a32015-07-08 15:31:35 -07001036 requests = &rc->data.registered.registered_method->requests;
Craig Tiller04cc8be2015-02-10 16:11:22 -08001037 break;
1038 }
Craig Tiller76d2c3b2015-07-07 11:46:01 -07001039 if (calld != NULL) {
1040 gpr_mu_unlock(&server->mu_call);
1041 gpr_mu_lock(&calld->mu_state);
Craig Tillercce17ac2015-01-20 09:29:28 -08001042 GPR_ASSERT(calld->state == PENDING);
Craig Tillerbb3f22f2015-01-29 16:40:56 -08001043 calld->state = ACTIVATED;
Craig Tiller76d2c3b2015-07-07 11:46:01 -07001044 gpr_mu_unlock(&calld->mu_state);
Craig Tiller24be0f72015-02-10 14:04:22 -08001045 begin_call(server, calld, rc);
Craig Tillercce17ac2015-01-20 09:29:28 -08001046 return GRPC_CALL_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001047 } else {
Craig Tiller97fc6a32015-07-08 15:31:35 -07001048 rc->next = *requests;
1049 *requests = rc;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001050 gpr_mu_unlock(&server->mu_call);
Craig Tillercce17ac2015-01-20 09:29:28 -08001051 return GRPC_CALL_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001052 }
Craig Tillercce17ac2015-01-20 09:29:28 -08001053}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001054
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001055grpc_call_error grpc_server_request_call(
1056 grpc_server *server, grpc_call **call, grpc_call_details *details,
1057 grpc_metadata_array *initial_metadata,
1058 grpc_completion_queue *cq_bound_to_call,
1059 grpc_completion_queue *cq_for_notification, void *tag) {
Craig Tiller97fc6a32015-07-08 15:31:35 -07001060 requested_call *rc = gpr_malloc(sizeof(*rc));
murgatroid99ad7c20c2015-05-22 14:42:29 -07001061 GRPC_SERVER_LOG_REQUEST_CALL(GPR_INFO, server, call, details,
1062 initial_metadata, cq_bound_to_call,
1063 cq_for_notification, tag);
Craig Tillerb56975c2015-06-15 10:11:16 -07001064 if (!grpc_cq_is_server_cq(cq_for_notification)) {
Craig Tiller97fc6a32015-07-08 15:31:35 -07001065 gpr_free(rc);
Craig Tillerb56975c2015-06-15 10:11:16 -07001066 return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
1067 }
Craig Tiller97fc6a32015-07-08 15:31:35 -07001068 grpc_cq_begin_op(cq_for_notification);
1069 rc->type = BATCH_CALL;
1070 rc->tag = tag;
1071 rc->cq_bound_to_call = cq_bound_to_call;
1072 rc->cq_for_notification = cq_for_notification;
1073 rc->call = call;
1074 rc->data.batch.details = details;
1075 rc->data.batch.initial_metadata = initial_metadata;
1076 return queue_call_request(server, rc);
Craig Tiller24be0f72015-02-10 14:04:22 -08001077}
1078
1079grpc_call_error grpc_server_request_registered_call(
Craig Tillerec3257c2015-02-12 15:59:43 -08001080 grpc_server *server, void *rm, grpc_call **call, gpr_timespec *deadline,
1081 grpc_metadata_array *initial_metadata, grpc_byte_buffer **optional_payload,
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001082 grpc_completion_queue *cq_bound_to_call,
1083 grpc_completion_queue *cq_for_notification, void *tag) {
Craig Tiller97fc6a32015-07-08 15:31:35 -07001084 requested_call *rc = gpr_malloc(sizeof(*rc));
Craig Tiller20bc56d2015-02-12 09:02:56 -08001085 registered_method *registered_method = rm;
Craig Tillerb56975c2015-06-15 10:11:16 -07001086 if (!grpc_cq_is_server_cq(cq_for_notification)) {
Craig Tiller97fc6a32015-07-08 15:31:35 -07001087 gpr_free(rc);
Craig Tillerb56975c2015-06-15 10:11:16 -07001088 return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
1089 }
Craig Tiller97fc6a32015-07-08 15:31:35 -07001090 grpc_cq_begin_op(cq_for_notification);
1091 rc->type = REGISTERED_CALL;
1092 rc->tag = tag;
1093 rc->cq_bound_to_call = cq_bound_to_call;
1094 rc->cq_for_notification = cq_for_notification;
1095 rc->call = call;
1096 rc->data.registered.registered_method = registered_method;
1097 rc->data.registered.deadline = deadline;
1098 rc->data.registered.initial_metadata = initial_metadata;
1099 rc->data.registered.optional_payload = optional_payload;
1100 return queue_call_request(server, rc);
Craig Tiller24be0f72015-02-10 14:04:22 -08001101}
1102
Craig Tiller64be9f72015-05-04 14:53:51 -07001103static void publish_registered_or_batch(grpc_call *call, int success,
Craig Tiller24be0f72015-02-10 14:04:22 -08001104 void *tag);
Craig Tiller64be9f72015-05-04 14:53:51 -07001105static void publish_was_not_set(grpc_call *call, int success, void *tag) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001106 abort();
1107}
Craig Tiller24be0f72015-02-10 14:04:22 -08001108
Craig Tiller166e2502015-02-03 20:14:41 -08001109static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
1110 gpr_slice slice = value->slice;
1111 size_t len = GPR_SLICE_LENGTH(slice);
1112
1113 if (len + 1 > *capacity) {
1114 *capacity = GPR_MAX(len + 1, *capacity * 2);
1115 *dest = gpr_realloc(*dest, *capacity);
1116 }
1117 memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
1118}
1119
Craig Tiller24be0f72015-02-10 14:04:22 -08001120static void begin_call(grpc_server *server, call_data *calld,
1121 requested_call *rc) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001122 grpc_ioreq_completion_func publish = publish_was_not_set;
Craig Tiller24be0f72015-02-10 14:04:22 -08001123 grpc_ioreq req[2];
1124 grpc_ioreq *r = req;
1125
1126 /* called once initial metadata has been read by the call, but BEFORE
1127 the ioreq to fetch it out of the call has been executed.
1128 This means metadata related fields can be relied on in calld, but to
1129 fill in the metadata array passed by the client, we need to perform
1130 an ioreq op, that should complete immediately. */
1131
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001132 grpc_call_set_completion_queue(calld->call, rc->cq_bound_to_call);
1133 *rc->call = calld->call;
1134 calld->cq_new = rc->cq_for_notification;
Craig Tiller24be0f72015-02-10 14:04:22 -08001135 switch (rc->type) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001136 case BATCH_CALL:
Craig Tiller04c5d4b2015-06-26 17:21:41 -07001137 GPR_ASSERT(calld->host != NULL);
1138 GPR_ASSERT(calld->path != NULL);
Craig Tiller24be0f72015-02-10 14:04:22 -08001139 cpstr(&rc->data.batch.details->host,
1140 &rc->data.batch.details->host_capacity, calld->host);
1141 cpstr(&rc->data.batch.details->method,
1142 &rc->data.batch.details->method_capacity, calld->path);
Masood Malekghassemibf177c82015-04-27 12:14:38 -07001143 rc->data.batch.details->deadline = calld->deadline;
Craig Tiller24be0f72015-02-10 14:04:22 -08001144 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1145 r->data.recv_metadata = rc->data.batch.initial_metadata;
David Garcia Quintasb8f54502015-06-15 16:19:10 -07001146 r->flags = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001147 r++;
1148 publish = publish_registered_or_batch;
1149 break;
1150 case REGISTERED_CALL:
1151 *rc->data.registered.deadline = calld->deadline;
Craig Tiller24be0f72015-02-10 14:04:22 -08001152 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1153 r->data.recv_metadata = rc->data.registered.initial_metadata;
David Garcia Quintasb8f54502015-06-15 16:19:10 -07001154 r->flags = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001155 r++;
1156 if (rc->data.registered.optional_payload) {
1157 r->op = GRPC_IOREQ_RECV_MESSAGE;
1158 r->data.recv_message = rc->data.registered.optional_payload;
David Garcia Quintasb8f54502015-06-15 16:19:10 -07001159 r->flags = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001160 r++;
1161 }
1162 publish = publish_registered_or_batch;
1163 break;
1164 }
1165
Craig Tiller4df412b2015-04-28 07:57:54 -07001166 GRPC_CALL_INTERNAL_REF(calld->call, "server");
Craig Tiller12cf5372015-07-09 13:48:11 -07001167 grpc_call_start_ioreq_and_call_back(calld->call, req, r - req, publish, rc);
Craig Tiller97fc6a32015-07-08 15:31:35 -07001168}
1169
1170static void done_request_event(void *req, grpc_cq_completion *c) {
1171 gpr_free(req);
Craig Tiller24be0f72015-02-10 14:04:22 -08001172}
1173
1174static void fail_call(grpc_server *server, requested_call *rc) {
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001175 *rc->call = NULL;
Craig Tiller24be0f72015-02-10 14:04:22 -08001176 switch (rc->type) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001177 case BATCH_CALL:
Craig Tiller24be0f72015-02-10 14:04:22 -08001178 rc->data.batch.initial_metadata->count = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001179 break;
1180 case REGISTERED_CALL:
Craig Tiller24be0f72015-02-10 14:04:22 -08001181 rc->data.registered.initial_metadata->count = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001182 break;
1183 }
Craig Tiller12cf5372015-07-09 13:48:11 -07001184 grpc_cq_end_op(rc->cq_for_notification, rc->tag, 0, done_request_event, rc,
1185 &rc->completion);
Craig Tiller24be0f72015-02-10 14:04:22 -08001186}
1187
Craig Tiller64be9f72015-05-04 14:53:51 -07001188static void publish_registered_or_batch(grpc_call *call, int success,
Craig Tiller97fc6a32015-07-08 15:31:35 -07001189 void *prc) {
Craig Tiller8e8fd892015-02-10 17:02:08 -08001190 grpc_call_element *elem =
1191 grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
Craig Tiller97fc6a32015-07-08 15:31:35 -07001192 requested_call *rc = prc;
Craig Tiller20bc56d2015-02-12 09:02:56 -08001193 call_data *calld = elem->call_data;
Craig Tiller12cf5372015-07-09 13:48:11 -07001194 grpc_cq_end_op(calld->cq_new, rc->tag, success, done_request_event, rc,
1195 &rc->completion);
Craig Tillerc0122582015-07-09 13:21:36 -07001196 GRPC_CALL_INTERNAL_UNREF(call, "server", 0);
Craig Tiller24be0f72015-02-10 14:04:22 -08001197}
1198
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001199const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) {
1200 return server->channel_args;
Craig Tiller190d3602015-02-18 09:23:38 -08001201}
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001202
1203int grpc_server_has_open_connections(grpc_server *server) {
1204 int r;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001205 gpr_mu_lock(&server->mu_global);
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001206 r = server->root_channel_data.next != &server->root_channel_data;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001207 gpr_mu_unlock(&server->mu_global);
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001208 return r;
1209}