blob: 7ac7f4ece825c702e10b2da5fe430466c1e25729 [file] [log] [blame]
Mark D. Roth71403822016-12-02 10:51:39 -08001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2015 gRPC authors.
Mark D. Roth71403822016-12-02 10:51:39 -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
Mark D. Roth71403822016-12-02 10:51:39 -08008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
Mark D. Roth71403822016-12-02 10:51:39 -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.
Mark D. Roth71403822016-12-02 10:51:39 -080016 *
17 */
18
19#include "src/core/ext/transport/chttp2/server/chttp2_server.h"
20
21#include <grpc/grpc.h>
22
Yash Tibrewalfcd26bc2017-09-25 15:08:28 -070023#include <inttypes.h>
Mark D. Roth71403822016-12-02 10:51:39 -080024#include <string.h>
25
26#include <grpc/support/alloc.h>
27#include <grpc/support/log.h>
28#include <grpc/support/string_util.h>
29#include <grpc/support/sync.h>
30#include <grpc/support/useful.h>
31
Craig Tillere3593d92017-04-03 14:51:02 -070032#include "src/core/ext/filters/http/server/http_server_filter.h"
Mark D. Roth71403822016-12-02 10:51:39 -080033#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
34#include "src/core/lib/channel/channel_args.h"
35#include "src/core/lib/channel/handshaker.h"
Mark D. Roth1f0f23c2017-01-06 13:07:19 -080036#include "src/core/lib/channel/handshaker_registry.h"
Mark D. Roth71403822016-12-02 10:51:39 -080037#include "src/core/lib/iomgr/endpoint.h"
38#include "src/core/lib/iomgr/resolve_address.h"
39#include "src/core/lib/iomgr/tcp_server.h"
Craig Tiller6822a7a2016-12-06 19:28:52 -080040#include "src/core/lib/slice/slice_internal.h"
Mark D. Roth71403822016-12-02 10:51:39 -080041#include "src/core/lib/surface/api_trace.h"
42#include "src/core/lib/surface/server.h"
43
Mark D. Roth71403822016-12-02 10:51:39 -080044typedef struct {
45 grpc_server *server;
46 grpc_tcp_server *tcp_server;
47 grpc_channel_args *args;
Mark D. Roth71403822016-12-02 10:51:39 -080048 gpr_mu mu;
49 bool shutdown;
50 grpc_closure tcp_server_shutdown_complete;
51 grpc_closure *server_destroy_listener_done;
yang-g6da1e852017-02-16 10:34:06 -080052 grpc_handshake_manager *pending_handshake_mgrs;
Mark D. Roth71403822016-12-02 10:51:39 -080053} server_state;
54
55typedef struct {
Yash Tibrewala4952202017-09-13 10:53:28 -070056 server_state *svr_state;
Mark D. Roth71403822016-12-02 10:51:39 -080057 grpc_pollset *accepting_pollset;
58 grpc_tcp_server_acceptor *acceptor;
59 grpc_handshake_manager *handshake_mgr;
60} server_connection_state;
61
Mark D. Roth71403822016-12-02 10:51:39 -080062static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
63 grpc_error *error) {
Yash Tibrewalca3c1c02017-09-07 22:47:16 -070064 grpc_handshaker_args *args = (grpc_handshaker_args *)arg;
65 server_connection_state *connection_state =
66 (server_connection_state *)args->user_data;
Yash Tibrewala4952202017-09-13 10:53:28 -070067 gpr_mu_lock(&connection_state->svr_state->mu);
68 if (error != GRPC_ERROR_NONE || connection_state->svr_state->shutdown) {
Mark D. Roth71403822016-12-02 10:51:39 -080069 const char *error_str = grpc_error_string(error);
David Garcia Quintasc3fc8342017-04-21 15:01:18 -070070 gpr_log(GPR_DEBUG, "Handshaking failed: %s", error_str);
Craig Tiller7c70b6c2017-01-23 07:48:42 -080071
Mark D. Roth0ee1dbb2016-12-09 09:57:20 -080072 if (error == GRPC_ERROR_NONE && args->endpoint != NULL) {
Mark D. Roth71403822016-12-02 10:51:39 -080073 // We were shut down after handshaking completed successfully, so
74 // destroy the endpoint here.
75 // TODO(ctiller): It is currently necessary to shutdown endpoints
76 // before destroying them, even if we know that there are no
77 // pending read/write callbacks. This should be fixed, at which
78 // point this can be removed.
Craig Tillercda759d2017-01-27 11:37:37 -080079 grpc_endpoint_shutdown(exec_ctx, args->endpoint, GRPC_ERROR_NONE);
Mark D. Roth71403822016-12-02 10:51:39 -080080 grpc_endpoint_destroy(exec_ctx, args->endpoint);
Craig Tiller397bff32016-12-06 15:05:59 -080081 grpc_channel_args_destroy(exec_ctx, args->args);
Craig Tiller6822a7a2016-12-06 19:28:52 -080082 grpc_slice_buffer_destroy_internal(exec_ctx, args->read_buffer);
Mark D. Roth71403822016-12-02 10:51:39 -080083 gpr_free(args->read_buffer);
84 }
85 } else {
Mark D. Roth30598282016-12-07 07:13:58 -080086 // If the handshaking succeeded but there is no endpoint, then the
87 // handshaker may have handed off the connection to some external
88 // code, so we can just clean up here without creating a transport.
Mark D. Rothcc527cf2016-12-06 10:43:12 -080089 if (args->endpoint != NULL) {
90 grpc_transport *transport =
91 grpc_create_chttp2_transport(exec_ctx, args->args, args->endpoint, 0);
92 grpc_server_setup_transport(
Yash Tibrewala4952202017-09-13 10:53:28 -070093 exec_ctx, connection_state->svr_state->server, transport,
Mark D. Rothcc527cf2016-12-06 10:43:12 -080094 connection_state->accepting_pollset, args->args);
95 grpc_chttp2_transport_start_reading(exec_ctx, transport,
96 args->read_buffer);
Craig Tiller1a7c57b2016-12-12 06:38:13 -080097 grpc_channel_args_destroy(exec_ctx, args->args);
Mark D. Rothcc527cf2016-12-06 10:43:12 -080098 }
Mark D. Roth71403822016-12-02 10:51:39 -080099 }
yang-g6da1e852017-02-16 10:34:06 -0800100 grpc_handshake_manager_pending_list_remove(
Yash Tibrewala4952202017-09-13 10:53:28 -0700101 &connection_state->svr_state->pending_handshake_mgrs,
yang-g6da1e852017-02-16 10:34:06 -0800102 connection_state->handshake_mgr);
Yash Tibrewala4952202017-09-13 10:53:28 -0700103 gpr_mu_unlock(&connection_state->svr_state->mu);
Mark D. Roth71403822016-12-02 10:51:39 -0800104 grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr);
Yash Tibrewala4952202017-09-13 10:53:28 -0700105 grpc_tcp_server_unref(exec_ctx, connection_state->svr_state->tcp_server);
Mark D. Rotheed38152016-12-08 13:59:13 -0800106 gpr_free(connection_state->acceptor);
Mark D. Roth71403822016-12-02 10:51:39 -0800107 gpr_free(connection_state);
108}
109
110static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
111 grpc_pollset *accepting_pollset,
112 grpc_tcp_server_acceptor *acceptor) {
Yash Tibrewalca3c1c02017-09-07 22:47:16 -0700113 server_state *state = (server_state *)arg;
Mark D. Roth71403822016-12-02 10:51:39 -0800114 gpr_mu_lock(&state->mu);
115 if (state->shutdown) {
116 gpr_mu_unlock(&state->mu);
Makarand Dharmapurikar9c156da2017-05-18 10:32:13 -0700117 grpc_endpoint_shutdown(exec_ctx, tcp, GRPC_ERROR_NONE);
Mark D. Roth71403822016-12-02 10:51:39 -0800118 grpc_endpoint_destroy(exec_ctx, tcp);
Mark D. Roth96ba68d2016-12-09 17:21:26 +0000119 gpr_free(acceptor);
Mark D. Roth71403822016-12-02 10:51:39 -0800120 return;
121 }
122 grpc_handshake_manager *handshake_mgr = grpc_handshake_manager_create();
yang-g6da1e852017-02-16 10:34:06 -0800123 grpc_handshake_manager_pending_list_add(&state->pending_handshake_mgrs,
124 handshake_mgr);
Mark D. Roth71403822016-12-02 10:51:39 -0800125 gpr_mu_unlock(&state->mu);
126 grpc_tcp_server_ref(state->tcp_server);
127 server_connection_state *connection_state =
Yash Tibrewalbc130da2017-09-12 22:44:08 -0700128 (server_connection_state *)gpr_malloc(sizeof(*connection_state));
Yash Tibrewala4952202017-09-13 10:53:28 -0700129 connection_state->svr_state = state;
Mark D. Roth71403822016-12-02 10:51:39 -0800130 connection_state->accepting_pollset = accepting_pollset;
131 connection_state->acceptor = acceptor;
132 connection_state->handshake_mgr = handshake_mgr;
Mark D. Roth1f0f23c2017-01-06 13:07:19 -0800133 grpc_handshakers_add(exec_ctx, HANDSHAKER_SERVER, state->args,
134 connection_state->handshake_mgr);
Mark D. Roth71403822016-12-02 10:51:39 -0800135 // TODO(roth): We should really get this timeout value from channel
136 // args instead of hard-coding it.
Craig Tillerdc3998e2017-05-12 09:55:30 -0700137 const grpc_millis deadline =
138 grpc_exec_ctx_now(exec_ctx) + 120 * GPR_MS_PER_SEC;
Craig Tiller73122ba2016-12-05 08:16:58 -0800139 grpc_handshake_manager_do_handshake(exec_ctx, connection_state->handshake_mgr,
140 tcp, state->args, deadline, acceptor,
141 on_handshake_done, connection_state);
Mark D. Roth71403822016-12-02 10:51:39 -0800142}
143
144/* Server callback: start listening on our ports */
145static void server_start_listener(grpc_exec_ctx *exec_ctx, grpc_server *server,
146 void *arg, grpc_pollset **pollsets,
147 size_t pollset_count) {
Yash Tibrewalca3c1c02017-09-07 22:47:16 -0700148 server_state *state = (server_state *)arg;
Mark D. Roth71403822016-12-02 10:51:39 -0800149 gpr_mu_lock(&state->mu);
150 state->shutdown = false;
151 gpr_mu_unlock(&state->mu);
152 grpc_tcp_server_start(exec_ctx, state->tcp_server, pollsets, pollset_count,
153 on_accept, state);
154}
155
156static void tcp_server_shutdown_complete(grpc_exec_ctx *exec_ctx, void *arg,
157 grpc_error *error) {
Yash Tibrewalca3c1c02017-09-07 22:47:16 -0700158 server_state *state = (server_state *)arg;
Mark D. Roth71403822016-12-02 10:51:39 -0800159 /* ensure all threads have unlocked */
160 gpr_mu_lock(&state->mu);
161 grpc_closure *destroy_done = state->server_destroy_listener_done;
162 GPR_ASSERT(state->shutdown);
yang-g6da1e852017-02-16 10:34:06 -0800163 grpc_handshake_manager_pending_list_shutdown_all(
164 exec_ctx, state->pending_handshake_mgrs, GRPC_ERROR_REF(error));
Mark D. Roth71403822016-12-02 10:51:39 -0800165 gpr_mu_unlock(&state->mu);
166 // Flush queued work before destroying handshaker factory, since that
167 // may do a synchronous unref.
168 grpc_exec_ctx_flush(exec_ctx);
Mark D. Roth71403822016-12-02 10:51:39 -0800169 if (destroy_done != NULL) {
170 destroy_done->cb(exec_ctx, destroy_done->cb_arg, GRPC_ERROR_REF(error));
171 grpc_exec_ctx_flush(exec_ctx);
172 }
Craig Tiller397bff32016-12-06 15:05:59 -0800173 grpc_channel_args_destroy(exec_ctx, state->args);
Mark D. Roth71403822016-12-02 10:51:39 -0800174 gpr_mu_destroy(&state->mu);
175 gpr_free(state);
176}
177
178/* Server callback: destroy the tcp listener (so we don't generate further
179 callbacks) */
180static void server_destroy_listener(grpc_exec_ctx *exec_ctx,
181 grpc_server *server, void *arg,
182 grpc_closure *destroy_done) {
Yash Tibrewalca3c1c02017-09-07 22:47:16 -0700183 server_state *state = (server_state *)arg;
Mark D. Roth71403822016-12-02 10:51:39 -0800184 gpr_mu_lock(&state->mu);
185 state->shutdown = true;
186 state->server_destroy_listener_done = destroy_done;
187 grpc_tcp_server *tcp_server = state->tcp_server;
188 gpr_mu_unlock(&state->mu);
189 grpc_tcp_server_shutdown_listeners(exec_ctx, tcp_server);
190 grpc_tcp_server_unref(exec_ctx, tcp_server);
191}
192
Mark D. Roth1f0f23c2017-01-06 13:07:19 -0800193grpc_error *grpc_chttp2_server_add_port(grpc_exec_ctx *exec_ctx,
194 grpc_server *server, const char *addr,
195 grpc_channel_args *args,
196 int *port_num) {
Mark D. Roth71403822016-12-02 10:51:39 -0800197 grpc_resolved_addresses *resolved = NULL;
198 grpc_tcp_server *tcp_server = NULL;
199 size_t i;
200 size_t count = 0;
201 int port_temp;
202 grpc_error *err = GRPC_ERROR_NONE;
203 server_state *state = NULL;
Mark D. Rotha0bcfbb2016-12-02 12:10:25 -0800204 grpc_error **errors = NULL;
Yash Tibrewal533d1182017-09-18 10:48:22 -0700205 size_t naddrs = 0;
Mark D. Roth71403822016-12-02 10:51:39 -0800206
207 *port_num = -1;
208
209 /* resolve address */
210 err = grpc_blocking_resolve_address(addr, "https", &resolved);
211 if (err != GRPC_ERROR_NONE) {
212 goto error;
213 }
Yash Tibrewalca3c1c02017-09-07 22:47:16 -0700214 state = (server_state *)gpr_zalloc(sizeof(*state));
ncteisen274bbbe2017-06-08 14:57:11 -0700215 GRPC_CLOSURE_INIT(&state->tcp_server_shutdown_complete,
Craig Tiller91031da2016-12-28 15:44:25 -0800216 tcp_server_shutdown_complete, state,
217 grpc_schedule_on_exec_ctx);
Craig Tiller73122ba2016-12-05 08:16:58 -0800218 err = grpc_tcp_server_create(exec_ctx, &state->tcp_server_shutdown_complete,
219 args, &tcp_server);
Mark D. Roth71403822016-12-02 10:51:39 -0800220 if (err != GRPC_ERROR_NONE) {
221 goto error;
222 }
223
224 state->server = server;
225 state->tcp_server = tcp_server;
226 state->args = args;
Mark D. Roth71403822016-12-02 10:51:39 -0800227 state->shutdown = true;
228 gpr_mu_init(&state->mu);
229
Yash Tibrewal533d1182017-09-18 10:48:22 -0700230 naddrs = resolved->naddrs;
Yash Tibrewalca3c1c02017-09-07 22:47:16 -0700231 errors = (grpc_error **)gpr_malloc(sizeof(*errors) * naddrs);
Mark D. Roth71403822016-12-02 10:51:39 -0800232 for (i = 0; i < naddrs; i++) {
233 errors[i] =
234 grpc_tcp_server_add_port(tcp_server, &resolved->addrs[i], &port_temp);
235 if (errors[i] == GRPC_ERROR_NONE) {
236 if (*port_num == -1) {
237 *port_num = port_temp;
238 } else {
239 GPR_ASSERT(*port_num == port_temp);
240 }
241 count++;
242 }
243 }
244 if (count == 0) {
245 char *msg;
246 gpr_asprintf(&msg, "No address added out of total %" PRIuPTR " resolved",
247 naddrs);
ncteisen4b36a3d2017-03-13 19:08:06 -0700248 err = GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(msg, errors, naddrs);
Mark D. Roth71403822016-12-02 10:51:39 -0800249 gpr_free(msg);
250 goto error;
251 } else if (count != naddrs) {
252 char *msg;
253 gpr_asprintf(&msg, "Only %" PRIuPTR
254 " addresses added out of total %" PRIuPTR " resolved",
255 count, naddrs);
ncteisen4b36a3d2017-03-13 19:08:06 -0700256 err = GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(msg, errors, naddrs);
Mark D. Roth71403822016-12-02 10:51:39 -0800257 gpr_free(msg);
258
259 const char *warning_message = grpc_error_string(err);
260 gpr_log(GPR_INFO, "WARNING: %s", warning_message);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800261
Mark D. Roth71403822016-12-02 10:51:39 -0800262 /* we managed to bind some addresses: continue */
263 }
264 grpc_resolved_addresses_destroy(resolved);
265
266 /* Register with the server only upon success */
267 grpc_server_add_listener(exec_ctx, server, state, server_start_listener,
268 server_destroy_listener);
269 goto done;
270
271/* Error path: cleanup and return */
272error:
273 GPR_ASSERT(err != GRPC_ERROR_NONE);
274 if (resolved) {
275 grpc_resolved_addresses_destroy(resolved);
276 }
277 if (tcp_server) {
278 grpc_tcp_server_unref(exec_ctx, tcp_server);
Mark D. Roth0f4bbba2016-12-02 22:16:03 +0000279 } else {
Craig Tiller397bff32016-12-06 15:05:59 -0800280 grpc_channel_args_destroy(exec_ctx, args);
Mark D. Roth0f4bbba2016-12-02 22:16:03 +0000281 gpr_free(state);
Mark D. Roth71403822016-12-02 10:51:39 -0800282 }
Mark D. Roth71403822016-12-02 10:51:39 -0800283 *port_num = 0;
284
285done:
286 if (errors != NULL) {
287 for (i = 0; i < naddrs; i++) {
288 GRPC_ERROR_UNREF(errors[i]);
289 }
290 gpr_free(errors);
291 }
292 return err;
293}