blob: ee394bb33a7c0e4cdb308e9da841cb2a55772fa0 [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 Tillerb76d05b2015-05-29 17:21:56 -0700117 size_t num_calls;
Craig Tillere039f032015-06-25 12:54:23 -0700118 grpc_connectivity_state connectivity_state;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800119 grpc_channel *channel;
Craig Tillercce17ac2015-01-20 09:29:28 -0800120 grpc_mdstr *path_key;
121 grpc_mdstr *authority_key;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800122 /* linked list of all channels on a server */
123 channel_data *next;
124 channel_data *prev;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800125 channel_registered_method *registered_methods;
126 gpr_uint32 registered_method_slots;
127 gpr_uint32 registered_method_max_probes;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700128 grpc_iomgr_closure finish_destroy_channel_closure;
Craig Tillere039f032015-06-25 12:54:23 -0700129 grpc_iomgr_closure channel_connectivity_changed;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800130};
131
Craig Tillerbce999f2015-05-27 09:55:51 -0700132typedef struct shutdown_tag {
133 void *tag;
134 grpc_completion_queue *cq;
135} shutdown_tag;
136
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800137struct grpc_server {
138 size_t channel_filter_count;
139 const grpc_channel_filter **channel_filters;
140 grpc_channel_args *channel_args;
Craig Tillerec3257c2015-02-12 15:59:43 -0800141
Craig Tiller20bc56d2015-02-12 09:02:56 -0800142 grpc_completion_queue **cqs;
143 grpc_pollset **pollsets;
144 size_t cq_count;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800145
Vijay Paid2a82d92015-06-17 13:42:46 -0700146 /* The two following mutexes control access to server-state
147 mu_global controls access to non-call-related state (e.g., channel state)
148 mu_call controls access to call-related state (e.g., the call lists)
149
150 If they are ever required to be nested, you must lock mu_global
151 before mu_call. This is currently used in shutdown processing
152 (grpc_server_shutdown_and_notify and maybe_finish_shutdown) */
153 gpr_mu mu_global; /* mutex for server and channel state */
Craig Tiller079a11b2015-06-30 10:07:15 -0700154 gpr_mu mu_call; /* mutex for call-specific state */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800155
Craig Tiller24be0f72015-02-10 14:04:22 -0800156 registered_method *registered_methods;
157 requested_call_array requested_calls;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800158
159 gpr_uint8 shutdown;
Craig Tiller29f79dc2015-05-27 15:59:23 -0700160 gpr_uint8 shutdown_published;
Craig Tilleraea2fc02015-02-17 16:54:53 -0800161 size_t num_shutdown_tags;
Craig Tillerbce999f2015-05-27 09:55:51 -0700162 shutdown_tag *shutdown_tags;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800163
164 call_data *lists[CALL_LIST_COUNT];
165 channel_data root_channel_data;
166
167 listener *listeners;
Craig Tilleraec96aa2015-04-07 14:32:15 -0700168 int listeners_destroyed;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800169 gpr_refcount internal_refcount;
170};
171
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800172typedef enum {
173 /* waiting for metadata */
174 NOT_STARTED,
175 /* inital metadata read, not flow controlled in yet */
176 PENDING,
177 /* flow controlled in, on completion queue */
178 ACTIVATED,
179 /* cancelled before being queued */
180 ZOMBIED
181} call_state;
182
183struct call_data {
184 grpc_call *call;
185
Craig Tiller092d8d12015-07-04 22:35:00 -0700186 /** is this call counted towards the channels total
187 number of calls? */
188 gpr_uint8 active;
189
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800190 call_state state;
Craig Tillercce17ac2015-01-20 09:29:28 -0800191 grpc_mdstr *path;
192 grpc_mdstr *host;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700193 gpr_timespec deadline;
194 int got_initial_metadata;
Craig Tillercce17ac2015-01-20 09:29:28 -0800195
Craig Tiller20bc56d2015-02-12 09:02:56 -0800196 grpc_completion_queue *cq_new;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800197
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700198 grpc_stream_op_buffer *recv_ops;
199 grpc_stream_state *recv_state;
Craig Tiller1e6facb2015-06-11 22:47:11 -0700200 grpc_iomgr_closure *on_done_recv;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700201
Craig Tiller1e6facb2015-06-11 22:47:11 -0700202 grpc_iomgr_closure server_on_recv;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700203 grpc_iomgr_closure kill_zombie_closure;
204
Craig Tiller04cc8be2015-02-10 16:11:22 -0800205 call_data **root[CALL_LIST_COUNT];
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800206 call_link links[CALL_LIST_COUNT];
207};
208
Craig Tillerff3ae682015-06-29 17:44:04 -0700209typedef struct {
210 grpc_channel **channels;
Craig Tiller49924e02015-06-29 22:42:33 -0700211 grpc_channel **disconnects;
Craig Tillerff3ae682015-06-29 17:44:04 -0700212 size_t num_channels;
Craig Tiller49924e02015-06-29 22:42:33 -0700213 size_t num_disconnects;
Craig Tillerff3ae682015-06-29 17:44:04 -0700214} channel_broadcaster;
215
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800216#define SERVER_FROM_CALL_ELEM(elem) \
217 (((channel_data *)(elem)->channel_data)->server)
218
Craig Tiller24be0f72015-02-10 14:04:22 -0800219static void begin_call(grpc_server *server, call_data *calld,
220 requested_call *rc);
221static void fail_call(grpc_server *server, requested_call *rc);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700222/* Before calling maybe_finish_shutdown, we must hold mu_global and not
223 hold mu_call */
Craig Tiller52760dd2015-05-29 23:09:26 -0700224static void maybe_finish_shutdown(grpc_server *server);
Craig Tiller24be0f72015-02-10 14:04:22 -0800225
Craig Tillerff3ae682015-06-29 17:44:04 -0700226/* channel broadcaster */
227
228/* assumes server locked */
229static void channel_broadcaster_init(grpc_server *s, channel_broadcaster *cb) {
230 channel_data *c;
231 size_t count = 0;
Craig Tiller49924e02015-06-29 22:42:33 -0700232 size_t dc_count = 0;
Craig Tiller079a11b2015-06-30 10:07:15 -0700233 for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) {
234 count++;
Craig Tiller49924e02015-06-29 22:42:33 -0700235 if (c->num_calls == 0) {
Craig Tiller079a11b2015-06-30 10:07:15 -0700236 dc_count++;
Craig Tiller49924e02015-06-29 22:42:33 -0700237 }
Craig Tillerff3ae682015-06-29 17:44:04 -0700238 }
239 cb->num_channels = count;
Craig Tiller49924e02015-06-29 22:42:33 -0700240 cb->num_disconnects = dc_count;
Craig Tillerff3ae682015-06-29 17:44:04 -0700241 cb->channels = gpr_malloc(sizeof(*cb->channels) * cb->num_channels);
Craig Tiller49924e02015-06-29 22:42:33 -0700242 cb->disconnects = gpr_malloc(sizeof(*cb->channels) * cb->num_disconnects);
Craig Tillerff3ae682015-06-29 17:44:04 -0700243 count = 0;
Craig Tiller49924e02015-06-29 22:42:33 -0700244 dc_count = 0;
Craig Tiller079a11b2015-06-30 10:07:15 -0700245 for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) {
Craig Tiller49924e02015-06-29 22:42:33 -0700246 cb->channels[count++] = c->channel;
Craig Tillerff3ae682015-06-29 17:44:04 -0700247 GRPC_CHANNEL_INTERNAL_REF(c->channel, "broadcast");
Craig Tiller49924e02015-06-29 22:42:33 -0700248 if (c->num_calls == 0) {
249 cb->disconnects[dc_count++] = c->channel;
250 GRPC_CHANNEL_INTERNAL_REF(c->channel, "broadcast-disconnect");
251 }
Craig Tillerff3ae682015-06-29 17:44:04 -0700252 }
253}
254
255struct shutdown_cleanup_args {
256 grpc_iomgr_closure closure;
257 gpr_slice slice;
258};
259
260static void shutdown_cleanup(void *arg, int iomgr_status_ignored) {
261 struct shutdown_cleanup_args *a = arg;
262 gpr_slice_unref(a->slice);
263 gpr_free(a);
264}
265
Craig Tiller079a11b2015-06-30 10:07:15 -0700266static void send_shutdown(grpc_channel *channel, int send_goaway,
267 int send_disconnect) {
Craig Tillerff3ae682015-06-29 17:44:04 -0700268 grpc_transport_op op;
269 struct shutdown_cleanup_args *sc;
270 grpc_channel_element *elem;
271
272 memset(&op, 0, sizeof(op));
Craig Tillerff3ae682015-06-29 17:44:04 -0700273 op.send_goaway = send_goaway;
274 sc = gpr_malloc(sizeof(*sc));
275 sc->slice = gpr_slice_from_copied_string("Server shutdown");
276 op.goaway_message = &sc->slice;
277 op.goaway_status = GRPC_STATUS_OK;
278 op.disconnect = send_disconnect;
279 grpc_iomgr_closure_init(&sc->closure, shutdown_cleanup, sc);
280 op.on_consumed = &sc->closure;
281
Craig Tiller079a11b2015-06-30 10:07:15 -0700282 elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
Craig Tillerff3ae682015-06-29 17:44:04 -0700283 elem->filter->start_transport_op(elem, &op);
284}
285
Craig Tiller079a11b2015-06-30 10:07:15 -0700286static void channel_broadcaster_shutdown(channel_broadcaster *cb,
Craig Tiller092d8d12015-07-04 22:35:00 -0700287 int send_goaway, int force_disconnect) {
Craig Tillerff3ae682015-06-29 17:44:04 -0700288 size_t i;
289
Craig Tiller092d8d12015-07-04 22:35:00 -0700290 if (send_goaway) {
291 for (i = 0; i < cb->num_channels; i++) {
292 send_shutdown(cb->channels[i], 1, 0);
293 }
294 }
295 if (force_disconnect) {
296 for (i = 0; i < cb->num_channels; i++) {
297 send_shutdown(cb->channels[i], 0, 1);
298 }
299 } else {
300 for (i = 0; i < cb->num_disconnects; i++) {
301 send_shutdown(cb->disconnects[i], 0, 1);
302 }
303 }
Craig Tillerff3ae682015-06-29 17:44:04 -0700304 for (i = 0; i < cb->num_channels; i++) {
Craig Tillerff3ae682015-06-29 17:44:04 -0700305 GRPC_CHANNEL_INTERNAL_UNREF(cb->channels[i], "broadcast");
306 }
Craig Tiller49924e02015-06-29 22:42:33 -0700307 for (i = 0; i < cb->num_disconnects; i++) {
Craig Tiller49924e02015-06-29 22:42:33 -0700308 GRPC_CHANNEL_INTERNAL_UNREF(cb->channels[i], "broadcast-disconnect");
309 }
Craig Tillerff3ae682015-06-29 17:44:04 -0700310 gpr_free(cb->channels);
Craig Tiller49924e02015-06-29 22:42:33 -0700311 gpr_free(cb->disconnects);
Craig Tillerff3ae682015-06-29 17:44:04 -0700312}
313
314/* call list */
315
Craig Tiller3b29b562015-02-11 12:58:46 -0800316static int call_list_join(call_data **root, call_data *call, call_list list) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800317 GPR_ASSERT(!call->root[list]);
318 call->root[list] = root;
319 if (!*root) {
320 *root = call;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800321 call->links[list].next = call->links[list].prev = call;
322 } else {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800323 call->links[list].next = *root;
324 call->links[list].prev = (*root)->links[list].prev;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800325 call->links[list].next->links[list].prev =
326 call->links[list].prev->links[list].next = call;
327 }
328 return 1;
329}
330
Craig Tiller04cc8be2015-02-10 16:11:22 -0800331static call_data *call_list_remove_head(call_data **root, call_list list) {
332 call_data *out = *root;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800333 if (out) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800334 out->root[list] = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800335 if (out->links[list].next == out) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800336 *root = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800337 } else {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800338 *root = out->links[list].next;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800339 out->links[list].next->links[list].prev = out->links[list].prev;
340 out->links[list].prev->links[list].next = out->links[list].next;
341 }
342 }
343 return out;
344}
345
Craig Tiller04cc8be2015-02-10 16:11:22 -0800346static int call_list_remove(call_data *call, call_list list) {
347 call_data **root = call->root[list];
348 if (root == NULL) return 0;
349 call->root[list] = NULL;
350 if (*root == call) {
351 *root = call->links[list].next;
352 if (*root == call) {
353 *root = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800354 return 1;
355 }
356 }
Craig Tiller04cc8be2015-02-10 16:11:22 -0800357 GPR_ASSERT(*root != call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800358 call->links[list].next->links[list].prev = call->links[list].prev;
359 call->links[list].prev->links[list].next = call->links[list].next;
360 return 1;
361}
362
Craig Tiller24be0f72015-02-10 14:04:22 -0800363static void requested_call_array_destroy(requested_call_array *array) {
364 gpr_free(array->calls);
365}
366
367static requested_call *requested_call_array_add(requested_call_array *array) {
368 requested_call *rc;
369 if (array->count == array->capacity) {
370 array->capacity = GPR_MAX(array->capacity + 8, array->capacity * 2);
371 array->calls =
372 gpr_realloc(array->calls, sizeof(requested_call) * array->capacity);
373 }
374 rc = &array->calls[array->count++];
375 memset(rc, 0, sizeof(*rc));
376 return rc;
377}
378
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800379static void server_ref(grpc_server *server) {
380 gpr_ref(&server->internal_refcount);
381}
382
Craig Tilleree945e82015-05-26 16:15:34 -0700383static void server_delete(grpc_server *server) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800384 registered_method *rm;
Craig Tiller89504612015-04-27 11:48:46 -0700385 size_t i;
Craig Tilleree945e82015-05-26 16:15:34 -0700386 grpc_channel_args_destroy(server->channel_args);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700387 gpr_mu_destroy(&server->mu_global);
388 gpr_mu_destroy(&server->mu_call);
Craig Tilleree945e82015-05-26 16:15:34 -0700389 gpr_free(server->channel_filters);
390 requested_call_array_destroy(&server->requested_calls);
391 while ((rm = server->registered_methods) != NULL) {
392 server->registered_methods = rm->next;
393 gpr_free(rm->method);
394 gpr_free(rm->host);
395 requested_call_array_destroy(&rm->requested);
396 gpr_free(rm);
397 }
398 for (i = 0; i < server->cq_count; i++) {
Craig Tiller463f2372015-05-28 16:16:15 -0700399 GRPC_CQ_INTERNAL_UNREF(server->cqs[i], "server");
Craig Tilleree945e82015-05-26 16:15:34 -0700400 }
401 gpr_free(server->cqs);
402 gpr_free(server->pollsets);
403 gpr_free(server->shutdown_tags);
404 gpr_free(server);
405}
406
407static void server_unref(grpc_server *server) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800408 if (gpr_unref(&server->internal_refcount)) {
Craig Tilleree945e82015-05-26 16:15:34 -0700409 server_delete(server);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800410 }
411}
412
413static int is_channel_orphaned(channel_data *chand) {
414 return chand->next == chand;
415}
416
417static void orphan_channel(channel_data *chand) {
418 chand->next->prev = chand->prev;
419 chand->prev->next = chand->next;
420 chand->next = chand->prev = chand;
421}
422
ctiller58393c22015-01-07 14:03:30 -0800423static void finish_destroy_channel(void *cd, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800424 channel_data *chand = cd;
425 grpc_server *server = chand->server;
Craig Tiller9ec2a522015-05-29 22:46:54 -0700426 GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "server");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800427 server_unref(server);
428}
429
430static void destroy_channel(channel_data *chand) {
431 if (is_channel_orphaned(chand)) return;
432 GPR_ASSERT(chand->server != NULL);
433 orphan_channel(chand);
434 server_ref(chand->server);
Craig Tiller52760dd2015-05-29 23:09:26 -0700435 maybe_finish_shutdown(chand->server);
David Garcia Quintas284488b2015-05-28 16:27:39 -0700436 chand->finish_destroy_channel_closure.cb = finish_destroy_channel;
437 chand->finish_destroy_channel_closure.cb_arg = chand;
438 grpc_iomgr_add_callback(&chand->finish_destroy_channel_closure);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800439}
440
Craig Tiller3b29b562015-02-11 12:58:46 -0800441static void finish_start_new_rpc_and_unlock(grpc_server *server,
442 grpc_call_element *elem,
443 call_data **pending_root,
444 requested_call_array *array) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800445 requested_call rc;
446 call_data *calld = elem->call_data;
447 if (array->count == 0) {
448 calld->state = PENDING;
449 call_list_join(pending_root, calld, PENDING_START);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700450 gpr_mu_unlock(&server->mu_call);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800451 } else {
Craig Tiller0ef1a922015-02-11 16:23:01 -0800452 rc = array->calls[--array->count];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800453 calld->state = ACTIVATED;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700454 gpr_mu_unlock(&server->mu_call);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800455 begin_call(server, calld, &rc);
456 }
457}
458
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800459static void start_new_rpc(grpc_call_element *elem) {
460 channel_data *chand = elem->channel_data;
461 call_data *calld = elem->call_data;
462 grpc_server *server = chand->server;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800463 gpr_uint32 i;
464 gpr_uint32 hash;
465 channel_registered_method *rm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800466
Vijay Pai8931cdd2015-06-17 12:42:17 -0700467 gpr_mu_lock(&server->mu_call);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800468 if (chand->registered_methods && calld->path && calld->host) {
Craig Tillera94beff2015-02-17 22:02:06 -0800469 /* TODO(ctiller): unify these two searches */
Craig Tiller04cc8be2015-02-10 16:11:22 -0800470 /* check for an exact match with host */
471 hash = GRPC_MDSTR_KV_HASH(calld->host->hash, calld->path->hash);
472 for (i = 0; i < chand->registered_method_max_probes; i++) {
Craig Tiller3b29b562015-02-11 12:58:46 -0800473 rm = &chand->registered_methods[(hash + i) %
474 chand->registered_method_slots];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800475 if (!rm) break;
476 if (rm->host != calld->host) continue;
477 if (rm->method != calld->path) continue;
Craig Tiller3b29b562015-02-11 12:58:46 -0800478 finish_start_new_rpc_and_unlock(server, elem,
479 &rm->server_registered_method->pending,
480 &rm->server_registered_method->requested);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800481 return;
482 }
483 /* check for a wildcard method definition (no host set) */
484 hash = GRPC_MDSTR_KV_HASH(0, calld->path->hash);
Craig Tiller0ef1a922015-02-11 16:23:01 -0800485 for (i = 0; i <= chand->registered_method_max_probes; i++) {
Craig Tiller3b29b562015-02-11 12:58:46 -0800486 rm = &chand->registered_methods[(hash + i) %
487 chand->registered_method_slots];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800488 if (!rm) break;
489 if (rm->host != NULL) continue;
490 if (rm->method != calld->path) continue;
Craig Tiller3b29b562015-02-11 12:58:46 -0800491 finish_start_new_rpc_and_unlock(server, elem,
492 &rm->server_registered_method->pending,
493 &rm->server_registered_method->requested);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800494 return;
495 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800496 }
Craig Tiller3b29b562015-02-11 12:58:46 -0800497 finish_start_new_rpc_and_unlock(server, elem, &server->lists[PENDING_START],
498 &server->requested_calls);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800499}
500
ctiller58393c22015-01-07 14:03:30 -0800501static void kill_zombie(void *elem, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800502 grpc_call_destroy(grpc_call_from_top_element(elem));
503}
504
Craig Tilleree945e82015-05-26 16:15:34 -0700505static int num_listeners(grpc_server *server) {
506 listener *l;
507 int n = 0;
508 for (l = server->listeners; l; l = l->next) {
509 n++;
510 }
511 return n;
512}
513
Craig Tillerdc627722015-05-26 15:27:02 -0700514static void maybe_finish_shutdown(grpc_server *server) {
Craig Tillerbce999f2015-05-27 09:55:51 -0700515 size_t i;
Craig Tillerc4a1f522015-05-29 22:32:04 -0700516 if (!server->shutdown || server->shutdown_published) {
517 return;
518 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700519
Craig Tillerc4a1f522015-05-29 22:32:04 -0700520 if (server->root_channel_data.next != &server->root_channel_data) {
521 gpr_log(GPR_DEBUG,
Craig Tiller3e9ff5c2015-05-29 23:03:13 -0700522 "Waiting for all channels to close before destroying server");
Craig Tillerc4a1f522015-05-29 22:32:04 -0700523 return;
524 }
525 if (server->listeners_destroyed < num_listeners(server)) {
526 gpr_log(GPR_DEBUG, "Waiting for all listeners to be destroyed (@ %d/%d)",
527 server->listeners_destroyed, num_listeners(server));
528 return;
529 }
530 server->shutdown_published = 1;
531 for (i = 0; i < server->num_shutdown_tags; i++) {
532 grpc_cq_end_op(server->shutdown_tags[i].cq, server->shutdown_tags[i].tag,
533 NULL, 1);
Craig Tillerdc627722015-05-26 15:27:02 -0700534 }
535}
536
Craig Tiller6902ad22015-04-16 08:01:49 -0700537static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
538 grpc_call_element *elem = user_data;
Craig Tillercce17ac2015-01-20 09:29:28 -0800539 channel_data *chand = elem->channel_data;
540 call_data *calld = elem->call_data;
Craig Tiller6902ad22015-04-16 08:01:49 -0700541 if (md->key == chand->path_key) {
542 calld->path = grpc_mdstr_ref(md->value);
543 return NULL;
544 } else if (md->key == chand->authority_key) {
545 calld->host = grpc_mdstr_ref(md->value);
546 return NULL;
547 }
548 return md;
549}
550
Craig Tillerff3ae682015-06-29 17:44:04 -0700551static int decrement_call_count(channel_data *chand) {
552 int disconnect = 0;
Craig Tillerc4a1f522015-05-29 22:32:04 -0700553 chand->num_calls--;
554 if (0 == chand->num_calls && chand->server->shutdown) {
Craig Tillerff3ae682015-06-29 17:44:04 -0700555 disconnect = 1;
Craig Tillerc4a1f522015-05-29 22:32:04 -0700556 }
557 maybe_finish_shutdown(chand->server);
Craig Tillerff3ae682015-06-29 17:44:04 -0700558 return disconnect;
Craig Tillerc4a1f522015-05-29 22:32:04 -0700559}
560
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700561static void server_on_recv(void *ptr, int success) {
562 grpc_call_element *elem = ptr;
Craig Tiller6902ad22015-04-16 08:01:49 -0700563 call_data *calld = elem->call_data;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700564 channel_data *chand = elem->channel_data;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700565 int remove_res;
Craig Tillerff3ae682015-06-29 17:44:04 -0700566 int disconnect = 0;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700567
568 if (success && !calld->got_initial_metadata) {
569 size_t i;
570 size_t nops = calld->recv_ops->nops;
571 grpc_stream_op *ops = calld->recv_ops->ops;
572 for (i = 0; i < nops; i++) {
573 grpc_stream_op *op = &ops[i];
574 if (op->type != GRPC_OP_METADATA) continue;
Craig Tiller205aee12015-04-16 14:46:41 -0700575 grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700576 if (0 != gpr_time_cmp(op->data.metadata.deadline, gpr_inf_future)) {
Craig Tiller6902ad22015-04-16 08:01:49 -0700577 calld->deadline = op->data.metadata.deadline;
Craig Tillercce17ac2015-01-20 09:29:28 -0800578 }
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700579 calld->got_initial_metadata = 1;
580 start_new_rpc(elem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800581 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700582 }
583 }
584
585 switch (*calld->recv_state) {
Craig Tiller06aeea72015-04-23 10:54:45 -0700586 case GRPC_STREAM_OPEN:
587 break;
588 case GRPC_STREAM_SEND_CLOSED:
589 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700590 case GRPC_STREAM_RECV_CLOSED:
Vijay Pai8931cdd2015-06-17 12:42:17 -0700591 gpr_mu_lock(&chand->server->mu_call);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700592 if (calld->state == NOT_STARTED) {
593 calld->state = ZOMBIED;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700594 grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
595 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700596 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700597 gpr_mu_unlock(&chand->server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800598 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700599 case GRPC_STREAM_CLOSED:
Vijay Pai8931cdd2015-06-17 12:42:17 -0700600 gpr_mu_lock(&chand->server->mu_call);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700601 if (calld->state == NOT_STARTED) {
602 calld->state = ZOMBIED;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700603 grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
604 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700605 } else if (calld->state == PENDING) {
606 call_list_remove(calld, PENDING_START);
Craig Tillerc9d03822015-05-20 16:08:45 -0700607 calld->state = ZOMBIED;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700608 grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
609 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700610 }
Craig Tiller092d8d12015-07-04 22:35:00 -0700611 remove_res = calld->active;
612 calld->active = 0;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700613 gpr_mu_unlock(&chand->server->mu_call);
614 gpr_mu_lock(&chand->server->mu_global);
615 if (remove_res) {
Craig Tillerff3ae682015-06-29 17:44:04 -0700616 disconnect = decrement_call_count(chand);
617 if (disconnect) {
618 GRPC_CHANNEL_INTERNAL_REF(chand->channel, "send-disconnect");
619 }
Craig Tiller29f79dc2015-05-27 15:59:23 -0700620 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700621 gpr_mu_unlock(&chand->server->mu_global);
Craig Tillerff3ae682015-06-29 17:44:04 -0700622 if (disconnect) {
623 send_shutdown(chand->channel, 0, 1);
624 GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "send-disconnect");
625 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800626 break;
627 }
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700628
Craig Tiller1e6facb2015-06-11 22:47:11 -0700629 calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700630}
631
Craig Tillerb7959a02015-06-25 08:50:54 -0700632static void server_mutate_op(grpc_call_element *elem,
633 grpc_transport_stream_op *op) {
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700634 call_data *calld = elem->call_data;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700635
636 if (op->recv_ops) {
637 /* substitute our callback for the higher callback */
638 calld->recv_ops = op->recv_ops;
639 calld->recv_state = op->recv_state;
640 calld->on_done_recv = op->on_done_recv;
Craig Tiller1e6facb2015-06-11 22:47:11 -0700641 op->on_done_recv = &calld->server_on_recv;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700642 }
Craig Tiller50d9db52015-04-23 10:52:14 -0700643}
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700644
Craig Tillere039f032015-06-25 12:54:23 -0700645static void server_start_transport_stream_op(grpc_call_element *elem,
646 grpc_transport_stream_op *op) {
Craig Tiller50d9db52015-04-23 10:52:14 -0700647 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
648 server_mutate_op(elem, op);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700649 grpc_call_next_op(elem, op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800650}
651
Craig Tillere039f032015-06-25 12:54:23 -0700652static void accept_stream(void *cd, grpc_transport *transport,
653 const void *transport_server_data) {
654 channel_data *chand = cd;
655 /* create a call */
656 grpc_call_create(chand->channel, NULL, transport_server_data, NULL, 0,
657 gpr_inf_future);
658}
659
660static void channel_connectivity_changed(void *cd, int iomgr_status_ignored) {
661 channel_data *chand = cd;
662 grpc_server *server = chand->server;
663 if (chand->connectivity_state != GRPC_CHANNEL_FATAL_FAILURE) {
664 grpc_transport_op op;
665 memset(&op, 0, sizeof(op));
666 op.on_connectivity_state_change = &chand->channel_connectivity_changed,
667 op.connectivity_state = &chand->connectivity_state;
668 grpc_channel_next_op(grpc_channel_stack_element(
669 grpc_channel_get_channel_stack(chand->channel), 0),
670 &op);
671 } else {
672 gpr_mu_lock(&server->mu_global);
673 destroy_channel(chand);
674 gpr_mu_unlock(&server->mu_global);
675 GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "connectivity");
676 }
677}
678
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800679static void init_call_elem(grpc_call_element *elem,
Craig Tiller06aeea72015-04-23 10:54:45 -0700680 const void *server_transport_data,
Craig Tillerb7959a02015-06-25 08:50:54 -0700681 grpc_transport_stream_op *initial_op) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800682 call_data *calld = elem->call_data;
683 channel_data *chand = elem->channel_data;
684 memset(calld, 0, sizeof(call_data));
685 calld->deadline = gpr_inf_future;
686 calld->call = grpc_call_from_top_element(elem);
Craig Tiller092d8d12015-07-04 22:35:00 -0700687 calld->active = 1;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800688
Craig Tiller1e6facb2015-06-11 22:47:11 -0700689 grpc_iomgr_closure_init(&calld->server_on_recv, server_on_recv, elem);
690
Vijay Pai8931cdd2015-06-17 12:42:17 -0700691 gpr_mu_lock(&chand->server->mu_global);
Craig Tillerb76d05b2015-05-29 17:21:56 -0700692 chand->num_calls++;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700693 gpr_mu_unlock(&chand->server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800694
695 server_ref(chand->server);
Craig Tiller50d9db52015-04-23 10:52:14 -0700696
Craig Tiller482ef8b2015-04-23 11:38:20 -0700697 if (initial_op) server_mutate_op(elem, initial_op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800698}
699
700static void destroy_call_elem(grpc_call_element *elem) {
701 channel_data *chand = elem->channel_data;
Craig Tillerdb7db992015-01-29 11:19:01 -0800702 call_data *calld = elem->call_data;
Craig Tiller092d8d12015-07-04 22:35:00 -0700703 int disconnect = 0;
704 int active;
Craig Tillerdc627722015-05-26 15:27:02 -0700705 size_t i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800706
Vijay Pai8931cdd2015-06-17 12:42:17 -0700707 gpr_mu_lock(&chand->server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800708 for (i = 0; i < CALL_LIST_COUNT; i++) {
Craig Tiller092d8d12015-07-04 22:35:00 -0700709 call_list_remove(elem->call_data, i);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800710 }
Craig Tiller092d8d12015-07-04 22:35:00 -0700711 active = calld->active;
712 calld->active = 0;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700713 gpr_mu_unlock(&chand->server->mu_call);
Craig Tiller092d8d12015-07-04 22:35:00 -0700714 if (active) {
Vijay Paif75ed232015-06-18 11:40:47 -0700715 gpr_mu_lock(&chand->server->mu_global);
Craig Tiller092d8d12015-07-04 22:35:00 -0700716 disconnect = decrement_call_count(chand);
717 if (disconnect) {
718 GRPC_CHANNEL_INTERNAL_REF(chand->channel, "send-disconnect");
719 }
Vijay Paif75ed232015-06-18 11:40:47 -0700720 gpr_mu_unlock(&chand->server->mu_global);
Craig Tilleree945e82015-05-26 16:15:34 -0700721 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800722
Craig Tiller092d8d12015-07-04 22:35:00 -0700723 if (disconnect) {
724 send_shutdown(chand->channel, 0, 1);
725 GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "send-disconnect");
726 }
727
Craig Tiller4df31a62015-01-30 09:44:31 -0800728 if (calld->host) {
729 grpc_mdstr_unref(calld->host);
730 }
731 if (calld->path) {
732 grpc_mdstr_unref(calld->path);
733 }
734
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800735 server_unref(chand->server);
736}
737
Craig Tiller079a11b2015-06-30 10:07:15 -0700738static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800739 const grpc_channel_args *args,
740 grpc_mdctx *metadata_context, int is_first,
741 int is_last) {
742 channel_data *chand = elem->channel_data;
743 GPR_ASSERT(is_first);
744 GPR_ASSERT(!is_last);
745 chand->server = NULL;
Craig Tillerb76d05b2015-05-29 17:21:56 -0700746 chand->num_calls = 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800747 chand->channel = NULL;
Craig Tillercce17ac2015-01-20 09:29:28 -0800748 chand->path_key = grpc_mdstr_from_string(metadata_context, ":path");
749 chand->authority_key = grpc_mdstr_from_string(metadata_context, ":authority");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800750 chand->next = chand->prev = chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800751 chand->registered_methods = NULL;
Craig Tillere039f032015-06-25 12:54:23 -0700752 chand->connectivity_state = GRPC_CHANNEL_IDLE;
753 grpc_iomgr_closure_init(&chand->channel_connectivity_changed,
754 channel_connectivity_changed, chand);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800755}
756
757static void destroy_channel_elem(grpc_channel_element *elem) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800758 size_t i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800759 channel_data *chand = elem->channel_data;
Craig Tillerec3257c2015-02-12 15:59:43 -0800760 if (chand->registered_methods) {
761 for (i = 0; i < chand->registered_method_slots; i++) {
762 if (chand->registered_methods[i].method) {
763 grpc_mdstr_unref(chand->registered_methods[i].method);
764 }
765 if (chand->registered_methods[i].host) {
766 grpc_mdstr_unref(chand->registered_methods[i].host);
767 }
768 }
769 gpr_free(chand->registered_methods);
770 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800771 if (chand->server) {
Vijay Pai8931cdd2015-06-17 12:42:17 -0700772 gpr_mu_lock(&chand->server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800773 chand->next->prev = chand->prev;
774 chand->prev->next = chand->next;
775 chand->next = chand->prev = chand;
Craig Tillerb76d05b2015-05-29 17:21:56 -0700776 maybe_finish_shutdown(chand->server);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700777 gpr_mu_unlock(&chand->server->mu_global);
Craig Tillercce17ac2015-01-20 09:29:28 -0800778 grpc_mdstr_unref(chand->path_key);
779 grpc_mdstr_unref(chand->authority_key);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800780 server_unref(chand->server);
781 }
782}
783
784static const grpc_channel_filter server_surface_filter = {
Craig Tillere039f032015-06-25 12:54:23 -0700785 server_start_transport_stream_op,
786 grpc_channel_next_op,
Craig Tillerb76d05b2015-05-29 17:21:56 -0700787 sizeof(call_data),
788 init_call_elem,
789 destroy_call_elem,
790 sizeof(channel_data),
791 init_channel_elem,
792 destroy_channel_elem,
793 "server",
Craig Tiller9f28ac22015-01-27 17:01:29 -0800794};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800795
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700796void grpc_server_register_completion_queue(grpc_server *server,
797 grpc_completion_queue *cq) {
Craig Tiller20bc56d2015-02-12 09:02:56 -0800798 size_t i, n;
799 for (i = 0; i < server->cq_count; i++) {
800 if (server->cqs[i] == cq) return;
801 }
Craig Tiller463f2372015-05-28 16:16:15 -0700802 GRPC_CQ_INTERNAL_REF(cq, "server");
Craig Tillerb56975c2015-06-15 10:11:16 -0700803 grpc_cq_mark_server_cq(cq);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800804 n = server->cq_count++;
Craig Tillerec3257c2015-02-12 15:59:43 -0800805 server->cqs = gpr_realloc(server->cqs,
806 server->cq_count * sizeof(grpc_completion_queue *));
Craig Tiller20bc56d2015-02-12 09:02:56 -0800807 server->cqs[n] = cq;
808}
809
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700810grpc_server *grpc_server_create_from_filters(grpc_channel_filter **filters,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800811 size_t filter_count,
812 const grpc_channel_args *args) {
813 size_t i;
Alistair Veitch9d48ebf2015-06-01 10:01:03 -0700814 /* TODO(census): restore this once we finalize census filter etc.
815 int census_enabled = grpc_channel_args_is_census_enabled(args); */
816 int census_enabled = 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800817
818 grpc_server *server = gpr_malloc(sizeof(grpc_server));
Craig Tiller60fd3612015-03-05 16:24:22 -0800819
820 GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
821
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800822 memset(server, 0, sizeof(grpc_server));
823
Vijay Pai8931cdd2015-06-17 12:42:17 -0700824 gpr_mu_init(&server->mu_global);
825 gpr_mu_init(&server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800826
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800827 /* decremented by grpc_server_destroy */
828 gpr_ref_init(&server->internal_refcount, 1);
829 server->root_channel_data.next = server->root_channel_data.prev =
830 &server->root_channel_data;
831
832 /* Server filter stack is:
833
834 server_surface_filter - for making surface API calls
835 grpc_server_census_filter (optional) - for stats collection and tracing
836 {passed in filter stack}
837 grpc_connected_channel_filter - for interfacing with transports */
838 server->channel_filter_count = filter_count + 1 + census_enabled;
839 server->channel_filters =
840 gpr_malloc(server->channel_filter_count * sizeof(grpc_channel_filter *));
841 server->channel_filters[0] = &server_surface_filter;
Alistair Veitch9d48ebf2015-06-01 10:01:03 -0700842 /* TODO(census): restore this once we rework census filter
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800843 if (census_enabled) {
844 server->channel_filters[1] = &grpc_server_census_filter;
Alistair Veitch9686dab2015-05-26 14:26:47 -0700845 } */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800846 for (i = 0; i < filter_count; i++) {
847 server->channel_filters[i + 1 + census_enabled] = filters[i];
848 }
849
850 server->channel_args = grpc_channel_args_copy(args);
851
852 return server;
853}
854
Craig Tiller24be0f72015-02-10 14:04:22 -0800855static int streq(const char *a, const char *b) {
856 if (a == NULL && b == NULL) return 1;
857 if (a == NULL) return 0;
858 if (b == NULL) return 0;
859 return 0 == strcmp(a, b);
860}
861
862void *grpc_server_register_method(grpc_server *server, const char *method,
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700863 const char *host) {
Craig Tiller24be0f72015-02-10 14:04:22 -0800864 registered_method *m;
865 if (!method) {
Craig Tillerb76d05b2015-05-29 17:21:56 -0700866 gpr_log(GPR_ERROR,
867 "grpc_server_register_method method string cannot be NULL");
Craig Tiller24be0f72015-02-10 14:04:22 -0800868 return NULL;
869 }
870 for (m = server->registered_methods; m; m = m->next) {
871 if (streq(m->method, method) && streq(m->host, host)) {
872 gpr_log(GPR_ERROR, "duplicate registration for %s@%s", method,
873 host ? host : "*");
874 return NULL;
875 }
876 }
877 m = gpr_malloc(sizeof(registered_method));
878 memset(m, 0, sizeof(*m));
879 m->method = gpr_strdup(method);
880 m->host = gpr_strdup(host);
881 m->next = server->registered_methods;
882 server->registered_methods = m;
883 return m;
884}
885
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800886void grpc_server_start(grpc_server *server) {
887 listener *l;
Craig Tiller20bc56d2015-02-12 09:02:56 -0800888 size_t i;
889
Craig Tillerec3257c2015-02-12 15:59:43 -0800890 server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800891 for (i = 0; i < server->cq_count; i++) {
892 server->pollsets[i] = grpc_cq_pollset(server->cqs[i]);
893 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800894
895 for (l = server->listeners; l; l = l->next) {
Craig Tiller20bc56d2015-02-12 09:02:56 -0800896 l->start(server, l->arg, server->pollsets, server->cq_count);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800897 }
898}
899
Craig Tiller1064f8b2015-06-25 13:52:57 -0700900void grpc_server_setup_transport(grpc_server *s, grpc_transport *transport,
901 grpc_channel_filter const **extra_filters,
902 size_t num_extra_filters, grpc_mdctx *mdctx,
903 const grpc_channel_args *args) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800904 size_t num_filters = s->channel_filter_count + num_extra_filters + 1;
905 grpc_channel_filter const **filters =
906 gpr_malloc(sizeof(grpc_channel_filter *) * num_filters);
907 size_t i;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800908 size_t num_registered_methods;
909 size_t alloc;
910 registered_method *rm;
911 channel_registered_method *crm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800912 grpc_channel *channel;
913 channel_data *chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800914 grpc_mdstr *host;
915 grpc_mdstr *method;
916 gpr_uint32 hash;
917 gpr_uint32 slots;
918 gpr_uint32 probes;
919 gpr_uint32 max_probes = 0;
Craig Tillere039f032015-06-25 12:54:23 -0700920 grpc_transport_op op;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800921
922 for (i = 0; i < s->channel_filter_count; i++) {
923 filters[i] = s->channel_filters[i];
924 }
925 for (; i < s->channel_filter_count + num_extra_filters; i++) {
926 filters[i] = extra_filters[i - s->channel_filter_count];
927 }
928 filters[i] = &grpc_connected_channel_filter;
929
Craig Tiller20bc56d2015-02-12 09:02:56 -0800930 for (i = 0; i < s->cq_count; i++) {
Craig Tillere039f032015-06-25 12:54:23 -0700931 memset(&op, 0, sizeof(op));
932 op.bind_pollset = grpc_cq_pollset(s->cqs[i]);
933 grpc_transport_perform_op(transport, &op);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800934 }
ctillerd79b4862014-12-17 16:36:59 -0800935
Julien Boeufc6f8d0a2015-05-11 22:40:02 -0700936 channel =
937 grpc_channel_create_from_filters(filters, num_filters, args, mdctx, 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800938 chand = (channel_data *)grpc_channel_stack_element(
Craig Tillerc02c1d82015-04-07 16:21:55 -0700939 grpc_channel_get_channel_stack(channel), 0)
940 ->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800941 chand->server = s;
942 server_ref(s);
943 chand->channel = channel;
944
Craig Tiller04cc8be2015-02-10 16:11:22 -0800945 num_registered_methods = 0;
946 for (rm = s->registered_methods; rm; rm = rm->next) {
947 num_registered_methods++;
948 }
949 /* build a lookup table phrased in terms of mdstr's in this channels context
950 to quickly find registered methods */
951 if (num_registered_methods > 0) {
952 slots = 2 * num_registered_methods;
953 alloc = sizeof(channel_registered_method) * slots;
954 chand->registered_methods = gpr_malloc(alloc);
955 memset(chand->registered_methods, 0, alloc);
956 for (rm = s->registered_methods; rm; rm = rm->next) {
957 host = rm->host ? grpc_mdstr_from_string(mdctx, rm->host) : NULL;
Craig Tillere76c9662015-02-11 13:18:31 -0800958 method = grpc_mdstr_from_string(mdctx, rm->method);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800959 hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash);
Craig Tiller3b29b562015-02-11 12:58:46 -0800960 for (probes = 0; chand->registered_methods[(hash + probes) % slots]
Craig Tillerc02c1d82015-04-07 16:21:55 -0700961 .server_registered_method != NULL;
Craig Tiller3b29b562015-02-11 12:58:46 -0800962 probes++)
963 ;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800964 if (probes > max_probes) max_probes = probes;
965 crm = &chand->registered_methods[(hash + probes) % slots];
966 crm->server_registered_method = rm;
967 crm->host = host;
968 crm->method = method;
969 }
970 chand->registered_method_slots = slots;
971 chand->registered_method_max_probes = max_probes;
972 }
973
Craig Tiller1064f8b2015-06-25 13:52:57 -0700974 grpc_connected_channel_bind_transport(grpc_channel_get_channel_stack(channel),
975 transport);
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800976
Vijay Pai8931cdd2015-06-17 12:42:17 -0700977 gpr_mu_lock(&s->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800978 chand->next = &s->root_channel_data;
979 chand->prev = chand->next->prev;
980 chand->next->prev = chand->prev->next = chand;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700981 gpr_mu_unlock(&s->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800982
983 gpr_free(filters);
Craig Tiller4b804102015-06-26 16:16:12 -0700984
985 GRPC_CHANNEL_INTERNAL_REF(channel, "connectivity");
986 memset(&op, 0, sizeof(op));
987 op.set_accept_stream = accept_stream;
988 op.set_accept_stream_user_data = chand;
989 op.on_connectivity_state_change = &chand->channel_connectivity_changed;
990 op.connectivity_state = &chand->connectivity_state;
991 grpc_transport_perform_op(transport, &op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800992}
993
Craig Tillerbce999f2015-05-27 09:55:51 -0700994void grpc_server_shutdown_and_notify(grpc_server *server,
995 grpc_completion_queue *cq, void *tag) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800996 listener *l;
Craig Tiller24be0f72015-02-10 14:04:22 -0800997 requested_call_array requested_calls;
Craig Tillerdc627722015-05-26 15:27:02 -0700998 size_t i;
Craig Tillerbd217572015-02-11 18:10:56 -0800999 registered_method *rm;
Craig Tillerbce999f2015-05-27 09:55:51 -07001000 shutdown_tag *sdt;
Craig Tillerff3ae682015-06-29 17:44:04 -07001001 channel_broadcaster broadcaster;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001002
1003 /* lock, and gather up some stuff to do */
Vijay Pai8931cdd2015-06-17 12:42:17 -07001004 gpr_mu_lock(&server->mu_global);
Craig Tiller29f79dc2015-05-27 15:59:23 -07001005 grpc_cq_begin_op(cq, NULL);
Craig Tilleree945e82015-05-26 16:15:34 -07001006 server->shutdown_tags =
1007 gpr_realloc(server->shutdown_tags,
Craig Tiller208d2122015-05-29 08:50:08 -07001008 sizeof(shutdown_tag) * (server->num_shutdown_tags + 1));
Craig Tillerbce999f2015-05-27 09:55:51 -07001009 sdt = &server->shutdown_tags[server->num_shutdown_tags++];
1010 sdt->tag = tag;
1011 sdt->cq = cq;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001012 if (server->shutdown) {
Vijay Pai8931cdd2015-06-17 12:42:17 -07001013 gpr_mu_unlock(&server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001014 return;
1015 }
1016
Craig Tillerff3ae682015-06-29 17:44:04 -07001017 channel_broadcaster_init(server, &broadcaster);
nnoble0c475f02014-12-05 15:37:39 -08001018
Craig Tillerbd217572015-02-11 18:10:56 -08001019 /* collect all unregistered then registered calls */
Vijay Pai8931cdd2015-06-17 12:42:17 -07001020 gpr_mu_lock(&server->mu_call);
Craig Tillercce17ac2015-01-20 09:29:28 -08001021 requested_calls = server->requested_calls;
Craig Tiller24be0f72015-02-10 14:04:22 -08001022 memset(&server->requested_calls, 0, sizeof(server->requested_calls));
Craig Tillerbd217572015-02-11 18:10:56 -08001023 for (rm = server->registered_methods; rm; rm = rm->next) {
Craig Tillerec3257c2015-02-12 15:59:43 -08001024 if (requested_calls.count + rm->requested.count >
1025 requested_calls.capacity) {
1026 requested_calls.capacity =
1027 GPR_MAX(requested_calls.count + rm->requested.count,
1028 2 * requested_calls.capacity);
1029 requested_calls.calls =
1030 gpr_realloc(requested_calls.calls, sizeof(*requested_calls.calls) *
1031 requested_calls.capacity);
Craig Tillerbd217572015-02-11 18:10:56 -08001032 }
Craig Tillerec3257c2015-02-12 15:59:43 -08001033 memcpy(requested_calls.calls + requested_calls.count, rm->requested.calls,
1034 sizeof(*requested_calls.calls) * rm->requested.count);
Craig Tillerbd217572015-02-11 18:10:56 -08001035 requested_calls.count += rm->requested.count;
Craig Tillerec3257c2015-02-12 15:59:43 -08001036 gpr_free(rm->requested.calls);
Craig Tillerbd217572015-02-11 18:10:56 -08001037 memset(&rm->requested, 0, sizeof(rm->requested));
1038 }
Vijay Pai8931cdd2015-06-17 12:42:17 -07001039 gpr_mu_unlock(&server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001040
1041 server->shutdown = 1;
Craig Tillerdc627722015-05-26 15:27:02 -07001042 maybe_finish_shutdown(server);
Vijay Pai8931cdd2015-06-17 12:42:17 -07001043 gpr_mu_unlock(&server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001044
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001045 /* terminate all the requested calls */
Craig Tiller24be0f72015-02-10 14:04:22 -08001046 for (i = 0; i < requested_calls.count; i++) {
1047 fail_call(server, &requested_calls.calls[i]);
Craig Tillercce17ac2015-01-20 09:29:28 -08001048 }
Craig Tiller24be0f72015-02-10 14:04:22 -08001049 gpr_free(requested_calls.calls);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001050
1051 /* Shutdown listeners */
1052 for (l = server->listeners; l; l = l->next) {
1053 l->destroy(server, l->arg);
1054 }
Craig Tillerff3ae682015-06-29 17:44:04 -07001055
1056 channel_broadcaster_shutdown(&broadcaster, 1, 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001057}
1058
Craig Tilleraec96aa2015-04-07 14:32:15 -07001059void grpc_server_listener_destroy_done(void *s) {
1060 grpc_server *server = s;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001061 gpr_mu_lock(&server->mu_global);
Craig Tilleraec96aa2015-04-07 14:32:15 -07001062 server->listeners_destroyed++;
Craig Tilleree945e82015-05-26 16:15:34 -07001063 maybe_finish_shutdown(server);
Vijay Pai8931cdd2015-06-17 12:42:17 -07001064 gpr_mu_unlock(&server->mu_global);
Craig Tilleraec96aa2015-04-07 14:32:15 -07001065}
1066
Craig Tillerafa2d632015-05-26 16:39:13 -07001067void grpc_server_cancel_all_calls(grpc_server *server) {
Craig Tiller092d8d12015-07-04 22:35:00 -07001068 channel_broadcaster broadcaster;
Craig Tillerafa2d632015-05-26 16:39:13 -07001069
Craig Tiller092d8d12015-07-04 22:35:00 -07001070 gpr_mu_lock(&server->mu_global);
1071 channel_broadcaster_init(server, &broadcaster);
1072 gpr_mu_unlock(&server->mu_global);
Craig Tillerafa2d632015-05-26 16:39:13 -07001073
Craig Tiller092d8d12015-07-04 22:35:00 -07001074 channel_broadcaster_shutdown(&broadcaster, 0, 1);
Craig Tillerafa2d632015-05-26 16:39:13 -07001075}
1076
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001077void grpc_server_destroy(grpc_server *server) {
Craig Tilleraec96aa2015-04-07 14:32:15 -07001078 listener *l;
Craig Tiller872af022015-04-24 15:57:52 -07001079
Vijay Pai8931cdd2015-06-17 12:42:17 -07001080 gpr_mu_lock(&server->mu_global);
Masood Malekghassemi38bb18f2015-06-10 17:32:02 -07001081 GPR_ASSERT(server->shutdown || !server->listeners);
Craig Tilleree945e82015-05-26 16:15:34 -07001082 GPR_ASSERT(server->listeners_destroyed == num_listeners(server));
Craig Tilleraec96aa2015-04-07 14:32:15 -07001083
1084 while (server->listeners) {
1085 l = server->listeners;
1086 server->listeners = l->next;
1087 gpr_free(l);
1088 }
1089
Vijay Pai8931cdd2015-06-17 12:42:17 -07001090 gpr_mu_unlock(&server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001091
1092 server_unref(server);
1093}
1094
1095void grpc_server_add_listener(grpc_server *server, void *arg,
ctiller58393c22015-01-07 14:03:30 -08001096 void (*start)(grpc_server *server, void *arg,
Craig Tillerec3257c2015-02-12 15:59:43 -08001097 grpc_pollset **pollsets,
1098 size_t pollset_count),
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001099 void (*destroy)(grpc_server *server, void *arg)) {
1100 listener *l = gpr_malloc(sizeof(listener));
1101 l->arg = arg;
1102 l->start = start;
1103 l->destroy = destroy;
1104 l->next = server->listeners;
1105 server->listeners = l;
1106}
1107
Craig Tiller9f28ac22015-01-27 17:01:29 -08001108static grpc_call_error queue_call_request(grpc_server *server,
Craig Tiller24be0f72015-02-10 14:04:22 -08001109 requested_call *rc) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001110 call_data *calld = NULL;
Craig Tiller0ef1a922015-02-11 16:23:01 -08001111 requested_call_array *requested_calls = NULL;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001112 gpr_mu_lock(&server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001113 if (server->shutdown) {
Vijay Pai8931cdd2015-06-17 12:42:17 -07001114 gpr_mu_unlock(&server->mu_call);
Craig Tiller24be0f72015-02-10 14:04:22 -08001115 fail_call(server, rc);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001116 return GRPC_CALL_OK;
1117 }
Craig Tiller04cc8be2015-02-10 16:11:22 -08001118 switch (rc->type) {
Craig Tiller04cc8be2015-02-10 16:11:22 -08001119 case BATCH_CALL:
Craig Tiller3b29b562015-02-11 12:58:46 -08001120 calld =
1121 call_list_remove_head(&server->lists[PENDING_START], PENDING_START);
Craig Tiller0ef1a922015-02-11 16:23:01 -08001122 requested_calls = &server->requested_calls;
Craig Tiller04cc8be2015-02-10 16:11:22 -08001123 break;
1124 case REGISTERED_CALL:
Craig Tiller3b29b562015-02-11 12:58:46 -08001125 calld = call_list_remove_head(
1126 &rc->data.registered.registered_method->pending, PENDING_START);
Craig Tiller0ef1a922015-02-11 16:23:01 -08001127 requested_calls = &rc->data.registered.registered_method->requested;
Craig Tiller04cc8be2015-02-10 16:11:22 -08001128 break;
1129 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001130 if (calld) {
Craig Tillercce17ac2015-01-20 09:29:28 -08001131 GPR_ASSERT(calld->state == PENDING);
Craig Tillerbb3f22f2015-01-29 16:40:56 -08001132 calld->state = ACTIVATED;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001133 gpr_mu_unlock(&server->mu_call);
Craig Tiller24be0f72015-02-10 14:04:22 -08001134 begin_call(server, calld, rc);
Craig Tillercce17ac2015-01-20 09:29:28 -08001135 return GRPC_CALL_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001136 } else {
Craig Tiller0ef1a922015-02-11 16:23:01 -08001137 *requested_call_array_add(requested_calls) = *rc;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001138 gpr_mu_unlock(&server->mu_call);
Craig Tillercce17ac2015-01-20 09:29:28 -08001139 return GRPC_CALL_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001140 }
Craig Tillercce17ac2015-01-20 09:29:28 -08001141}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001142
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001143grpc_call_error grpc_server_request_call(
1144 grpc_server *server, grpc_call **call, grpc_call_details *details,
1145 grpc_metadata_array *initial_metadata,
1146 grpc_completion_queue *cq_bound_to_call,
1147 grpc_completion_queue *cq_for_notification, void *tag) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001148 requested_call rc;
murgatroid99ad7c20c2015-05-22 14:42:29 -07001149 GRPC_SERVER_LOG_REQUEST_CALL(GPR_INFO, server, call, details,
1150 initial_metadata, cq_bound_to_call,
1151 cq_for_notification, tag);
Craig Tillerb56975c2015-06-15 10:11:16 -07001152 if (!grpc_cq_is_server_cq(cq_for_notification)) {
1153 return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
1154 }
Craig Tiller54478f82015-05-12 14:08:56 -07001155 grpc_cq_begin_op(cq_for_notification, NULL);
Craig Tiller24be0f72015-02-10 14:04:22 -08001156 rc.type = BATCH_CALL;
1157 rc.tag = tag;
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001158 rc.cq_bound_to_call = cq_bound_to_call;
1159 rc.cq_for_notification = cq_for_notification;
1160 rc.call = call;
Craig Tiller24be0f72015-02-10 14:04:22 -08001161 rc.data.batch.details = details;
1162 rc.data.batch.initial_metadata = initial_metadata;
1163 return queue_call_request(server, &rc);
1164}
1165
1166grpc_call_error grpc_server_request_registered_call(
Craig Tillerec3257c2015-02-12 15:59:43 -08001167 grpc_server *server, void *rm, grpc_call **call, gpr_timespec *deadline,
1168 grpc_metadata_array *initial_metadata, grpc_byte_buffer **optional_payload,
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001169 grpc_completion_queue *cq_bound_to_call,
1170 grpc_completion_queue *cq_for_notification, void *tag) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001171 requested_call rc;
Craig Tiller20bc56d2015-02-12 09:02:56 -08001172 registered_method *registered_method = rm;
Craig Tillerb56975c2015-06-15 10:11:16 -07001173 if (!grpc_cq_is_server_cq(cq_for_notification)) {
1174 return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
1175 }
Craig Tiller54478f82015-05-12 14:08:56 -07001176 grpc_cq_begin_op(cq_for_notification, NULL);
Craig Tiller24be0f72015-02-10 14:04:22 -08001177 rc.type = REGISTERED_CALL;
1178 rc.tag = tag;
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001179 rc.cq_bound_to_call = cq_bound_to_call;
1180 rc.cq_for_notification = cq_for_notification;
1181 rc.call = call;
Craig Tiller24be0f72015-02-10 14:04:22 -08001182 rc.data.registered.registered_method = registered_method;
1183 rc.data.registered.deadline = deadline;
1184 rc.data.registered.initial_metadata = initial_metadata;
1185 rc.data.registered.optional_payload = optional_payload;
1186 return queue_call_request(server, &rc);
1187}
1188
Craig Tiller64be9f72015-05-04 14:53:51 -07001189static void publish_registered_or_batch(grpc_call *call, int success,
Craig Tiller24be0f72015-02-10 14:04:22 -08001190 void *tag);
Craig Tiller64be9f72015-05-04 14:53:51 -07001191static void publish_was_not_set(grpc_call *call, int success, void *tag) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001192 abort();
1193}
Craig Tiller24be0f72015-02-10 14:04:22 -08001194
Craig Tiller166e2502015-02-03 20:14:41 -08001195static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
1196 gpr_slice slice = value->slice;
1197 size_t len = GPR_SLICE_LENGTH(slice);
1198
1199 if (len + 1 > *capacity) {
1200 *capacity = GPR_MAX(len + 1, *capacity * 2);
1201 *dest = gpr_realloc(*dest, *capacity);
1202 }
1203 memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
1204}
1205
Craig Tiller24be0f72015-02-10 14:04:22 -08001206static void begin_call(grpc_server *server, call_data *calld,
1207 requested_call *rc) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001208 grpc_ioreq_completion_func publish = publish_was_not_set;
Craig Tiller24be0f72015-02-10 14:04:22 -08001209 grpc_ioreq req[2];
1210 grpc_ioreq *r = req;
1211
1212 /* called once initial metadata has been read by the call, but BEFORE
1213 the ioreq to fetch it out of the call has been executed.
1214 This means metadata related fields can be relied on in calld, but to
1215 fill in the metadata array passed by the client, we need to perform
1216 an ioreq op, that should complete immediately. */
1217
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001218 grpc_call_set_completion_queue(calld->call, rc->cq_bound_to_call);
1219 *rc->call = calld->call;
1220 calld->cq_new = rc->cq_for_notification;
Craig Tiller24be0f72015-02-10 14:04:22 -08001221 switch (rc->type) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001222 case BATCH_CALL:
Craig Tiller04c5d4b2015-06-26 17:21:41 -07001223 GPR_ASSERT(calld->host != NULL);
1224 GPR_ASSERT(calld->path != NULL);
Craig Tiller24be0f72015-02-10 14:04:22 -08001225 cpstr(&rc->data.batch.details->host,
1226 &rc->data.batch.details->host_capacity, calld->host);
1227 cpstr(&rc->data.batch.details->method,
1228 &rc->data.batch.details->method_capacity, calld->path);
Masood Malekghassemibf177c82015-04-27 12:14:38 -07001229 rc->data.batch.details->deadline = calld->deadline;
Craig Tiller24be0f72015-02-10 14:04:22 -08001230 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1231 r->data.recv_metadata = rc->data.batch.initial_metadata;
David Garcia Quintasb8f54502015-06-15 16:19:10 -07001232 r->flags = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001233 r++;
1234 publish = publish_registered_or_batch;
1235 break;
1236 case REGISTERED_CALL:
1237 *rc->data.registered.deadline = calld->deadline;
Craig Tiller24be0f72015-02-10 14:04:22 -08001238 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1239 r->data.recv_metadata = rc->data.registered.initial_metadata;
David Garcia Quintasb8f54502015-06-15 16:19:10 -07001240 r->flags = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001241 r++;
1242 if (rc->data.registered.optional_payload) {
1243 r->op = GRPC_IOREQ_RECV_MESSAGE;
1244 r->data.recv_message = rc->data.registered.optional_payload;
David Garcia Quintasb8f54502015-06-15 16:19:10 -07001245 r->flags = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001246 r++;
1247 }
1248 publish = publish_registered_or_batch;
1249 break;
1250 }
1251
Craig Tiller4df412b2015-04-28 07:57:54 -07001252 GRPC_CALL_INTERNAL_REF(calld->call, "server");
Craig Tiller24be0f72015-02-10 14:04:22 -08001253 grpc_call_start_ioreq_and_call_back(calld->call, req, r - req, publish,
1254 rc->tag);
1255}
1256
1257static void fail_call(grpc_server *server, requested_call *rc) {
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001258 *rc->call = NULL;
Craig Tiller24be0f72015-02-10 14:04:22 -08001259 switch (rc->type) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001260 case BATCH_CALL:
Craig Tiller24be0f72015-02-10 14:04:22 -08001261 rc->data.batch.initial_metadata->count = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001262 break;
1263 case REGISTERED_CALL:
Craig Tiller24be0f72015-02-10 14:04:22 -08001264 rc->data.registered.initial_metadata->count = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001265 break;
1266 }
Craig Tiller54478f82015-05-12 14:08:56 -07001267 grpc_cq_end_op(rc->cq_for_notification, rc->tag, NULL, 0);
Craig Tiller24be0f72015-02-10 14:04:22 -08001268}
1269
Craig Tiller64be9f72015-05-04 14:53:51 -07001270static void publish_registered_or_batch(grpc_call *call, int success,
Craig Tiller24be0f72015-02-10 14:04:22 -08001271 void *tag) {
Craig Tiller8e8fd892015-02-10 17:02:08 -08001272 grpc_call_element *elem =
1273 grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
Craig Tiller20bc56d2015-02-12 09:02:56 -08001274 call_data *calld = elem->call_data;
Craig Tiller64be9f72015-05-04 14:53:51 -07001275 grpc_cq_end_op(calld->cq_new, tag, call, success);
Craig Tiller24be0f72015-02-10 14:04:22 -08001276}
1277
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001278const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) {
1279 return server->channel_args;
Craig Tiller190d3602015-02-18 09:23:38 -08001280}
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001281
1282int grpc_server_has_open_connections(grpc_server *server) {
1283 int r;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001284 gpr_mu_lock(&server->mu_global);
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001285 r = server->root_channel_data.next != &server->root_channel_data;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001286 gpr_mu_unlock(&server->mu_global);
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001287 return r;
1288}