blob: 60244e163b2678dd9b6933af2fab3a8026677aa4 [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
23#include <string.h>
24
25#include <grpc/support/alloc.h>
26#include <grpc/support/log.h>
27#include <grpc/support/string_util.h>
28#include <grpc/support/sync.h>
29#include <grpc/support/useful.h>
30
Craig Tillere3593d92017-04-03 14:51:02 -070031#include "src/core/ext/filters/http/server/http_server_filter.h"
Mark D. Roth71403822016-12-02 10:51:39 -080032#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
33#include "src/core/lib/channel/channel_args.h"
34#include "src/core/lib/channel/handshaker.h"
Mark D. Roth1f0f23c2017-01-06 13:07:19 -080035#include "src/core/lib/channel/handshaker_registry.h"
Mark D. Roth71403822016-12-02 10:51:39 -080036#include "src/core/lib/iomgr/endpoint.h"
37#include "src/core/lib/iomgr/resolve_address.h"
38#include "src/core/lib/iomgr/tcp_server.h"
Craig Tiller6822a7a2016-12-06 19:28:52 -080039#include "src/core/lib/slice/slice_internal.h"
Mark D. Roth71403822016-12-02 10:51:39 -080040#include "src/core/lib/surface/api_trace.h"
41#include "src/core/lib/surface/server.h"
42
Mark D. Roth71403822016-12-02 10:51:39 -080043typedef struct {
44 grpc_server *server;
45 grpc_tcp_server *tcp_server;
46 grpc_channel_args *args;
Mark D. Roth71403822016-12-02 10:51:39 -080047 gpr_mu mu;
48 bool shutdown;
49 grpc_closure tcp_server_shutdown_complete;
50 grpc_closure *server_destroy_listener_done;
yang-g6da1e852017-02-16 10:34:06 -080051 grpc_handshake_manager *pending_handshake_mgrs;
Yash Tibrewala4952202017-09-13 10:53:28 -070052} server_state;
Mark D. Roth71403822016-12-02 10:51:39 -080053
54typedef struct {
Yash Tibrewala4952202017-09-13 10:53:28 -070055 server_state *svr_state;
Mark D. Roth71403822016-12-02 10:51:39 -080056 grpc_pollset *accepting_pollset;
57 grpc_tcp_server_acceptor *acceptor;
58 grpc_handshake_manager *handshake_mgr;
59} server_connection_state;
60
Mark D. Roth71403822016-12-02 10:51:39 -080061static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
62 grpc_error *error) {
Yash Tibrewalca3c1c02017-09-07 22:47:16 -070063 grpc_handshaker_args *args = (grpc_handshaker_args *)arg;
64 server_connection_state *connection_state =
65 (server_connection_state *)args->user_data;
Yash Tibrewala4952202017-09-13 10:53:28 -070066 gpr_mu_lock(&connection_state->svr_state->mu);
67 if (error != GRPC_ERROR_NONE || connection_state->svr_state->shutdown) {
Mark D. Roth71403822016-12-02 10:51:39 -080068 const char *error_str = grpc_error_string(error);
David Garcia Quintasc3fc8342017-04-21 15:01:18 -070069 gpr_log(GPR_DEBUG, "Handshaking failed: %s", error_str);
Craig Tiller7c70b6c2017-01-23 07:48:42 -080070
Mark D. Roth0ee1dbb2016-12-09 09:57:20 -080071 if (error == GRPC_ERROR_NONE && args->endpoint != NULL) {
Mark D. Roth71403822016-12-02 10:51:39 -080072 // We were shut down after handshaking completed successfully, so
73 // destroy the endpoint here.
74 // TODO(ctiller): It is currently necessary to shutdown endpoints
75 // before destroying them, even if we know that there are no
76 // pending read/write callbacks. This should be fixed, at which
77 // point this can be removed.
Craig Tillercda759d2017-01-27 11:37:37 -080078 grpc_endpoint_shutdown(exec_ctx, args->endpoint, GRPC_ERROR_NONE);
Mark D. Roth71403822016-12-02 10:51:39 -080079 grpc_endpoint_destroy(exec_ctx, args->endpoint);
Craig Tiller397bff32016-12-06 15:05:59 -080080 grpc_channel_args_destroy(exec_ctx, args->args);
Craig Tiller6822a7a2016-12-06 19:28:52 -080081 grpc_slice_buffer_destroy_internal(exec_ctx, args->read_buffer);
Mark D. Roth71403822016-12-02 10:51:39 -080082 gpr_free(args->read_buffer);
83 }
84 } else {
Mark D. Roth30598282016-12-07 07:13:58 -080085 // If the handshaking succeeded but there is no endpoint, then the
86 // handshaker may have handed off the connection to some external
87 // code, so we can just clean up here without creating a transport.
Mark D. Rothcc527cf2016-12-06 10:43:12 -080088 if (args->endpoint != NULL) {
89 grpc_transport *transport =
90 grpc_create_chttp2_transport(exec_ctx, args->args, args->endpoint, 0);
91 grpc_server_setup_transport(
Yash Tibrewala4952202017-09-13 10:53:28 -070092 exec_ctx, connection_state->svr_state->server, transport,
Mark D. Rothcc527cf2016-12-06 10:43:12 -080093 connection_state->accepting_pollset, args->args);
94 grpc_chttp2_transport_start_reading(exec_ctx, transport,
95 args->read_buffer);
Craig Tiller1a7c57b2016-12-12 06:38:13 -080096 grpc_channel_args_destroy(exec_ctx, args->args);
Mark D. Rothcc527cf2016-12-06 10:43:12 -080097 }
Mark D. Roth71403822016-12-02 10:51:39 -080098 }
yang-g6da1e852017-02-16 10:34:06 -080099 grpc_handshake_manager_pending_list_remove(
Yash Tibrewala4952202017-09-13 10:53:28 -0700100 &connection_state->svr_state->pending_handshake_mgrs,
yang-g6da1e852017-02-16 10:34:06 -0800101 connection_state->handshake_mgr);
Yash Tibrewala4952202017-09-13 10:53:28 -0700102 gpr_mu_unlock(&connection_state->svr_state->mu);
Mark D. Roth71403822016-12-02 10:51:39 -0800103 grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr);
Yash Tibrewala4952202017-09-13 10:53:28 -0700104 grpc_tcp_server_unref(exec_ctx, connection_state->svr_state->tcp_server);
Mark D. Rotheed38152016-12-08 13:59:13 -0800105 gpr_free(connection_state->acceptor);
Mark D. Roth71403822016-12-02 10:51:39 -0800106 gpr_free(connection_state);
107}
108
109static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
110 grpc_pollset *accepting_pollset,
111 grpc_tcp_server_acceptor *acceptor) {
Yash Tibrewala4952202017-09-13 10:53:28 -0700112 server_state *state = (server_state *)arg;
Mark D. Roth71403822016-12-02 10:51:39 -0800113 gpr_mu_lock(&state->mu);
114 if (state->shutdown) {
115 gpr_mu_unlock(&state->mu);
Makarand Dharmapurikar9c156da2017-05-18 10:32:13 -0700116 grpc_endpoint_shutdown(exec_ctx, tcp, GRPC_ERROR_NONE);
Mark D. Roth71403822016-12-02 10:51:39 -0800117 grpc_endpoint_destroy(exec_ctx, tcp);
Mark D. Roth96ba68d2016-12-09 17:21:26 +0000118 gpr_free(acceptor);
Mark D. Roth71403822016-12-02 10:51:39 -0800119 return;
120 }
121 grpc_handshake_manager *handshake_mgr = grpc_handshake_manager_create();
yang-g6da1e852017-02-16 10:34:06 -0800122 grpc_handshake_manager_pending_list_add(&state->pending_handshake_mgrs,
123 handshake_mgr);
Mark D. Roth71403822016-12-02 10:51:39 -0800124 gpr_mu_unlock(&state->mu);
125 grpc_tcp_server_ref(state->tcp_server);
126 server_connection_state *connection_state =
Yash Tibrewalbc130da2017-09-12 22:44:08 -0700127 (server_connection_state *)gpr_malloc(sizeof(*connection_state));
Yash Tibrewala4952202017-09-13 10:53:28 -0700128 connection_state->svr_state = state;
Mark D. Roth71403822016-12-02 10:51:39 -0800129 connection_state->accepting_pollset = accepting_pollset;
130 connection_state->acceptor = acceptor;
131 connection_state->handshake_mgr = handshake_mgr;
Mark D. Roth1f0f23c2017-01-06 13:07:19 -0800132 grpc_handshakers_add(exec_ctx, HANDSHAKER_SERVER, state->args,
133 connection_state->handshake_mgr);
Mark D. Roth71403822016-12-02 10:51:39 -0800134 // TODO(roth): We should really get this timeout value from channel
135 // args instead of hard-coding it.
136 const gpr_timespec deadline = gpr_time_add(
137 gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(120, GPR_TIMESPAN));
Craig Tiller73122ba2016-12-05 08:16:58 -0800138 grpc_handshake_manager_do_handshake(exec_ctx, connection_state->handshake_mgr,
139 tcp, state->args, deadline, acceptor,
140 on_handshake_done, connection_state);
Mark D. Roth71403822016-12-02 10:51:39 -0800141}
142
143/* Server callback: start listening on our ports */
144static void server_start_listener(grpc_exec_ctx *exec_ctx, grpc_server *server,
145 void *arg, grpc_pollset **pollsets,
146 size_t pollset_count) {
Yash Tibrewala4952202017-09-13 10:53:28 -0700147 server_state *state = (server_state *)arg;
Mark D. Roth71403822016-12-02 10:51:39 -0800148 gpr_mu_lock(&state->mu);
149 state->shutdown = false;
150 gpr_mu_unlock(&state->mu);
151 grpc_tcp_server_start(exec_ctx, state->tcp_server, pollsets, pollset_count,
152 on_accept, state);
153}
154
155static void tcp_server_shutdown_complete(grpc_exec_ctx *exec_ctx, void *arg,
156 grpc_error *error) {
Yash Tibrewala4952202017-09-13 10:53:28 -0700157 server_state *state = (server_state *)arg;
Mark D. Roth71403822016-12-02 10:51:39 -0800158 /* ensure all threads have unlocked */
159 gpr_mu_lock(&state->mu);
160 grpc_closure *destroy_done = state->server_destroy_listener_done;
161 GPR_ASSERT(state->shutdown);
yang-g6da1e852017-02-16 10:34:06 -0800162 grpc_handshake_manager_pending_list_shutdown_all(
163 exec_ctx, state->pending_handshake_mgrs, GRPC_ERROR_REF(error));
Mark D. Roth71403822016-12-02 10:51:39 -0800164 gpr_mu_unlock(&state->mu);
165 // Flush queued work before destroying handshaker factory, since that
166 // may do a synchronous unref.
167 grpc_exec_ctx_flush(exec_ctx);
Mark D. Roth71403822016-12-02 10:51:39 -0800168 if (destroy_done != NULL) {
169 destroy_done->cb(exec_ctx, destroy_done->cb_arg, GRPC_ERROR_REF(error));
170 grpc_exec_ctx_flush(exec_ctx);
171 }
Craig Tiller397bff32016-12-06 15:05:59 -0800172 grpc_channel_args_destroy(exec_ctx, state->args);
Mark D. Roth71403822016-12-02 10:51:39 -0800173 gpr_mu_destroy(&state->mu);
174 gpr_free(state);
175}
176
177/* Server callback: destroy the tcp listener (so we don't generate further
178 callbacks) */
179static void server_destroy_listener(grpc_exec_ctx *exec_ctx,
180 grpc_server *server, void *arg,
181 grpc_closure *destroy_done) {
Yash Tibrewala4952202017-09-13 10:53:28 -0700182 server_state *state = (server_state *)arg;
Mark D. Roth71403822016-12-02 10:51:39 -0800183 gpr_mu_lock(&state->mu);
184 state->shutdown = true;
185 state->server_destroy_listener_done = destroy_done;
186 grpc_tcp_server *tcp_server = state->tcp_server;
187 gpr_mu_unlock(&state->mu);
188 grpc_tcp_server_shutdown_listeners(exec_ctx, tcp_server);
189 grpc_tcp_server_unref(exec_ctx, tcp_server);
190}
191
Mark D. Roth1f0f23c2017-01-06 13:07:19 -0800192grpc_error *grpc_chttp2_server_add_port(grpc_exec_ctx *exec_ctx,
193 grpc_server *server, const char *addr,
194 grpc_channel_args *args,
195 int *port_num) {
Mark D. Roth71403822016-12-02 10:51:39 -0800196 grpc_resolved_addresses *resolved = NULL;
197 grpc_tcp_server *tcp_server = NULL;
198 size_t i;
199 size_t count = 0;
200 int port_temp;
201 grpc_error *err = GRPC_ERROR_NONE;
Yash Tibrewala4952202017-09-13 10:53:28 -0700202 server_state *state = NULL;
Mark D. Rotha0bcfbb2016-12-02 12:10:25 -0800203 grpc_error **errors = NULL;
Yash Tibrewal533d1182017-09-18 10:48:22 -0700204 size_t naddrs = 0;
Mark D. Roth71403822016-12-02 10:51:39 -0800205
206 *port_num = -1;
207
208 /* resolve address */
209 err = grpc_blocking_resolve_address(addr, "https", &resolved);
210 if (err != GRPC_ERROR_NONE) {
211 goto error;
212 }
Yash Tibrewala4952202017-09-13 10:53:28 -0700213 state = (server_state *)gpr_zalloc(sizeof(*state));
ncteisen274bbbe2017-06-08 14:57:11 -0700214 GRPC_CLOSURE_INIT(&state->tcp_server_shutdown_complete,
Craig Tiller91031da2016-12-28 15:44:25 -0800215 tcp_server_shutdown_complete, state,
216 grpc_schedule_on_exec_ctx);
Craig Tiller73122ba2016-12-05 08:16:58 -0800217 err = grpc_tcp_server_create(exec_ctx, &state->tcp_server_shutdown_complete,
218 args, &tcp_server);
Mark D. Roth71403822016-12-02 10:51:39 -0800219 if (err != GRPC_ERROR_NONE) {
220 goto error;
221 }
222
223 state->server = server;
224 state->tcp_server = tcp_server;
225 state->args = args;
Mark D. Roth71403822016-12-02 10:51:39 -0800226 state->shutdown = true;
227 gpr_mu_init(&state->mu);
228
Yash Tibrewal533d1182017-09-18 10:48:22 -0700229 naddrs = resolved->naddrs;
Yash Tibrewalca3c1c02017-09-07 22:47:16 -0700230 errors = (grpc_error **)gpr_malloc(sizeof(*errors) * naddrs);
Mark D. Roth71403822016-12-02 10:51:39 -0800231 for (i = 0; i < naddrs; i++) {
232 errors[i] =
233 grpc_tcp_server_add_port(tcp_server, &resolved->addrs[i], &port_temp);
234 if (errors[i] == GRPC_ERROR_NONE) {
235 if (*port_num == -1) {
236 *port_num = port_temp;
237 } else {
238 GPR_ASSERT(*port_num == port_temp);
239 }
240 count++;
241 }
242 }
243 if (count == 0) {
244 char *msg;
245 gpr_asprintf(&msg, "No address added out of total %" PRIuPTR " resolved",
246 naddrs);
ncteisen4b36a3d2017-03-13 19:08:06 -0700247 err = GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(msg, errors, naddrs);
Mark D. Roth71403822016-12-02 10:51:39 -0800248 gpr_free(msg);
249 goto error;
250 } else if (count != naddrs) {
251 char *msg;
252 gpr_asprintf(&msg, "Only %" PRIuPTR
253 " addresses added out of total %" PRIuPTR " resolved",
254 count, naddrs);
ncteisen4b36a3d2017-03-13 19:08:06 -0700255 err = GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(msg, errors, naddrs);
Mark D. Roth71403822016-12-02 10:51:39 -0800256 gpr_free(msg);
257
258 const char *warning_message = grpc_error_string(err);
259 gpr_log(GPR_INFO, "WARNING: %s", warning_message);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800260
Mark D. Roth71403822016-12-02 10:51:39 -0800261 /* we managed to bind some addresses: continue */
262 }
263 grpc_resolved_addresses_destroy(resolved);
264
265 /* Register with the server only upon success */
266 grpc_server_add_listener(exec_ctx, server, state, server_start_listener,
267 server_destroy_listener);
268 goto done;
269
270/* Error path: cleanup and return */
271error:
272 GPR_ASSERT(err != GRPC_ERROR_NONE);
273 if (resolved) {
274 grpc_resolved_addresses_destroy(resolved);
275 }
276 if (tcp_server) {
277 grpc_tcp_server_unref(exec_ctx, tcp_server);
Mark D. Roth0f4bbba2016-12-02 22:16:03 +0000278 } else {
Craig Tiller397bff32016-12-06 15:05:59 -0800279 grpc_channel_args_destroy(exec_ctx, args);
Mark D. Roth0f4bbba2016-12-02 22:16:03 +0000280 gpr_free(state);
Mark D. Roth71403822016-12-02 10:51:39 -0800281 }
Mark D. Roth71403822016-12-02 10:51:39 -0800282 *port_num = 0;
283
284done:
285 if (errors != NULL) {
286 for (i = 0; i < naddrs; i++) {
287 GRPC_ERROR_UNREF(errors[i]);
288 }
289 gpr_free(errors);
290 }
291 return err;
292}