blob: 6f63f999bfd1f77d336002a0f26262e32656a418 [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
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080054typedef struct listener {
55 void *arg;
Craig Tillerec3257c2015-02-12 15:59:43 -080056 void (*start)(grpc_server *server, void *arg, grpc_pollset **pollsets,
57 size_t pollset_count);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080058 void (*destroy)(grpc_server *server, void *arg);
59 struct listener *next;
60} listener;
61
62typedef struct call_data call_data;
63typedef struct channel_data channel_data;
Craig Tiller24be0f72015-02-10 14:04:22 -080064typedef struct registered_method registered_method;
65
66typedef struct {
67 call_data *next;
68 call_data *prev;
69} call_link;
70
Craig Tiller0e919562015-04-28 14:03:47 -070071typedef enum { BATCH_CALL, REGISTERED_CALL } requested_call_type;
Craig Tiller24be0f72015-02-10 14:04:22 -080072
Craig Tiller97fc6a32015-07-08 15:31:35 -070073typedef struct requested_call {
Craig Tiller24be0f72015-02-10 14:04:22 -080074 requested_call_type type;
Craig Tiller97fc6a32015-07-08 15:31:35 -070075 struct requested_call *next;
Craig Tiller24be0f72015-02-10 14:04:22 -080076 void *tag;
Craig Tillerf9e6adf2015-05-06 11:45:59 -070077 grpc_completion_queue *cq_bound_to_call;
78 grpc_completion_queue *cq_for_notification;
79 grpc_call **call;
Craig Tiller97fc6a32015-07-08 15:31:35 -070080 grpc_cq_completion completion;
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
Craig Tiller24be0f72015-02-10 14:04:22 -080095typedef struct channel_registered_method {
96 registered_method *server_registered_method;
97 grpc_mdstr *method;
98 grpc_mdstr *host;
99} channel_registered_method;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800100
101struct channel_data {
102 grpc_server *server;
Craig Tillere039f032015-06-25 12:54:23 -0700103 grpc_connectivity_state connectivity_state;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800104 grpc_channel *channel;
Craig Tillercce17ac2015-01-20 09:29:28 -0800105 grpc_mdstr *path_key;
106 grpc_mdstr *authority_key;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800107 /* linked list of all channels on a server */
108 channel_data *next;
109 channel_data *prev;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800110 channel_registered_method *registered_methods;
111 gpr_uint32 registered_method_slots;
112 gpr_uint32 registered_method_max_probes;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700113 grpc_iomgr_closure finish_destroy_channel_closure;
Craig Tillere039f032015-06-25 12:54:23 -0700114 grpc_iomgr_closure channel_connectivity_changed;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800115};
116
Craig Tillerbce999f2015-05-27 09:55:51 -0700117typedef struct shutdown_tag {
118 void *tag;
119 grpc_completion_queue *cq;
Craig Tiller97fc6a32015-07-08 15:31:35 -0700120 grpc_cq_completion completion;
Craig Tillerbce999f2015-05-27 09:55:51 -0700121} shutdown_tag;
122
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800123typedef enum {
124 /* waiting for metadata */
125 NOT_STARTED,
126 /* inital metadata read, not flow controlled in yet */
127 PENDING,
128 /* flow controlled in, on completion queue */
129 ACTIVATED,
130 /* cancelled before being queued */
131 ZOMBIED
132} call_state;
133
Craig Tiller729b35a2015-07-13 12:36:47 -0700134typedef struct request_matcher request_matcher;
135
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800136struct call_data {
137 grpc_call *call;
138
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700139 /** protects state */
140 gpr_mu mu_state;
141 /** the current state of a call - see call_state */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800142 call_state state;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700143
Craig Tillercce17ac2015-01-20 09:29:28 -0800144 grpc_mdstr *path;
145 grpc_mdstr *host;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700146 gpr_timespec deadline;
147 int got_initial_metadata;
Craig Tillercce17ac2015-01-20 09:29:28 -0800148
Craig Tiller20bc56d2015-02-12 09:02:56 -0800149 grpc_completion_queue *cq_new;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800150
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700151 grpc_stream_op_buffer *recv_ops;
152 grpc_stream_state *recv_state;
Craig Tiller1e6facb2015-06-11 22:47:11 -0700153 grpc_iomgr_closure *on_done_recv;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700154
Craig Tiller1e6facb2015-06-11 22:47:11 -0700155 grpc_iomgr_closure server_on_recv;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700156 grpc_iomgr_closure kill_zombie_closure;
157
Craig Tiller729b35a2015-07-13 12:36:47 -0700158 call_data *pending_next;
159};
160
161struct request_matcher {
162 call_data *pending_head;
163 call_data *pending_tail;
164 requested_call *requests;
165};
166
167struct registered_method {
168 char *method;
169 char *host;
170 request_matcher request_matcher;
171 registered_method *next;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800172};
173
Craig Tillerff3ae682015-06-29 17:44:04 -0700174typedef struct {
175 grpc_channel **channels;
176 size_t num_channels;
177} channel_broadcaster;
178
Craig Tiller729b35a2015-07-13 12:36:47 -0700179struct grpc_server {
180 size_t channel_filter_count;
181 const grpc_channel_filter **channel_filters;
182 grpc_channel_args *channel_args;
183
184 grpc_completion_queue **cqs;
185 grpc_pollset **pollsets;
186 size_t cq_count;
187
188 /* The two following mutexes control access to server-state
189 mu_global controls access to non-call-related state (e.g., channel state)
190 mu_call controls access to call-related state (e.g., the call lists)
191
192 If they are ever required to be nested, you must lock mu_global
193 before mu_call. This is currently used in shutdown processing
194 (grpc_server_shutdown_and_notify and maybe_finish_shutdown) */
195 gpr_mu mu_global; /* mutex for server and channel state */
196 gpr_mu mu_call; /* mutex for call-specific state */
197
198 registered_method *registered_methods;
199 request_matcher unregistered_request_matcher;
200
201 gpr_uint8 shutdown;
202 gpr_uint8 shutdown_published;
203 size_t num_shutdown_tags;
204 shutdown_tag *shutdown_tags;
205
206 channel_data root_channel_data;
207
208 listener *listeners;
209 int listeners_destroyed;
210 gpr_refcount internal_refcount;
211
212 /** when did we print the last shutdown progress message */
213 gpr_timespec last_shutdown_message_time;
214};
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 Tiller729b35a2015-07-13 12:36:47 -0700226/*
227 * channel broadcaster
228 */
Craig Tillerff3ae682015-06-29 17:44:04 -0700229
230/* assumes server locked */
231static void channel_broadcaster_init(grpc_server *s, channel_broadcaster *cb) {
232 channel_data *c;
233 size_t count = 0;
Craig Tiller079a11b2015-06-30 10:07:15 -0700234 for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) {
235 count++;
Craig Tillerff3ae682015-06-29 17:44:04 -0700236 }
237 cb->num_channels = count;
238 cb->channels = gpr_malloc(sizeof(*cb->channels) * cb->num_channels);
239 count = 0;
Craig Tiller079a11b2015-06-30 10:07:15 -0700240 for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) {
Craig Tiller49924e02015-06-29 22:42:33 -0700241 cb->channels[count++] = c->channel;
Craig Tillerff3ae682015-06-29 17:44:04 -0700242 GRPC_CHANNEL_INTERNAL_REF(c->channel, "broadcast");
Craig Tillerff3ae682015-06-29 17:44:04 -0700243 }
244}
245
246struct shutdown_cleanup_args {
247 grpc_iomgr_closure closure;
248 gpr_slice slice;
249};
250
251static void shutdown_cleanup(void *arg, int iomgr_status_ignored) {
252 struct shutdown_cleanup_args *a = arg;
253 gpr_slice_unref(a->slice);
254 gpr_free(a);
255}
256
Craig Tiller079a11b2015-06-30 10:07:15 -0700257static void send_shutdown(grpc_channel *channel, int send_goaway,
258 int send_disconnect) {
Craig Tillerff3ae682015-06-29 17:44:04 -0700259 grpc_transport_op op;
260 struct shutdown_cleanup_args *sc;
261 grpc_channel_element *elem;
262
263 memset(&op, 0, sizeof(op));
Craig Tillerff3ae682015-06-29 17:44:04 -0700264 op.send_goaway = send_goaway;
265 sc = gpr_malloc(sizeof(*sc));
266 sc->slice = gpr_slice_from_copied_string("Server shutdown");
267 op.goaway_message = &sc->slice;
268 op.goaway_status = GRPC_STATUS_OK;
269 op.disconnect = send_disconnect;
270 grpc_iomgr_closure_init(&sc->closure, shutdown_cleanup, sc);
271 op.on_consumed = &sc->closure;
272
Craig Tiller079a11b2015-06-30 10:07:15 -0700273 elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
Craig Tillerff3ae682015-06-29 17:44:04 -0700274 elem->filter->start_transport_op(elem, &op);
275}
276
Craig Tiller079a11b2015-06-30 10:07:15 -0700277static void channel_broadcaster_shutdown(channel_broadcaster *cb,
Craig Tiller12cf5372015-07-09 13:48:11 -0700278 int send_goaway,
279 int force_disconnect) {
Craig Tillerff3ae682015-06-29 17:44:04 -0700280 size_t i;
281
282 for (i = 0; i < cb->num_channels; i++) {
Craig Tiller9188d7a2015-07-05 12:44:37 -0700283 send_shutdown(cb->channels[i], send_goaway, force_disconnect);
Craig Tillerff3ae682015-06-29 17:44:04 -0700284 GRPC_CHANNEL_INTERNAL_UNREF(cb->channels[i], "broadcast");
285 }
286 gpr_free(cb->channels);
287}
288
Craig Tiller729b35a2015-07-13 12:36:47 -0700289/*
290 * request_matcher
291 */
Craig Tillerff3ae682015-06-29 17:44:04 -0700292
Craig Tiller729b35a2015-07-13 12:36:47 -0700293static void request_matcher_init(request_matcher *request_matcher) {
294 memset(request_matcher, 0, sizeof(*request_matcher));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800295}
296
Craig Tiller729b35a2015-07-13 12:36:47 -0700297static void kill_zombie(void *elem, int success) {
298 grpc_call_destroy(grpc_call_from_top_element(elem));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800299}
300
Craig Tiller729b35a2015-07-13 12:36:47 -0700301static void request_matcher_zombify_all_pending_calls(
302 request_matcher *request_matcher) {
303 while (request_matcher->pending_head) {
304 call_data *calld = request_matcher->pending_head;
305 request_matcher->pending_head = calld->pending_next;
306 calld->state = ZOMBIED;
307 grpc_iomgr_closure_init(
308 &calld->kill_zombie_closure, kill_zombie,
309 grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
310 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800311 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800312}
313
Craig Tiller729b35a2015-07-13 12:36:47 -0700314/*
315 * server proper
316 */
317
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800318static void server_ref(grpc_server *server) {
319 gpr_ref(&server->internal_refcount);
320}
321
Craig Tilleree945e82015-05-26 16:15:34 -0700322static void server_delete(grpc_server *server) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800323 registered_method *rm;
Craig Tiller89504612015-04-27 11:48:46 -0700324 size_t i;
Craig Tilleree945e82015-05-26 16:15:34 -0700325 grpc_channel_args_destroy(server->channel_args);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700326 gpr_mu_destroy(&server->mu_global);
327 gpr_mu_destroy(&server->mu_call);
Craig Tilleree945e82015-05-26 16:15:34 -0700328 gpr_free(server->channel_filters);
Craig Tilleree945e82015-05-26 16:15:34 -0700329 while ((rm = server->registered_methods) != NULL) {
330 server->registered_methods = rm->next;
331 gpr_free(rm->method);
332 gpr_free(rm->host);
Craig Tilleree945e82015-05-26 16:15:34 -0700333 gpr_free(rm);
334 }
335 for (i = 0; i < server->cq_count; i++) {
Craig Tiller463f2372015-05-28 16:16:15 -0700336 GRPC_CQ_INTERNAL_UNREF(server->cqs[i], "server");
Craig Tilleree945e82015-05-26 16:15:34 -0700337 }
338 gpr_free(server->cqs);
339 gpr_free(server->pollsets);
340 gpr_free(server->shutdown_tags);
341 gpr_free(server);
342}
343
344static void server_unref(grpc_server *server) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800345 if (gpr_unref(&server->internal_refcount)) {
Craig Tilleree945e82015-05-26 16:15:34 -0700346 server_delete(server);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800347 }
348}
349
350static int is_channel_orphaned(channel_data *chand) {
351 return chand->next == chand;
352}
353
354static void orphan_channel(channel_data *chand) {
355 chand->next->prev = chand->prev;
356 chand->prev->next = chand->next;
357 chand->next = chand->prev = chand;
358}
359
ctiller58393c22015-01-07 14:03:30 -0800360static void finish_destroy_channel(void *cd, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800361 channel_data *chand = cd;
362 grpc_server *server = chand->server;
Craig Tiller9ec2a522015-05-29 22:46:54 -0700363 GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "server");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800364 server_unref(server);
365}
366
367static void destroy_channel(channel_data *chand) {
368 if (is_channel_orphaned(chand)) return;
369 GPR_ASSERT(chand->server != NULL);
370 orphan_channel(chand);
371 server_ref(chand->server);
Craig Tiller52760dd2015-05-29 23:09:26 -0700372 maybe_finish_shutdown(chand->server);
David Garcia Quintas284488b2015-05-28 16:27:39 -0700373 chand->finish_destroy_channel_closure.cb = finish_destroy_channel;
374 chand->finish_destroy_channel_closure.cb_arg = chand;
375 grpc_iomgr_add_callback(&chand->finish_destroy_channel_closure);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800376}
377
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700378static void finish_start_new_rpc(grpc_server *server, grpc_call_element *elem,
Craig Tiller729b35a2015-07-13 12:36:47 -0700379 request_matcher *request_matcher) {
Craig Tillerea0c3612015-07-08 15:43:18 -0700380 requested_call *rc;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800381 call_data *calld = elem->call_data;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700382 gpr_mu_lock(&server->mu_call);
Craig Tiller729b35a2015-07-13 12:36:47 -0700383 rc = request_matcher->requests;
Craig Tiller97fc6a32015-07-08 15:31:35 -0700384 if (rc == NULL) {
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700385 gpr_mu_lock(&calld->mu_state);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800386 calld->state = PENDING;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700387 gpr_mu_unlock(&calld->mu_state);
Craig Tiller729b35a2015-07-13 12:36:47 -0700388 if (request_matcher->pending_head == NULL) {
389 request_matcher->pending_tail = request_matcher->pending_head = calld;
390 } else {
391 request_matcher->pending_tail->pending_next = calld;
392 request_matcher->pending_tail = calld;
393 }
394 calld->pending_next = NULL;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700395 gpr_mu_unlock(&server->mu_call);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800396 } else {
Craig Tiller729b35a2015-07-13 12:36:47 -0700397 request_matcher->requests = rc->next;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700398 gpr_mu_lock(&calld->mu_state);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800399 calld->state = ACTIVATED;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700400 gpr_mu_unlock(&calld->mu_state);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700401 gpr_mu_unlock(&server->mu_call);
Craig Tiller97fc6a32015-07-08 15:31:35 -0700402 begin_call(server, calld, rc);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800403 }
404}
405
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800406static void start_new_rpc(grpc_call_element *elem) {
407 channel_data *chand = elem->channel_data;
408 call_data *calld = elem->call_data;
409 grpc_server *server = chand->server;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800410 gpr_uint32 i;
411 gpr_uint32 hash;
412 channel_registered_method *rm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800413
Craig Tiller04cc8be2015-02-10 16:11:22 -0800414 if (chand->registered_methods && calld->path && calld->host) {
Craig Tillera94beff2015-02-17 22:02:06 -0800415 /* TODO(ctiller): unify these two searches */
Craig Tiller04cc8be2015-02-10 16:11:22 -0800416 /* check for an exact match with host */
417 hash = GRPC_MDSTR_KV_HASH(calld->host->hash, calld->path->hash);
Craig Tillerc6d6d902015-07-09 15:53:50 -0700418 for (i = 0; i <= chand->registered_method_max_probes; i++) {
Craig Tiller3b29b562015-02-11 12:58:46 -0800419 rm = &chand->registered_methods[(hash + i) %
420 chand->registered_method_slots];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800421 if (!rm) break;
422 if (rm->host != calld->host) continue;
423 if (rm->method != calld->path) continue;
Craig Tiller729b35a2015-07-13 12:36:47 -0700424 finish_start_new_rpc(server, elem,
425 &rm->server_registered_method->request_matcher);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800426 return;
427 }
428 /* check for a wildcard method definition (no host set) */
429 hash = GRPC_MDSTR_KV_HASH(0, calld->path->hash);
Craig Tiller0ef1a922015-02-11 16:23:01 -0800430 for (i = 0; i <= chand->registered_method_max_probes; i++) {
Craig Tiller3b29b562015-02-11 12:58:46 -0800431 rm = &chand->registered_methods[(hash + i) %
432 chand->registered_method_slots];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800433 if (!rm) break;
434 if (rm->host != NULL) continue;
435 if (rm->method != calld->path) continue;
Craig Tiller729b35a2015-07-13 12:36:47 -0700436 finish_start_new_rpc(server, elem,
437 &rm->server_registered_method->request_matcher);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800438 return;
439 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800440 }
Craig Tiller729b35a2015-07-13 12:36:47 -0700441 finish_start_new_rpc(server, elem, &server->unregistered_request_matcher);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800442}
443
Craig Tilleree945e82015-05-26 16:15:34 -0700444static int num_listeners(grpc_server *server) {
445 listener *l;
446 int n = 0;
447 for (l = server->listeners; l; l = l->next) {
448 n++;
449 }
450 return n;
451}
452
Craig Tiller97fc6a32015-07-08 15:31:35 -0700453static void done_shutdown_event(void *server, grpc_cq_completion *completion) {
454 server_unref(server);
455}
456
Craig Tillerab54f792015-07-08 08:34:20 -0700457static int num_channels(grpc_server *server) {
458 channel_data *chand;
459 int n = 0;
460 for (chand = server->root_channel_data.next;
461 chand != &server->root_channel_data; chand = chand->next) {
462 n++;
463 }
464 return n;
465}
466
Craig Tillerdc627722015-05-26 15:27:02 -0700467static void maybe_finish_shutdown(grpc_server *server) {
Craig Tillerbce999f2015-05-27 09:55:51 -0700468 size_t i;
Craig Tillerc4a1f522015-05-29 22:32:04 -0700469 if (!server->shutdown || server->shutdown_published) {
470 return;
471 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700472
Craig Tillerab54f792015-07-08 08:34:20 -0700473 if (server->root_channel_data.next != &server->root_channel_data ||
474 server->listeners_destroyed < num_listeners(server)) {
475 if (gpr_time_cmp(
Craig Tiller080d6c52015-07-10 10:23:10 -0700476 gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), server->last_shutdown_message_time),
Craig Tillerab54f792015-07-08 08:34:20 -0700477 gpr_time_from_seconds(1)) >= 0) {
Craig Tiller080d6c52015-07-10 10:23:10 -0700478 server->last_shutdown_message_time = gpr_now(GPR_CLOCK_REALTIME);
Craig Tillerab54f792015-07-08 08:34:20 -0700479 gpr_log(GPR_DEBUG,
480 "Waiting for %d channels and %d/%d listeners to be destroyed"
481 " before shutting down server",
482 num_channels(server),
483 num_listeners(server) - server->listeners_destroyed,
484 num_listeners(server));
485 }
Craig Tillerc4a1f522015-05-29 22:32:04 -0700486 return;
487 }
488 server->shutdown_published = 1;
489 for (i = 0; i < server->num_shutdown_tags; i++) {
Craig Tiller97fc6a32015-07-08 15:31:35 -0700490 server_ref(server);
Craig Tiller12cf5372015-07-09 13:48:11 -0700491 grpc_cq_end_op(server->shutdown_tags[i].cq, server->shutdown_tags[i].tag, 1,
492 done_shutdown_event, server,
493 &server->shutdown_tags[i].completion);
Craig Tillerdc627722015-05-26 15:27:02 -0700494 }
495}
496
Craig Tiller6902ad22015-04-16 08:01:49 -0700497static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
498 grpc_call_element *elem = user_data;
Craig Tillercce17ac2015-01-20 09:29:28 -0800499 channel_data *chand = elem->channel_data;
500 call_data *calld = elem->call_data;
Craig Tiller6902ad22015-04-16 08:01:49 -0700501 if (md->key == chand->path_key) {
Craig Tiller1a65a232015-07-06 10:22:32 -0700502 calld->path = GRPC_MDSTR_REF(md->value);
Craig Tiller6902ad22015-04-16 08:01:49 -0700503 return NULL;
504 } else if (md->key == chand->authority_key) {
Craig Tiller1a65a232015-07-06 10:22:32 -0700505 calld->host = GRPC_MDSTR_REF(md->value);
Craig Tiller6902ad22015-04-16 08:01:49 -0700506 return NULL;
507 }
508 return md;
509}
510
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700511static void server_on_recv(void *ptr, int success) {
512 grpc_call_element *elem = ptr;
Craig Tiller6902ad22015-04-16 08:01:49 -0700513 call_data *calld = elem->call_data;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700514
515 if (success && !calld->got_initial_metadata) {
516 size_t i;
517 size_t nops = calld->recv_ops->nops;
518 grpc_stream_op *ops = calld->recv_ops->ops;
519 for (i = 0; i < nops; i++) {
520 grpc_stream_op *op = &ops[i];
521 if (op->type != GRPC_OP_METADATA) continue;
Craig Tiller205aee12015-04-16 14:46:41 -0700522 grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700523 if (0 != gpr_time_cmp(op->data.metadata.deadline, gpr_inf_future)) {
Craig Tiller6902ad22015-04-16 08:01:49 -0700524 calld->deadline = op->data.metadata.deadline;
Craig Tillercce17ac2015-01-20 09:29:28 -0800525 }
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700526 calld->got_initial_metadata = 1;
527 start_new_rpc(elem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800528 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700529 }
530 }
531
532 switch (*calld->recv_state) {
Craig Tiller06aeea72015-04-23 10:54:45 -0700533 case GRPC_STREAM_OPEN:
534 break;
535 case GRPC_STREAM_SEND_CLOSED:
536 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700537 case GRPC_STREAM_RECV_CLOSED:
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700538 gpr_mu_lock(&calld->mu_state);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700539 if (calld->state == NOT_STARTED) {
540 calld->state = ZOMBIED;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700541 gpr_mu_unlock(&calld->mu_state);
David Garcia Quintas284488b2015-05-28 16:27:39 -0700542 grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
543 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700544 } else {
545 gpr_mu_unlock(&calld->mu_state);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700546 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800547 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700548 case GRPC_STREAM_CLOSED:
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700549 gpr_mu_lock(&calld->mu_state);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700550 if (calld->state == NOT_STARTED) {
551 calld->state = ZOMBIED;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700552 gpr_mu_unlock(&calld->mu_state);
David Garcia Quintas284488b2015-05-28 16:27:39 -0700553 grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
554 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700555 } else if (calld->state == PENDING) {
Craig Tillerc9d03822015-05-20 16:08:45 -0700556 calld->state = ZOMBIED;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700557 gpr_mu_unlock(&calld->mu_state);
Craig Tiller729b35a2015-07-13 12:36:47 -0700558 /* zombied call will be destroyed when it's removed from the pending
559 queue... later */
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700560 } else {
561 gpr_mu_unlock(&calld->mu_state);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700562 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800563 break;
564 }
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700565
Craig Tiller1e6facb2015-06-11 22:47:11 -0700566 calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700567}
568
Craig Tillerb7959a02015-06-25 08:50:54 -0700569static void server_mutate_op(grpc_call_element *elem,
570 grpc_transport_stream_op *op) {
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700571 call_data *calld = elem->call_data;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700572
573 if (op->recv_ops) {
574 /* substitute our callback for the higher callback */
575 calld->recv_ops = op->recv_ops;
576 calld->recv_state = op->recv_state;
577 calld->on_done_recv = op->on_done_recv;
Craig Tiller1e6facb2015-06-11 22:47:11 -0700578 op->on_done_recv = &calld->server_on_recv;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700579 }
Craig Tiller50d9db52015-04-23 10:52:14 -0700580}
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700581
Craig Tillere039f032015-06-25 12:54:23 -0700582static void server_start_transport_stream_op(grpc_call_element *elem,
583 grpc_transport_stream_op *op) {
Craig Tiller50d9db52015-04-23 10:52:14 -0700584 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
585 server_mutate_op(elem, op);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700586 grpc_call_next_op(elem, op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800587}
588
Craig Tillere039f032015-06-25 12:54:23 -0700589static void accept_stream(void *cd, grpc_transport *transport,
590 const void *transport_server_data) {
591 channel_data *chand = cd;
592 /* create a call */
593 grpc_call_create(chand->channel, NULL, transport_server_data, NULL, 0,
594 gpr_inf_future);
595}
596
597static void channel_connectivity_changed(void *cd, int iomgr_status_ignored) {
598 channel_data *chand = cd;
599 grpc_server *server = chand->server;
600 if (chand->connectivity_state != GRPC_CHANNEL_FATAL_FAILURE) {
601 grpc_transport_op op;
602 memset(&op, 0, sizeof(op));
603 op.on_connectivity_state_change = &chand->channel_connectivity_changed,
604 op.connectivity_state = &chand->connectivity_state;
605 grpc_channel_next_op(grpc_channel_stack_element(
606 grpc_channel_get_channel_stack(chand->channel), 0),
607 &op);
608 } else {
609 gpr_mu_lock(&server->mu_global);
610 destroy_channel(chand);
611 gpr_mu_unlock(&server->mu_global);
612 GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "connectivity");
613 }
614}
615
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800616static void init_call_elem(grpc_call_element *elem,
Craig Tiller06aeea72015-04-23 10:54:45 -0700617 const void *server_transport_data,
Craig Tillerb7959a02015-06-25 08:50:54 -0700618 grpc_transport_stream_op *initial_op) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800619 call_data *calld = elem->call_data;
620 channel_data *chand = elem->channel_data;
621 memset(calld, 0, sizeof(call_data));
622 calld->deadline = gpr_inf_future;
623 calld->call = grpc_call_from_top_element(elem);
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700624 gpr_mu_init(&calld->mu_state);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800625
Craig Tiller1e6facb2015-06-11 22:47:11 -0700626 grpc_iomgr_closure_init(&calld->server_on_recv, server_on_recv, elem);
627
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800628 server_ref(chand->server);
Craig Tiller50d9db52015-04-23 10:52:14 -0700629
Craig Tiller482ef8b2015-04-23 11:38:20 -0700630 if (initial_op) server_mutate_op(elem, initial_op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800631}
632
633static void destroy_call_elem(grpc_call_element *elem) {
634 channel_data *chand = elem->channel_data;
Craig Tillerdb7db992015-01-29 11:19:01 -0800635 call_data *calld = elem->call_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800636
Craig Tiller729b35a2015-07-13 12:36:47 -0700637 GPR_ASSERT(calld->state != PENDING);
Craig Tiller092d8d12015-07-04 22:35:00 -0700638
Craig Tiller4df31a62015-01-30 09:44:31 -0800639 if (calld->host) {
Craig Tiller1a65a232015-07-06 10:22:32 -0700640 GRPC_MDSTR_UNREF(calld->host);
Craig Tiller4df31a62015-01-30 09:44:31 -0800641 }
642 if (calld->path) {
Craig Tiller1a65a232015-07-06 10:22:32 -0700643 GRPC_MDSTR_UNREF(calld->path);
Craig Tiller4df31a62015-01-30 09:44:31 -0800644 }
645
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700646 gpr_mu_destroy(&calld->mu_state);
647
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800648 server_unref(chand->server);
649}
650
Craig Tiller079a11b2015-06-30 10:07:15 -0700651static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800652 const grpc_channel_args *args,
653 grpc_mdctx *metadata_context, int is_first,
654 int is_last) {
655 channel_data *chand = elem->channel_data;
656 GPR_ASSERT(is_first);
657 GPR_ASSERT(!is_last);
658 chand->server = NULL;
659 chand->channel = NULL;
Craig Tillercce17ac2015-01-20 09:29:28 -0800660 chand->path_key = grpc_mdstr_from_string(metadata_context, ":path");
661 chand->authority_key = grpc_mdstr_from_string(metadata_context, ":authority");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800662 chand->next = chand->prev = chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800663 chand->registered_methods = NULL;
Craig Tillere039f032015-06-25 12:54:23 -0700664 chand->connectivity_state = GRPC_CHANNEL_IDLE;
665 grpc_iomgr_closure_init(&chand->channel_connectivity_changed,
666 channel_connectivity_changed, chand);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800667}
668
669static void destroy_channel_elem(grpc_channel_element *elem) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800670 size_t i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800671 channel_data *chand = elem->channel_data;
Craig Tillerec3257c2015-02-12 15:59:43 -0800672 if (chand->registered_methods) {
673 for (i = 0; i < chand->registered_method_slots; i++) {
674 if (chand->registered_methods[i].method) {
Craig Tiller1a65a232015-07-06 10:22:32 -0700675 GRPC_MDSTR_UNREF(chand->registered_methods[i].method);
Craig Tillerec3257c2015-02-12 15:59:43 -0800676 }
677 if (chand->registered_methods[i].host) {
Craig Tiller1a65a232015-07-06 10:22:32 -0700678 GRPC_MDSTR_UNREF(chand->registered_methods[i].host);
Craig Tillerec3257c2015-02-12 15:59:43 -0800679 }
680 }
681 gpr_free(chand->registered_methods);
682 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800683 if (chand->server) {
Vijay Pai8931cdd2015-06-17 12:42:17 -0700684 gpr_mu_lock(&chand->server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800685 chand->next->prev = chand->prev;
686 chand->prev->next = chand->next;
687 chand->next = chand->prev = chand;
Craig Tillerb76d05b2015-05-29 17:21:56 -0700688 maybe_finish_shutdown(chand->server);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700689 gpr_mu_unlock(&chand->server->mu_global);
Craig Tiller1a65a232015-07-06 10:22:32 -0700690 GRPC_MDSTR_UNREF(chand->path_key);
691 GRPC_MDSTR_UNREF(chand->authority_key);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800692 server_unref(chand->server);
693 }
694}
695
696static const grpc_channel_filter server_surface_filter = {
Craig Tillere039f032015-06-25 12:54:23 -0700697 server_start_transport_stream_op,
698 grpc_channel_next_op,
Craig Tillerb76d05b2015-05-29 17:21:56 -0700699 sizeof(call_data),
700 init_call_elem,
701 destroy_call_elem,
702 sizeof(channel_data),
703 init_channel_elem,
704 destroy_channel_elem,
705 "server",
Craig Tiller9f28ac22015-01-27 17:01:29 -0800706};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800707
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700708void grpc_server_register_completion_queue(grpc_server *server,
709 grpc_completion_queue *cq) {
Craig Tiller20bc56d2015-02-12 09:02:56 -0800710 size_t i, n;
711 for (i = 0; i < server->cq_count; i++) {
712 if (server->cqs[i] == cq) return;
713 }
Craig Tiller463f2372015-05-28 16:16:15 -0700714 GRPC_CQ_INTERNAL_REF(cq, "server");
Craig Tillerb56975c2015-06-15 10:11:16 -0700715 grpc_cq_mark_server_cq(cq);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800716 n = server->cq_count++;
Craig Tillerec3257c2015-02-12 15:59:43 -0800717 server->cqs = gpr_realloc(server->cqs,
718 server->cq_count * sizeof(grpc_completion_queue *));
Craig Tiller20bc56d2015-02-12 09:02:56 -0800719 server->cqs[n] = cq;
720}
721
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700722grpc_server *grpc_server_create_from_filters(grpc_channel_filter **filters,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800723 size_t filter_count,
724 const grpc_channel_args *args) {
725 size_t i;
Alistair Veitch9d48ebf2015-06-01 10:01:03 -0700726 /* TODO(census): restore this once we finalize census filter etc.
727 int census_enabled = grpc_channel_args_is_census_enabled(args); */
728 int census_enabled = 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800729
730 grpc_server *server = gpr_malloc(sizeof(grpc_server));
Craig Tiller60fd3612015-03-05 16:24:22 -0800731
732 GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
733
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800734 memset(server, 0, sizeof(grpc_server));
735
Vijay Pai8931cdd2015-06-17 12:42:17 -0700736 gpr_mu_init(&server->mu_global);
737 gpr_mu_init(&server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800738
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800739 /* decremented by grpc_server_destroy */
740 gpr_ref_init(&server->internal_refcount, 1);
741 server->root_channel_data.next = server->root_channel_data.prev =
742 &server->root_channel_data;
743
Craig Tiller729b35a2015-07-13 12:36:47 -0700744 request_matcher_init(&server->unregistered_request_matcher);
745
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800746 /* Server filter stack is:
747
748 server_surface_filter - for making surface API calls
749 grpc_server_census_filter (optional) - for stats collection and tracing
750 {passed in filter stack}
751 grpc_connected_channel_filter - for interfacing with transports */
752 server->channel_filter_count = filter_count + 1 + census_enabled;
753 server->channel_filters =
754 gpr_malloc(server->channel_filter_count * sizeof(grpc_channel_filter *));
755 server->channel_filters[0] = &server_surface_filter;
Alistair Veitch9d48ebf2015-06-01 10:01:03 -0700756 /* TODO(census): restore this once we rework census filter
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800757 if (census_enabled) {
758 server->channel_filters[1] = &grpc_server_census_filter;
Alistair Veitch9686dab2015-05-26 14:26:47 -0700759 } */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800760 for (i = 0; i < filter_count; i++) {
761 server->channel_filters[i + 1 + census_enabled] = filters[i];
762 }
763
764 server->channel_args = grpc_channel_args_copy(args);
765
766 return server;
767}
768
Craig Tiller24be0f72015-02-10 14:04:22 -0800769static int streq(const char *a, const char *b) {
770 if (a == NULL && b == NULL) return 1;
771 if (a == NULL) return 0;
772 if (b == NULL) return 0;
773 return 0 == strcmp(a, b);
774}
775
776void *grpc_server_register_method(grpc_server *server, const char *method,
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700777 const char *host) {
Craig Tiller24be0f72015-02-10 14:04:22 -0800778 registered_method *m;
779 if (!method) {
Craig Tillerb76d05b2015-05-29 17:21:56 -0700780 gpr_log(GPR_ERROR,
781 "grpc_server_register_method method string cannot be NULL");
Craig Tiller24be0f72015-02-10 14:04:22 -0800782 return NULL;
783 }
784 for (m = server->registered_methods; m; m = m->next) {
785 if (streq(m->method, method) && streq(m->host, host)) {
786 gpr_log(GPR_ERROR, "duplicate registration for %s@%s", method,
787 host ? host : "*");
788 return NULL;
789 }
790 }
791 m = gpr_malloc(sizeof(registered_method));
792 memset(m, 0, sizeof(*m));
Craig Tiller729b35a2015-07-13 12:36:47 -0700793 request_matcher_init(&m->request_matcher);
Craig Tiller24be0f72015-02-10 14:04:22 -0800794 m->method = gpr_strdup(method);
795 m->host = gpr_strdup(host);
796 m->next = server->registered_methods;
797 server->registered_methods = m;
798 return m;
799}
800
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800801void grpc_server_start(grpc_server *server) {
802 listener *l;
Craig Tiller20bc56d2015-02-12 09:02:56 -0800803 size_t i;
804
Craig Tillerec3257c2015-02-12 15:59:43 -0800805 server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800806 for (i = 0; i < server->cq_count; i++) {
807 server->pollsets[i] = grpc_cq_pollset(server->cqs[i]);
808 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800809
810 for (l = server->listeners; l; l = l->next) {
Craig Tiller20bc56d2015-02-12 09:02:56 -0800811 l->start(server, l->arg, server->pollsets, server->cq_count);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800812 }
813}
814
Craig Tiller1064f8b2015-06-25 13:52:57 -0700815void grpc_server_setup_transport(grpc_server *s, grpc_transport *transport,
816 grpc_channel_filter const **extra_filters,
817 size_t num_extra_filters, grpc_mdctx *mdctx,
818 const grpc_channel_args *args) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800819 size_t num_filters = s->channel_filter_count + num_extra_filters + 1;
820 grpc_channel_filter const **filters =
821 gpr_malloc(sizeof(grpc_channel_filter *) * num_filters);
822 size_t i;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800823 size_t num_registered_methods;
824 size_t alloc;
825 registered_method *rm;
826 channel_registered_method *crm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800827 grpc_channel *channel;
828 channel_data *chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800829 grpc_mdstr *host;
830 grpc_mdstr *method;
831 gpr_uint32 hash;
832 gpr_uint32 slots;
833 gpr_uint32 probes;
834 gpr_uint32 max_probes = 0;
Craig Tillere039f032015-06-25 12:54:23 -0700835 grpc_transport_op op;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800836
837 for (i = 0; i < s->channel_filter_count; i++) {
838 filters[i] = s->channel_filters[i];
839 }
840 for (; i < s->channel_filter_count + num_extra_filters; i++) {
841 filters[i] = extra_filters[i - s->channel_filter_count];
842 }
843 filters[i] = &grpc_connected_channel_filter;
844
Craig Tiller20bc56d2015-02-12 09:02:56 -0800845 for (i = 0; i < s->cq_count; i++) {
Craig Tillere039f032015-06-25 12:54:23 -0700846 memset(&op, 0, sizeof(op));
847 op.bind_pollset = grpc_cq_pollset(s->cqs[i]);
848 grpc_transport_perform_op(transport, &op);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800849 }
ctillerd79b4862014-12-17 16:36:59 -0800850
Julien Boeufc6f8d0a2015-05-11 22:40:02 -0700851 channel =
852 grpc_channel_create_from_filters(filters, num_filters, args, mdctx, 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800853 chand = (channel_data *)grpc_channel_stack_element(
Craig Tillerc02c1d82015-04-07 16:21:55 -0700854 grpc_channel_get_channel_stack(channel), 0)
855 ->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800856 chand->server = s;
857 server_ref(s);
858 chand->channel = channel;
859
Craig Tiller04cc8be2015-02-10 16:11:22 -0800860 num_registered_methods = 0;
861 for (rm = s->registered_methods; rm; rm = rm->next) {
862 num_registered_methods++;
863 }
864 /* build a lookup table phrased in terms of mdstr's in this channels context
865 to quickly find registered methods */
866 if (num_registered_methods > 0) {
867 slots = 2 * num_registered_methods;
868 alloc = sizeof(channel_registered_method) * slots;
869 chand->registered_methods = gpr_malloc(alloc);
870 memset(chand->registered_methods, 0, alloc);
871 for (rm = s->registered_methods; rm; rm = rm->next) {
872 host = rm->host ? grpc_mdstr_from_string(mdctx, rm->host) : NULL;
Craig Tillere76c9662015-02-11 13:18:31 -0800873 method = grpc_mdstr_from_string(mdctx, rm->method);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800874 hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash);
Craig Tiller3b29b562015-02-11 12:58:46 -0800875 for (probes = 0; chand->registered_methods[(hash + probes) % slots]
Craig Tillerc02c1d82015-04-07 16:21:55 -0700876 .server_registered_method != NULL;
Craig Tiller3b29b562015-02-11 12:58:46 -0800877 probes++)
878 ;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800879 if (probes > max_probes) max_probes = probes;
880 crm = &chand->registered_methods[(hash + probes) % slots];
881 crm->server_registered_method = rm;
882 crm->host = host;
883 crm->method = method;
884 }
885 chand->registered_method_slots = slots;
886 chand->registered_method_max_probes = max_probes;
887 }
888
Craig Tiller1064f8b2015-06-25 13:52:57 -0700889 grpc_connected_channel_bind_transport(grpc_channel_get_channel_stack(channel),
890 transport);
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800891
Vijay Pai8931cdd2015-06-17 12:42:17 -0700892 gpr_mu_lock(&s->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800893 chand->next = &s->root_channel_data;
894 chand->prev = chand->next->prev;
895 chand->next->prev = chand->prev->next = chand;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700896 gpr_mu_unlock(&s->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800897
898 gpr_free(filters);
Craig Tiller4b804102015-06-26 16:16:12 -0700899
900 GRPC_CHANNEL_INTERNAL_REF(channel, "connectivity");
901 memset(&op, 0, sizeof(op));
902 op.set_accept_stream = accept_stream;
903 op.set_accept_stream_user_data = chand;
904 op.on_connectivity_state_change = &chand->channel_connectivity_changed;
905 op.connectivity_state = &chand->connectivity_state;
906 grpc_transport_perform_op(transport, &op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800907}
908
Craig Tillerbce999f2015-05-27 09:55:51 -0700909void grpc_server_shutdown_and_notify(grpc_server *server,
910 grpc_completion_queue *cq, void *tag) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800911 listener *l;
Craig Tiller97fc6a32015-07-08 15:31:35 -0700912 requested_call *requests = NULL;
Craig Tillerbd217572015-02-11 18:10:56 -0800913 registered_method *rm;
Craig Tillerbce999f2015-05-27 09:55:51 -0700914 shutdown_tag *sdt;
Craig Tillerff3ae682015-06-29 17:44:04 -0700915 channel_broadcaster broadcaster;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800916
917 /* lock, and gather up some stuff to do */
Vijay Pai8931cdd2015-06-17 12:42:17 -0700918 gpr_mu_lock(&server->mu_global);
Craig Tiller97fc6a32015-07-08 15:31:35 -0700919 grpc_cq_begin_op(cq);
Craig Tilleree945e82015-05-26 16:15:34 -0700920 server->shutdown_tags =
921 gpr_realloc(server->shutdown_tags,
Craig Tiller208d2122015-05-29 08:50:08 -0700922 sizeof(shutdown_tag) * (server->num_shutdown_tags + 1));
Craig Tillerbce999f2015-05-27 09:55:51 -0700923 sdt = &server->shutdown_tags[server->num_shutdown_tags++];
924 sdt->tag = tag;
925 sdt->cq = cq;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800926 if (server->shutdown) {
Vijay Pai8931cdd2015-06-17 12:42:17 -0700927 gpr_mu_unlock(&server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800928 return;
929 }
930
Craig Tiller080d6c52015-07-10 10:23:10 -0700931 server->last_shutdown_message_time = gpr_now(GPR_CLOCK_REALTIME);
Craig Tillerab54f792015-07-08 08:34:20 -0700932
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 Tiller729b35a2015-07-13 12:36:47 -0700937 requests = server->unregistered_request_matcher.requests;
938 server->unregistered_request_matcher.requests = NULL;
939 request_matcher_zombify_all_pending_calls(
940 &server->unregistered_request_matcher);
Craig Tillerbd217572015-02-11 18:10:56 -0800941 for (rm = server->registered_methods; rm; rm = rm->next) {
Craig Tiller729b35a2015-07-13 12:36:47 -0700942 while (rm->request_matcher.requests != NULL) {
943 requested_call *c = rm->request_matcher.requests;
944 rm->request_matcher.requests = c->next;
Craig Tiller97fc6a32015-07-08 15:31:35 -0700945 c->next = requests;
946 requests = c;
Craig Tillerbd217572015-02-11 18:10:56 -0800947 }
Craig Tiller729b35a2015-07-13 12:36:47 -0700948 request_matcher_zombify_all_pending_calls(&rm->request_matcher);
Craig Tillerbd217572015-02-11 18:10:56 -0800949 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700950 gpr_mu_unlock(&server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800951
952 server->shutdown = 1;
Craig Tillerdc627722015-05-26 15:27:02 -0700953 maybe_finish_shutdown(server);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700954 gpr_mu_unlock(&server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800955
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800956 /* terminate all the requested calls */
Craig Tiller97fc6a32015-07-08 15:31:35 -0700957 while (requests != NULL) {
958 requested_call *next = requests->next;
959 fail_call(server, requests);
960 requests = next;
Craig Tillercce17ac2015-01-20 09:29:28 -0800961 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800962
963 /* Shutdown listeners */
964 for (l = server->listeners; l; l = l->next) {
965 l->destroy(server, l->arg);
966 }
Craig Tillerff3ae682015-06-29 17:44:04 -0700967
968 channel_broadcaster_shutdown(&broadcaster, 1, 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800969}
970
Craig Tilleraec96aa2015-04-07 14:32:15 -0700971void grpc_server_listener_destroy_done(void *s) {
972 grpc_server *server = s;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700973 gpr_mu_lock(&server->mu_global);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700974 server->listeners_destroyed++;
Craig Tilleree945e82015-05-26 16:15:34 -0700975 maybe_finish_shutdown(server);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700976 gpr_mu_unlock(&server->mu_global);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700977}
978
Craig Tillerafa2d632015-05-26 16:39:13 -0700979void grpc_server_cancel_all_calls(grpc_server *server) {
Craig Tiller092d8d12015-07-04 22:35:00 -0700980 channel_broadcaster broadcaster;
Craig Tillerafa2d632015-05-26 16:39:13 -0700981
Craig Tiller092d8d12015-07-04 22:35:00 -0700982 gpr_mu_lock(&server->mu_global);
983 channel_broadcaster_init(server, &broadcaster);
984 gpr_mu_unlock(&server->mu_global);
Craig Tillerafa2d632015-05-26 16:39:13 -0700985
Craig Tiller092d8d12015-07-04 22:35:00 -0700986 channel_broadcaster_shutdown(&broadcaster, 0, 1);
Craig Tillerafa2d632015-05-26 16:39:13 -0700987}
988
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800989void grpc_server_destroy(grpc_server *server) {
Craig Tilleraec96aa2015-04-07 14:32:15 -0700990 listener *l;
Craig Tiller872af022015-04-24 15:57:52 -0700991
Vijay Pai8931cdd2015-06-17 12:42:17 -0700992 gpr_mu_lock(&server->mu_global);
Masood Malekghassemi38bb18f2015-06-10 17:32:02 -0700993 GPR_ASSERT(server->shutdown || !server->listeners);
Craig Tilleree945e82015-05-26 16:15:34 -0700994 GPR_ASSERT(server->listeners_destroyed == num_listeners(server));
Craig Tilleraec96aa2015-04-07 14:32:15 -0700995
996 while (server->listeners) {
997 l = server->listeners;
998 server->listeners = l->next;
999 gpr_free(l);
1000 }
1001
Vijay Pai8931cdd2015-06-17 12:42:17 -07001002 gpr_mu_unlock(&server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001003
1004 server_unref(server);
1005}
1006
1007void grpc_server_add_listener(grpc_server *server, void *arg,
ctiller58393c22015-01-07 14:03:30 -08001008 void (*start)(grpc_server *server, void *arg,
Craig Tillerec3257c2015-02-12 15:59:43 -08001009 grpc_pollset **pollsets,
1010 size_t pollset_count),
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001011 void (*destroy)(grpc_server *server, void *arg)) {
1012 listener *l = gpr_malloc(sizeof(listener));
1013 l->arg = arg;
1014 l->start = start;
1015 l->destroy = destroy;
1016 l->next = server->listeners;
1017 server->listeners = l;
1018}
1019
Craig Tiller9f28ac22015-01-27 17:01:29 -08001020static grpc_call_error queue_call_request(grpc_server *server,
Craig Tiller24be0f72015-02-10 14:04:22 -08001021 requested_call *rc) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001022 call_data *calld = NULL;
Craig Tiller729b35a2015-07-13 12:36:47 -07001023 request_matcher *request_matcher = NULL;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001024 gpr_mu_lock(&server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001025 if (server->shutdown) {
Vijay Pai8931cdd2015-06-17 12:42:17 -07001026 gpr_mu_unlock(&server->mu_call);
Craig Tiller24be0f72015-02-10 14:04:22 -08001027 fail_call(server, rc);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001028 return GRPC_CALL_OK;
1029 }
Craig Tiller04cc8be2015-02-10 16:11:22 -08001030 switch (rc->type) {
Craig Tiller04cc8be2015-02-10 16:11:22 -08001031 case BATCH_CALL:
Craig Tiller729b35a2015-07-13 12:36:47 -07001032 request_matcher = &server->unregistered_request_matcher;
Craig Tiller04cc8be2015-02-10 16:11:22 -08001033 break;
1034 case REGISTERED_CALL:
Craig Tiller729b35a2015-07-13 12:36:47 -07001035 request_matcher = &rc->data.registered.registered_method->request_matcher;
Craig Tiller04cc8be2015-02-10 16:11:22 -08001036 break;
1037 }
Craig Tiller729b35a2015-07-13 12:36:47 -07001038 if (request_matcher->pending_head != NULL) {
1039 calld = request_matcher->pending_head;
1040 request_matcher->pending_head = calld->pending_next;
1041 }
Craig Tiller76d2c3b2015-07-07 11:46:01 -07001042 if (calld != NULL) {
1043 gpr_mu_unlock(&server->mu_call);
1044 gpr_mu_lock(&calld->mu_state);
Craig Tiller729b35a2015-07-13 12:36:47 -07001045 if (calld->state == ZOMBIED) {
1046 gpr_mu_unlock(&calld->mu_state);
1047 grpc_iomgr_closure_init(
1048 &calld->kill_zombie_closure, kill_zombie,
1049 grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
1050 grpc_iomgr_add_callback(&calld->kill_zombie_closure);
1051 return queue_call_request(server, rc); /* retry */
1052 }
Craig Tillercce17ac2015-01-20 09:29:28 -08001053 GPR_ASSERT(calld->state == PENDING);
Craig Tillerbb3f22f2015-01-29 16:40:56 -08001054 calld->state = ACTIVATED;
Craig Tiller76d2c3b2015-07-07 11:46:01 -07001055 gpr_mu_unlock(&calld->mu_state);
Craig Tiller24be0f72015-02-10 14:04:22 -08001056 begin_call(server, calld, rc);
Craig Tillercce17ac2015-01-20 09:29:28 -08001057 return GRPC_CALL_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001058 } else {
Craig Tiller729b35a2015-07-13 12:36:47 -07001059 rc->next = request_matcher->requests;
1060 request_matcher->requests = rc;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001061 gpr_mu_unlock(&server->mu_call);
Craig Tillercce17ac2015-01-20 09:29:28 -08001062 return GRPC_CALL_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001063 }
Craig Tillercce17ac2015-01-20 09:29:28 -08001064}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001065
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001066grpc_call_error grpc_server_request_call(
1067 grpc_server *server, grpc_call **call, grpc_call_details *details,
1068 grpc_metadata_array *initial_metadata,
1069 grpc_completion_queue *cq_bound_to_call,
1070 grpc_completion_queue *cq_for_notification, void *tag) {
Craig Tiller97fc6a32015-07-08 15:31:35 -07001071 requested_call *rc = gpr_malloc(sizeof(*rc));
murgatroid99ad7c20c2015-05-22 14:42:29 -07001072 GRPC_SERVER_LOG_REQUEST_CALL(GPR_INFO, server, call, details,
1073 initial_metadata, cq_bound_to_call,
1074 cq_for_notification, tag);
Craig Tillerb56975c2015-06-15 10:11:16 -07001075 if (!grpc_cq_is_server_cq(cq_for_notification)) {
Craig Tiller97fc6a32015-07-08 15:31:35 -07001076 gpr_free(rc);
Craig Tillerb56975c2015-06-15 10:11:16 -07001077 return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
1078 }
Craig Tiller97fc6a32015-07-08 15:31:35 -07001079 grpc_cq_begin_op(cq_for_notification);
1080 rc->type = BATCH_CALL;
1081 rc->tag = tag;
1082 rc->cq_bound_to_call = cq_bound_to_call;
1083 rc->cq_for_notification = cq_for_notification;
1084 rc->call = call;
1085 rc->data.batch.details = details;
1086 rc->data.batch.initial_metadata = initial_metadata;
1087 return queue_call_request(server, rc);
Craig Tiller24be0f72015-02-10 14:04:22 -08001088}
1089
1090grpc_call_error grpc_server_request_registered_call(
Craig Tillerec3257c2015-02-12 15:59:43 -08001091 grpc_server *server, void *rm, grpc_call **call, gpr_timespec *deadline,
1092 grpc_metadata_array *initial_metadata, grpc_byte_buffer **optional_payload,
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001093 grpc_completion_queue *cq_bound_to_call,
1094 grpc_completion_queue *cq_for_notification, void *tag) {
Craig Tiller97fc6a32015-07-08 15:31:35 -07001095 requested_call *rc = gpr_malloc(sizeof(*rc));
Craig Tiller20bc56d2015-02-12 09:02:56 -08001096 registered_method *registered_method = rm;
Craig Tillerb56975c2015-06-15 10:11:16 -07001097 if (!grpc_cq_is_server_cq(cq_for_notification)) {
Craig Tiller97fc6a32015-07-08 15:31:35 -07001098 gpr_free(rc);
Craig Tillerb56975c2015-06-15 10:11:16 -07001099 return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
1100 }
Craig Tiller97fc6a32015-07-08 15:31:35 -07001101 grpc_cq_begin_op(cq_for_notification);
1102 rc->type = REGISTERED_CALL;
1103 rc->tag = tag;
1104 rc->cq_bound_to_call = cq_bound_to_call;
1105 rc->cq_for_notification = cq_for_notification;
1106 rc->call = call;
1107 rc->data.registered.registered_method = registered_method;
1108 rc->data.registered.deadline = deadline;
1109 rc->data.registered.initial_metadata = initial_metadata;
1110 rc->data.registered.optional_payload = optional_payload;
1111 return queue_call_request(server, rc);
Craig Tiller24be0f72015-02-10 14:04:22 -08001112}
1113
Craig Tiller64be9f72015-05-04 14:53:51 -07001114static void publish_registered_or_batch(grpc_call *call, int success,
Craig Tiller24be0f72015-02-10 14:04:22 -08001115 void *tag);
Craig Tiller64be9f72015-05-04 14:53:51 -07001116static void publish_was_not_set(grpc_call *call, int success, void *tag) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001117 abort();
1118}
Craig Tiller24be0f72015-02-10 14:04:22 -08001119
Craig Tiller166e2502015-02-03 20:14:41 -08001120static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
1121 gpr_slice slice = value->slice;
1122 size_t len = GPR_SLICE_LENGTH(slice);
1123
1124 if (len + 1 > *capacity) {
1125 *capacity = GPR_MAX(len + 1, *capacity * 2);
1126 *dest = gpr_realloc(*dest, *capacity);
1127 }
1128 memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
1129}
1130
Craig Tiller24be0f72015-02-10 14:04:22 -08001131static void begin_call(grpc_server *server, call_data *calld,
1132 requested_call *rc) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001133 grpc_ioreq_completion_func publish = publish_was_not_set;
Craig Tiller24be0f72015-02-10 14:04:22 -08001134 grpc_ioreq req[2];
1135 grpc_ioreq *r = req;
1136
1137 /* called once initial metadata has been read by the call, but BEFORE
1138 the ioreq to fetch it out of the call has been executed.
1139 This means metadata related fields can be relied on in calld, but to
1140 fill in the metadata array passed by the client, we need to perform
1141 an ioreq op, that should complete immediately. */
1142
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001143 grpc_call_set_completion_queue(calld->call, rc->cq_bound_to_call);
1144 *rc->call = calld->call;
1145 calld->cq_new = rc->cq_for_notification;
Craig Tiller24be0f72015-02-10 14:04:22 -08001146 switch (rc->type) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001147 case BATCH_CALL:
Craig Tiller04c5d4b2015-06-26 17:21:41 -07001148 GPR_ASSERT(calld->host != NULL);
1149 GPR_ASSERT(calld->path != NULL);
Craig Tiller24be0f72015-02-10 14:04:22 -08001150 cpstr(&rc->data.batch.details->host,
1151 &rc->data.batch.details->host_capacity, calld->host);
1152 cpstr(&rc->data.batch.details->method,
1153 &rc->data.batch.details->method_capacity, calld->path);
Masood Malekghassemibf177c82015-04-27 12:14:38 -07001154 rc->data.batch.details->deadline = calld->deadline;
Craig Tiller24be0f72015-02-10 14:04:22 -08001155 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1156 r->data.recv_metadata = rc->data.batch.initial_metadata;
David Garcia Quintasb8f54502015-06-15 16:19:10 -07001157 r->flags = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001158 r++;
1159 publish = publish_registered_or_batch;
1160 break;
1161 case REGISTERED_CALL:
1162 *rc->data.registered.deadline = calld->deadline;
Craig Tiller24be0f72015-02-10 14:04:22 -08001163 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1164 r->data.recv_metadata = rc->data.registered.initial_metadata;
David Garcia Quintasb8f54502015-06-15 16:19:10 -07001165 r->flags = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001166 r++;
1167 if (rc->data.registered.optional_payload) {
1168 r->op = GRPC_IOREQ_RECV_MESSAGE;
1169 r->data.recv_message = rc->data.registered.optional_payload;
David Garcia Quintasb8f54502015-06-15 16:19:10 -07001170 r->flags = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001171 r++;
1172 }
1173 publish = publish_registered_or_batch;
1174 break;
1175 }
1176
Craig Tiller4df412b2015-04-28 07:57:54 -07001177 GRPC_CALL_INTERNAL_REF(calld->call, "server");
Craig Tiller12cf5372015-07-09 13:48:11 -07001178 grpc_call_start_ioreq_and_call_back(calld->call, req, r - req, publish, rc);
Craig Tiller97fc6a32015-07-08 15:31:35 -07001179}
1180
1181static void done_request_event(void *req, grpc_cq_completion *c) {
1182 gpr_free(req);
Craig Tiller24be0f72015-02-10 14:04:22 -08001183}
1184
1185static void fail_call(grpc_server *server, requested_call *rc) {
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001186 *rc->call = NULL;
Craig Tiller24be0f72015-02-10 14:04:22 -08001187 switch (rc->type) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001188 case BATCH_CALL:
Craig Tiller24be0f72015-02-10 14:04:22 -08001189 rc->data.batch.initial_metadata->count = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001190 break;
1191 case REGISTERED_CALL:
Craig Tiller24be0f72015-02-10 14:04:22 -08001192 rc->data.registered.initial_metadata->count = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001193 break;
1194 }
Craig Tiller12cf5372015-07-09 13:48:11 -07001195 grpc_cq_end_op(rc->cq_for_notification, rc->tag, 0, done_request_event, rc,
1196 &rc->completion);
Craig Tiller24be0f72015-02-10 14:04:22 -08001197}
1198
Craig Tiller64be9f72015-05-04 14:53:51 -07001199static void publish_registered_or_batch(grpc_call *call, int success,
Craig Tiller97fc6a32015-07-08 15:31:35 -07001200 void *prc) {
Craig Tiller8e8fd892015-02-10 17:02:08 -08001201 grpc_call_element *elem =
1202 grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
Craig Tiller97fc6a32015-07-08 15:31:35 -07001203 requested_call *rc = prc;
Craig Tiller20bc56d2015-02-12 09:02:56 -08001204 call_data *calld = elem->call_data;
Craig Tiller12cf5372015-07-09 13:48:11 -07001205 grpc_cq_end_op(calld->cq_new, rc->tag, success, done_request_event, rc,
1206 &rc->completion);
Craig Tillerc0122582015-07-09 13:21:36 -07001207 GRPC_CALL_INTERNAL_UNREF(call, "server", 0);
Craig Tiller24be0f72015-02-10 14:04:22 -08001208}
1209
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001210const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) {
1211 return server->channel_args;
Craig Tiller190d3602015-02-18 09:23:38 -08001212}
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001213
1214int grpc_server_has_open_connections(grpc_server *server) {
1215 int r;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001216 gpr_mu_lock(&server->mu_global);
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001217 r = server->root_channel_data.next != &server->root_channel_data;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001218 gpr_mu_unlock(&server->mu_global);
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001219 return r;
1220}