blob: 24545c67e1296de3e8343c4e34eb95befd61a2ee [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
Craig Tillerf96dfc32015-09-10 14:43:18 -070036#include <limits.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080037#include <stdlib.h>
38#include <string.h>
39
Craig Tiller6a006ce2015-07-13 16:25:40 -070040#include <grpc/support/alloc.h>
41#include <grpc/support/log.h>
42#include <grpc/support/string_util.h>
43#include <grpc/support/useful.h>
44
Hongyu Chene09dc782015-08-21 11:28:33 -070045#include "src/core/census/grpc_filter.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080046#include "src/core/channel/channel_args.h"
47#include "src/core/channel/connected_channel.h"
ctiller18b49ab2014-12-09 14:39:16 -080048#include "src/core/iomgr/iomgr.h"
Craig Tiller6a006ce2015-07-13 16:25:40 -070049#include "src/core/support/stack_lockfree.h"
Craig Tiller485d7762015-01-23 12:54:05 -080050#include "src/core/support/string.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080051#include "src/core/surface/call.h"
52#include "src/core/surface/channel.h"
53#include "src/core/surface/completion_queue.h"
Craig Tiller60fd3612015-03-05 16:24:22 -080054#include "src/core/surface/init.h"
Craig Tillercce17ac2015-01-20 09:29:28 -080055#include "src/core/transport/metadata.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080056
57typedef struct listener {
58 void *arg;
Craig Tillerec3257c2015-02-12 15:59:43 -080059 void (*start)(grpc_server *server, void *arg, grpc_pollset **pollsets,
Craig Tillerdfff1b82015-09-21 14:39:57 -070060 size_t pollset_count, grpc_call_list *call_list);
61 void (*destroy)(grpc_server *server, void *arg, grpc_closure *closure,
62 grpc_call_list *call_list);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080063 struct listener *next;
Craig Tillerdfff1b82015-09-21 14:39:57 -070064 grpc_closure destroy_done;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080065} listener;
66
67typedef struct call_data call_data;
68typedef struct channel_data channel_data;
Craig Tiller24be0f72015-02-10 14:04:22 -080069typedef struct registered_method registered_method;
70
71typedef struct {
72 call_data *next;
73 call_data *prev;
74} call_link;
75
Craig Tiller0e919562015-04-28 14:03:47 -070076typedef enum { BATCH_CALL, REGISTERED_CALL } requested_call_type;
Craig Tiller24be0f72015-02-10 14:04:22 -080077
Craig Tiller97fc6a32015-07-08 15:31:35 -070078typedef struct requested_call {
Craig Tiller24be0f72015-02-10 14:04:22 -080079 requested_call_type type;
80 void *tag;
Craig Tiller6a006ce2015-07-13 16:25:40 -070081 grpc_server *server;
Craig Tillerf9e6adf2015-05-06 11:45:59 -070082 grpc_completion_queue *cq_bound_to_call;
83 grpc_completion_queue *cq_for_notification;
84 grpc_call **call;
Craig Tiller97fc6a32015-07-08 15:31:35 -070085 grpc_cq_completion completion;
Craig Tiller24be0f72015-02-10 14:04:22 -080086 union {
87 struct {
Craig Tiller24be0f72015-02-10 14:04:22 -080088 grpc_call_details *details;
89 grpc_metadata_array *initial_metadata;
90 } batch;
91 struct {
Craig Tiller24be0f72015-02-10 14:04:22 -080092 registered_method *registered_method;
93 gpr_timespec *deadline;
94 grpc_metadata_array *initial_metadata;
95 grpc_byte_buffer **optional_payload;
96 } registered;
97 } data;
98} requested_call;
99
Craig Tiller24be0f72015-02-10 14:04:22 -0800100typedef struct channel_registered_method {
101 registered_method *server_registered_method;
102 grpc_mdstr *method;
103 grpc_mdstr *host;
104} channel_registered_method;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800105
106struct channel_data {
107 grpc_server *server;
Craig Tillere039f032015-06-25 12:54:23 -0700108 grpc_connectivity_state connectivity_state;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800109 grpc_channel *channel;
Craig Tillercce17ac2015-01-20 09:29:28 -0800110 grpc_mdstr *path_key;
111 grpc_mdstr *authority_key;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800112 /* linked list of all channels on a server */
113 channel_data *next;
114 channel_data *prev;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800115 channel_registered_method *registered_methods;
116 gpr_uint32 registered_method_slots;
117 gpr_uint32 registered_method_max_probes;
Craig Tiller33825112015-09-18 07:44:19 -0700118 grpc_closure finish_destroy_channel_closure;
119 grpc_closure channel_connectivity_changed;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800120};
121
Craig Tillerbce999f2015-05-27 09:55:51 -0700122typedef struct shutdown_tag {
123 void *tag;
124 grpc_completion_queue *cq;
Craig Tiller97fc6a32015-07-08 15:31:35 -0700125 grpc_cq_completion completion;
Craig Tillerbce999f2015-05-27 09:55:51 -0700126} shutdown_tag;
127
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800128typedef enum {
129 /* waiting for metadata */
130 NOT_STARTED,
131 /* inital metadata read, not flow controlled in yet */
132 PENDING,
133 /* flow controlled in, on completion queue */
134 ACTIVATED,
135 /* cancelled before being queued */
136 ZOMBIED
137} call_state;
138
Craig Tiller729b35a2015-07-13 12:36:47 -0700139typedef struct request_matcher request_matcher;
140
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800141struct call_data {
142 grpc_call *call;
143
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700144 /** protects state */
145 gpr_mu mu_state;
146 /** the current state of a call - see call_state */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800147 call_state state;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700148
Craig Tillercce17ac2015-01-20 09:29:28 -0800149 grpc_mdstr *path;
150 grpc_mdstr *host;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700151 gpr_timespec deadline;
152 int got_initial_metadata;
Craig Tillercce17ac2015-01-20 09:29:28 -0800153
Craig Tiller20bc56d2015-02-12 09:02:56 -0800154 grpc_completion_queue *cq_new;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800155
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700156 grpc_stream_op_buffer *recv_ops;
157 grpc_stream_state *recv_state;
Craig Tiller33825112015-09-18 07:44:19 -0700158 grpc_closure *on_done_recv;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700159
Craig Tiller33825112015-09-18 07:44:19 -0700160 grpc_closure server_on_recv;
161 grpc_closure kill_zombie_closure;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700162
Craig Tiller729b35a2015-07-13 12:36:47 -0700163 call_data *pending_next;
164};
165
166struct request_matcher {
167 call_data *pending_head;
168 call_data *pending_tail;
Craig Tiller6a006ce2015-07-13 16:25:40 -0700169 gpr_stack_lockfree *requests;
Craig Tiller729b35a2015-07-13 12:36:47 -0700170};
171
172struct registered_method {
173 char *method;
174 char *host;
175 request_matcher request_matcher;
176 registered_method *next;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800177};
178
Craig Tillerff3ae682015-06-29 17:44:04 -0700179typedef struct {
180 grpc_channel **channels;
181 size_t num_channels;
182} channel_broadcaster;
183
Craig Tiller729b35a2015-07-13 12:36:47 -0700184struct grpc_server {
185 size_t channel_filter_count;
186 const grpc_channel_filter **channel_filters;
187 grpc_channel_args *channel_args;
188
189 grpc_completion_queue **cqs;
190 grpc_pollset **pollsets;
191 size_t cq_count;
192
193 /* The two following mutexes control access to server-state
194 mu_global controls access to non-call-related state (e.g., channel state)
195 mu_call controls access to call-related state (e.g., the call lists)
196
197 If they are ever required to be nested, you must lock mu_global
198 before mu_call. This is currently used in shutdown processing
199 (grpc_server_shutdown_and_notify and maybe_finish_shutdown) */
200 gpr_mu mu_global; /* mutex for server and channel state */
201 gpr_mu mu_call; /* mutex for call-specific state */
202
203 registered_method *registered_methods;
204 request_matcher unregistered_request_matcher;
Craig Tiller6a006ce2015-07-13 16:25:40 -0700205 /** free list of available requested_calls indices */
206 gpr_stack_lockfree *request_freelist;
207 /** requested call backing data */
208 requested_call *requested_calls;
Craig Tiller32ca48c2015-09-10 11:47:15 -0700209 size_t max_requested_calls;
Craig Tiller729b35a2015-07-13 12:36:47 -0700210
Craig Tiller6a006ce2015-07-13 16:25:40 -0700211 gpr_atm shutdown_flag;
Craig Tiller729b35a2015-07-13 12:36:47 -0700212 gpr_uint8 shutdown_published;
213 size_t num_shutdown_tags;
214 shutdown_tag *shutdown_tags;
215
216 channel_data root_channel_data;
217
218 listener *listeners;
219 int listeners_destroyed;
220 gpr_refcount internal_refcount;
221
222 /** when did we print the last shutdown progress message */
223 gpr_timespec last_shutdown_message_time;
224};
225
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800226#define SERVER_FROM_CALL_ELEM(elem) \
227 (((channel_data *)(elem)->channel_data)->server)
228
Craig Tiller24be0f72015-02-10 14:04:22 -0800229static void begin_call(grpc_server *server, call_data *calld,
Craig Tillerdfff1b82015-09-21 14:39:57 -0700230 requested_call *rc, grpc_call_list *call_list);
231static void fail_call(grpc_server *server, requested_call *rc,
232 grpc_call_list *call_list);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700233/* Before calling maybe_finish_shutdown, we must hold mu_global and not
234 hold mu_call */
Craig Tillerdfff1b82015-09-21 14:39:57 -0700235static void maybe_finish_shutdown(grpc_server *server,
236 grpc_call_list *call_list);
Craig Tiller24be0f72015-02-10 14:04:22 -0800237
Craig Tiller729b35a2015-07-13 12:36:47 -0700238/*
239 * channel broadcaster
240 */
Craig Tillerff3ae682015-06-29 17:44:04 -0700241
242/* assumes server locked */
243static void channel_broadcaster_init(grpc_server *s, channel_broadcaster *cb) {
244 channel_data *c;
245 size_t count = 0;
Craig Tiller079a11b2015-06-30 10:07:15 -0700246 for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) {
247 count++;
Craig Tillerff3ae682015-06-29 17:44:04 -0700248 }
249 cb->num_channels = count;
250 cb->channels = gpr_malloc(sizeof(*cb->channels) * cb->num_channels);
251 count = 0;
Craig Tiller079a11b2015-06-30 10:07:15 -0700252 for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) {
Craig Tiller49924e02015-06-29 22:42:33 -0700253 cb->channels[count++] = c->channel;
Craig Tillerff3ae682015-06-29 17:44:04 -0700254 GRPC_CHANNEL_INTERNAL_REF(c->channel, "broadcast");
Craig Tillerff3ae682015-06-29 17:44:04 -0700255 }
256}
257
258struct shutdown_cleanup_args {
Craig Tiller33825112015-09-18 07:44:19 -0700259 grpc_closure closure;
Craig Tillerff3ae682015-06-29 17:44:04 -0700260 gpr_slice slice;
261};
262
Craig Tillerdfff1b82015-09-21 14:39:57 -0700263static void shutdown_cleanup(void *arg, int iomgr_status_ignored,
264 grpc_call_list *call_list) {
Craig Tillerff3ae682015-06-29 17:44:04 -0700265 struct shutdown_cleanup_args *a = arg;
266 gpr_slice_unref(a->slice);
267 gpr_free(a);
268}
269
Craig Tiller079a11b2015-06-30 10:07:15 -0700270static void send_shutdown(grpc_channel *channel, int send_goaway,
Craig Tillerdfff1b82015-09-21 14:39:57 -0700271 int send_disconnect, grpc_call_list *call_list) {
Craig Tillerff3ae682015-06-29 17:44:04 -0700272 grpc_transport_op op;
273 struct shutdown_cleanup_args *sc;
274 grpc_channel_element *elem;
275
276 memset(&op, 0, sizeof(op));
Craig Tillerff3ae682015-06-29 17:44:04 -0700277 op.send_goaway = send_goaway;
278 sc = gpr_malloc(sizeof(*sc));
279 sc->slice = gpr_slice_from_copied_string("Server shutdown");
280 op.goaway_message = &sc->slice;
281 op.goaway_status = GRPC_STATUS_OK;
282 op.disconnect = send_disconnect;
Craig Tiller33825112015-09-18 07:44:19 -0700283 grpc_closure_init(&sc->closure, shutdown_cleanup, sc);
Craig Tillerff3ae682015-06-29 17:44:04 -0700284 op.on_consumed = &sc->closure;
285
Craig Tiller079a11b2015-06-30 10:07:15 -0700286 elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
Craig Tillerdfff1b82015-09-21 14:39:57 -0700287 elem->filter->start_transport_op(elem, &op, call_list);
Craig Tillerff3ae682015-06-29 17:44:04 -0700288}
289
Craig Tiller079a11b2015-06-30 10:07:15 -0700290static void channel_broadcaster_shutdown(channel_broadcaster *cb,
Craig Tillerdfff1b82015-09-21 14:39:57 -0700291 int send_goaway, int force_disconnect,
292 grpc_call_list *call_list) {
Craig Tillerff3ae682015-06-29 17:44:04 -0700293 size_t i;
294
295 for (i = 0; i < cb->num_channels; i++) {
Craig Tillerdfff1b82015-09-21 14:39:57 -0700296 send_shutdown(cb->channels[i], send_goaway, force_disconnect, call_list);
297 GRPC_CHANNEL_INTERNAL_UNREF(cb->channels[i], "broadcast", call_list);
Craig Tillerff3ae682015-06-29 17:44:04 -0700298 }
299 gpr_free(cb->channels);
300}
301
Craig Tiller729b35a2015-07-13 12:36:47 -0700302/*
303 * request_matcher
304 */
Craig Tillerff3ae682015-06-29 17:44:04 -0700305
Craig Tiller6a006ce2015-07-13 16:25:40 -0700306static void request_matcher_init(request_matcher *request_matcher,
Craig Tiller32ca48c2015-09-10 11:47:15 -0700307 size_t entries) {
Craig Tiller729b35a2015-07-13 12:36:47 -0700308 memset(request_matcher, 0, sizeof(*request_matcher));
Craig Tiller6a006ce2015-07-13 16:25:40 -0700309 request_matcher->requests = gpr_stack_lockfree_create(entries);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800310}
311
Craig Tiller6a006ce2015-07-13 16:25:40 -0700312static void request_matcher_destroy(request_matcher *request_matcher) {
313 GPR_ASSERT(gpr_stack_lockfree_pop(request_matcher->requests) == -1);
314 gpr_stack_lockfree_destroy(request_matcher->requests);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800315}
316
Craig Tillerdfff1b82015-09-21 14:39:57 -0700317static void kill_zombie(void *elem, int success, grpc_call_list *call_list) {
Craig Tiller729b35a2015-07-13 12:36:47 -0700318 grpc_call_destroy(grpc_call_from_top_element(elem));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800319}
320
Craig Tiller729b35a2015-07-13 12:36:47 -0700321static void request_matcher_zombify_all_pending_calls(
Craig Tillerdfff1b82015-09-21 14:39:57 -0700322 request_matcher *request_matcher, grpc_call_list *call_list) {
Craig Tiller729b35a2015-07-13 12:36:47 -0700323 while (request_matcher->pending_head) {
324 call_data *calld = request_matcher->pending_head;
325 request_matcher->pending_head = calld->pending_next;
Craig Tillerb6450262015-07-14 07:12:19 -0700326 gpr_mu_lock(&calld->mu_state);
Craig Tiller729b35a2015-07-13 12:36:47 -0700327 calld->state = ZOMBIED;
Craig Tillerb6450262015-07-14 07:12:19 -0700328 gpr_mu_unlock(&calld->mu_state);
Craig Tiller33825112015-09-18 07:44:19 -0700329 grpc_closure_init(
Craig Tiller729b35a2015-07-13 12:36:47 -0700330 &calld->kill_zombie_closure, kill_zombie,
331 grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
Craig Tillerdfff1b82015-09-21 14:39:57 -0700332 grpc_call_list_add(call_list, &calld->kill_zombie_closure, 1);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800333 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800334}
335
Craig Tiller1191e212015-07-30 14:49:02 -0700336static void request_matcher_kill_requests(grpc_server *server,
Craig Tillerdfff1b82015-09-21 14:39:57 -0700337 request_matcher *rm,
338 grpc_call_list *call_list) {
Craig Tiller1191e212015-07-30 14:49:02 -0700339 int request_id;
340 while ((request_id = gpr_stack_lockfree_pop(rm->requests)) != -1) {
Craig Tillerdfff1b82015-09-21 14:39:57 -0700341 fail_call(server, &server->requested_calls[request_id], call_list);
Craig Tiller1191e212015-07-30 14:49:02 -0700342 }
343}
344
Craig Tiller729b35a2015-07-13 12:36:47 -0700345/*
346 * server proper
347 */
348
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800349static void server_ref(grpc_server *server) {
350 gpr_ref(&server->internal_refcount);
351}
352
Craig Tillerdfff1b82015-09-21 14:39:57 -0700353static void server_delete(grpc_server *server, grpc_call_list *call_list) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800354 registered_method *rm;
Craig Tiller89504612015-04-27 11:48:46 -0700355 size_t i;
Craig Tilleree945e82015-05-26 16:15:34 -0700356 grpc_channel_args_destroy(server->channel_args);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700357 gpr_mu_destroy(&server->mu_global);
358 gpr_mu_destroy(&server->mu_call);
Craig Tilleree945e82015-05-26 16:15:34 -0700359 gpr_free(server->channel_filters);
Craig Tilleree945e82015-05-26 16:15:34 -0700360 while ((rm = server->registered_methods) != NULL) {
361 server->registered_methods = rm->next;
Craig Tiller6a006ce2015-07-13 16:25:40 -0700362 request_matcher_destroy(&rm->request_matcher);
Craig Tilleree945e82015-05-26 16:15:34 -0700363 gpr_free(rm->method);
364 gpr_free(rm->host);
Craig Tilleree945e82015-05-26 16:15:34 -0700365 gpr_free(rm);
366 }
367 for (i = 0; i < server->cq_count; i++) {
Craig Tiller463f2372015-05-28 16:16:15 -0700368 GRPC_CQ_INTERNAL_UNREF(server->cqs[i], "server");
Craig Tilleree945e82015-05-26 16:15:34 -0700369 }
Craig Tiller6a006ce2015-07-13 16:25:40 -0700370 request_matcher_destroy(&server->unregistered_request_matcher);
371 gpr_stack_lockfree_destroy(server->request_freelist);
Craig Tilleree945e82015-05-26 16:15:34 -0700372 gpr_free(server->cqs);
373 gpr_free(server->pollsets);
374 gpr_free(server->shutdown_tags);
Craig Tiller6a006ce2015-07-13 16:25:40 -0700375 gpr_free(server->requested_calls);
Craig Tilleree945e82015-05-26 16:15:34 -0700376 gpr_free(server);
377}
378
Craig Tillerdfff1b82015-09-21 14:39:57 -0700379static void server_unref(grpc_server *server, grpc_call_list *call_list) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800380 if (gpr_unref(&server->internal_refcount)) {
Craig Tillerdfff1b82015-09-21 14:39:57 -0700381 server_delete(server, call_list);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800382 }
383}
384
385static int is_channel_orphaned(channel_data *chand) {
386 return chand->next == chand;
387}
388
389static void orphan_channel(channel_data *chand) {
390 chand->next->prev = chand->prev;
391 chand->prev->next = chand->next;
392 chand->next = chand->prev = chand;
393}
394
Craig Tillerdfff1b82015-09-21 14:39:57 -0700395static void finish_destroy_channel(void *cd, int success,
396 grpc_call_list *call_list) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800397 channel_data *chand = cd;
398 grpc_server *server = chand->server;
Craig Tiller3cd6a512015-09-16 16:15:47 -0700399 gpr_log(GPR_DEBUG, "finish_destroy_channel: %p", chand->channel);
Craig Tillerdfff1b82015-09-21 14:39:57 -0700400 GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "server", call_list);
401 server_unref(server, call_list);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800402}
403
Craig Tillerdfff1b82015-09-21 14:39:57 -0700404static void destroy_channel(channel_data *chand, grpc_call_list *call_list) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800405 if (is_channel_orphaned(chand)) return;
406 GPR_ASSERT(chand->server != NULL);
407 orphan_channel(chand);
408 server_ref(chand->server);
Craig Tillerdfff1b82015-09-21 14:39:57 -0700409 maybe_finish_shutdown(chand->server, call_list);
David Garcia Quintas284488b2015-05-28 16:27:39 -0700410 chand->finish_destroy_channel_closure.cb = finish_destroy_channel;
411 chand->finish_destroy_channel_closure.cb_arg = chand;
Craig Tillerdfff1b82015-09-21 14:39:57 -0700412 grpc_call_list_add(call_list, &chand->finish_destroy_channel_closure, 1);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800413}
414
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700415static void finish_start_new_rpc(grpc_server *server, grpc_call_element *elem,
Craig Tillerdfff1b82015-09-21 14:39:57 -0700416 request_matcher *request_matcher,
417 grpc_call_list *call_list) {
Craig Tiller04cc8be2015-02-10 16:11:22 -0800418 call_data *calld = elem->call_data;
Craig Tiller6a006ce2015-07-13 16:25:40 -0700419 int request_id;
420
Craig Tiller9835a132015-07-22 17:37:39 -0700421 if (gpr_atm_acq_load(&server->shutdown_flag)) {
422 gpr_mu_lock(&calld->mu_state);
423 calld->state = ZOMBIED;
424 gpr_mu_unlock(&calld->mu_state);
Craig Tiller33825112015-09-18 07:44:19 -0700425 grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
Craig Tillerdfff1b82015-09-21 14:39:57 -0700426 grpc_call_list_add(call_list, &calld->kill_zombie_closure, 1);
Craig Tiller9835a132015-07-22 17:37:39 -0700427 return;
428 }
429
Craig Tiller6a006ce2015-07-13 16:25:40 -0700430 request_id = gpr_stack_lockfree_pop(request_matcher->requests);
431 if (request_id == -1) {
432 gpr_mu_lock(&server->mu_call);
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700433 gpr_mu_lock(&calld->mu_state);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800434 calld->state = PENDING;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700435 gpr_mu_unlock(&calld->mu_state);
Craig Tiller729b35a2015-07-13 12:36:47 -0700436 if (request_matcher->pending_head == NULL) {
437 request_matcher->pending_tail = request_matcher->pending_head = calld;
438 } else {
439 request_matcher->pending_tail->pending_next = calld;
440 request_matcher->pending_tail = calld;
441 }
442 calld->pending_next = NULL;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700443 gpr_mu_unlock(&server->mu_call);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800444 } else {
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700445 gpr_mu_lock(&calld->mu_state);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800446 calld->state = ACTIVATED;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700447 gpr_mu_unlock(&calld->mu_state);
Craig Tillerdfff1b82015-09-21 14:39:57 -0700448 begin_call(server, calld, &server->requested_calls[request_id], call_list);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800449 }
450}
451
Craig Tillerdfff1b82015-09-21 14:39:57 -0700452static void start_new_rpc(grpc_call_element *elem, grpc_call_list *call_list) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800453 channel_data *chand = elem->channel_data;
454 call_data *calld = elem->call_data;
455 grpc_server *server = chand->server;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800456 gpr_uint32 i;
457 gpr_uint32 hash;
458 channel_registered_method *rm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800459
Craig Tiller04cc8be2015-02-10 16:11:22 -0800460 if (chand->registered_methods && calld->path && calld->host) {
Craig Tillera94beff2015-02-17 22:02:06 -0800461 /* TODO(ctiller): unify these two searches */
Craig Tiller04cc8be2015-02-10 16:11:22 -0800462 /* check for an exact match with host */
463 hash = GRPC_MDSTR_KV_HASH(calld->host->hash, calld->path->hash);
Craig Tillerc6d6d902015-07-09 15:53:50 -0700464 for (i = 0; i <= chand->registered_method_max_probes; i++) {
Craig Tiller3b29b562015-02-11 12:58:46 -0800465 rm = &chand->registered_methods[(hash + i) %
466 chand->registered_method_slots];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800467 if (!rm) break;
468 if (rm->host != calld->host) continue;
469 if (rm->method != calld->path) continue;
Craig Tiller729b35a2015-07-13 12:36:47 -0700470 finish_start_new_rpc(server, elem,
Craig Tillerdfff1b82015-09-21 14:39:57 -0700471 &rm->server_registered_method->request_matcher,
472 call_list);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800473 return;
474 }
475 /* check for a wildcard method definition (no host set) */
476 hash = GRPC_MDSTR_KV_HASH(0, calld->path->hash);
Craig Tiller0ef1a922015-02-11 16:23:01 -0800477 for (i = 0; i <= chand->registered_method_max_probes; i++) {
Craig Tiller3b29b562015-02-11 12:58:46 -0800478 rm = &chand->registered_methods[(hash + i) %
479 chand->registered_method_slots];
Craig Tiller04cc8be2015-02-10 16:11:22 -0800480 if (!rm) break;
481 if (rm->host != NULL) continue;
482 if (rm->method != calld->path) continue;
Craig Tiller729b35a2015-07-13 12:36:47 -0700483 finish_start_new_rpc(server, elem,
Craig Tillerdfff1b82015-09-21 14:39:57 -0700484 &rm->server_registered_method->request_matcher,
485 call_list);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800486 return;
487 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800488 }
Craig Tillerdfff1b82015-09-21 14:39:57 -0700489 finish_start_new_rpc(server, elem, &server->unregistered_request_matcher,
490 call_list);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800491}
492
Craig Tilleree945e82015-05-26 16:15:34 -0700493static int num_listeners(grpc_server *server) {
494 listener *l;
495 int n = 0;
496 for (l = server->listeners; l; l = l->next) {
497 n++;
498 }
499 return n;
500}
501
Craig Tillerdfff1b82015-09-21 14:39:57 -0700502static void done_shutdown_event(void *server, grpc_cq_completion *completion,
503 grpc_call_list *call_list) {
504 server_unref(server, call_list);
Craig Tiller97fc6a32015-07-08 15:31:35 -0700505}
506
Craig Tillerab54f792015-07-08 08:34:20 -0700507static int num_channels(grpc_server *server) {
508 channel_data *chand;
509 int n = 0;
510 for (chand = server->root_channel_data.next;
511 chand != &server->root_channel_data; chand = chand->next) {
512 n++;
513 }
514 return n;
515}
516
Craig Tillerdfff1b82015-09-21 14:39:57 -0700517static void kill_pending_work_locked(grpc_server *server,
518 grpc_call_list *call_list) {
Craig Tiller1191e212015-07-30 14:49:02 -0700519 registered_method *rm;
Craig Tillerdfff1b82015-09-21 14:39:57 -0700520 request_matcher_kill_requests(server, &server->unregistered_request_matcher,
521 call_list);
Craig Tiller1191e212015-07-30 14:49:02 -0700522 request_matcher_zombify_all_pending_calls(
Craig Tillerdfff1b82015-09-21 14:39:57 -0700523 &server->unregistered_request_matcher, call_list);
Craig Tiller1191e212015-07-30 14:49:02 -0700524 for (rm = server->registered_methods; rm; rm = rm->next) {
Craig Tillerdfff1b82015-09-21 14:39:57 -0700525 request_matcher_kill_requests(server, &rm->request_matcher, call_list);
526 request_matcher_zombify_all_pending_calls(&rm->request_matcher, call_list);
Craig Tiller1191e212015-07-30 14:49:02 -0700527 }
528}
529
Craig Tillerdfff1b82015-09-21 14:39:57 -0700530static void maybe_finish_shutdown(grpc_server *server,
531 grpc_call_list *call_list) {
Craig Tillerbce999f2015-05-27 09:55:51 -0700532 size_t i;
Craig Tiller6a006ce2015-07-13 16:25:40 -0700533 if (!gpr_atm_acq_load(&server->shutdown_flag) || server->shutdown_published) {
Craig Tillerc4a1f522015-05-29 22:32:04 -0700534 return;
535 }
Vijay Pai8931cdd2015-06-17 12:42:17 -0700536
Craig Tillerdfff1b82015-09-21 14:39:57 -0700537 kill_pending_work_locked(server, call_list);
Craig Tiller1191e212015-07-30 14:49:02 -0700538
Craig Tillerab54f792015-07-08 08:34:20 -0700539 if (server->root_channel_data.next != &server->root_channel_data ||
540 server->listeners_destroyed < num_listeners(server)) {
Craig Tiller58bbc862015-07-13 09:51:17 -0700541 if (gpr_time_cmp(gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME),
542 server->last_shutdown_message_time),
543 gpr_time_from_seconds(1, GPR_TIMESPAN)) >= 0) {
Craig Tiller080d6c52015-07-10 10:23:10 -0700544 server->last_shutdown_message_time = gpr_now(GPR_CLOCK_REALTIME);
Craig Tillerab54f792015-07-08 08:34:20 -0700545 gpr_log(GPR_DEBUG,
546 "Waiting for %d channels and %d/%d listeners to be destroyed"
547 " before shutting down server",
548 num_channels(server),
549 num_listeners(server) - server->listeners_destroyed,
550 num_listeners(server));
551 }
Craig Tillerc4a1f522015-05-29 22:32:04 -0700552 return;
553 }
554 server->shutdown_published = 1;
555 for (i = 0; i < server->num_shutdown_tags; i++) {
Craig Tiller97fc6a32015-07-08 15:31:35 -0700556 server_ref(server);
Craig Tiller12cf5372015-07-09 13:48:11 -0700557 grpc_cq_end_op(server->shutdown_tags[i].cq, server->shutdown_tags[i].tag, 1,
558 done_shutdown_event, server,
Craig Tillerdfff1b82015-09-21 14:39:57 -0700559 &server->shutdown_tags[i].completion, call_list);
Craig Tillerdc627722015-05-26 15:27:02 -0700560 }
561}
562
Craig Tiller6902ad22015-04-16 08:01:49 -0700563static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
564 grpc_call_element *elem = user_data;
Craig Tillercce17ac2015-01-20 09:29:28 -0800565 channel_data *chand = elem->channel_data;
566 call_data *calld = elem->call_data;
Craig Tiller6902ad22015-04-16 08:01:49 -0700567 if (md->key == chand->path_key) {
Craig Tiller1a65a232015-07-06 10:22:32 -0700568 calld->path = GRPC_MDSTR_REF(md->value);
Craig Tiller6902ad22015-04-16 08:01:49 -0700569 return NULL;
570 } else if (md->key == chand->authority_key) {
Craig Tiller1a65a232015-07-06 10:22:32 -0700571 calld->host = GRPC_MDSTR_REF(md->value);
Craig Tiller6902ad22015-04-16 08:01:49 -0700572 return NULL;
573 }
574 return md;
575}
576
Craig Tillerdfff1b82015-09-21 14:39:57 -0700577static void server_on_recv(void *ptr, int success, grpc_call_list *call_list) {
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700578 grpc_call_element *elem = ptr;
Craig Tiller6902ad22015-04-16 08:01:49 -0700579 call_data *calld = elem->call_data;
Craig Tiller94329d02015-07-23 09:52:11 -0700580 gpr_timespec op_deadline;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700581
582 if (success && !calld->got_initial_metadata) {
583 size_t i;
584 size_t nops = calld->recv_ops->nops;
585 grpc_stream_op *ops = calld->recv_ops->ops;
586 for (i = 0; i < nops; i++) {
587 grpc_stream_op *op = &ops[i];
588 if (op->type != GRPC_OP_METADATA) continue;
Craig Tiller205aee12015-04-16 14:46:41 -0700589 grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem);
Craig Tiller94329d02015-07-23 09:52:11 -0700590 op_deadline = op->data.metadata.deadline;
591 if (0 !=
592 gpr_time_cmp(op_deadline, gpr_inf_future(op_deadline.clock_type))) {
Craig Tiller6902ad22015-04-16 08:01:49 -0700593 calld->deadline = op->data.metadata.deadline;
Craig Tillercce17ac2015-01-20 09:29:28 -0800594 }
Craig Tillerc4b56b62015-07-23 17:44:11 -0700595 if (calld->host && calld->path) {
596 calld->got_initial_metadata = 1;
Craig Tillerdfff1b82015-09-21 14:39:57 -0700597 start_new_rpc(elem, call_list);
Craig Tillerc4b56b62015-07-23 17:44:11 -0700598 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800599 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700600 }
601 }
602
603 switch (*calld->recv_state) {
Craig Tiller06aeea72015-04-23 10:54:45 -0700604 case GRPC_STREAM_OPEN:
605 break;
606 case GRPC_STREAM_SEND_CLOSED:
607 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700608 case GRPC_STREAM_RECV_CLOSED:
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700609 gpr_mu_lock(&calld->mu_state);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700610 if (calld->state == NOT_STARTED) {
611 calld->state = ZOMBIED;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700612 gpr_mu_unlock(&calld->mu_state);
Craig Tiller33825112015-09-18 07:44:19 -0700613 grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
Craig Tillerdfff1b82015-09-21 14:39:57 -0700614 grpc_call_list_add(call_list, &calld->kill_zombie_closure, 1);
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700615 } else {
616 gpr_mu_unlock(&calld->mu_state);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700617 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800618 break;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700619 case GRPC_STREAM_CLOSED:
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700620 gpr_mu_lock(&calld->mu_state);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700621 if (calld->state == NOT_STARTED) {
622 calld->state = ZOMBIED;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700623 gpr_mu_unlock(&calld->mu_state);
Craig Tiller33825112015-09-18 07:44:19 -0700624 grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
Craig Tillerdfff1b82015-09-21 14:39:57 -0700625 grpc_call_list_add(call_list, &calld->kill_zombie_closure, 1);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700626 } else if (calld->state == PENDING) {
Craig Tillerc9d03822015-05-20 16:08:45 -0700627 calld->state = ZOMBIED;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700628 gpr_mu_unlock(&calld->mu_state);
Craig Tiller729b35a2015-07-13 12:36:47 -0700629 /* zombied call will be destroyed when it's removed from the pending
630 queue... later */
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700631 } else {
632 gpr_mu_unlock(&calld->mu_state);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700633 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800634 break;
635 }
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700636
Craig Tillerdfff1b82015-09-21 14:39:57 -0700637 calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success, call_list);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700638}
639
Craig Tillerb7959a02015-06-25 08:50:54 -0700640static void server_mutate_op(grpc_call_element *elem,
641 grpc_transport_stream_op *op) {
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700642 call_data *calld = elem->call_data;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700643
644 if (op->recv_ops) {
645 /* substitute our callback for the higher callback */
646 calld->recv_ops = op->recv_ops;
647 calld->recv_state = op->recv_state;
648 calld->on_done_recv = op->on_done_recv;
Craig Tiller1e6facb2015-06-11 22:47:11 -0700649 op->on_done_recv = &calld->server_on_recv;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700650 }
Craig Tiller50d9db52015-04-23 10:52:14 -0700651}
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700652
Craig Tillere039f032015-06-25 12:54:23 -0700653static void server_start_transport_stream_op(grpc_call_element *elem,
Craig Tillerdfff1b82015-09-21 14:39:57 -0700654 grpc_transport_stream_op *op,
655 grpc_call_list *call_list) {
Craig Tiller50d9db52015-04-23 10:52:14 -0700656 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
657 server_mutate_op(elem, op);
Craig Tillerdfff1b82015-09-21 14:39:57 -0700658 grpc_call_next_op(elem, op, call_list);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800659}
660
Craig Tillere039f032015-06-25 12:54:23 -0700661static void accept_stream(void *cd, grpc_transport *transport,
662 const void *transport_server_data) {
663 channel_data *chand = cd;
664 /* create a call */
Craig Tiller3e7c6a72015-07-31 16:17:04 -0700665 grpc_call_create(chand->channel, NULL, 0, NULL, transport_server_data, NULL,
666 0, gpr_inf_future(GPR_CLOCK_MONOTONIC));
Craig Tillere039f032015-06-25 12:54:23 -0700667}
668
Craig Tillerdfff1b82015-09-21 14:39:57 -0700669static void channel_connectivity_changed(void *cd, int iomgr_status_ignored,
670 grpc_call_list *call_list) {
Craig Tillere039f032015-06-25 12:54:23 -0700671 channel_data *chand = cd;
672 grpc_server *server = chand->server;
673 if (chand->connectivity_state != GRPC_CHANNEL_FATAL_FAILURE) {
674 grpc_transport_op op;
675 memset(&op, 0, sizeof(op));
676 op.on_connectivity_state_change = &chand->channel_connectivity_changed,
677 op.connectivity_state = &chand->connectivity_state;
678 grpc_channel_next_op(grpc_channel_stack_element(
679 grpc_channel_get_channel_stack(chand->channel), 0),
Craig Tillerdfff1b82015-09-21 14:39:57 -0700680 &op, call_list);
Craig Tillere039f032015-06-25 12:54:23 -0700681 } else {
682 gpr_mu_lock(&server->mu_global);
Craig Tillerdfff1b82015-09-21 14:39:57 -0700683 destroy_channel(chand, call_list);
Craig Tillere039f032015-06-25 12:54:23 -0700684 gpr_mu_unlock(&server->mu_global);
Craig Tillerdfff1b82015-09-21 14:39:57 -0700685 GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "connectivity", call_list);
Craig Tillere039f032015-06-25 12:54:23 -0700686 }
687}
688
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800689static void init_call_elem(grpc_call_element *elem,
Craig Tiller06aeea72015-04-23 10:54:45 -0700690 const void *server_transport_data,
Craig Tillerdfff1b82015-09-21 14:39:57 -0700691 grpc_transport_stream_op *initial_op,
692 grpc_call_list *call_list) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800693 call_data *calld = elem->call_data;
694 channel_data *chand = elem->channel_data;
695 memset(calld, 0, sizeof(call_data));
Craig Tiller143e7bf2015-07-13 08:41:49 -0700696 calld->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800697 calld->call = grpc_call_from_top_element(elem);
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700698 gpr_mu_init(&calld->mu_state);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800699
Craig Tiller33825112015-09-18 07:44:19 -0700700 grpc_closure_init(&calld->server_on_recv, server_on_recv, elem);
Craig Tiller1e6facb2015-06-11 22:47:11 -0700701
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800702 server_ref(chand->server);
Craig Tiller50d9db52015-04-23 10:52:14 -0700703
Craig Tiller482ef8b2015-04-23 11:38:20 -0700704 if (initial_op) server_mutate_op(elem, initial_op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800705}
706
Craig Tillerdfff1b82015-09-21 14:39:57 -0700707static void destroy_call_elem(grpc_call_element *elem,
708 grpc_call_list *call_list) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800709 channel_data *chand = elem->channel_data;
Craig Tillerdb7db992015-01-29 11:19:01 -0800710 call_data *calld = elem->call_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800711
Craig Tiller729b35a2015-07-13 12:36:47 -0700712 GPR_ASSERT(calld->state != PENDING);
Craig Tiller092d8d12015-07-04 22:35:00 -0700713
Craig Tiller4df31a62015-01-30 09:44:31 -0800714 if (calld->host) {
Craig Tiller1a65a232015-07-06 10:22:32 -0700715 GRPC_MDSTR_UNREF(calld->host);
Craig Tiller4df31a62015-01-30 09:44:31 -0800716 }
717 if (calld->path) {
Craig Tiller1a65a232015-07-06 10:22:32 -0700718 GRPC_MDSTR_UNREF(calld->path);
Craig Tiller4df31a62015-01-30 09:44:31 -0800719 }
720
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700721 gpr_mu_destroy(&calld->mu_state);
722
Craig Tillerdfff1b82015-09-21 14:39:57 -0700723 server_unref(chand->server, call_list);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800724}
725
Craig Tiller079a11b2015-06-30 10:07:15 -0700726static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800727 const grpc_channel_args *args,
728 grpc_mdctx *metadata_context, int is_first,
Craig Tillerdfff1b82015-09-21 14:39:57 -0700729 int is_last, grpc_call_list *call_list) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800730 channel_data *chand = elem->channel_data;
731 GPR_ASSERT(is_first);
732 GPR_ASSERT(!is_last);
733 chand->server = NULL;
734 chand->channel = NULL;
Craig Tiller6999c092015-07-22 08:14:12 -0700735 chand->path_key = grpc_mdstr_from_string(metadata_context, ":path", 0);
Craig Tillerd6c98df2015-08-18 09:33:44 -0700736 chand->authority_key =
737 grpc_mdstr_from_string(metadata_context, ":authority", 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800738 chand->next = chand->prev = chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800739 chand->registered_methods = NULL;
Craig Tillere039f032015-06-25 12:54:23 -0700740 chand->connectivity_state = GRPC_CHANNEL_IDLE;
Craig Tiller33825112015-09-18 07:44:19 -0700741 grpc_closure_init(&chand->channel_connectivity_changed,
742 channel_connectivity_changed, chand);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800743}
744
Craig Tillerdfff1b82015-09-21 14:39:57 -0700745static void destroy_channel_elem(grpc_channel_element *elem,
746 grpc_call_list *call_list) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800747 size_t i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800748 channel_data *chand = elem->channel_data;
Craig Tillerec3257c2015-02-12 15:59:43 -0800749 if (chand->registered_methods) {
750 for (i = 0; i < chand->registered_method_slots; i++) {
751 if (chand->registered_methods[i].method) {
Craig Tiller1a65a232015-07-06 10:22:32 -0700752 GRPC_MDSTR_UNREF(chand->registered_methods[i].method);
Craig Tillerec3257c2015-02-12 15:59:43 -0800753 }
754 if (chand->registered_methods[i].host) {
Craig Tiller1a65a232015-07-06 10:22:32 -0700755 GRPC_MDSTR_UNREF(chand->registered_methods[i].host);
Craig Tillerec3257c2015-02-12 15:59:43 -0800756 }
757 }
758 gpr_free(chand->registered_methods);
759 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800760 if (chand->server) {
Vijay Pai8931cdd2015-06-17 12:42:17 -0700761 gpr_mu_lock(&chand->server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800762 chand->next->prev = chand->prev;
763 chand->prev->next = chand->next;
764 chand->next = chand->prev = chand;
Craig Tillerdfff1b82015-09-21 14:39:57 -0700765 maybe_finish_shutdown(chand->server, call_list);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700766 gpr_mu_unlock(&chand->server->mu_global);
Craig Tiller1a65a232015-07-06 10:22:32 -0700767 GRPC_MDSTR_UNREF(chand->path_key);
768 GRPC_MDSTR_UNREF(chand->authority_key);
Craig Tillerdfff1b82015-09-21 14:39:57 -0700769 server_unref(chand->server, call_list);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800770 }
771}
772
773static const grpc_channel_filter server_surface_filter = {
Craig Tillere039f032015-06-25 12:54:23 -0700774 server_start_transport_stream_op,
775 grpc_channel_next_op,
Craig Tillerb76d05b2015-05-29 17:21:56 -0700776 sizeof(call_data),
777 init_call_elem,
778 destroy_call_elem,
779 sizeof(channel_data),
780 init_channel_elem,
781 destroy_channel_elem,
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700782 grpc_call_next_get_peer,
Craig Tillerb76d05b2015-05-29 17:21:56 -0700783 "server",
Craig Tiller9f28ac22015-01-27 17:01:29 -0800784};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800785
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700786void grpc_server_register_completion_queue(grpc_server *server,
Nicolas "Pixel" Nobleebb51402015-07-23 02:41:33 +0200787 grpc_completion_queue *cq,
788 void *reserved) {
Craig Tiller20bc56d2015-02-12 09:02:56 -0800789 size_t i, n;
Nicolas "Pixel" Noble45992882015-07-29 23:52:14 +0200790 GPR_ASSERT(!reserved);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800791 for (i = 0; i < server->cq_count; i++) {
792 if (server->cqs[i] == cq) return;
793 }
Craig Tiller463f2372015-05-28 16:16:15 -0700794 GRPC_CQ_INTERNAL_REF(cq, "server");
Craig Tillerb56975c2015-06-15 10:11:16 -0700795 grpc_cq_mark_server_cq(cq);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800796 n = server->cq_count++;
Craig Tillerec3257c2015-02-12 15:59:43 -0800797 server->cqs = gpr_realloc(server->cqs,
798 server->cq_count * sizeof(grpc_completion_queue *));
Craig Tiller20bc56d2015-02-12 09:02:56 -0800799 server->cqs[n] = cq;
800}
801
David Garcia Quintase25e9282015-06-23 10:18:52 -0700802grpc_server *grpc_server_create_from_filters(
803 const grpc_channel_filter **filters, size_t filter_count,
804 const grpc_channel_args *args) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800805 size_t i;
Alistair Veitch9d48ebf2015-06-01 10:01:03 -0700806 /* TODO(census): restore this once we finalize census filter etc.
807 int census_enabled = grpc_channel_args_is_census_enabled(args); */
808 int census_enabled = 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800809
810 grpc_server *server = gpr_malloc(sizeof(grpc_server));
Craig Tiller60fd3612015-03-05 16:24:22 -0800811
812 GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
813
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800814 memset(server, 0, sizeof(grpc_server));
815
Vijay Pai8931cdd2015-06-17 12:42:17 -0700816 gpr_mu_init(&server->mu_global);
817 gpr_mu_init(&server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800818
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800819 /* decremented by grpc_server_destroy */
820 gpr_ref_init(&server->internal_refcount, 1);
821 server->root_channel_data.next = server->root_channel_data.prev =
822 &server->root_channel_data;
823
Craig Tiller6a006ce2015-07-13 16:25:40 -0700824 /* TODO(ctiller): expose a channel_arg for this */
825 server->max_requested_calls = 32768;
826 server->request_freelist =
827 gpr_stack_lockfree_create(server->max_requested_calls);
828 for (i = 0; i < (size_t)server->max_requested_calls; i++) {
Craig Tillerf96dfc32015-09-10 14:43:18 -0700829 gpr_stack_lockfree_push(server->request_freelist, (int)i);
Craig Tiller6a006ce2015-07-13 16:25:40 -0700830 }
831 request_matcher_init(&server->unregistered_request_matcher,
832 server->max_requested_calls);
833 server->requested_calls = gpr_malloc(server->max_requested_calls *
834 sizeof(*server->requested_calls));
Craig Tiller729b35a2015-07-13 12:36:47 -0700835
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800836 /* Server filter stack is:
837
838 server_surface_filter - for making surface API calls
839 grpc_server_census_filter (optional) - for stats collection and tracing
840 {passed in filter stack}
841 grpc_connected_channel_filter - for interfacing with transports */
Craig Tiller32ca48c2015-09-10 11:47:15 -0700842 server->channel_filter_count = filter_count + 1u + (census_enabled ? 1u : 0u);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800843 server->channel_filters =
844 gpr_malloc(server->channel_filter_count * sizeof(grpc_channel_filter *));
845 server->channel_filters[0] = &server_surface_filter;
846 if (census_enabled) {
847 server->channel_filters[1] = &grpc_server_census_filter;
Hongyu Chenf68e4722015-08-07 18:06:42 -0700848 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800849 for (i = 0; i < filter_count; i++) {
Craig Tiller32ca48c2015-09-10 11:47:15 -0700850 server->channel_filters[i + 1u + (census_enabled ? 1u : 0u)] = filters[i];
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800851 }
852
853 server->channel_args = grpc_channel_args_copy(args);
854
855 return server;
856}
857
Craig Tiller24be0f72015-02-10 14:04:22 -0800858static int streq(const char *a, const char *b) {
859 if (a == NULL && b == NULL) return 1;
860 if (a == NULL) return 0;
861 if (b == NULL) return 0;
862 return 0 == strcmp(a, b);
863}
864
865void *grpc_server_register_method(grpc_server *server, const char *method,
Craig Tillerf9e6adf2015-05-06 11:45:59 -0700866 const char *host) {
Craig Tiller24be0f72015-02-10 14:04:22 -0800867 registered_method *m;
868 if (!method) {
Craig Tillerb76d05b2015-05-29 17:21:56 -0700869 gpr_log(GPR_ERROR,
870 "grpc_server_register_method method string cannot be NULL");
Craig Tiller24be0f72015-02-10 14:04:22 -0800871 return NULL;
872 }
873 for (m = server->registered_methods; m; m = m->next) {
874 if (streq(m->method, method) && streq(m->host, host)) {
875 gpr_log(GPR_ERROR, "duplicate registration for %s@%s", method,
876 host ? host : "*");
877 return NULL;
878 }
879 }
880 m = gpr_malloc(sizeof(registered_method));
881 memset(m, 0, sizeof(*m));
Craig Tiller6a006ce2015-07-13 16:25:40 -0700882 request_matcher_init(&m->request_matcher, server->max_requested_calls);
Craig Tiller24be0f72015-02-10 14:04:22 -0800883 m->method = gpr_strdup(method);
884 m->host = gpr_strdup(host);
885 m->next = server->registered_methods;
886 server->registered_methods = m;
887 return m;
888}
889
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800890void grpc_server_start(grpc_server *server) {
891 listener *l;
Craig Tiller20bc56d2015-02-12 09:02:56 -0800892 size_t i;
Craig Tillerdfff1b82015-09-21 14:39:57 -0700893 grpc_call_list call_list = GRPC_CALL_LIST_INIT;
Craig Tiller20bc56d2015-02-12 09:02:56 -0800894
Craig Tillerec3257c2015-02-12 15:59:43 -0800895 server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800896 for (i = 0; i < server->cq_count; i++) {
897 server->pollsets[i] = grpc_cq_pollset(server->cqs[i]);
898 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800899
900 for (l = server->listeners; l; l = l->next) {
Craig Tillerdfff1b82015-09-21 14:39:57 -0700901 l->start(server, l->arg, server->pollsets, server->cq_count, &call_list);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800902 }
Craig Tillerdfff1b82015-09-21 14:39:57 -0700903
904 grpc_call_list_run(&call_list);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800905}
906
Craig Tiller1064f8b2015-06-25 13:52:57 -0700907void grpc_server_setup_transport(grpc_server *s, grpc_transport *transport,
908 grpc_channel_filter const **extra_filters,
909 size_t num_extra_filters, grpc_mdctx *mdctx,
Craig Tiller47a708e2015-09-15 16:16:06 -0700910 grpc_workqueue *workqueue,
Craig Tillerdfff1b82015-09-21 14:39:57 -0700911 const grpc_channel_args *args,
912 grpc_call_list *call_list) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800913 size_t num_filters = s->channel_filter_count + num_extra_filters + 1;
914 grpc_channel_filter const **filters =
915 gpr_malloc(sizeof(grpc_channel_filter *) * num_filters);
916 size_t i;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800917 size_t num_registered_methods;
918 size_t alloc;
919 registered_method *rm;
920 channel_registered_method *crm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800921 grpc_channel *channel;
922 channel_data *chand;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800923 grpc_mdstr *host;
924 grpc_mdstr *method;
925 gpr_uint32 hash;
Craig Tillerf96dfc32015-09-10 14:43:18 -0700926 size_t slots;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800927 gpr_uint32 probes;
928 gpr_uint32 max_probes = 0;
Craig Tillere039f032015-06-25 12:54:23 -0700929 grpc_transport_op op;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800930
931 for (i = 0; i < s->channel_filter_count; i++) {
932 filters[i] = s->channel_filters[i];
933 }
934 for (; i < s->channel_filter_count + num_extra_filters; i++) {
935 filters[i] = extra_filters[i - s->channel_filter_count];
936 }
937 filters[i] = &grpc_connected_channel_filter;
938
Craig Tiller20bc56d2015-02-12 09:02:56 -0800939 for (i = 0; i < s->cq_count; i++) {
Craig Tillere039f032015-06-25 12:54:23 -0700940 memset(&op, 0, sizeof(op));
941 op.bind_pollset = grpc_cq_pollset(s->cqs[i]);
Craig Tillerdfff1b82015-09-21 14:39:57 -0700942 grpc_transport_perform_op(transport, &op, call_list);
Craig Tiller20bc56d2015-02-12 09:02:56 -0800943 }
ctillerd79b4862014-12-17 16:36:59 -0800944
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700945 channel = grpc_channel_create_from_filters(NULL, filters, num_filters, args,
Craig Tillerdfff1b82015-09-21 14:39:57 -0700946 mdctx, workqueue, 0, call_list);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800947 chand = (channel_data *)grpc_channel_stack_element(
Craig Tillerc02c1d82015-04-07 16:21:55 -0700948 grpc_channel_get_channel_stack(channel), 0)
949 ->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800950 chand->server = s;
951 server_ref(s);
952 chand->channel = channel;
953
Craig Tiller04cc8be2015-02-10 16:11:22 -0800954 num_registered_methods = 0;
955 for (rm = s->registered_methods; rm; rm = rm->next) {
956 num_registered_methods++;
957 }
958 /* build a lookup table phrased in terms of mdstr's in this channels context
959 to quickly find registered methods */
960 if (num_registered_methods > 0) {
961 slots = 2 * num_registered_methods;
962 alloc = sizeof(channel_registered_method) * slots;
963 chand->registered_methods = gpr_malloc(alloc);
964 memset(chand->registered_methods, 0, alloc);
965 for (rm = s->registered_methods; rm; rm = rm->next) {
Craig Tiller6999c092015-07-22 08:14:12 -0700966 host = rm->host ? grpc_mdstr_from_string(mdctx, rm->host, 0) : NULL;
967 method = grpc_mdstr_from_string(mdctx, rm->method, 0);
Craig Tiller04cc8be2015-02-10 16:11:22 -0800968 hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash);
Craig Tiller3b29b562015-02-11 12:58:46 -0800969 for (probes = 0; chand->registered_methods[(hash + probes) % slots]
Craig Tillerc02c1d82015-04-07 16:21:55 -0700970 .server_registered_method != NULL;
Craig Tiller3b29b562015-02-11 12:58:46 -0800971 probes++)
972 ;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800973 if (probes > max_probes) max_probes = probes;
974 crm = &chand->registered_methods[(hash + probes) % slots];
975 crm->server_registered_method = rm;
976 crm->host = host;
977 crm->method = method;
978 }
Craig Tillerf96dfc32015-09-10 14:43:18 -0700979 GPR_ASSERT(slots <= GPR_UINT32_MAX);
980 chand->registered_method_slots = (gpr_uint32)slots;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800981 chand->registered_method_max_probes = max_probes;
982 }
983
Craig Tiller1064f8b2015-06-25 13:52:57 -0700984 grpc_connected_channel_bind_transport(grpc_channel_get_channel_stack(channel),
985 transport);
Craig Tiller7bd5ab12015-02-17 22:29:04 -0800986
Vijay Pai8931cdd2015-06-17 12:42:17 -0700987 gpr_mu_lock(&s->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800988 chand->next = &s->root_channel_data;
989 chand->prev = chand->next->prev;
990 chand->next->prev = chand->prev->next = chand;
Vijay Pai8931cdd2015-06-17 12:42:17 -0700991 gpr_mu_unlock(&s->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800992
993 gpr_free(filters);
Craig Tiller4b804102015-06-26 16:16:12 -0700994
995 GRPC_CHANNEL_INTERNAL_REF(channel, "connectivity");
996 memset(&op, 0, sizeof(op));
997 op.set_accept_stream = accept_stream;
998 op.set_accept_stream_user_data = chand;
999 op.on_connectivity_state_change = &chand->channel_connectivity_changed;
1000 op.connectivity_state = &chand->connectivity_state;
Craig Tillerf96dfc32015-09-10 14:43:18 -07001001 op.disconnect = gpr_atm_acq_load(&s->shutdown_flag) != 0;
Craig Tillerdfff1b82015-09-21 14:39:57 -07001002 grpc_transport_perform_op(transport, &op, call_list);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001003}
1004
Craig Tillerdfff1b82015-09-21 14:39:57 -07001005void done_published_shutdown(void *done_arg, grpc_cq_completion *storage,
1006 grpc_call_list *call_list) {
murgatroid9900a3dab2015-08-19 11:15:38 -07001007 (void) done_arg;
1008 gpr_free(storage);
1009}
1010
Craig Tillerdfff1b82015-09-21 14:39:57 -07001011static void listener_destroy_done(void *s, int success,
1012 grpc_call_list *call_list) {
1013 grpc_server *server = s;
1014 gpr_mu_lock(&server->mu_global);
1015 server->listeners_destroyed++;
1016 maybe_finish_shutdown(server, call_list);
1017 gpr_mu_unlock(&server->mu_global);
1018}
1019
Craig Tillerbce999f2015-05-27 09:55:51 -07001020void grpc_server_shutdown_and_notify(grpc_server *server,
1021 grpc_completion_queue *cq, void *tag) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001022 listener *l;
Craig Tillerbce999f2015-05-27 09:55:51 -07001023 shutdown_tag *sdt;
Craig Tillerff3ae682015-06-29 17:44:04 -07001024 channel_broadcaster broadcaster;
Craig Tillerdfff1b82015-09-21 14:39:57 -07001025 grpc_call_list call_list = GRPC_CALL_LIST_INIT;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001026
Craig Tiller7156fca2015-07-15 13:54:20 -07001027 GRPC_SERVER_LOG_SHUTDOWN(GPR_INFO, server, cq, tag);
1028
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001029 /* lock, and gather up some stuff to do */
Vijay Pai8931cdd2015-06-17 12:42:17 -07001030 gpr_mu_lock(&server->mu_global);
Craig Tiller97fc6a32015-07-08 15:31:35 -07001031 grpc_cq_begin_op(cq);
murgatroid9900a3dab2015-08-19 11:15:38 -07001032 if (server->shutdown_published) {
1033 grpc_cq_end_op(cq, tag, 1, done_published_shutdown, NULL,
Craig Tillerdfff1b82015-09-21 14:39:57 -07001034 gpr_malloc(sizeof(grpc_cq_completion)), &call_list);
murgatroid9900a3dab2015-08-19 11:15:38 -07001035 gpr_mu_unlock(&server->mu_global);
Craig Tillerdfff1b82015-09-21 14:39:57 -07001036 goto done;
murgatroid9900a3dab2015-08-19 11:15:38 -07001037 }
Craig Tilleree945e82015-05-26 16:15:34 -07001038 server->shutdown_tags =
1039 gpr_realloc(server->shutdown_tags,
Craig Tiller208d2122015-05-29 08:50:08 -07001040 sizeof(shutdown_tag) * (server->num_shutdown_tags + 1));
Craig Tillerbce999f2015-05-27 09:55:51 -07001041 sdt = &server->shutdown_tags[server->num_shutdown_tags++];
1042 sdt->tag = tag;
1043 sdt->cq = cq;
Craig Tiller6a006ce2015-07-13 16:25:40 -07001044 if (gpr_atm_acq_load(&server->shutdown_flag)) {
Vijay Pai8931cdd2015-06-17 12:42:17 -07001045 gpr_mu_unlock(&server->mu_global);
Craig Tillerdfff1b82015-09-21 14:39:57 -07001046 goto done;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001047 }
1048
Craig Tiller080d6c52015-07-10 10:23:10 -07001049 server->last_shutdown_message_time = gpr_now(GPR_CLOCK_REALTIME);
Craig Tillerab54f792015-07-08 08:34:20 -07001050
Craig Tillerff3ae682015-06-29 17:44:04 -07001051 channel_broadcaster_init(server, &broadcaster);
nnoble0c475f02014-12-05 15:37:39 -08001052
Craig Tillerbd217572015-02-11 18:10:56 -08001053 /* collect all unregistered then registered calls */
Vijay Pai8931cdd2015-06-17 12:42:17 -07001054 gpr_mu_lock(&server->mu_call);
Craig Tillerdfff1b82015-09-21 14:39:57 -07001055 kill_pending_work_locked(server, &call_list);
Vijay Pai8931cdd2015-06-17 12:42:17 -07001056 gpr_mu_unlock(&server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001057
Craig Tiller6a006ce2015-07-13 16:25:40 -07001058 gpr_atm_rel_store(&server->shutdown_flag, 1);
Craig Tillerdfff1b82015-09-21 14:39:57 -07001059 maybe_finish_shutdown(server, &call_list);
Vijay Pai8931cdd2015-06-17 12:42:17 -07001060 gpr_mu_unlock(&server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001061
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001062 /* Shutdown listeners */
1063 for (l = server->listeners; l; l = l->next) {
Craig Tillerdfff1b82015-09-21 14:39:57 -07001064 grpc_closure_init(&l->destroy_done, listener_destroy_done, server);
1065 l->destroy(server, l->arg, &l->destroy_done, &call_list);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001066 }
Craig Tillerff3ae682015-06-29 17:44:04 -07001067
Craig Tillerdfff1b82015-09-21 14:39:57 -07001068 channel_broadcaster_shutdown(&broadcaster, 1, 0, &call_list);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001069
Craig Tillerdfff1b82015-09-21 14:39:57 -07001070done:
1071 grpc_call_list_run(&call_list);
Craig Tilleraec96aa2015-04-07 14:32:15 -07001072}
1073
Craig Tillerafa2d632015-05-26 16:39:13 -07001074void grpc_server_cancel_all_calls(grpc_server *server) {
Craig Tiller092d8d12015-07-04 22:35:00 -07001075 channel_broadcaster broadcaster;
Craig Tillerdfff1b82015-09-21 14:39:57 -07001076 grpc_call_list call_list = GRPC_CALL_LIST_INIT;
Craig Tillerafa2d632015-05-26 16:39:13 -07001077
Craig Tiller092d8d12015-07-04 22:35:00 -07001078 gpr_mu_lock(&server->mu_global);
1079 channel_broadcaster_init(server, &broadcaster);
1080 gpr_mu_unlock(&server->mu_global);
Craig Tillerafa2d632015-05-26 16:39:13 -07001081
Craig Tillerdfff1b82015-09-21 14:39:57 -07001082 channel_broadcaster_shutdown(&broadcaster, 0, 1, &call_list);
1083 grpc_call_list_run(&call_list);
Craig Tillerafa2d632015-05-26 16:39:13 -07001084}
1085
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001086void grpc_server_destroy(grpc_server *server) {
Craig Tilleraec96aa2015-04-07 14:32:15 -07001087 listener *l;
Craig Tillerdfff1b82015-09-21 14:39:57 -07001088 grpc_call_list call_list = GRPC_CALL_LIST_INIT;
Craig Tiller872af022015-04-24 15:57:52 -07001089
Vijay Pai8931cdd2015-06-17 12:42:17 -07001090 gpr_mu_lock(&server->mu_global);
Craig Tiller6a006ce2015-07-13 16:25:40 -07001091 GPR_ASSERT(gpr_atm_acq_load(&server->shutdown_flag) || !server->listeners);
Craig Tilleree945e82015-05-26 16:15:34 -07001092 GPR_ASSERT(server->listeners_destroyed == num_listeners(server));
Craig Tilleraec96aa2015-04-07 14:32:15 -07001093
1094 while (server->listeners) {
1095 l = server->listeners;
1096 server->listeners = l->next;
1097 gpr_free(l);
1098 }
1099
Vijay Pai8931cdd2015-06-17 12:42:17 -07001100 gpr_mu_unlock(&server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001101
Craig Tillerdfff1b82015-09-21 14:39:57 -07001102 server_unref(server, &call_list);
1103 grpc_call_list_run(&call_list);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001104}
1105
Craig Tillerdfff1b82015-09-21 14:39:57 -07001106void grpc_server_add_listener(
1107 grpc_server *server, void *arg,
1108 void (*start)(grpc_server *server, void *arg, grpc_pollset **pollsets,
1109 size_t pollset_count, grpc_call_list *call_list),
1110 void (*destroy)(grpc_server *server, void *arg, grpc_closure *on_done,
1111 grpc_call_list *call_list),
1112 grpc_call_list *call_list) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001113 listener *l = gpr_malloc(sizeof(listener));
1114 l->arg = arg;
1115 l->start = start;
1116 l->destroy = destroy;
1117 l->next = server->listeners;
1118 server->listeners = l;
1119}
1120
Craig Tiller9f28ac22015-01-27 17:01:29 -08001121static grpc_call_error queue_call_request(grpc_server *server,
Craig Tillerdfff1b82015-09-21 14:39:57 -07001122 requested_call *rc,
1123 grpc_call_list *call_list) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001124 call_data *calld = NULL;
Craig Tiller729b35a2015-07-13 12:36:47 -07001125 request_matcher *request_matcher = NULL;
Craig Tiller6a006ce2015-07-13 16:25:40 -07001126 int request_id;
1127 if (gpr_atm_acq_load(&server->shutdown_flag)) {
Craig Tillerdfff1b82015-09-21 14:39:57 -07001128 fail_call(server, rc, call_list);
Craig Tiller6a006ce2015-07-13 16:25:40 -07001129 return GRPC_CALL_OK;
1130 }
1131 request_id = gpr_stack_lockfree_pop(server->request_freelist);
1132 if (request_id == -1) {
1133 /* out of request ids: just fail this one */
Craig Tillerdfff1b82015-09-21 14:39:57 -07001134 fail_call(server, rc, call_list);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001135 return GRPC_CALL_OK;
1136 }
Craig Tiller04cc8be2015-02-10 16:11:22 -08001137 switch (rc->type) {
Craig Tiller04cc8be2015-02-10 16:11:22 -08001138 case BATCH_CALL:
Craig Tiller729b35a2015-07-13 12:36:47 -07001139 request_matcher = &server->unregistered_request_matcher;
Craig Tiller04cc8be2015-02-10 16:11:22 -08001140 break;
1141 case REGISTERED_CALL:
Craig Tiller729b35a2015-07-13 12:36:47 -07001142 request_matcher = &rc->data.registered.registered_method->request_matcher;
Craig Tiller04cc8be2015-02-10 16:11:22 -08001143 break;
1144 }
Craig Tiller6a006ce2015-07-13 16:25:40 -07001145 server->requested_calls[request_id] = *rc;
1146 gpr_free(rc);
1147 if (gpr_stack_lockfree_push(request_matcher->requests, request_id)) {
1148 /* this was the first queued request: we need to lock and start
1149 matching calls */
1150 gpr_mu_lock(&server->mu_call);
1151 while ((calld = request_matcher->pending_head) != NULL) {
1152 request_id = gpr_stack_lockfree_pop(request_matcher->requests);
1153 if (request_id == -1) break;
1154 request_matcher->pending_head = calld->pending_next;
1155 gpr_mu_unlock(&server->mu_call);
1156 gpr_mu_lock(&calld->mu_state);
1157 if (calld->state == ZOMBIED) {
1158 gpr_mu_unlock(&calld->mu_state);
Craig Tiller33825112015-09-18 07:44:19 -07001159 grpc_closure_init(
Craig Tiller6a006ce2015-07-13 16:25:40 -07001160 &calld->kill_zombie_closure, kill_zombie,
1161 grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
Craig Tillerdfff1b82015-09-21 14:39:57 -07001162 grpc_call_list_add(call_list, &calld->kill_zombie_closure, 1);
Craig Tiller6a006ce2015-07-13 16:25:40 -07001163 } else {
1164 GPR_ASSERT(calld->state == PENDING);
1165 calld->state = ACTIVATED;
1166 gpr_mu_unlock(&calld->mu_state);
Craig Tillerdfff1b82015-09-21 14:39:57 -07001167 begin_call(server, calld, &server->requested_calls[request_id],
1168 call_list);
Craig Tiller6a006ce2015-07-13 16:25:40 -07001169 }
1170 gpr_mu_lock(&server->mu_call);
Craig Tiller729b35a2015-07-13 12:36:47 -07001171 }
Craig Tiller76d2c3b2015-07-07 11:46:01 -07001172 gpr_mu_unlock(&server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001173 }
Craig Tiller6a006ce2015-07-13 16:25:40 -07001174 return GRPC_CALL_OK;
Craig Tillercce17ac2015-01-20 09:29:28 -08001175}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001176
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001177grpc_call_error grpc_server_request_call(
1178 grpc_server *server, grpc_call **call, grpc_call_details *details,
1179 grpc_metadata_array *initial_metadata,
1180 grpc_completion_queue *cq_bound_to_call,
1181 grpc_completion_queue *cq_for_notification, void *tag) {
Craig Tillerdfff1b82015-09-21 14:39:57 -07001182 grpc_call_error error;
1183 grpc_call_list call_list = GRPC_CALL_LIST_INIT;
Craig Tiller97fc6a32015-07-08 15:31:35 -07001184 requested_call *rc = gpr_malloc(sizeof(*rc));
murgatroid99ad7c20c2015-05-22 14:42:29 -07001185 GRPC_SERVER_LOG_REQUEST_CALL(GPR_INFO, server, call, details,
1186 initial_metadata, cq_bound_to_call,
1187 cq_for_notification, tag);
Craig Tillerb56975c2015-06-15 10:11:16 -07001188 if (!grpc_cq_is_server_cq(cq_for_notification)) {
Craig Tiller97fc6a32015-07-08 15:31:35 -07001189 gpr_free(rc);
Craig Tillerdfff1b82015-09-21 14:39:57 -07001190 error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
1191 goto done;
Craig Tillerb56975c2015-06-15 10:11:16 -07001192 }
Craig Tiller97fc6a32015-07-08 15:31:35 -07001193 grpc_cq_begin_op(cq_for_notification);
Craig Tiller9928d392015-08-18 09:40:24 -07001194 details->reserved = NULL;
Craig Tiller97fc6a32015-07-08 15:31:35 -07001195 rc->type = BATCH_CALL;
Craig Tiller6a006ce2015-07-13 16:25:40 -07001196 rc->server = server;
Craig Tiller97fc6a32015-07-08 15:31:35 -07001197 rc->tag = tag;
1198 rc->cq_bound_to_call = cq_bound_to_call;
1199 rc->cq_for_notification = cq_for_notification;
1200 rc->call = call;
1201 rc->data.batch.details = details;
1202 rc->data.batch.initial_metadata = initial_metadata;
Craig Tillerdfff1b82015-09-21 14:39:57 -07001203 error = queue_call_request(server, rc, &call_list);
1204done:
1205 grpc_call_list_run(&call_list);
1206 return error;
Craig Tiller24be0f72015-02-10 14:04:22 -08001207}
1208
1209grpc_call_error grpc_server_request_registered_call(
Craig Tillerec3257c2015-02-12 15:59:43 -08001210 grpc_server *server, void *rm, grpc_call **call, gpr_timespec *deadline,
1211 grpc_metadata_array *initial_metadata, grpc_byte_buffer **optional_payload,
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001212 grpc_completion_queue *cq_bound_to_call,
1213 grpc_completion_queue *cq_for_notification, void *tag) {
Craig Tillerdfff1b82015-09-21 14:39:57 -07001214 grpc_call_error error;
1215 grpc_call_list call_list = GRPC_CALL_LIST_INIT;
Craig Tiller97fc6a32015-07-08 15:31:35 -07001216 requested_call *rc = gpr_malloc(sizeof(*rc));
Craig Tiller20bc56d2015-02-12 09:02:56 -08001217 registered_method *registered_method = rm;
Craig Tillerb56975c2015-06-15 10:11:16 -07001218 if (!grpc_cq_is_server_cq(cq_for_notification)) {
Craig Tiller97fc6a32015-07-08 15:31:35 -07001219 gpr_free(rc);
Craig Tillerdfff1b82015-09-21 14:39:57 -07001220 error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
1221 goto done;
Craig Tillerb56975c2015-06-15 10:11:16 -07001222 }
Craig Tiller97fc6a32015-07-08 15:31:35 -07001223 grpc_cq_begin_op(cq_for_notification);
1224 rc->type = REGISTERED_CALL;
Craig Tiller6a006ce2015-07-13 16:25:40 -07001225 rc->server = server;
Craig Tiller97fc6a32015-07-08 15:31:35 -07001226 rc->tag = tag;
1227 rc->cq_bound_to_call = cq_bound_to_call;
1228 rc->cq_for_notification = cq_for_notification;
1229 rc->call = call;
1230 rc->data.registered.registered_method = registered_method;
1231 rc->data.registered.deadline = deadline;
1232 rc->data.registered.initial_metadata = initial_metadata;
1233 rc->data.registered.optional_payload = optional_payload;
Craig Tillerdfff1b82015-09-21 14:39:57 -07001234 error = queue_call_request(server, rc, &call_list);
1235done:
1236 grpc_call_list_run(&call_list);
1237 return error;
Craig Tiller24be0f72015-02-10 14:04:22 -08001238}
1239
Craig Tillerdfff1b82015-09-21 14:39:57 -07001240static void publish_registered_or_batch(grpc_call *call, int success, void *tag,
1241 grpc_call_list *call_list);
1242static void publish_was_not_set(grpc_call *call, int success, void *tag,
1243 grpc_call_list *call_list) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001244 abort();
1245}
Craig Tiller24be0f72015-02-10 14:04:22 -08001246
Craig Tiller166e2502015-02-03 20:14:41 -08001247static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
1248 gpr_slice slice = value->slice;
1249 size_t len = GPR_SLICE_LENGTH(slice);
1250
1251 if (len + 1 > *capacity) {
1252 *capacity = GPR_MAX(len + 1, *capacity * 2);
1253 *dest = gpr_realloc(*dest, *capacity);
1254 }
1255 memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
1256}
1257
Craig Tiller24be0f72015-02-10 14:04:22 -08001258static void begin_call(grpc_server *server, call_data *calld,
Craig Tillerdfff1b82015-09-21 14:39:57 -07001259 requested_call *rc, grpc_call_list *call_list) {
Yang Gaoeb8e7cd2015-02-11 11:43:40 -08001260 grpc_ioreq_completion_func publish = publish_was_not_set;
Craig Tiller24be0f72015-02-10 14:04:22 -08001261 grpc_ioreq req[2];
1262 grpc_ioreq *r = req;
1263
1264 /* called once initial metadata has been read by the call, but BEFORE
1265 the ioreq to fetch it out of the call has been executed.
1266 This means metadata related fields can be relied on in calld, but to
1267 fill in the metadata array passed by the client, we need to perform
1268 an ioreq op, that should complete immediately. */
1269
Craig Tillerdfff1b82015-09-21 14:39:57 -07001270 grpc_call_set_completion_queue(calld->call, rc->cq_bound_to_call, call_list);
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001271 *rc->call = calld->call;
1272 calld->cq_new = rc->cq_for_notification;
Craig Tiller24be0f72015-02-10 14:04:22 -08001273 switch (rc->type) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001274 case BATCH_CALL:
Craig Tiller04c5d4b2015-06-26 17:21:41 -07001275 GPR_ASSERT(calld->host != NULL);
1276 GPR_ASSERT(calld->path != NULL);
Craig Tiller24be0f72015-02-10 14:04:22 -08001277 cpstr(&rc->data.batch.details->host,
1278 &rc->data.batch.details->host_capacity, calld->host);
1279 cpstr(&rc->data.batch.details->method,
1280 &rc->data.batch.details->method_capacity, calld->path);
Masood Malekghassemibf177c82015-04-27 12:14:38 -07001281 rc->data.batch.details->deadline = calld->deadline;
Craig Tiller24be0f72015-02-10 14:04:22 -08001282 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1283 r->data.recv_metadata = rc->data.batch.initial_metadata;
David Garcia Quintasb8f54502015-06-15 16:19:10 -07001284 r->flags = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001285 r++;
1286 publish = publish_registered_or_batch;
1287 break;
1288 case REGISTERED_CALL:
1289 *rc->data.registered.deadline = calld->deadline;
Craig Tiller24be0f72015-02-10 14:04:22 -08001290 r->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1291 r->data.recv_metadata = rc->data.registered.initial_metadata;
David Garcia Quintasb8f54502015-06-15 16:19:10 -07001292 r->flags = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001293 r++;
1294 if (rc->data.registered.optional_payload) {
1295 r->op = GRPC_IOREQ_RECV_MESSAGE;
1296 r->data.recv_message = rc->data.registered.optional_payload;
David Garcia Quintasb8f54502015-06-15 16:19:10 -07001297 r->flags = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001298 r++;
1299 }
1300 publish = publish_registered_or_batch;
1301 break;
1302 }
1303
Craig Tiller4df412b2015-04-28 07:57:54 -07001304 GRPC_CALL_INTERNAL_REF(calld->call, "server");
Craig Tiller32ca48c2015-09-10 11:47:15 -07001305 grpc_call_start_ioreq_and_call_back(calld->call, req, (size_t)(r - req),
Craig Tillerdfff1b82015-09-21 14:39:57 -07001306 publish, rc, call_list);
Craig Tiller97fc6a32015-07-08 15:31:35 -07001307}
1308
Craig Tillerdfff1b82015-09-21 14:39:57 -07001309static void done_request_event(void *req, grpc_cq_completion *c,
1310 grpc_call_list *call_list) {
Craig Tiller6a006ce2015-07-13 16:25:40 -07001311 requested_call *rc = req;
1312 grpc_server *server = rc->server;
1313
1314 if (rc >= server->requested_calls &&
1315 rc < server->requested_calls + server->max_requested_calls) {
Craig Tillerf96dfc32015-09-10 14:43:18 -07001316 GPR_ASSERT(rc - server->requested_calls <= INT_MAX);
Craig Tiller6a006ce2015-07-13 16:25:40 -07001317 gpr_stack_lockfree_push(server->request_freelist,
Craig Tillerf96dfc32015-09-10 14:43:18 -07001318 (int)(rc - server->requested_calls));
Craig Tiller6a006ce2015-07-13 16:25:40 -07001319 } else {
1320 gpr_free(req);
1321 }
Craig Tillere2b3bfa2015-07-30 10:40:22 -07001322
Craig Tillerdfff1b82015-09-21 14:39:57 -07001323 server_unref(server, call_list);
Craig Tiller24be0f72015-02-10 14:04:22 -08001324}
1325
Craig Tillerdfff1b82015-09-21 14:39:57 -07001326static void fail_call(grpc_server *server, requested_call *rc,
1327 grpc_call_list *call_list) {
Craig Tillerf9e6adf2015-05-06 11:45:59 -07001328 *rc->call = NULL;
Craig Tiller24be0f72015-02-10 14:04:22 -08001329 switch (rc->type) {
Craig Tiller24be0f72015-02-10 14:04:22 -08001330 case BATCH_CALL:
Craig Tiller24be0f72015-02-10 14:04:22 -08001331 rc->data.batch.initial_metadata->count = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001332 break;
1333 case REGISTERED_CALL:
Craig Tiller24be0f72015-02-10 14:04:22 -08001334 rc->data.registered.initial_metadata->count = 0;
Craig Tiller24be0f72015-02-10 14:04:22 -08001335 break;
1336 }
Craig Tillere2b3bfa2015-07-30 10:40:22 -07001337 server_ref(server);
Craig Tiller12cf5372015-07-09 13:48:11 -07001338 grpc_cq_end_op(rc->cq_for_notification, rc->tag, 0, done_request_event, rc,
Craig Tillerdfff1b82015-09-21 14:39:57 -07001339 &rc->completion, call_list);
Craig Tiller24be0f72015-02-10 14:04:22 -08001340}
1341
Craig Tillerdfff1b82015-09-21 14:39:57 -07001342static void publish_registered_or_batch(grpc_call *call, int success, void *prc,
1343 grpc_call_list *call_list) {
Craig Tiller8e8fd892015-02-10 17:02:08 -08001344 grpc_call_element *elem =
1345 grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
Craig Tiller97fc6a32015-07-08 15:31:35 -07001346 requested_call *rc = prc;
Craig Tiller20bc56d2015-02-12 09:02:56 -08001347 call_data *calld = elem->call_data;
Craig Tillere2b3bfa2015-07-30 10:40:22 -07001348 channel_data *chand = elem->channel_data;
1349 server_ref(chand->server);
Craig Tiller12cf5372015-07-09 13:48:11 -07001350 grpc_cq_end_op(calld->cq_new, rc->tag, success, done_request_event, rc,
Craig Tillerdfff1b82015-09-21 14:39:57 -07001351 &rc->completion, call_list);
Craig Tiller3ffd8222015-09-21 08:21:57 -07001352 GRPC_CALL_INTERNAL_UNREF(call, "server", call_list);
Craig Tiller24be0f72015-02-10 14:04:22 -08001353}
1354
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001355const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) {
1356 return server->channel_args;
Craig Tiller190d3602015-02-18 09:23:38 -08001357}
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001358
1359int grpc_server_has_open_connections(grpc_server *server) {
1360 int r;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001361 gpr_mu_lock(&server->mu_global);
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001362 r = server->root_channel_data.next != &server->root_channel_data;
Vijay Pai8931cdd2015-06-17 12:42:17 -07001363 gpr_mu_unlock(&server->mu_global);
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001364 return r;
1365}