blob: 2e8609ee9e6d3c38d2c5049bf6ef66f67f18e8dd [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2015-2016 gRPC authors.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080016 *
17 */
18
Craig Tiller9533d042016-03-25 17:11:06 -070019#include "src/core/lib/surface/server.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080020
Craig Tillerf96dfc32015-09-10 14:43:18 -070021#include <limits.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080022#include <stdlib.h>
23#include <string.h>
24
Craig Tiller6a006ce2015-07-13 16:25:40 -070025#include <grpc/support/alloc.h>
26#include <grpc/support/log.h>
27#include <grpc/support/string_util.h>
28#include <grpc/support/useful.h>
29
Craig Tiller9533d042016-03-25 17:11:06 -070030#include "src/core/lib/channel/channel_args.h"
31#include "src/core/lib/channel/connected_channel.h"
Craig Tiller561dc322017-09-05 13:00:46 -070032#include "src/core/lib/debug/stats.h"
Craig Tiller9d9313c2017-04-11 15:05:46 -070033#include "src/core/lib/iomgr/executor.h"
Craig Tiller9533d042016-03-25 17:11:06 -070034#include "src/core/lib/iomgr/iomgr.h"
Craig Tillera59c16c2016-10-31 07:25:01 -070035#include "src/core/lib/slice/slice_internal.h"
Ken Paysone1533572017-11-07 11:27:02 -080036#include "src/core/lib/support/mpscq.h"
37#include "src/core/lib/support/spinlock.h"
Craig Tiller9533d042016-03-25 17:11:06 -070038#include "src/core/lib/support/string.h"
39#include "src/core/lib/surface/api_trace.h"
40#include "src/core/lib/surface/call.h"
41#include "src/core/lib/surface/channel.h"
42#include "src/core/lib/surface/completion_queue.h"
43#include "src/core/lib/surface/init.h"
44#include "src/core/lib/transport/metadata.h"
45#include "src/core/lib/transport/static_metadata.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080046
Craig Tillera82950e2015-09-22 12:33:20 -070047typedef struct listener {
Craig Tillerbaa14a92017-11-03 09:09:36 -070048 void* arg;
49 void (*start)(grpc_exec_ctx* exec_ctx, grpc_server* server, void* arg,
50 grpc_pollset** pollsets, size_t pollset_count);
51 void (*destroy)(grpc_exec_ctx* exec_ctx, grpc_server* server, void* arg,
52 grpc_closure* closure);
53 struct listener* next;
Craig Tillerdfff1b82015-09-21 14:39:57 -070054 grpc_closure destroy_done;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080055} listener;
56
57typedef struct call_data call_data;
58typedef struct channel_data channel_data;
Craig Tiller24be0f72015-02-10 14:04:22 -080059typedef struct registered_method registered_method;
60
Craig Tillera82950e2015-09-22 12:33:20 -070061typedef enum { BATCH_CALL, REGISTERED_CALL } requested_call_type;
Craig Tiller24be0f72015-02-10 14:04:22 -080062
ncteisen7712c7c2017-07-12 23:11:27 -070063grpc_tracer_flag grpc_server_channel_trace =
64 GRPC_TRACER_INITIALIZER(false, "server_channel");
Craig Tiller687a0e62016-09-21 10:48:59 -070065
Craig Tillera82950e2015-09-22 12:33:20 -070066typedef struct requested_call {
Ken Paysone1533572017-11-07 11:27:02 -080067 gpr_mpscq_node request_link; /* must be first */
Craig Tiller24be0f72015-02-10 14:04:22 -080068 requested_call_type type;
Craig Tillerb19dbea2016-07-12 15:33:11 -070069 size_t cq_idx;
Craig Tillerbaa14a92017-11-03 09:09:36 -070070 void* tag;
71 grpc_server* server;
72 grpc_completion_queue* cq_bound_to_call;
73 grpc_call** call;
Craig Tiller97fc6a32015-07-08 15:31:35 -070074 grpc_cq_completion completion;
Craig Tillerbaa14a92017-11-03 09:09:36 -070075 grpc_metadata_array* initial_metadata;
Craig Tillera82950e2015-09-22 12:33:20 -070076 union {
77 struct {
Craig Tillerbaa14a92017-11-03 09:09:36 -070078 grpc_call_details* details;
Craig Tiller24be0f72015-02-10 14:04:22 -080079 } batch;
Craig Tillera82950e2015-09-22 12:33:20 -070080 struct {
Craig Tillerbaa14a92017-11-03 09:09:36 -070081 registered_method* method;
82 gpr_timespec* deadline;
83 grpc_byte_buffer** optional_payload;
Craig Tiller24be0f72015-02-10 14:04:22 -080084 } registered;
85 } data;
86} requested_call;
87
Craig Tillera82950e2015-09-22 12:33:20 -070088typedef struct channel_registered_method {
Craig Tillerbaa14a92017-11-03 09:09:36 -070089 registered_method* server_registered_method;
Craig Tillerb2906862016-03-10 06:50:07 -080090 uint32_t flags;
Craig Tiller7c70b6c2017-01-23 07:48:42 -080091 bool has_host;
92 grpc_slice method;
93 grpc_slice host;
Craig Tiller24be0f72015-02-10 14:04:22 -080094} channel_registered_method;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080095
Craig Tillera82950e2015-09-22 12:33:20 -070096struct channel_data {
Craig Tillerbaa14a92017-11-03 09:09:36 -070097 grpc_server* server;
Craig Tillere039f032015-06-25 12:54:23 -070098 grpc_connectivity_state connectivity_state;
Craig Tillerbaa14a92017-11-03 09:09:36 -070099 grpc_channel* channel;
Craig Tiller418a8212016-05-16 16:27:51 -0700100 size_t cq_idx;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800101 /* linked list of all channels on a server */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700102 channel_data* next;
103 channel_data* prev;
104 channel_registered_method* registered_methods;
Craig Tiller7536af02015-12-22 13:49:30 -0800105 uint32_t registered_method_slots;
106 uint32_t registered_method_max_probes;
Craig Tiller33825112015-09-18 07:44:19 -0700107 grpc_closure finish_destroy_channel_closure;
108 grpc_closure channel_connectivity_changed;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800109};
110
Craig Tillera82950e2015-09-22 12:33:20 -0700111typedef struct shutdown_tag {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700112 void* tag;
113 grpc_completion_queue* cq;
Craig Tiller97fc6a32015-07-08 15:31:35 -0700114 grpc_cq_completion completion;
Craig Tillerbce999f2015-05-27 09:55:51 -0700115} shutdown_tag;
116
Craig Tillera82950e2015-09-22 12:33:20 -0700117typedef enum {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800118 /* waiting for metadata */
119 NOT_STARTED,
120 /* inital metadata read, not flow controlled in yet */
121 PENDING,
122 /* flow controlled in, on completion queue */
123 ACTIVATED,
124 /* cancelled before being queued */
125 ZOMBIED
126} call_state;
127
Craig Tiller729b35a2015-07-13 12:36:47 -0700128typedef struct request_matcher request_matcher;
129
Craig Tillera82950e2015-09-22 12:33:20 -0700130struct call_data {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700131 grpc_call* call;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800132
Ken Paysone1533572017-11-07 11:27:02 -0800133 gpr_atm state;
Craig Tiller76d2c3b2015-07-07 11:46:01 -0700134
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800135 bool path_set;
136 bool host_set;
137 grpc_slice path;
138 grpc_slice host;
Craig Tiller89c14282017-07-19 15:32:27 -0700139 grpc_millis deadline;
Craig Tillercce17ac2015-01-20 09:29:28 -0800140
Craig Tillerbaa14a92017-11-03 09:09:36 -0700141 grpc_completion_queue* cq_new;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800142
Craig Tillerbaa14a92017-11-03 09:09:36 -0700143 grpc_metadata_batch* recv_initial_metadata;
Craig Tiller72920cc2017-03-10 10:20:17 -0800144 uint32_t recv_initial_metadata_flags;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800145 grpc_metadata_array initial_metadata;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700146
Craig Tillerbaa14a92017-11-03 09:09:36 -0700147 request_matcher* matcher;
148 grpc_byte_buffer* payload;
Craig Tiller88512692016-04-04 09:32:52 -0700149
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800150 grpc_closure got_initial_metadata;
151 grpc_closure server_on_recv_initial_metadata;
Craig Tiller33825112015-09-18 07:44:19 -0700152 grpc_closure kill_zombie_closure;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700153 grpc_closure* on_done_recv_initial_metadata;
David Garcia Quintas284488b2015-05-28 16:27:39 -0700154
Craig Tiller88512692016-04-04 09:32:52 -0700155 grpc_closure publish;
156
Craig Tillerbaa14a92017-11-03 09:09:36 -0700157 call_data* pending_next;
Craig Tiller729b35a2015-07-13 12:36:47 -0700158};
159
Craig Tillera82950e2015-09-22 12:33:20 -0700160struct request_matcher {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700161 grpc_server* server;
162 call_data* pending_head;
163 call_data* pending_tail;
Ken Paysone1533572017-11-07 11:27:02 -0800164 gpr_locked_mpscq* requests_per_cq;
Craig Tiller729b35a2015-07-13 12:36:47 -0700165};
166
Craig Tillera82950e2015-09-22 12:33:20 -0700167struct registered_method {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700168 char* method;
169 char* host;
Craig Tiller06cb1a92016-04-04 08:10:47 -0700170 grpc_server_register_method_payload_handling payload_handling;
Craig Tillerb2906862016-03-10 06:50:07 -0800171 uint32_t flags;
Craig Tillerfa96d862016-05-21 12:39:56 -0700172 /* one request matcher per method */
Yash Tibrewala4952202017-09-13 10:53:28 -0700173 request_matcher matcher;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700174 registered_method* next;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800175};
176
Craig Tillera82950e2015-09-22 12:33:20 -0700177typedef struct {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700178 grpc_channel** channels;
Craig Tillerff3ae682015-06-29 17:44:04 -0700179 size_t num_channels;
180} channel_broadcaster;
181
Craig Tillera82950e2015-09-22 12:33:20 -0700182struct grpc_server {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700183 grpc_channel_args* channel_args;
Craig Tiller729b35a2015-07-13 12:36:47 -0700184
Craig Tillerbaa14a92017-11-03 09:09:36 -0700185 grpc_completion_queue** cqs;
186 grpc_pollset** pollsets;
Craig Tiller729b35a2015-07-13 12:36:47 -0700187 size_t cq_count;
Craig Tiller1d0fce92016-10-26 08:26:22 -0700188 size_t pollset_count;
Craig Tiller88ef00e2016-05-17 09:31:49 -0700189 bool started;
Craig Tiller729b35a2015-07-13 12:36:47 -0700190
191 /* The two following mutexes control access to server-state
192 mu_global controls access to non-call-related state (e.g., channel state)
193 mu_call controls access to call-related state (e.g., the call lists)
194
195 If they are ever required to be nested, you must lock mu_global
196 before mu_call. This is currently used in shutdown processing
197 (grpc_server_shutdown_and_notify and maybe_finish_shutdown) */
Craig Tillera82950e2015-09-22 12:33:20 -0700198 gpr_mu mu_global; /* mutex for server and channel state */
199 gpr_mu mu_call; /* mutex for call-specific state */
Craig Tiller729b35a2015-07-13 12:36:47 -0700200
Craig Tillerbd3cc402017-04-12 08:06:44 -0700201 /* startup synchronization: flag is protected by mu_global, signals whether
202 we are doing the listener start routine or not */
203 bool starting;
204 gpr_cv starting_cv;
205
Craig Tillerbaa14a92017-11-03 09:09:36 -0700206 registered_method* registered_methods;
Craig Tillerfa96d862016-05-21 12:39:56 -0700207 /** one request matcher for unregistered methods */
Craig Tiller729b35a2015-07-13 12:36:47 -0700208 request_matcher unregistered_request_matcher;
209
Craig Tiller6a006ce2015-07-13 16:25:40 -0700210 gpr_atm shutdown_flag;
Craig Tiller7536af02015-12-22 13:49:30 -0800211 uint8_t shutdown_published;
Craig Tiller729b35a2015-07-13 12:36:47 -0700212 size_t num_shutdown_tags;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700213 shutdown_tag* shutdown_tags;
Craig Tiller729b35a2015-07-13 12:36:47 -0700214
215 channel_data root_channel_data;
216
Craig Tillerbaa14a92017-11-03 09:09:36 -0700217 listener* listeners;
Craig Tiller729b35a2015-07-13 12:36:47 -0700218 int listeners_destroyed;
219 gpr_refcount internal_refcount;
220
221 /** when did we print the last shutdown progress message */
222 gpr_timespec last_shutdown_message_time;
223};
224
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800225#define SERVER_FROM_CALL_ELEM(elem) \
Craig Tillerbaa14a92017-11-03 09:09:36 -0700226 (((channel_data*)(elem)->channel_data)->server)
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800227
Craig Tillerbaa14a92017-11-03 09:09:36 -0700228static void publish_new_rpc(grpc_exec_ctx* exec_ctx, void* calld,
229 grpc_error* error);
230static void fail_call(grpc_exec_ctx* exec_ctx, grpc_server* server,
231 size_t cq_idx, requested_call* rc, grpc_error* error);
Vijay Pai8931cdd2015-06-17 12:42:17 -0700232/* Before calling maybe_finish_shutdown, we must hold mu_global and not
233 hold mu_call */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700234static void maybe_finish_shutdown(grpc_exec_ctx* exec_ctx, grpc_server* server);
Craig Tiller24be0f72015-02-10 14:04:22 -0800235
Craig Tiller729b35a2015-07-13 12:36:47 -0700236/*
237 * channel broadcaster
238 */
Craig Tillerff3ae682015-06-29 17:44:04 -0700239
240/* assumes server locked */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700241static void channel_broadcaster_init(grpc_server* s, channel_broadcaster* cb) {
242 channel_data* c;
Craig Tillerff3ae682015-06-29 17:44:04 -0700243 size_t count = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700244 for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) {
245 count++;
246 }
Craig Tillerff3ae682015-06-29 17:44:04 -0700247 cb->num_channels = count;
Yash Tibrewalca3c1c02017-09-07 22:47:16 -0700248 cb->channels =
Craig Tillerbaa14a92017-11-03 09:09:36 -0700249 (grpc_channel**)gpr_malloc(sizeof(*cb->channels) * cb->num_channels);
Craig Tillerff3ae682015-06-29 17:44:04 -0700250 count = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700251 for (c = s->root_channel_data.next; c != &s->root_channel_data; c = c->next) {
252 cb->channels[count++] = c->channel;
253 GRPC_CHANNEL_INTERNAL_REF(c->channel, "broadcast");
254 }
Craig Tillerff3ae682015-06-29 17:44:04 -0700255}
256
Craig Tillera82950e2015-09-22 12:33:20 -0700257struct shutdown_cleanup_args {
Craig Tiller33825112015-09-18 07:44:19 -0700258 grpc_closure closure;
Craig Tillerd41a4a72016-10-26 16:16:06 -0700259 grpc_slice slice;
Craig Tillerff3ae682015-06-29 17:44:04 -0700260};
261
Craig Tillerbaa14a92017-11-03 09:09:36 -0700262static void shutdown_cleanup(grpc_exec_ctx* exec_ctx, void* arg,
263 grpc_error* error) {
264 struct shutdown_cleanup_args* a = (struct shutdown_cleanup_args*)arg;
Craig Tillera59c16c2016-10-31 07:25:01 -0700265 grpc_slice_unref_internal(exec_ctx, a->slice);
Craig Tillera82950e2015-09-22 12:33:20 -0700266 gpr_free(a);
Craig Tillerff3ae682015-06-29 17:44:04 -0700267}
268
Craig Tillerbaa14a92017-11-03 09:09:36 -0700269static void send_shutdown(grpc_exec_ctx* exec_ctx, grpc_channel* channel,
270 bool send_goaway, grpc_error* send_disconnect) {
271 struct shutdown_cleanup_args* sc =
272 (struct shutdown_cleanup_args*)gpr_malloc(sizeof(*sc));
ncteisen274bbbe2017-06-08 14:57:11 -0700273 GRPC_CLOSURE_INIT(&sc->closure, shutdown_cleanup, sc,
Craig Tiller91031da2016-12-28 15:44:25 -0800274 grpc_schedule_on_exec_ctx);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700275 grpc_transport_op* op = grpc_make_transport_op(&sc->closure);
276 grpc_channel_element* elem;
Craig Tillerff3ae682015-06-29 17:44:04 -0700277
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800278 op->goaway_error =
ncteisen4b36a3d2017-03-13 19:08:06 -0700279 send_goaway ? grpc_error_set_int(
280 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Server shutdown"),
281 GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_OK)
282 : GRPC_ERROR_NONE;
Craig Tillere194ff02016-08-29 15:48:41 -0700283 op->set_accept_stream = true;
Craig Tillerd41a4a72016-10-26 16:16:06 -0700284 sc->slice = grpc_slice_from_copied_string("Server shutdown");
Craig Tillere0221ff2016-07-11 15:56:08 -0700285 op->disconnect_with_error = send_disconnect;
Craig Tillerff3ae682015-06-29 17:44:04 -0700286
Craig Tillera82950e2015-09-22 12:33:20 -0700287 elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
Craig Tillere0221ff2016-07-11 15:56:08 -0700288 elem->filter->start_transport_op(exec_ctx, elem, op);
Craig Tillerff3ae682015-06-29 17:44:04 -0700289}
290
Craig Tillerbaa14a92017-11-03 09:09:36 -0700291static void channel_broadcaster_shutdown(grpc_exec_ctx* exec_ctx,
292 channel_broadcaster* cb,
Mark D. Roth7f8db252016-06-24 08:24:15 -0700293 bool send_goaway,
Craig Tillerbaa14a92017-11-03 09:09:36 -0700294 grpc_error* force_disconnect) {
Craig Tillerff3ae682015-06-29 17:44:04 -0700295 size_t i;
296
Craig Tillera82950e2015-09-22 12:33:20 -0700297 for (i = 0; i < cb->num_channels; i++) {
Craig Tiller71f96652016-05-11 23:17:45 -0700298 send_shutdown(exec_ctx, cb->channels[i], send_goaway,
299 GRPC_ERROR_REF(force_disconnect));
Craig Tillera82950e2015-09-22 12:33:20 -0700300 GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, cb->channels[i], "broadcast");
301 }
302 gpr_free(cb->channels);
Craig Tiller71f96652016-05-11 23:17:45 -0700303 GRPC_ERROR_UNREF(force_disconnect);
Craig Tillerff3ae682015-06-29 17:44:04 -0700304}
305
Craig Tiller729b35a2015-07-13 12:36:47 -0700306/*
307 * request_matcher
308 */
Craig Tillerff3ae682015-06-29 17:44:04 -0700309
Ken Paysone1533572017-11-07 11:27:02 -0800310static void request_matcher_init(request_matcher* rm, grpc_server* server) {
Craig Tillerb9d35962015-09-11 13:31:16 -0700311 memset(rm, 0, sizeof(*rm));
Craig Tiller88512692016-04-04 09:32:52 -0700312 rm->server = server;
Ken Paysone1533572017-11-07 11:27:02 -0800313 rm->requests_per_cq = (gpr_locked_mpscq*)gpr_malloc(
Yash Tibrewalca3c1c02017-09-07 22:47:16 -0700314 sizeof(*rm->requests_per_cq) * server->cq_count);
Craig Tillerdb7c3562016-05-19 11:02:52 -0700315 for (size_t i = 0; i < server->cq_count; i++) {
Ken Paysone1533572017-11-07 11:27:02 -0800316 gpr_locked_mpscq_init(&rm->requests_per_cq[i]);
Craig Tillerdb7c3562016-05-19 11:02:52 -0700317 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800318}
319
Craig Tillerbaa14a92017-11-03 09:09:36 -0700320static void request_matcher_destroy(request_matcher* rm) {
Craig Tillerdb7c3562016-05-19 11:02:52 -0700321 for (size_t i = 0; i < rm->server->cq_count; i++) {
Craig Tiller4782d922017-11-10 09:53:21 -0800322 GPR_ASSERT(gpr_locked_mpscq_pop(&rm->requests_per_cq[i]) == nullptr);
Ken Paysone1533572017-11-07 11:27:02 -0800323 gpr_locked_mpscq_destroy(&rm->requests_per_cq[i]);
Craig Tillerdb7c3562016-05-19 11:02:52 -0700324 }
325 gpr_free(rm->requests_per_cq);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800326}
327
Craig Tillerbaa14a92017-11-03 09:09:36 -0700328static void kill_zombie(grpc_exec_ctx* exec_ctx, void* elem,
329 grpc_error* error) {
330 grpc_call_unref(grpc_call_from_top_element((grpc_call_element*)elem));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800331}
332
Craig Tillerbaa14a92017-11-03 09:09:36 -0700333static void request_matcher_zombify_all_pending_calls(grpc_exec_ctx* exec_ctx,
334 request_matcher* rm) {
Craig Tillerb9d35962015-09-11 13:31:16 -0700335 while (rm->pending_head) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700336 call_data* calld = rm->pending_head;
Craig Tillerb9d35962015-09-11 13:31:16 -0700337 rm->pending_head = calld->pending_next;
Ken Paysone1533572017-11-07 11:27:02 -0800338 gpr_atm_no_barrier_store(&calld->state, ZOMBIED);
ncteisen274bbbe2017-06-08 14:57:11 -0700339 GRPC_CLOSURE_INIT(
Craig Tillera82950e2015-09-22 12:33:20 -0700340 &calld->kill_zombie_closure, kill_zombie,
Craig Tiller91031da2016-12-28 15:44:25 -0800341 grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0),
342 grpc_schedule_on_exec_ctx);
ncteisen274bbbe2017-06-08 14:57:11 -0700343 GRPC_CLOSURE_SCHED(exec_ctx, &calld->kill_zombie_closure, GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -0700344 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800345}
346
Craig Tillerbaa14a92017-11-03 09:09:36 -0700347static void request_matcher_kill_requests(grpc_exec_ctx* exec_ctx,
348 grpc_server* server,
349 request_matcher* rm,
350 grpc_error* error) {
Ken Paysone1533572017-11-07 11:27:02 -0800351 requested_call* rc;
Craig Tillerdb7c3562016-05-19 11:02:52 -0700352 for (size_t i = 0; i < server->cq_count; i++) {
Ken Payson24908a62017-11-16 12:35:43 -0800353 while ((rc = (requested_call*)gpr_locked_mpscq_pop(
354 &rm->requests_per_cq[i])) != nullptr) {
Ken Paysone1533572017-11-07 11:27:02 -0800355 fail_call(exec_ctx, server, i, rc, GRPC_ERROR_REF(error));
Craig Tillerdb7c3562016-05-19 11:02:52 -0700356 }
Craig Tillera82950e2015-09-22 12:33:20 -0700357 }
Craig Tillercae4b1b2016-05-10 09:11:09 -0700358 GRPC_ERROR_UNREF(error);
Craig Tiller1191e212015-07-30 14:49:02 -0700359}
360
Craig Tiller729b35a2015-07-13 12:36:47 -0700361/*
362 * server proper
363 */
364
Craig Tillerbaa14a92017-11-03 09:09:36 -0700365static void server_ref(grpc_server* server) {
Craig Tillera82950e2015-09-22 12:33:20 -0700366 gpr_ref(&server->internal_refcount);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800367}
368
Craig Tillerbaa14a92017-11-03 09:09:36 -0700369static void server_delete(grpc_exec_ctx* exec_ctx, grpc_server* server) {
370 registered_method* rm;
Craig Tiller89504612015-04-27 11:48:46 -0700371 size_t i;
Craig Tillera59c16c2016-10-31 07:25:01 -0700372 grpc_channel_args_destroy(exec_ctx, server->channel_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700373 gpr_mu_destroy(&server->mu_global);
374 gpr_mu_destroy(&server->mu_call);
Craig Tillerbd3cc402017-04-12 08:06:44 -0700375 gpr_cv_destroy(&server->starting_cv);
Craig Tiller4782d922017-11-10 09:53:21 -0800376 while ((rm = server->registered_methods) != nullptr) {
Craig Tillera82950e2015-09-22 12:33:20 -0700377 server->registered_methods = rm->next;
Craig Tiller88ef00e2016-05-17 09:31:49 -0700378 if (server->started) {
Yash Tibrewala4952202017-09-13 10:53:28 -0700379 request_matcher_destroy(&rm->matcher);
Craig Tiller418a8212016-05-16 16:27:51 -0700380 }
Craig Tillera82950e2015-09-22 12:33:20 -0700381 gpr_free(rm->method);
382 gpr_free(rm->host);
383 gpr_free(rm);
384 }
Craig Tillerdb7c3562016-05-19 11:02:52 -0700385 if (server->started) {
386 request_matcher_destroy(&server->unregistered_request_matcher);
387 }
Craig Tillera82950e2015-09-22 12:33:20 -0700388 for (i = 0; i < server->cq_count; i++) {
Craig Tillerf8401102017-04-17 09:47:28 -0700389 GRPC_CQ_INTERNAL_UNREF(exec_ctx, server->cqs[i], "server");
Craig Tillera82950e2015-09-22 12:33:20 -0700390 }
Craig Tillera82950e2015-09-22 12:33:20 -0700391 gpr_free(server->cqs);
392 gpr_free(server->pollsets);
393 gpr_free(server->shutdown_tags);
Craig Tillera82950e2015-09-22 12:33:20 -0700394 gpr_free(server);
Craig Tilleree945e82015-05-26 16:15:34 -0700395}
396
Craig Tillerbaa14a92017-11-03 09:09:36 -0700397static void server_unref(grpc_exec_ctx* exec_ctx, grpc_server* server) {
Craig Tillera82950e2015-09-22 12:33:20 -0700398 if (gpr_unref(&server->internal_refcount)) {
399 server_delete(exec_ctx, server);
400 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800401}
402
Craig Tillerbaa14a92017-11-03 09:09:36 -0700403static int is_channel_orphaned(channel_data* chand) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800404 return chand->next == chand;
405}
406
Craig Tillerbaa14a92017-11-03 09:09:36 -0700407static void orphan_channel(channel_data* chand) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800408 chand->next->prev = chand->prev;
409 chand->prev->next = chand->next;
410 chand->next = chand->prev = chand;
411}
412
Craig Tillerbaa14a92017-11-03 09:09:36 -0700413static void finish_destroy_channel(grpc_exec_ctx* exec_ctx, void* cd,
414 grpc_error* error) {
415 channel_data* chand = (channel_data*)cd;
416 grpc_server* server = chand->server;
Craig Tillera82950e2015-09-22 12:33:20 -0700417 GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, chand->channel, "server");
418 server_unref(exec_ctx, server);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800419}
420
Craig Tillerbaa14a92017-11-03 09:09:36 -0700421static void destroy_channel(grpc_exec_ctx* exec_ctx, channel_data* chand,
422 grpc_error* error) {
Craig Tillera82950e2015-09-22 12:33:20 -0700423 if (is_channel_orphaned(chand)) return;
Craig Tiller4782d922017-11-10 09:53:21 -0800424 GPR_ASSERT(chand->server != nullptr);
Craig Tillera82950e2015-09-22 12:33:20 -0700425 orphan_channel(chand);
426 server_ref(chand->server);
427 maybe_finish_shutdown(exec_ctx, chand->server);
ncteisen274bbbe2017-06-08 14:57:11 -0700428 GRPC_CLOSURE_INIT(&chand->finish_destroy_channel_closure,
Craig Tiller3cb34472016-12-28 16:11:38 -0800429 finish_destroy_channel, chand, grpc_schedule_on_exec_ctx);
Craig Tillerd7f12e32016-03-03 10:08:31 -0800430
Craig Tiller84f75d42017-05-03 13:06:35 -0700431 if (GRPC_TRACER_ON(grpc_server_channel_trace) && error != GRPC_ERROR_NONE) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700432 const char* msg = grpc_error_string(error);
Craig Tillere7603b82016-07-18 15:43:42 -0700433 gpr_log(GPR_INFO, "Disconnected client: %s", msg);
Craig Tillere7603b82016-07-18 15:43:42 -0700434 }
435 GRPC_ERROR_UNREF(error);
Craig Tillerdf1d3da2016-09-01 13:51:42 -0700436
Craig Tillerbaa14a92017-11-03 09:09:36 -0700437 grpc_transport_op* op =
Craig Tiller44b12f92016-09-08 10:06:14 -0700438 grpc_make_transport_op(&chand->finish_destroy_channel_closure);
Craig Tillerdf1d3da2016-09-01 13:51:42 -0700439 op->set_accept_stream = true;
440 grpc_channel_next_op(exec_ctx,
441 grpc_channel_stack_element(
442 grpc_channel_get_channel_stack(chand->channel), 0),
443 op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800444}
445
Craig Tillerbaa14a92017-11-03 09:09:36 -0700446static void done_request_event(grpc_exec_ctx* exec_ctx, void* req,
447 grpc_cq_completion* c) {
Ken Paysone1533572017-11-07 11:27:02 -0800448 gpr_free(req);
Craig Tiller88512692016-04-04 09:32:52 -0700449}
Craig Tiller06cb1a92016-04-04 08:10:47 -0700450
Craig Tillerbaa14a92017-11-03 09:09:36 -0700451static void publish_call(grpc_exec_ctx* exec_ctx, grpc_server* server,
452 call_data* calld, size_t cq_idx, requested_call* rc) {
Craig Tiller06cb1a92016-04-04 08:10:47 -0700453 grpc_call_set_completion_queue(exec_ctx, calld->call, rc->cq_bound_to_call);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700454 grpc_call* call = calld->call;
Craig Tiller88512692016-04-04 09:32:52 -0700455 *rc->call = call;
Craig Tiller9f9d4222016-05-16 17:02:14 -0700456 calld->cq_new = server->cqs[cq_idx];
Craig Tiller06cb1a92016-04-04 08:10:47 -0700457 GPR_SWAP(grpc_metadata_array, *rc->initial_metadata, calld->initial_metadata);
458 switch (rc->type) {
459 case BATCH_CALL:
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800460 GPR_ASSERT(calld->host_set);
461 GPR_ASSERT(calld->path_set);
462 rc->data.batch.details->host = grpc_slice_ref_internal(calld->host);
463 rc->data.batch.details->method = grpc_slice_ref_internal(calld->path);
Craig Tiller89c14282017-07-19 15:32:27 -0700464 rc->data.batch.details->deadline =
Craig Tillerb6034892017-09-20 16:01:19 -0700465 grpc_millis_to_timespec(calld->deadline, GPR_CLOCK_MONOTONIC);
Craig Tiller72920cc2017-03-10 10:20:17 -0800466 rc->data.batch.details->flags = calld->recv_initial_metadata_flags;
Craig Tiller06cb1a92016-04-04 08:10:47 -0700467 break;
468 case REGISTERED_CALL:
Craig Tiller89c14282017-07-19 15:32:27 -0700469 *rc->data.registered.deadline =
Craig Tillerb6034892017-09-20 16:01:19 -0700470 grpc_millis_to_timespec(calld->deadline, GPR_CLOCK_MONOTONIC);
Craig Tiller06cb1a92016-04-04 08:10:47 -0700471 if (rc->data.registered.optional_payload) {
Craig Tiller88512692016-04-04 09:32:52 -0700472 *rc->data.registered.optional_payload = calld->payload;
Craig Tiller4782d922017-11-10 09:53:21 -0800473 calld->payload = nullptr;
Craig Tiller06cb1a92016-04-04 08:10:47 -0700474 }
475 break;
476 default:
477 GPR_UNREACHABLE_CODE(return );
478 }
479
Craig Tillerf51457b2016-05-03 17:06:32 -0700480 grpc_cq_end_op(exec_ctx, calld->cq_new, rc->tag, GRPC_ERROR_NONE,
481 done_request_event, rc, &rc->completion);
Craig Tiller06cb1a92016-04-04 08:10:47 -0700482}
483
Craig Tillerbaa14a92017-11-03 09:09:36 -0700484static void publish_new_rpc(grpc_exec_ctx* exec_ctx, void* arg,
485 grpc_error* error) {
486 grpc_call_element* call_elem = (grpc_call_element*)arg;
487 call_data* calld = (call_data*)call_elem->call_data;
488 channel_data* chand = (channel_data*)call_elem->channel_data;
489 request_matcher* rm = calld->matcher;
490 grpc_server* server = rm->server;
Craig Tiller6a006ce2015-07-13 16:25:40 -0700491
Craig Tillerf51457b2016-05-03 17:06:32 -0700492 if (error != GRPC_ERROR_NONE || gpr_atm_acq_load(&server->shutdown_flag)) {
Ken Paysone1533572017-11-07 11:27:02 -0800493 gpr_atm_no_barrier_store(&calld->state, ZOMBIED);
ncteisen274bbbe2017-06-08 14:57:11 -0700494 GRPC_CLOSURE_INIT(
Craig Tiller88512692016-04-04 09:32:52 -0700495 &calld->kill_zombie_closure, kill_zombie,
Craig Tiller91031da2016-12-28 15:44:25 -0800496 grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0),
497 grpc_schedule_on_exec_ctx);
ncteisen274bbbe2017-06-08 14:57:11 -0700498 GRPC_CLOSURE_SCHED(exec_ctx, &calld->kill_zombie_closure,
yang-g23f777d2017-02-22 23:32:26 -0800499 GRPC_ERROR_REF(error));
Craig Tillera82950e2015-09-22 12:33:20 -0700500 return;
501 }
Craig Tiller45724b32015-09-22 10:42:19 -0700502
Craig Tillerdb7c3562016-05-19 11:02:52 -0700503 for (size_t i = 0; i < server->cq_count; i++) {
504 size_t cq_idx = (chand->cq_idx + i) % server->cq_count;
Ken Paysone1533572017-11-07 11:27:02 -0800505 requested_call* rc =
506 (requested_call*)gpr_locked_mpscq_try_pop(&rm->requests_per_cq[cq_idx]);
Craig Tiller4782d922017-11-10 09:53:21 -0800507 if (rc == nullptr) {
Craig Tillerdb7c3562016-05-19 11:02:52 -0700508 continue;
Craig Tillera82950e2015-09-22 12:33:20 -0700509 } else {
Craig Tiller561dc322017-09-05 13:00:46 -0700510 GRPC_STATS_INC_SERVER_CQS_CHECKED(exec_ctx, i);
Ken Paysone1533572017-11-07 11:27:02 -0800511 gpr_atm_no_barrier_store(&calld->state, ACTIVATED);
512 publish_call(exec_ctx, server, calld, cq_idx, rc);
Craig Tillerdb7c3562016-05-19 11:02:52 -0700513 return; /* early out */
Craig Tiller45724b32015-09-22 10:42:19 -0700514 }
Craig Tiller88512692016-04-04 09:32:52 -0700515 }
Craig Tillerdb7c3562016-05-19 11:02:52 -0700516
517 /* no cq to take the request found: queue it on the slow list */
Craig Tiller561dc322017-09-05 13:00:46 -0700518 GRPC_STATS_INC_SERVER_SLOWPATH_REQUESTS_QUEUED(exec_ctx);
Craig Tillerdb7c3562016-05-19 11:02:52 -0700519 gpr_mu_lock(&server->mu_call);
Ken Paysone1533572017-11-07 11:27:02 -0800520
521 // We need to ensure that all the queues are empty. We do this under
522 // the server mu_call lock to ensure that if something is added to
523 // an empty request queue, it will block until the call is actually
524 // added to the pending list.
525 for (size_t i = 0; i < server->cq_count; i++) {
526 size_t cq_idx = (chand->cq_idx + i) % server->cq_count;
527 requested_call* rc =
528 (requested_call*)gpr_locked_mpscq_pop(&rm->requests_per_cq[cq_idx]);
Craig Tiller4782d922017-11-10 09:53:21 -0800529 if (rc == nullptr) {
Ken Paysone1533572017-11-07 11:27:02 -0800530 continue;
531 } else {
532 gpr_mu_unlock(&server->mu_call);
533 GRPC_STATS_INC_SERVER_CQS_CHECKED(exec_ctx, i + server->cq_count);
534 gpr_atm_no_barrier_store(&calld->state, ACTIVATED);
535 publish_call(exec_ctx, server, calld, cq_idx, rc);
536 return; /* early out */
537 }
538 }
539
540 gpr_atm_no_barrier_store(&calld->state, PENDING);
Craig Tiller4782d922017-11-10 09:53:21 -0800541 if (rm->pending_head == nullptr) {
Craig Tillerdb7c3562016-05-19 11:02:52 -0700542 rm->pending_tail = rm->pending_head = calld;
543 } else {
544 rm->pending_tail->pending_next = calld;
545 rm->pending_tail = calld;
546 }
Craig Tiller4782d922017-11-10 09:53:21 -0800547 calld->pending_next = nullptr;
Craig Tillerdb7c3562016-05-19 11:02:52 -0700548 gpr_mu_unlock(&server->mu_call);
Craig Tiller88512692016-04-04 09:32:52 -0700549}
550
551static void finish_start_new_rpc(
Craig Tillerbaa14a92017-11-03 09:09:36 -0700552 grpc_exec_ctx* exec_ctx, grpc_server* server, grpc_call_element* elem,
553 request_matcher* rm,
Craig Tiller88512692016-04-04 09:32:52 -0700554 grpc_server_register_method_payload_handling payload_handling) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700555 call_data* calld = (call_data*)elem->call_data;
Craig Tiller88512692016-04-04 09:32:52 -0700556
557 if (gpr_atm_acq_load(&server->shutdown_flag)) {
Ken Paysone1533572017-11-07 11:27:02 -0800558 gpr_atm_no_barrier_store(&calld->state, ZOMBIED);
ncteisen274bbbe2017-06-08 14:57:11 -0700559 GRPC_CLOSURE_INIT(&calld->kill_zombie_closure, kill_zombie, elem,
Craig Tiller91031da2016-12-28 15:44:25 -0800560 grpc_schedule_on_exec_ctx);
ncteisen274bbbe2017-06-08 14:57:11 -0700561 GRPC_CLOSURE_SCHED(exec_ctx, &calld->kill_zombie_closure, GRPC_ERROR_NONE);
Craig Tiller88512692016-04-04 09:32:52 -0700562 return;
563 }
564
Yash Tibrewala4952202017-09-13 10:53:28 -0700565 calld->matcher = rm;
Craig Tiller88512692016-04-04 09:32:52 -0700566
567 switch (payload_handling) {
568 case GRPC_SRM_PAYLOAD_NONE:
Craig Tiller48abdde2016-05-24 06:55:28 -0700569 publish_new_rpc(exec_ctx, elem, GRPC_ERROR_NONE);
Craig Tiller88512692016-04-04 09:32:52 -0700570 break;
571 case GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER: {
572 grpc_op op;
573 memset(&op, 0, sizeof(op));
574 op.op = GRPC_OP_RECV_MESSAGE;
Mark D. Roth448c1f02017-01-25 10:44:30 -0800575 op.data.recv_message.recv_message = &calld->payload;
ncteisen274bbbe2017-06-08 14:57:11 -0700576 GRPC_CLOSURE_INIT(&calld->publish, publish_new_rpc, elem,
Craig Tiller91031da2016-12-28 15:44:25 -0800577 grpc_schedule_on_exec_ctx);
Craig Tiller88512692016-04-04 09:32:52 -0700578 grpc_call_start_batch_and_execute(exec_ctx, calld->call, &op, 1,
579 &calld->publish);
580 break;
581 }
Craig Tillera82950e2015-09-22 12:33:20 -0700582 }
Craig Tiller04cc8be2015-02-10 16:11:22 -0800583}
584
Craig Tillerbaa14a92017-11-03 09:09:36 -0700585static void start_new_rpc(grpc_exec_ctx* exec_ctx, grpc_call_element* elem) {
586 channel_data* chand = (channel_data*)elem->channel_data;
587 call_data* calld = (call_data*)elem->call_data;
588 grpc_server* server = chand->server;
Craig Tiller7536af02015-12-22 13:49:30 -0800589 uint32_t i;
590 uint32_t hash;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700591 channel_registered_method* rm;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800592
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800593 if (chand->registered_methods && calld->path_set && calld->host_set) {
Craig Tillera82950e2015-09-22 12:33:20 -0700594 /* TODO(ctiller): unify these two searches */
595 /* check for an exact match with host */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800596 hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(calld->host),
597 grpc_slice_hash(calld->path));
Craig Tillera82950e2015-09-22 12:33:20 -0700598 for (i = 0; i <= chand->registered_method_max_probes; i++) {
599 rm = &chand->registered_methods[(hash + i) %
600 chand->registered_method_slots];
601 if (!rm) break;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800602 if (!rm->has_host) continue;
603 if (!grpc_slice_eq(rm->host, calld->host)) continue;
604 if (!grpc_slice_eq(rm->method, calld->path)) continue;
Craig Tillerb2906862016-03-10 06:50:07 -0800605 if ((rm->flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) &&
Craig Tiller72920cc2017-03-10 10:20:17 -0800606 0 == (calld->recv_initial_metadata_flags &
607 GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST)) {
Craig Tillerb2906862016-03-10 06:50:07 -0800608 continue;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800609 }
Craig Tillera82950e2015-09-22 12:33:20 -0700610 finish_start_new_rpc(exec_ctx, server, elem,
Yash Tibrewala4952202017-09-13 10:53:28 -0700611 &rm->server_registered_method->matcher,
Craig Tiller88512692016-04-04 09:32:52 -0700612 rm->server_registered_method->payload_handling);
Craig Tillera82950e2015-09-22 12:33:20 -0700613 return;
Craig Tiller04cc8be2015-02-10 16:11:22 -0800614 }
Craig Tillera82950e2015-09-22 12:33:20 -0700615 /* check for a wildcard method definition (no host set) */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800616 hash = GRPC_MDSTR_KV_HASH(0, grpc_slice_hash(calld->path));
Craig Tillera82950e2015-09-22 12:33:20 -0700617 for (i = 0; i <= chand->registered_method_max_probes; i++) {
618 rm = &chand->registered_methods[(hash + i) %
619 chand->registered_method_slots];
620 if (!rm) break;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800621 if (rm->has_host) continue;
622 if (!grpc_slice_eq(rm->method, calld->path)) continue;
Craig Tillerb2906862016-03-10 06:50:07 -0800623 if ((rm->flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) &&
Craig Tiller72920cc2017-03-10 10:20:17 -0800624 0 == (calld->recv_initial_metadata_flags &
625 GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST)) {
Craig Tillerb2906862016-03-10 06:50:07 -0800626 continue;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800627 }
Craig Tillera82950e2015-09-22 12:33:20 -0700628 finish_start_new_rpc(exec_ctx, server, elem,
Yash Tibrewala4952202017-09-13 10:53:28 -0700629 &rm->server_registered_method->matcher,
Craig Tiller88512692016-04-04 09:32:52 -0700630 rm->server_registered_method->payload_handling);
Craig Tillera82950e2015-09-22 12:33:20 -0700631 return;
632 }
633 }
634 finish_start_new_rpc(exec_ctx, server, elem,
Craig Tiller88512692016-04-04 09:32:52 -0700635 &server->unregistered_request_matcher,
636 GRPC_SRM_PAYLOAD_NONE);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800637}
638
Craig Tillerbaa14a92017-11-03 09:09:36 -0700639static int num_listeners(grpc_server* server) {
640 listener* l;
Craig Tilleree945e82015-05-26 16:15:34 -0700641 int n = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700642 for (l = server->listeners; l; l = l->next) {
643 n++;
644 }
Craig Tilleree945e82015-05-26 16:15:34 -0700645 return n;
646}
647
Craig Tillerbaa14a92017-11-03 09:09:36 -0700648static void done_shutdown_event(grpc_exec_ctx* exec_ctx, void* server,
649 grpc_cq_completion* completion) {
650 server_unref(exec_ctx, (grpc_server*)server);
Craig Tiller97fc6a32015-07-08 15:31:35 -0700651}
652
Craig Tillerbaa14a92017-11-03 09:09:36 -0700653static int num_channels(grpc_server* server) {
654 channel_data* chand;
Craig Tillerab54f792015-07-08 08:34:20 -0700655 int n = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700656 for (chand = server->root_channel_data.next;
657 chand != &server->root_channel_data; chand = chand->next) {
658 n++;
659 }
Craig Tillerab54f792015-07-08 08:34:20 -0700660 return n;
661}
662
Craig Tillerbaa14a92017-11-03 09:09:36 -0700663static void kill_pending_work_locked(grpc_exec_ctx* exec_ctx,
664 grpc_server* server, grpc_error* error) {
Craig Tiller88ef00e2016-05-17 09:31:49 -0700665 if (server->started) {
Craig Tillerdb7c3562016-05-19 11:02:52 -0700666 request_matcher_kill_requests(exec_ctx, server,
Craig Tiller48abdde2016-05-24 06:55:28 -0700667 &server->unregistered_request_matcher,
Craig Tillercae4b1b2016-05-10 09:11:09 -0700668 GRPC_ERROR_REF(error));
Craig Tillerdb7c3562016-05-19 11:02:52 -0700669 request_matcher_zombify_all_pending_calls(
670 exec_ctx, &server->unregistered_request_matcher);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700671 for (registered_method* rm = server->registered_methods; rm;
Craig Tillerdb7c3562016-05-19 11:02:52 -0700672 rm = rm->next) {
Yash Tibrewala4952202017-09-13 10:53:28 -0700673 request_matcher_kill_requests(exec_ctx, server, &rm->matcher,
Craig Tiller48abdde2016-05-24 06:55:28 -0700674 GRPC_ERROR_REF(error));
Yash Tibrewala4952202017-09-13 10:53:28 -0700675 request_matcher_zombify_all_pending_calls(exec_ctx, &rm->matcher);
Craig Tiller418a8212016-05-16 16:27:51 -0700676 }
Craig Tillera82950e2015-09-22 12:33:20 -0700677 }
Craig Tillercae4b1b2016-05-10 09:11:09 -0700678 GRPC_ERROR_UNREF(error);
Craig Tillerdc627722015-05-26 15:27:02 -0700679}
680
Craig Tillerbaa14a92017-11-03 09:09:36 -0700681static void maybe_finish_shutdown(grpc_exec_ctx* exec_ctx,
682 grpc_server* server) {
Craig Tiller45724b32015-09-22 10:42:19 -0700683 size_t i;
Craig Tillera82950e2015-09-22 12:33:20 -0700684 if (!gpr_atm_acq_load(&server->shutdown_flag) || server->shutdown_published) {
685 return;
686 }
Craig Tiller45724b32015-09-22 10:42:19 -0700687
ncteisen4b36a3d2017-03-13 19:08:06 -0700688 kill_pending_work_locked(
689 exec_ctx, server,
690 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Server Shutdown"));
Craig Tiller45724b32015-09-22 10:42:19 -0700691
Craig Tillera82950e2015-09-22 12:33:20 -0700692 if (server->root_channel_data.next != &server->root_channel_data ||
693 server->listeners_destroyed < num_listeners(server)) {
694 if (gpr_time_cmp(gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME),
695 server->last_shutdown_message_time),
696 gpr_time_from_seconds(1, GPR_TIMESPAN)) >= 0) {
697 server->last_shutdown_message_time = gpr_now(GPR_CLOCK_REALTIME);
698 gpr_log(GPR_DEBUG,
699 "Waiting for %d channels and %d/%d listeners to be destroyed"
700 " before shutting down server",
701 num_channels(server),
702 num_listeners(server) - server->listeners_destroyed,
703 num_listeners(server));
Craig Tiller45724b32015-09-22 10:42:19 -0700704 }
Craig Tillera82950e2015-09-22 12:33:20 -0700705 return;
706 }
Craig Tiller45724b32015-09-22 10:42:19 -0700707 server->shutdown_published = 1;
Craig Tillera82950e2015-09-22 12:33:20 -0700708 for (i = 0; i < server->num_shutdown_tags; i++) {
709 server_ref(server);
710 grpc_cq_end_op(exec_ctx, server->shutdown_tags[i].cq,
Craig Tillerf51457b2016-05-03 17:06:32 -0700711 server->shutdown_tags[i].tag, GRPC_ERROR_NONE,
712 done_shutdown_event, server,
Craig Tillera82950e2015-09-22 12:33:20 -0700713 &server->shutdown_tags[i].completion);
714 }
Craig Tiller45724b32015-09-22 10:42:19 -0700715}
716
Craig Tillerbaa14a92017-11-03 09:09:36 -0700717static void server_on_recv_initial_metadata(grpc_exec_ctx* exec_ctx, void* ptr,
718 grpc_error* error) {
719 grpc_call_element* elem = (grpc_call_element*)ptr;
720 call_data* calld = (call_data*)elem->call_data;
Craig Tiller89c14282017-07-19 15:32:27 -0700721 grpc_millis op_deadline;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700722
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800723 if (error == GRPC_ERROR_NONE) {
Craig Tiller4782d922017-11-10 09:53:21 -0800724 GPR_ASSERT(calld->recv_initial_metadata->idx.named.path != nullptr);
725 GPR_ASSERT(calld->recv_initial_metadata->idx.named.authority != nullptr);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800726 calld->path = grpc_slice_ref_internal(
727 GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.path->md));
728 calld->host = grpc_slice_ref_internal(
729 GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.authority->md));
730 calld->path_set = true;
731 calld->host_set = true;
732 grpc_metadata_batch_remove(exec_ctx, calld->recv_initial_metadata,
733 calld->recv_initial_metadata->idx.named.path);
734 grpc_metadata_batch_remove(
735 exec_ctx, calld->recv_initial_metadata,
736 calld->recv_initial_metadata->idx.named.authority);
737 } else {
738 GRPC_ERROR_REF(error);
739 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800740 op_deadline = calld->recv_initial_metadata->deadline;
Craig Tiller89c14282017-07-19 15:32:27 -0700741 if (op_deadline != GRPC_MILLIS_INF_FUTURE) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800742 calld->deadline = op_deadline;
743 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800744 if (calld->host_set && calld->path_set) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800745 /* do nothing */
746 } else {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700747 grpc_error* src_error = error;
ncteisen4b36a3d2017-03-13 19:08:06 -0700748 error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
749 "Missing :authority or :path", &error, 1);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800750 GRPC_ERROR_UNREF(src_error);
Craig Tillera82950e2015-09-22 12:33:20 -0700751 }
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700752
ncteisen274bbbe2017-06-08 14:57:11 -0700753 GRPC_CLOSURE_RUN(exec_ctx, calld->on_done_recv_initial_metadata, error);
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700754}
755
Craig Tillerbaa14a92017-11-03 09:09:36 -0700756static void server_mutate_op(grpc_call_element* elem,
757 grpc_transport_stream_op_batch* op) {
758 call_data* calld = (call_data*)elem->call_data;
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700759
Craig Tiller72920cc2017-03-10 10:20:17 -0800760 if (op->recv_initial_metadata) {
Craig Tiller4782d922017-11-10 09:53:21 -0800761 GPR_ASSERT(op->payload->recv_initial_metadata.recv_flags == nullptr);
Craig Tiller72920cc2017-03-10 10:20:17 -0800762 calld->recv_initial_metadata =
763 op->payload->recv_initial_metadata.recv_initial_metadata;
764 calld->on_done_recv_initial_metadata =
765 op->payload->recv_initial_metadata.recv_initial_metadata_ready;
766 op->payload->recv_initial_metadata.recv_initial_metadata_ready =
767 &calld->server_on_recv_initial_metadata;
768 op->payload->recv_initial_metadata.recv_flags =
769 &calld->recv_initial_metadata_flags;
Craig Tillera82950e2015-09-22 12:33:20 -0700770 }
Craig Tiller50d9db52015-04-23 10:52:14 -0700771}
Craig Tillerbe18b8d2015-04-22 14:00:47 -0700772
Craig Tillera0f3abd2017-03-31 15:42:16 -0700773static void server_start_transport_stream_op_batch(
Craig Tillerbaa14a92017-11-03 09:09:36 -0700774 grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
775 grpc_transport_stream_op_batch* op) {
Craig Tillera82950e2015-09-22 12:33:20 -0700776 server_mutate_op(elem, op);
777 grpc_call_next_op(exec_ctx, elem, op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800778}
779
Craig Tillerbaa14a92017-11-03 09:09:36 -0700780static void got_initial_metadata(grpc_exec_ctx* exec_ctx, void* ptr,
781 grpc_error* error) {
782 grpc_call_element* elem = (grpc_call_element*)ptr;
783 call_data* calld = (call_data*)elem->call_data;
Craig Tillerf51457b2016-05-03 17:06:32 -0700784 if (error == GRPC_ERROR_NONE) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800785 start_new_rpc(exec_ctx, elem);
786 } else {
Ken Paysone1533572017-11-07 11:27:02 -0800787 if (gpr_atm_full_cas(&calld->state, NOT_STARTED, ZOMBIED)) {
ncteisen274bbbe2017-06-08 14:57:11 -0700788 GRPC_CLOSURE_INIT(&calld->kill_zombie_closure, kill_zombie, elem,
Craig Tiller91031da2016-12-28 15:44:25 -0800789 grpc_schedule_on_exec_ctx);
ncteisen274bbbe2017-06-08 14:57:11 -0700790 GRPC_CLOSURE_SCHED(exec_ctx, &calld->kill_zombie_closure,
Craig Tiller91031da2016-12-28 15:44:25 -0800791 GRPC_ERROR_NONE);
Ken Paysone1533572017-11-07 11:27:02 -0800792 } else if (gpr_atm_full_cas(&calld->state, PENDING, ZOMBIED)) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800793 /* zombied call will be destroyed when it's removed from the pending
794 queue... later */
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800795 }
796 }
797}
798
Craig Tillerbaa14a92017-11-03 09:09:36 -0700799static void accept_stream(grpc_exec_ctx* exec_ctx, void* cd,
800 grpc_transport* transport,
801 const void* transport_server_data) {
802 channel_data* chand = (channel_data*)cd;
Craig Tillere039f032015-06-25 12:54:23 -0700803 /* create a call */
Craig Tiller8e214652016-08-19 09:54:31 -0700804 grpc_call_create_args args;
805 memset(&args, 0, sizeof(args));
806 args.channel = chand->channel;
807 args.server_transport_data = transport_server_data;
Craig Tiller89c14282017-07-19 15:32:27 -0700808 args.send_deadline = GRPC_MILLIS_INF_FUTURE;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700809 grpc_call* call;
810 grpc_error* error = grpc_call_create(exec_ctx, &args, &call);
811 grpc_call_element* elem =
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800812 grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
Craig Tiller8e214652016-08-19 09:54:31 -0700813 if (error != GRPC_ERROR_NONE) {
814 got_initial_metadata(exec_ctx, elem, error);
815 GRPC_ERROR_UNREF(error);
816 return;
817 }
Craig Tillerbaa14a92017-11-03 09:09:36 -0700818 call_data* calld = (call_data*)elem->call_data;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800819 grpc_op op;
820 memset(&op, 0, sizeof(op));
821 op.op = GRPC_OP_RECV_INITIAL_METADATA;
Mark D. Roth448c1f02017-01-25 10:44:30 -0800822 op.data.recv_initial_metadata.recv_initial_metadata =
823 &calld->initial_metadata;
ncteisen274bbbe2017-06-08 14:57:11 -0700824 GRPC_CLOSURE_INIT(&calld->got_initial_metadata, got_initial_metadata, elem,
Craig Tiller91031da2016-12-28 15:44:25 -0800825 grpc_schedule_on_exec_ctx);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800826 grpc_call_start_batch_and_execute(exec_ctx, call, &op, 1,
827 &calld->got_initial_metadata);
Craig Tillere039f032015-06-25 12:54:23 -0700828}
829
Craig Tillerbaa14a92017-11-03 09:09:36 -0700830static void channel_connectivity_changed(grpc_exec_ctx* exec_ctx, void* cd,
831 grpc_error* error) {
832 channel_data* chand = (channel_data*)cd;
833 grpc_server* server = chand->server;
Craig Tiller48ed92e2016-06-02 11:07:12 -0700834 if (chand->connectivity_state != GRPC_CHANNEL_SHUTDOWN) {
Craig Tiller4782d922017-11-10 09:53:21 -0800835 grpc_transport_op* op = grpc_make_transport_op(nullptr);
Craig Tillere0221ff2016-07-11 15:56:08 -0700836 op->on_connectivity_state_change = &chand->channel_connectivity_changed,
837 op->connectivity_state = &chand->connectivity_state;
Craig Tillera82950e2015-09-22 12:33:20 -0700838 grpc_channel_next_op(exec_ctx,
839 grpc_channel_stack_element(
840 grpc_channel_get_channel_stack(chand->channel), 0),
Craig Tillere0221ff2016-07-11 15:56:08 -0700841 op);
Craig Tillera82950e2015-09-22 12:33:20 -0700842 } else {
843 gpr_mu_lock(&server->mu_global);
Craig Tiller9d018482016-07-18 08:53:49 -0700844 destroy_channel(exec_ctx, chand, GRPC_ERROR_REF(error));
Craig Tillera82950e2015-09-22 12:33:20 -0700845 gpr_mu_unlock(&server->mu_global);
846 GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, chand->channel, "connectivity");
847 }
Craig Tillere039f032015-06-25 12:54:23 -0700848}
849
Craig Tillerbaa14a92017-11-03 09:09:36 -0700850static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
851 grpc_call_element* elem,
852 const grpc_call_element_args* args) {
853 call_data* calld = (call_data*)elem->call_data;
854 channel_data* chand = (channel_data*)elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700855 memset(calld, 0, sizeof(call_data));
Craig Tiller89c14282017-07-19 15:32:27 -0700856 calld->deadline = GRPC_MILLIS_INF_FUTURE;
Craig Tillera82950e2015-09-22 12:33:20 -0700857 calld->call = grpc_call_from_top_element(elem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800858
ncteisen274bbbe2017-06-08 14:57:11 -0700859 GRPC_CLOSURE_INIT(&calld->server_on_recv_initial_metadata,
Craig Tiller91031da2016-12-28 15:44:25 -0800860 server_on_recv_initial_metadata, elem,
861 grpc_schedule_on_exec_ctx);
Craig Tiller1e6facb2015-06-11 22:47:11 -0700862
Craig Tillera82950e2015-09-22 12:33:20 -0700863 server_ref(chand->server);
Mark D. Roth0badbe82016-06-23 10:15:12 -0700864 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800865}
866
Craig Tillerbaa14a92017-11-03 09:09:36 -0700867static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
868 const grpc_call_final_info* final_info,
869 grpc_closure* ignored) {
870 channel_data* chand = (channel_data*)elem->channel_data;
871 call_data* calld = (call_data*)elem->call_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800872
Craig Tillera82950e2015-09-22 12:33:20 -0700873 GPR_ASSERT(calld->state != PENDING);
Craig Tiller092d8d12015-07-04 22:35:00 -0700874
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800875 if (calld->host_set) {
876 grpc_slice_unref_internal(exec_ctx, calld->host);
Craig Tillera82950e2015-09-22 12:33:20 -0700877 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800878 if (calld->path_set) {
879 grpc_slice_unref_internal(exec_ctx, calld->path);
Craig Tillera82950e2015-09-22 12:33:20 -0700880 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800881 grpc_metadata_array_destroy(&calld->initial_metadata);
yang-g2b8b7482017-06-23 17:07:54 -0700882 grpc_byte_buffer_destroy(calld->payload);
Craig Tiller4df31a62015-01-30 09:44:31 -0800883
Craig Tillera82950e2015-09-22 12:33:20 -0700884 server_unref(exec_ctx, chand->server);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800885}
886
Craig Tillerbaa14a92017-11-03 09:09:36 -0700887static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
888 grpc_channel_element* elem,
889 grpc_channel_element_args* args) {
890 channel_data* chand = (channel_data*)elem->channel_data;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800891 GPR_ASSERT(args->is_first);
892 GPR_ASSERT(!args->is_last);
Craig Tiller4782d922017-11-10 09:53:21 -0800893 chand->server = nullptr;
894 chand->channel = nullptr;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800895 chand->next = chand->prev = chand;
Craig Tiller4782d922017-11-10 09:53:21 -0800896 chand->registered_methods = nullptr;
Craig Tillere039f032015-06-25 12:54:23 -0700897 chand->connectivity_state = GRPC_CHANNEL_IDLE;
ncteisen274bbbe2017-06-08 14:57:11 -0700898 GRPC_CLOSURE_INIT(&chand->channel_connectivity_changed,
Craig Tiller91031da2016-12-28 15:44:25 -0800899 channel_connectivity_changed, chand,
900 grpc_schedule_on_exec_ctx);
Mark D. Roth5e2566e2016-11-18 10:53:13 -0800901 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800902}
903
Craig Tillerbaa14a92017-11-03 09:09:36 -0700904static void destroy_channel_elem(grpc_exec_ctx* exec_ctx,
905 grpc_channel_element* elem) {
Craig Tillerec3257c2015-02-12 15:59:43 -0800906 size_t i;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700907 channel_data* chand = (channel_data*)elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700908 if (chand->registered_methods) {
909 for (i = 0; i < chand->registered_method_slots; i++) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800910 grpc_slice_unref_internal(exec_ctx, chand->registered_methods[i].method);
911 if (chand->registered_methods[i].has_host) {
912 grpc_slice_unref_internal(exec_ctx, chand->registered_methods[i].host);
Craig Tillera82950e2015-09-22 12:33:20 -0700913 }
Craig Tillerec3257c2015-02-12 15:59:43 -0800914 }
Craig Tillera82950e2015-09-22 12:33:20 -0700915 gpr_free(chand->registered_methods);
916 }
917 if (chand->server) {
918 gpr_mu_lock(&chand->server->mu_global);
919 chand->next->prev = chand->prev;
920 chand->prev->next = chand->next;
921 chand->next = chand->prev = chand;
922 maybe_finish_shutdown(exec_ctx, chand->server);
923 gpr_mu_unlock(&chand->server->mu_global);
Craig Tillera82950e2015-09-22 12:33:20 -0700924 server_unref(exec_ctx, chand->server);
925 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800926}
927
Craig Tiller178edfa2016-02-17 20:54:46 -0800928const grpc_channel_filter grpc_server_top_filter = {
Craig Tillera0f3abd2017-03-31 15:42:16 -0700929 server_start_transport_stream_op_batch,
Craig Tillerf40df232016-03-25 13:38:14 -0700930 grpc_channel_next_op,
931 sizeof(call_data),
932 init_call_elem,
David Garcia Quintas4afce7e2016-04-18 16:25:17 -0700933 grpc_call_stack_ignore_set_pollset_or_pollset_set,
Craig Tillerf40df232016-03-25 13:38:14 -0700934 destroy_call_elem,
935 sizeof(channel_data),
936 init_channel_elem,
937 destroy_channel_elem,
Mark D. Rothb2d24882016-10-27 15:44:07 -0700938 grpc_channel_next_get_info,
Craig Tillerf40df232016-03-25 13:38:14 -0700939 "server",
Craig Tiller9f28ac22015-01-27 17:01:29 -0800940};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800941
Craig Tillerbaa14a92017-11-03 09:09:36 -0700942static void register_completion_queue(grpc_server* server,
943 grpc_completion_queue* cq,
944 void* reserved) {
Craig Tiller20bc56d2015-02-12 09:02:56 -0800945 size_t i, n;
Craig Tillera82950e2015-09-22 12:33:20 -0700946 GPR_ASSERT(!reserved);
947 for (i = 0; i < server->cq_count; i++) {
948 if (server->cqs[i] == cq) return;
949 }
Sree Kuchibhotla1f5e2622016-04-21 12:28:09 -0700950
Craig Tiller509b30e2016-05-21 12:32:39 -0700951 GRPC_CQ_INTERNAL_REF(cq, "server");
Craig Tiller20bc56d2015-02-12 09:02:56 -0800952 n = server->cq_count++;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700953 server->cqs = (grpc_completion_queue**)gpr_realloc(
954 server->cqs, server->cq_count * sizeof(grpc_completion_queue*));
Craig Tiller20bc56d2015-02-12 09:02:56 -0800955 server->cqs[n] = cq;
956}
957
Craig Tillerbaa14a92017-11-03 09:09:36 -0700958void grpc_server_register_completion_queue(grpc_server* server,
959 grpc_completion_queue* cq,
960 void* reserved) {
Sree Kuchibhotla1f5e2622016-04-21 12:28:09 -0700961 GRPC_API_TRACE(
962 "grpc_server_register_completion_queue(server=%p, cq=%p, reserved=%p)", 3,
963 (server, cq, reserved));
Sree Kuchibhotla321881d2017-02-27 11:25:28 -0800964
965 if (grpc_get_cq_completion_type(cq) != GRPC_CQ_NEXT) {
Sree Kuchibhotlae7e38da2017-03-03 18:38:06 -0800966 gpr_log(GPR_INFO,
967 "Completion queue which is not of type GRPC_CQ_NEXT is being "
968 "registered as a server-completion-queue");
969 /* Ideally we should log an error and abort but ruby-wrapped-language API
970 calls grpc_completion_queue_pluck() on server completion queues */
Sree Kuchibhotla321881d2017-02-27 11:25:28 -0800971 }
972
Craig Tiller11c58322017-04-12 08:21:17 -0700973 register_completion_queue(server, cq, reserved);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800974}
975
Craig Tillerbaa14a92017-11-03 09:09:36 -0700976grpc_server* grpc_server_create(const grpc_channel_args* args, void* reserved) {
Craig Tiller178edfa2016-02-17 20:54:46 -0800977 GRPC_API_TRACE("grpc_server_create(%p, %p)", 2, (args, reserved));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800978
Craig Tillerbaa14a92017-11-03 09:09:36 -0700979 grpc_server* server = (grpc_server*)gpr_zalloc(sizeof(grpc_server));
Craig Tiller60fd3612015-03-05 16:24:22 -0800980
Craig Tillera82950e2015-09-22 12:33:20 -0700981 gpr_mu_init(&server->mu_global);
982 gpr_mu_init(&server->mu_call);
Craig Tillerbd3cc402017-04-12 08:06:44 -0700983 gpr_cv_init(&server->starting_cv);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800984
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800985 /* decremented by grpc_server_destroy */
Craig Tillera82950e2015-09-22 12:33:20 -0700986 gpr_ref_init(&server->internal_refcount, 1);
987 server->root_channel_data.next = server->root_channel_data.prev =
988 &server->root_channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800989
Craig Tillera82950e2015-09-22 12:33:20 -0700990 server->channel_args = grpc_channel_args_copy(args);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800991
992 return server;
993}
994
Craig Tillerbaa14a92017-11-03 09:09:36 -0700995static int streq(const char* a, const char* b) {
Craig Tiller4782d922017-11-10 09:53:21 -0800996 if (a == nullptr && b == nullptr) return 1;
997 if (a == nullptr) return 0;
998 if (b == nullptr) return 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700999 return 0 == strcmp(a, b);
Craig Tiller24be0f72015-02-10 14:04:22 -08001000}
1001
Craig Tillerbaa14a92017-11-03 09:09:36 -07001002void* grpc_server_register_method(
1003 grpc_server* server, const char* method, const char* host,
Craig Tiller06cb1a92016-04-04 08:10:47 -07001004 grpc_server_register_method_payload_handling payload_handling,
1005 uint32_t flags) {
Craig Tillerbaa14a92017-11-03 09:09:36 -07001006 registered_method* m;
Craig Tillerb2906862016-03-10 06:50:07 -08001007 GRPC_API_TRACE(
1008 "grpc_server_register_method(server=%p, method=%s, host=%s, "
1009 "flags=0x%08x)",
1010 4, (server, method, host, flags));
Craig Tillera82950e2015-09-22 12:33:20 -07001011 if (!method) {
1012 gpr_log(GPR_ERROR,
1013 "grpc_server_register_method method string cannot be NULL");
Craig Tiller4782d922017-11-10 09:53:21 -08001014 return nullptr;
Craig Tillera82950e2015-09-22 12:33:20 -07001015 }
1016 for (m = server->registered_methods; m; m = m->next) {
1017 if (streq(m->method, method) && streq(m->host, host)) {
1018 gpr_log(GPR_ERROR, "duplicate registration for %s@%s", method,
1019 host ? host : "*");
Craig Tiller4782d922017-11-10 09:53:21 -08001020 return nullptr;
Craig Tiller24be0f72015-02-10 14:04:22 -08001021 }
Craig Tillera82950e2015-09-22 12:33:20 -07001022 }
Craig Tillerb2906862016-03-10 06:50:07 -08001023 if ((flags & ~GRPC_INITIAL_METADATA_USED_MASK) != 0) {
1024 gpr_log(GPR_ERROR, "grpc_server_register_method invalid flags 0x%08x",
1025 flags);
Craig Tiller4782d922017-11-10 09:53:21 -08001026 return nullptr;
Craig Tillerb2906862016-03-10 06:50:07 -08001027 }
Craig Tillerbaa14a92017-11-03 09:09:36 -07001028 m = (registered_method*)gpr_zalloc(sizeof(registered_method));
Craig Tillera82950e2015-09-22 12:33:20 -07001029 m->method = gpr_strdup(method);
1030 m->host = gpr_strdup(host);
Craig Tiller24be0f72015-02-10 14:04:22 -08001031 m->next = server->registered_methods;
Craig Tiller5ada3d22016-04-04 08:30:59 -07001032 m->payload_handling = payload_handling;
Craig Tillerb2906862016-03-10 06:50:07 -08001033 m->flags = flags;
Craig Tiller24be0f72015-02-10 14:04:22 -08001034 server->registered_methods = m;
1035 return m;
1036}
1037
Craig Tillerbaa14a92017-11-03 09:09:36 -07001038static void start_listeners(grpc_exec_ctx* exec_ctx, void* s,
1039 grpc_error* error) {
1040 grpc_server* server = (grpc_server*)s;
1041 for (listener* l = server->listeners; l; l = l->next) {
Craig Tiller9d9313c2017-04-11 15:05:46 -07001042 l->start(exec_ctx, server, l->arg, server->pollsets, server->pollset_count);
1043 }
Craig Tillerbd3cc402017-04-12 08:06:44 -07001044
1045 gpr_mu_lock(&server->mu_global);
1046 server->starting = false;
1047 gpr_cv_signal(&server->starting_cv);
1048 gpr_mu_unlock(&server->mu_global);
1049
Craig Tiller9d9313c2017-04-11 15:05:46 -07001050 server_unref(exec_ctx, server);
1051}
1052
Craig Tillerbaa14a92017-11-03 09:09:36 -07001053void grpc_server_start(grpc_server* server) {
Craig Tiller20bc56d2015-02-12 09:02:56 -08001054 size_t i;
Craig Tillerf5768a62015-09-22 10:54:34 -07001055 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Craig Tiller20bc56d2015-02-12 09:02:56 -08001056
Masood Malekghassemi76c3d742015-08-19 18:22:53 -07001057 GRPC_API_TRACE("grpc_server_start(server=%p)", 1, (server));
1058
Craig Tiller88ef00e2016-05-17 09:31:49 -07001059 server->started = true;
Craig Tiller1d0fce92016-10-26 08:26:22 -07001060 server->pollset_count = 0;
Yash Tibrewalca3c1c02017-09-07 22:47:16 -07001061 server->pollsets =
Craig Tillerbaa14a92017-11-03 09:09:36 -07001062 (grpc_pollset**)gpr_malloc(sizeof(grpc_pollset*) * server->cq_count);
Craig Tillera82950e2015-09-22 12:33:20 -07001063 for (i = 0; i < server->cq_count; i++) {
Craig Tiller11c58322017-04-12 08:21:17 -07001064 if (grpc_cq_can_listen(server->cqs[i])) {
1065 server->pollsets[server->pollset_count++] =
1066 grpc_cq_pollset(server->cqs[i]);
Craig Tiller509b30e2016-05-21 12:32:39 -07001067 }
Craig Tillerdb7c3562016-05-19 11:02:52 -07001068 }
Ken Paysone1533572017-11-07 11:27:02 -08001069 request_matcher_init(&server->unregistered_request_matcher, server);
Craig Tillerbaa14a92017-11-03 09:09:36 -07001070 for (registered_method* rm = server->registered_methods; rm; rm = rm->next) {
Ken Paysone1533572017-11-07 11:27:02 -08001071 request_matcher_init(&rm->matcher, server);
Craig Tillera82950e2015-09-22 12:33:20 -07001072 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001073
Craig Tiller9d9313c2017-04-11 15:05:46 -07001074 server_ref(server);
Craig Tillerbd3cc402017-04-12 08:06:44 -07001075 server->starting = true;
Craig Tiller7a82afd2017-07-18 09:40:40 -07001076 GRPC_CLOSURE_SCHED(
1077 &exec_ctx,
1078 GRPC_CLOSURE_CREATE(start_listeners, server,
1079 grpc_executor_scheduler(GRPC_EXECUTOR_SHORT)),
1080 GRPC_ERROR_NONE);
Craig Tillerdfff1b82015-09-21 14:39:57 -07001081
Craig Tillera82950e2015-09-22 12:33:20 -07001082 grpc_exec_ctx_finish(&exec_ctx);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001083}
1084
Craig Tillerbaa14a92017-11-03 09:09:36 -07001085void grpc_server_get_pollsets(grpc_server* server, grpc_pollset*** pollsets,
1086 size_t* pollset_count) {
Craig Tiller1d0fce92016-10-26 08:26:22 -07001087 *pollset_count = server->pollset_count;
Sree Kuchibhotlacc357bf2016-08-22 16:08:50 -07001088 *pollsets = server->pollsets;
1089}
1090
Craig Tillerbaa14a92017-11-03 09:09:36 -07001091void grpc_server_setup_transport(grpc_exec_ctx* exec_ctx, grpc_server* s,
1092 grpc_transport* transport,
1093 grpc_pollset* accepting_pollset,
1094 const grpc_channel_args* args) {
Craig Tiller04cc8be2015-02-10 16:11:22 -08001095 size_t num_registered_methods;
1096 size_t alloc;
Craig Tillerbaa14a92017-11-03 09:09:36 -07001097 registered_method* rm;
1098 channel_registered_method* crm;
1099 grpc_channel* channel;
1100 channel_data* chand;
Craig Tiller7536af02015-12-22 13:49:30 -08001101 uint32_t hash;
Craig Tillerf96dfc32015-09-10 14:43:18 -07001102 size_t slots;
Craig Tiller7536af02015-12-22 13:49:30 -08001103 uint32_t probes;
1104 uint32_t max_probes = 0;
Craig Tiller4782d922017-11-10 09:53:21 -08001105 grpc_transport_op* op = nullptr;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001106
Craig Tillerbe98d242017-11-10 15:26:57 -08001107 channel = grpc_channel_create(exec_ctx, nullptr, args, GRPC_SERVER_CHANNEL,
1108 transport);
Craig Tillerbaa14a92017-11-03 09:09:36 -07001109 chand = (channel_data*)grpc_channel_stack_element(
Craig Tillerf40df232016-03-25 13:38:14 -07001110 grpc_channel_get_channel_stack(channel), 0)
1111 ->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001112 chand->server = s;
Craig Tillera82950e2015-09-22 12:33:20 -07001113 server_ref(s);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001114 chand->channel = channel;
1115
Craig Tiller9f9d4222016-05-16 17:02:14 -07001116 size_t cq_idx;
Craig Tiller9f9d4222016-05-16 17:02:14 -07001117 for (cq_idx = 0; cq_idx < s->cq_count; cq_idx++) {
Craig Tillerbe290852017-06-01 12:42:09 -07001118 if (grpc_cq_pollset(s->cqs[cq_idx]) == accepting_pollset) break;
Craig Tiller9f9d4222016-05-16 17:02:14 -07001119 }
1120 if (cq_idx == s->cq_count) {
1121 /* completion queue not found: pick a random one to publish new calls to */
1122 cq_idx = (size_t)rand() % s->cq_count;
1123 }
1124 chand->cq_idx = cq_idx;
1125
Craig Tiller04cc8be2015-02-10 16:11:22 -08001126 num_registered_methods = 0;
Craig Tillera82950e2015-09-22 12:33:20 -07001127 for (rm = s->registered_methods; rm; rm = rm->next) {
1128 num_registered_methods++;
1129 }
Craig Tiller04cc8be2015-02-10 16:11:22 -08001130 /* build a lookup table phrased in terms of mdstr's in this channels context
1131 to quickly find registered methods */
Craig Tillera82950e2015-09-22 12:33:20 -07001132 if (num_registered_methods > 0) {
1133 slots = 2 * num_registered_methods;
1134 alloc = sizeof(channel_registered_method) * slots;
Craig Tillerbaa14a92017-11-03 09:09:36 -07001135 chand->registered_methods = (channel_registered_method*)gpr_zalloc(alloc);
Craig Tillera82950e2015-09-22 12:33:20 -07001136 for (rm = s->registered_methods; rm; rm = rm->next) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001137 grpc_slice host;
1138 bool has_host;
1139 grpc_slice method;
Craig Tiller4782d922017-11-10 09:53:21 -08001140 if (rm->host != nullptr) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001141 host = grpc_slice_intern(grpc_slice_from_static_string(rm->host));
1142 has_host = true;
1143 } else {
1144 has_host = false;
1145 }
1146 method = grpc_slice_intern(grpc_slice_from_static_string(rm->method));
1147 hash = GRPC_MDSTR_KV_HASH(has_host ? grpc_slice_hash(host) : 0,
1148 grpc_slice_hash(method));
Craig Tillera82950e2015-09-22 12:33:20 -07001149 for (probes = 0; chand->registered_methods[(hash + probes) % slots]
Craig Tiller4782d922017-11-10 09:53:21 -08001150 .server_registered_method != nullptr;
Craig Tillera82950e2015-09-22 12:33:20 -07001151 probes++)
1152 ;
1153 if (probes > max_probes) max_probes = probes;
1154 crm = &chand->registered_methods[(hash + probes) % slots];
1155 crm->server_registered_method = rm;
Craig Tillerb2906862016-03-10 06:50:07 -08001156 crm->flags = rm->flags;
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001157 crm->has_host = has_host;
Eduardo Caceresa2b0e562017-02-21 20:33:40 +01001158 if (has_host) {
Eduardo Cáceres de la Calleca468792017-02-20 18:42:17 +01001159 crm->host = host;
1160 }
Craig Tillera82950e2015-09-22 12:33:20 -07001161 crm->method = method;
Craig Tiller04cc8be2015-02-10 16:11:22 -08001162 }
Craig Tiller7536af02015-12-22 13:49:30 -08001163 GPR_ASSERT(slots <= UINT32_MAX);
1164 chand->registered_method_slots = (uint32_t)slots;
Craig Tillera82950e2015-09-22 12:33:20 -07001165 chand->registered_method_max_probes = max_probes;
1166 }
Craig Tiller04cc8be2015-02-10 16:11:22 -08001167
Craig Tillera82950e2015-09-22 12:33:20 -07001168 gpr_mu_lock(&s->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001169 chand->next = &s->root_channel_data;
1170 chand->prev = chand->next->prev;
1171 chand->next->prev = chand->prev->next = chand;
Craig Tillera82950e2015-09-22 12:33:20 -07001172 gpr_mu_unlock(&s->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001173
Craig Tillera82950e2015-09-22 12:33:20 -07001174 GRPC_CHANNEL_INTERNAL_REF(channel, "connectivity");
Craig Tiller4782d922017-11-10 09:53:21 -08001175 op = grpc_make_transport_op(nullptr);
Craig Tillere0221ff2016-07-11 15:56:08 -07001176 op->set_accept_stream = true;
1177 op->set_accept_stream_fn = accept_stream;
1178 op->set_accept_stream_user_data = chand;
1179 op->on_connectivity_state_change = &chand->channel_connectivity_changed;
1180 op->connectivity_state = &chand->connectivity_state;
Craig Tiller804ff712016-05-05 16:25:40 -07001181 if (gpr_atm_acq_load(&s->shutdown_flag) != 0) {
ncteisen4b36a3d2017-03-13 19:08:06 -07001182 op->disconnect_with_error =
1183 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Server shutdown");
Craig Tiller804ff712016-05-05 16:25:40 -07001184 }
Craig Tillere0221ff2016-07-11 15:56:08 -07001185 grpc_transport_perform_op(exec_ctx, transport, op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001186}
1187
Craig Tillerbaa14a92017-11-03 09:09:36 -07001188void done_published_shutdown(grpc_exec_ctx* exec_ctx, void* done_arg,
1189 grpc_cq_completion* storage) {
Craig Tillera82950e2015-09-22 12:33:20 -07001190 (void)done_arg;
1191 gpr_free(storage);
murgatroid9900a3dab2015-08-19 11:15:38 -07001192}
1193
Craig Tillerbaa14a92017-11-03 09:09:36 -07001194static void listener_destroy_done(grpc_exec_ctx* exec_ctx, void* s,
1195 grpc_error* error) {
1196 grpc_server* server = (grpc_server*)s;
Craig Tillera82950e2015-09-22 12:33:20 -07001197 gpr_mu_lock(&server->mu_global);
Craig Tillerdfff1b82015-09-21 14:39:57 -07001198 server->listeners_destroyed++;
Craig Tillera82950e2015-09-22 12:33:20 -07001199 maybe_finish_shutdown(exec_ctx, server);
1200 gpr_mu_unlock(&server->mu_global);
Craig Tillerdfff1b82015-09-21 14:39:57 -07001201}
1202
Craig Tillerbaa14a92017-11-03 09:09:36 -07001203void grpc_server_shutdown_and_notify(grpc_server* server,
1204 grpc_completion_queue* cq, void* tag) {
1205 listener* l;
1206 shutdown_tag* sdt;
Craig Tillerff3ae682015-06-29 17:44:04 -07001207 channel_broadcaster broadcaster;
Craig Tillerf5768a62015-09-22 10:54:34 -07001208 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001209
Masood Malekghassemi76c3d742015-08-19 18:22:53 -07001210 GRPC_API_TRACE("grpc_server_shutdown_and_notify(server=%p, cq=%p, tag=%p)", 3,
1211 (server, cq, tag));
1212
Craig Tillerbd3cc402017-04-12 08:06:44 -07001213 /* wait for startup to be finished: locks mu_global */
Craig Tillera82950e2015-09-22 12:33:20 -07001214 gpr_mu_lock(&server->mu_global);
Craig Tillerbd3cc402017-04-12 08:06:44 -07001215 while (server->starting) {
1216 gpr_cv_wait(&server->starting_cv, &server->mu_global,
1217 gpr_inf_future(GPR_CLOCK_REALTIME));
1218 }
1219
1220 /* stay locked, and gather up some stuff to do */
yang-g7d6b9142017-07-13 11:48:56 -07001221 GPR_ASSERT(grpc_cq_begin_op(cq, tag));
Craig Tillera82950e2015-09-22 12:33:20 -07001222 if (server->shutdown_published) {
Craig Tillerbaa14a92017-11-03 09:09:36 -07001223 grpc_cq_end_op(&exec_ctx, cq, tag, GRPC_ERROR_NONE, done_published_shutdown,
Craig Tiller4782d922017-11-10 09:53:21 -08001224 nullptr,
Craig Tillerbaa14a92017-11-03 09:09:36 -07001225 (grpc_cq_completion*)gpr_malloc(sizeof(grpc_cq_completion)));
Craig Tillera82950e2015-09-22 12:33:20 -07001226 gpr_mu_unlock(&server->mu_global);
1227 goto done;
1228 }
Craig Tillerbaa14a92017-11-03 09:09:36 -07001229 server->shutdown_tags = (shutdown_tag*)gpr_realloc(
Yash Tibrewalca3c1c02017-09-07 22:47:16 -07001230 server->shutdown_tags,
1231 sizeof(shutdown_tag) * (server->num_shutdown_tags + 1));
Craig Tillerbce999f2015-05-27 09:55:51 -07001232 sdt = &server->shutdown_tags[server->num_shutdown_tags++];
1233 sdt->tag = tag;
1234 sdt->cq = cq;
Craig Tillera82950e2015-09-22 12:33:20 -07001235 if (gpr_atm_acq_load(&server->shutdown_flag)) {
1236 gpr_mu_unlock(&server->mu_global);
1237 goto done;
1238 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001239
Craig Tillera82950e2015-09-22 12:33:20 -07001240 server->last_shutdown_message_time = gpr_now(GPR_CLOCK_REALTIME);
Craig Tillerab54f792015-07-08 08:34:20 -07001241
Craig Tillera82950e2015-09-22 12:33:20 -07001242 channel_broadcaster_init(server, &broadcaster);
nnoble0c475f02014-12-05 15:37:39 -08001243
Craig Tillerfc193e12015-09-24 15:29:03 -07001244 gpr_atm_rel_store(&server->shutdown_flag, 1);
1245
Craig Tillerbd217572015-02-11 18:10:56 -08001246 /* collect all unregistered then registered calls */
Craig Tillera82950e2015-09-22 12:33:20 -07001247 gpr_mu_lock(&server->mu_call);
ncteisen4b36a3d2017-03-13 19:08:06 -07001248 kill_pending_work_locked(
1249 &exec_ctx, server,
1250 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Server Shutdown"));
Craig Tillera82950e2015-09-22 12:33:20 -07001251 gpr_mu_unlock(&server->mu_call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001252
Craig Tillera82950e2015-09-22 12:33:20 -07001253 maybe_finish_shutdown(&exec_ctx, server);
1254 gpr_mu_unlock(&server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001255
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001256 /* Shutdown listeners */
Craig Tillera82950e2015-09-22 12:33:20 -07001257 for (l = server->listeners; l; l = l->next) {
ncteisen274bbbe2017-06-08 14:57:11 -07001258 GRPC_CLOSURE_INIT(&l->destroy_done, listener_destroy_done, server,
Craig Tiller91031da2016-12-28 15:44:25 -08001259 grpc_schedule_on_exec_ctx);
Craig Tillera82950e2015-09-22 12:33:20 -07001260 l->destroy(&exec_ctx, server, l->arg, &l->destroy_done);
1261 }
Craig Tillerff3ae682015-06-29 17:44:04 -07001262
Mark D. Roth7f8db252016-06-24 08:24:15 -07001263 channel_broadcaster_shutdown(&exec_ctx, &broadcaster, true /* send_goaway */,
Mark D. Roth89ebe552016-06-29 07:50:18 -07001264 GRPC_ERROR_NONE);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001265
Craig Tillerdfff1b82015-09-21 14:39:57 -07001266done:
Craig Tillera82950e2015-09-22 12:33:20 -07001267 grpc_exec_ctx_finish(&exec_ctx);
Craig Tilleraec96aa2015-04-07 14:32:15 -07001268}
1269
Craig Tillerbaa14a92017-11-03 09:09:36 -07001270void grpc_server_cancel_all_calls(grpc_server* server) {
Craig Tiller092d8d12015-07-04 22:35:00 -07001271 channel_broadcaster broadcaster;
Craig Tillerf5768a62015-09-22 10:54:34 -07001272 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Craig Tillerafa2d632015-05-26 16:39:13 -07001273
Masood Malekghassemi76c3d742015-08-19 18:22:53 -07001274 GRPC_API_TRACE("grpc_server_cancel_all_calls(server=%p)", 1, (server));
1275
Craig Tillera82950e2015-09-22 12:33:20 -07001276 gpr_mu_lock(&server->mu_global);
1277 channel_broadcaster_init(server, &broadcaster);
1278 gpr_mu_unlock(&server->mu_global);
Craig Tillerafa2d632015-05-26 16:39:13 -07001279
ncteisen4b36a3d2017-03-13 19:08:06 -07001280 channel_broadcaster_shutdown(
1281 &exec_ctx, &broadcaster, false /* send_goaway */,
1282 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Cancelling all calls"));
Craig Tillera82950e2015-09-22 12:33:20 -07001283 grpc_exec_ctx_finish(&exec_ctx);
Craig Tillerafa2d632015-05-26 16:39:13 -07001284}
1285
Craig Tillerbaa14a92017-11-03 09:09:36 -07001286void grpc_server_destroy(grpc_server* server) {
1287 listener* l;
Craig Tillerf5768a62015-09-22 10:54:34 -07001288 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Craig Tiller872af022015-04-24 15:57:52 -07001289
Masood Malekghassemi76c3d742015-08-19 18:22:53 -07001290 GRPC_API_TRACE("grpc_server_destroy(server=%p)", 1, (server));
1291
Craig Tillera82950e2015-09-22 12:33:20 -07001292 gpr_mu_lock(&server->mu_global);
1293 GPR_ASSERT(gpr_atm_acq_load(&server->shutdown_flag) || !server->listeners);
1294 GPR_ASSERT(server->listeners_destroyed == num_listeners(server));
Craig Tilleraec96aa2015-04-07 14:32:15 -07001295
Craig Tillera82950e2015-09-22 12:33:20 -07001296 while (server->listeners) {
1297 l = server->listeners;
1298 server->listeners = l->next;
1299 gpr_free(l);
1300 }
Craig Tilleraec96aa2015-04-07 14:32:15 -07001301
Craig Tillera82950e2015-09-22 12:33:20 -07001302 gpr_mu_unlock(&server->mu_global);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001303
Craig Tillera82950e2015-09-22 12:33:20 -07001304 server_unref(&exec_ctx, server);
1305 grpc_exec_ctx_finish(&exec_ctx);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001306}
1307
Craig Tillera82950e2015-09-22 12:33:20 -07001308void grpc_server_add_listener(
Craig Tillerbaa14a92017-11-03 09:09:36 -07001309 grpc_exec_ctx* exec_ctx, grpc_server* server, void* arg,
1310 void (*start)(grpc_exec_ctx* exec_ctx, grpc_server* server, void* arg,
1311 grpc_pollset** pollsets, size_t pollset_count),
1312 void (*destroy)(grpc_exec_ctx* exec_ctx, grpc_server* server, void* arg,
1313 grpc_closure* on_done)) {
1314 listener* l = (listener*)gpr_malloc(sizeof(listener));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001315 l->arg = arg;
1316 l->start = start;
1317 l->destroy = destroy;
1318 l->next = server->listeners;
1319 server->listeners = l;
1320}
1321
Craig Tillerbaa14a92017-11-03 09:09:36 -07001322static grpc_call_error queue_call_request(grpc_exec_ctx* exec_ctx,
1323 grpc_server* server, size_t cq_idx,
1324 requested_call* rc) {
Craig Tiller4782d922017-11-10 09:53:21 -08001325 call_data* calld = nullptr;
1326 request_matcher* rm = nullptr;
Craig Tillera82950e2015-09-22 12:33:20 -07001327 if (gpr_atm_acq_load(&server->shutdown_flag)) {
Craig Tiller48abdde2016-05-24 06:55:28 -07001328 fail_call(exec_ctx, server, cq_idx, rc,
ncteisen4b36a3d2017-03-13 19:08:06 -07001329 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Server Shutdown"));
Craig Tillera82950e2015-09-22 12:33:20 -07001330 return GRPC_CALL_OK;
1331 }
Craig Tillera82950e2015-09-22 12:33:20 -07001332 switch (rc->type) {
Craig Tiller04cc8be2015-02-10 16:11:22 -08001333 case BATCH_CALL:
Craig Tillerb9d35962015-09-11 13:31:16 -07001334 rm = &server->unregistered_request_matcher;
Craig Tiller04cc8be2015-02-10 16:11:22 -08001335 break;
1336 case REGISTERED_CALL:
Yash Tibrewala4952202017-09-13 10:53:28 -07001337 rm = &rc->data.registered.method->matcher;
Craig Tiller04cc8be2015-02-10 16:11:22 -08001338 break;
Craig Tillera82950e2015-09-22 12:33:20 -07001339 }
Ken Paysone1533572017-11-07 11:27:02 -08001340 if (gpr_locked_mpscq_push(&rm->requests_per_cq[cq_idx], &rc->request_link)) {
Craig Tillera82950e2015-09-22 12:33:20 -07001341 /* this was the first queued request: we need to lock and start
1342 matching calls */
1343 gpr_mu_lock(&server->mu_call);
Craig Tiller4782d922017-11-10 09:53:21 -08001344 while ((calld = rm->pending_head) != nullptr) {
Ken Paysone1533572017-11-07 11:27:02 -08001345 rc = (requested_call*)gpr_locked_mpscq_pop(&rm->requests_per_cq[cq_idx]);
Craig Tiller4782d922017-11-10 09:53:21 -08001346 if (rc == nullptr) break;
Craig Tillerb9d35962015-09-11 13:31:16 -07001347 rm->pending_head = calld->pending_next;
Craig Tillera82950e2015-09-22 12:33:20 -07001348 gpr_mu_unlock(&server->mu_call);
Ken Paysone1533572017-11-07 11:27:02 -08001349 if (!gpr_atm_full_cas(&calld->state, PENDING, ACTIVATED)) {
1350 // Zombied Call
ncteisen274bbbe2017-06-08 14:57:11 -07001351 GRPC_CLOSURE_INIT(
Craig Tillera82950e2015-09-22 12:33:20 -07001352 &calld->kill_zombie_closure, kill_zombie,
Craig Tiller91031da2016-12-28 15:44:25 -08001353 grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0),
1354 grpc_schedule_on_exec_ctx);
ncteisen274bbbe2017-06-08 14:57:11 -07001355 GRPC_CLOSURE_SCHED(exec_ctx, &calld->kill_zombie_closure,
Craig Tiller91031da2016-12-28 15:44:25 -08001356 GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -07001357 } else {
Ken Paysone1533572017-11-07 11:27:02 -08001358 publish_call(exec_ctx, server, calld, cq_idx, rc);
Craig Tillera82950e2015-09-22 12:33:20 -07001359 }
1360 gpr_mu_lock(&server->mu_call);
Craig Tiller45724b32015-09-22 10:42:19 -07001361 }
Craig Tillera82950e2015-09-22 12:33:20 -07001362 gpr_mu_unlock(&server->mu_call);
1363 }
Craig Tiller6a006ce2015-07-13 16:25:40 -07001364 return GRPC_CALL_OK;
Craig Tillercce17ac2015-01-20 09:29:28 -08001365}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001366
Craig Tillera82950e2015-09-22 12:33:20 -07001367grpc_call_error grpc_server_request_call(
Craig Tillerbaa14a92017-11-03 09:09:36 -07001368 grpc_server* server, grpc_call** call, grpc_call_details* details,
1369 grpc_metadata_array* initial_metadata,
1370 grpc_completion_queue* cq_bound_to_call,
1371 grpc_completion_queue* cq_for_notification, void* tag) {
Craig Tillerdfff1b82015-09-21 14:39:57 -07001372 grpc_call_error error;
Craig Tillerf5768a62015-09-22 10:54:34 -07001373 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Craig Tillerbaa14a92017-11-03 09:09:36 -07001374 requested_call* rc = (requested_call*)gpr_malloc(sizeof(*rc));
Craig Tiller561dc322017-09-05 13:00:46 -07001375 GRPC_STATS_INC_SERVER_REQUESTED_CALLS(&exec_ctx);
Masood Malekghassemi76c3d742015-08-19 18:22:53 -07001376 GRPC_API_TRACE(
1377 "grpc_server_request_call("
Craig Tiller4de3e4f2015-10-05 08:55:50 -07001378 "server=%p, call=%p, details=%p, initial_metadata=%p, "
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001379 "cq_bound_to_call=%p, cq_for_notification=%p, tag=%p)",
Craig Tillerbaa14a92017-11-03 09:09:36 -07001380 7,
1381 (server, call, details, initial_metadata, cq_bound_to_call,
1382 cq_for_notification, tag));
Craig Tiller9f9d4222016-05-16 17:02:14 -07001383 size_t cq_idx;
1384 for (cq_idx = 0; cq_idx < server->cq_count; cq_idx++) {
1385 if (server->cqs[cq_idx] == cq_for_notification) {
1386 break;
1387 }
1388 }
1389 if (cq_idx == server->cq_count) {
Craig Tillera82950e2015-09-22 12:33:20 -07001390 gpr_free(rc);
1391 error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
1392 goto done;
1393 }
yang-g7d6b9142017-07-13 11:48:56 -07001394 if (grpc_cq_begin_op(cq_for_notification, tag) == false) {
yang-g0eaf7de2017-07-05 16:50:51 -07001395 gpr_free(rc);
1396 error = GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN;
1397 goto done;
1398 }
Craig Tiller4782d922017-11-10 09:53:21 -08001399 details->reserved = nullptr;
Craig Tillerb19dbea2016-07-12 15:33:11 -07001400 rc->cq_idx = cq_idx;
Craig Tiller97fc6a32015-07-08 15:31:35 -07001401 rc->type = BATCH_CALL;
Craig Tiller6a006ce2015-07-13 16:25:40 -07001402 rc->server = server;
Craig Tiller97fc6a32015-07-08 15:31:35 -07001403 rc->tag = tag;
1404 rc->cq_bound_to_call = cq_bound_to_call;
Craig Tiller97fc6a32015-07-08 15:31:35 -07001405 rc->call = call;
1406 rc->data.batch.details = details;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001407 rc->initial_metadata = initial_metadata;
Craig Tiller9f9d4222016-05-16 17:02:14 -07001408 error = queue_call_request(&exec_ctx, server, cq_idx, rc);
Craig Tillerdfff1b82015-09-21 14:39:57 -07001409done:
Craig Tillera82950e2015-09-22 12:33:20 -07001410 grpc_exec_ctx_finish(&exec_ctx);
Craig Tillerdfff1b82015-09-21 14:39:57 -07001411 return error;
Craig Tiller24be0f72015-02-10 14:04:22 -08001412}
1413
Craig Tillera82950e2015-09-22 12:33:20 -07001414grpc_call_error grpc_server_request_registered_call(
Craig Tillerbaa14a92017-11-03 09:09:36 -07001415 grpc_server* server, void* rmp, grpc_call** call, gpr_timespec* deadline,
1416 grpc_metadata_array* initial_metadata, grpc_byte_buffer** optional_payload,
1417 grpc_completion_queue* cq_bound_to_call,
1418 grpc_completion_queue* cq_for_notification, void* tag) {
Craig Tillerdfff1b82015-09-21 14:39:57 -07001419 grpc_call_error error;
Craig Tillerf5768a62015-09-22 10:54:34 -07001420 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Craig Tillerbaa14a92017-11-03 09:09:36 -07001421 requested_call* rc = (requested_call*)gpr_malloc(sizeof(*rc));
1422 registered_method* rm = (registered_method*)rmp;
Craig Tiller561dc322017-09-05 13:00:46 -07001423 GRPC_STATS_INC_SERVER_REQUESTED_CALLS(&exec_ctx);
Masood Malekghassemi76c3d742015-08-19 18:22:53 -07001424 GRPC_API_TRACE(
1425 "grpc_server_request_registered_call("
Craig Tiller4de3e4f2015-10-05 08:55:50 -07001426 "server=%p, rmp=%p, call=%p, deadline=%p, initial_metadata=%p, "
1427 "optional_payload=%p, cq_bound_to_call=%p, cq_for_notification=%p, "
1428 "tag=%p)",
Craig Tillerbaa14a92017-11-03 09:09:36 -07001429 9,
1430 (server, rmp, call, deadline, initial_metadata, optional_payload,
1431 cq_bound_to_call, cq_for_notification, tag));
Craig Tiller9f9d4222016-05-16 17:02:14 -07001432
1433 size_t cq_idx;
1434 for (cq_idx = 0; cq_idx < server->cq_count; cq_idx++) {
1435 if (server->cqs[cq_idx] == cq_for_notification) {
1436 break;
1437 }
1438 }
1439 if (cq_idx == server->cq_count) {
Craig Tillera82950e2015-09-22 12:33:20 -07001440 gpr_free(rc);
1441 error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
1442 goto done;
1443 }
Craig Tiller4782d922017-11-10 09:53:21 -08001444 if ((optional_payload == nullptr) !=
Craig Tiller06cb1a92016-04-04 08:10:47 -07001445 (rm->payload_handling == GRPC_SRM_PAYLOAD_NONE)) {
1446 gpr_free(rc);
1447 error = GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH;
1448 goto done;
1449 }
yang-g7d6b9142017-07-13 11:48:56 -07001450 if (grpc_cq_begin_op(cq_for_notification, tag) == false) {
yang-g0eaf7de2017-07-05 16:50:51 -07001451 gpr_free(rc);
1452 error = GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN;
1453 goto done;
1454 }
Craig Tillerb19dbea2016-07-12 15:33:11 -07001455 rc->cq_idx = cq_idx;
Craig Tiller97fc6a32015-07-08 15:31:35 -07001456 rc->type = REGISTERED_CALL;
Craig Tiller6a006ce2015-07-13 16:25:40 -07001457 rc->server = server;
Craig Tiller97fc6a32015-07-08 15:31:35 -07001458 rc->tag = tag;
1459 rc->cq_bound_to_call = cq_bound_to_call;
Craig Tiller97fc6a32015-07-08 15:31:35 -07001460 rc->call = call;
Yash Tibrewala4952202017-09-13 10:53:28 -07001461 rc->data.registered.method = rm;
Craig Tiller97fc6a32015-07-08 15:31:35 -07001462 rc->data.registered.deadline = deadline;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001463 rc->initial_metadata = initial_metadata;
Craig Tiller97fc6a32015-07-08 15:31:35 -07001464 rc->data.registered.optional_payload = optional_payload;
Craig Tiller9f9d4222016-05-16 17:02:14 -07001465 error = queue_call_request(&exec_ctx, server, cq_idx, rc);
Craig Tillerdfff1b82015-09-21 14:39:57 -07001466done:
Craig Tillera82950e2015-09-22 12:33:20 -07001467 grpc_exec_ctx_finish(&exec_ctx);
Craig Tillerdfff1b82015-09-21 14:39:57 -07001468 return error;
Craig Tiller24be0f72015-02-10 14:04:22 -08001469}
1470
Craig Tillerbaa14a92017-11-03 09:09:36 -07001471static void fail_call(grpc_exec_ctx* exec_ctx, grpc_server* server,
1472 size_t cq_idx, requested_call* rc, grpc_error* error) {
Craig Tiller4782d922017-11-10 09:53:21 -08001473 *rc->call = nullptr;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001474 rc->initial_metadata->count = 0;
Craig Tillercae4b1b2016-05-10 09:11:09 -07001475 GPR_ASSERT(error != GRPC_ERROR_NONE);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001476
Craig Tiller48abdde2016-05-24 06:55:28 -07001477 grpc_cq_end_op(exec_ctx, server->cqs[cq_idx], rc->tag, error,
Craig Tillera82950e2015-09-22 12:33:20 -07001478 done_request_event, rc, &rc->completion);
Craig Tiller24be0f72015-02-10 14:04:22 -08001479}
1480
Craig Tillerbaa14a92017-11-03 09:09:36 -07001481const grpc_channel_args* grpc_server_get_channel_args(grpc_server* server) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001482 return server->channel_args;
Craig Tiller190d3602015-02-18 09:23:38 -08001483}
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001484
Craig Tillerbaa14a92017-11-03 09:09:36 -07001485int grpc_server_has_open_connections(grpc_server* server) {
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001486 int r;
Craig Tillera82950e2015-09-22 12:33:20 -07001487 gpr_mu_lock(&server->mu_global);
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001488 r = server->root_channel_data.next != &server->root_channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -07001489 gpr_mu_unlock(&server->mu_global);
Craig Tillerba3c3cd2015-05-26 06:28:10 -07001490 return r;
1491}