blob: 837b9fd03d869aa49858b4ca6aefef38c854bba1 [file] [log] [blame]
Mark D. Roth71403822016-12-02 10:51:39 -08001/*
2 *
3 * Copyright 2015, Google Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#include "src/core/ext/transport/chttp2/server/chttp2_server.h"
35
36#include <grpc/grpc.h>
37
38#include <string.h>
39
40#include <grpc/support/alloc.h>
41#include <grpc/support/log.h>
42#include <grpc/support/string_util.h>
43#include <grpc/support/sync.h>
44#include <grpc/support/useful.h>
45
46#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
47#include "src/core/lib/channel/channel_args.h"
48#include "src/core/lib/channel/handshaker.h"
Mark D. Roth1f0f23c2017-01-06 13:07:19 -080049#include "src/core/lib/channel/handshaker_registry.h"
Mark D. Roth71403822016-12-02 10:51:39 -080050#include "src/core/lib/channel/http_server_filter.h"
51#include "src/core/lib/iomgr/endpoint.h"
52#include "src/core/lib/iomgr/resolve_address.h"
53#include "src/core/lib/iomgr/tcp_server.h"
Craig Tiller6822a7a2016-12-06 19:28:52 -080054#include "src/core/lib/slice/slice_internal.h"
Mark D. Roth71403822016-12-02 10:51:39 -080055#include "src/core/lib/surface/api_trace.h"
56#include "src/core/lib/surface/server.h"
57
Mark D. Roth71403822016-12-02 10:51:39 -080058typedef struct {
59 grpc_server *server;
60 grpc_tcp_server *tcp_server;
61 grpc_channel_args *args;
Mark D. Roth71403822016-12-02 10:51:39 -080062 gpr_mu mu;
63 bool shutdown;
64 grpc_closure tcp_server_shutdown_complete;
65 grpc_closure *server_destroy_listener_done;
yang-g6da1e852017-02-16 10:34:06 -080066 grpc_handshake_manager *pending_handshake_mgrs;
Mark D. Roth71403822016-12-02 10:51:39 -080067} server_state;
68
69typedef struct {
70 server_state *server_state;
71 grpc_pollset *accepting_pollset;
72 grpc_tcp_server_acceptor *acceptor;
73 grpc_handshake_manager *handshake_mgr;
74} server_connection_state;
75
Mark D. Roth71403822016-12-02 10:51:39 -080076static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
77 grpc_error *error) {
78 grpc_handshaker_args *args = arg;
79 server_connection_state *connection_state = args->user_data;
80 gpr_mu_lock(&connection_state->server_state->mu);
81 if (error != GRPC_ERROR_NONE || connection_state->server_state->shutdown) {
82 const char *error_str = grpc_error_string(error);
83 gpr_log(GPR_ERROR, "Handshaking failed: %s", error_str);
Craig Tiller7c70b6c2017-01-23 07:48:42 -080084
Mark D. Roth0ee1dbb2016-12-09 09:57:20 -080085 if (error == GRPC_ERROR_NONE && args->endpoint != NULL) {
Mark D. Roth71403822016-12-02 10:51:39 -080086 // We were shut down after handshaking completed successfully, so
87 // destroy the endpoint here.
88 // TODO(ctiller): It is currently necessary to shutdown endpoints
89 // before destroying them, even if we know that there are no
90 // pending read/write callbacks. This should be fixed, at which
91 // point this can be removed.
Craig Tillercda759d2017-01-27 11:37:37 -080092 grpc_endpoint_shutdown(exec_ctx, args->endpoint, GRPC_ERROR_NONE);
Mark D. Roth71403822016-12-02 10:51:39 -080093 grpc_endpoint_destroy(exec_ctx, args->endpoint);
Craig Tiller397bff32016-12-06 15:05:59 -080094 grpc_channel_args_destroy(exec_ctx, args->args);
Craig Tiller6822a7a2016-12-06 19:28:52 -080095 grpc_slice_buffer_destroy_internal(exec_ctx, args->read_buffer);
Mark D. Roth71403822016-12-02 10:51:39 -080096 gpr_free(args->read_buffer);
97 }
98 } else {
Mark D. Roth30598282016-12-07 07:13:58 -080099 // If the handshaking succeeded but there is no endpoint, then the
100 // handshaker may have handed off the connection to some external
101 // code, so we can just clean up here without creating a transport.
Mark D. Rothcc527cf2016-12-06 10:43:12 -0800102 if (args->endpoint != NULL) {
103 grpc_transport *transport =
104 grpc_create_chttp2_transport(exec_ctx, args->args, args->endpoint, 0);
105 grpc_server_setup_transport(
106 exec_ctx, connection_state->server_state->server, transport,
107 connection_state->accepting_pollset, args->args);
108 grpc_chttp2_transport_start_reading(exec_ctx, transport,
109 args->read_buffer);
Craig Tiller1a7c57b2016-12-12 06:38:13 -0800110 grpc_channel_args_destroy(exec_ctx, args->args);
Mark D. Rothcc527cf2016-12-06 10:43:12 -0800111 }
Mark D. Roth71403822016-12-02 10:51:39 -0800112 }
yang-g6da1e852017-02-16 10:34:06 -0800113 grpc_handshake_manager_pending_list_remove(
114 &connection_state->server_state->pending_handshake_mgrs,
115 connection_state->handshake_mgr);
Mark D. Roth71403822016-12-02 10:51:39 -0800116 gpr_mu_unlock(&connection_state->server_state->mu);
117 grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr);
118 grpc_tcp_server_unref(exec_ctx, connection_state->server_state->tcp_server);
Mark D. Rotheed38152016-12-08 13:59:13 -0800119 gpr_free(connection_state->acceptor);
Mark D. Roth71403822016-12-02 10:51:39 -0800120 gpr_free(connection_state);
121}
122
123static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
124 grpc_pollset *accepting_pollset,
125 grpc_tcp_server_acceptor *acceptor) {
126 server_state *state = arg;
127 gpr_mu_lock(&state->mu);
128 if (state->shutdown) {
129 gpr_mu_unlock(&state->mu);
130 grpc_endpoint_destroy(exec_ctx, tcp);
Mark D. Roth96ba68d2016-12-09 17:21:26 +0000131 gpr_free(acceptor);
Mark D. Roth71403822016-12-02 10:51:39 -0800132 return;
133 }
134 grpc_handshake_manager *handshake_mgr = grpc_handshake_manager_create();
yang-g6da1e852017-02-16 10:34:06 -0800135 grpc_handshake_manager_pending_list_add(&state->pending_handshake_mgrs,
136 handshake_mgr);
Mark D. Roth71403822016-12-02 10:51:39 -0800137 gpr_mu_unlock(&state->mu);
138 grpc_tcp_server_ref(state->tcp_server);
139 server_connection_state *connection_state =
140 gpr_malloc(sizeof(*connection_state));
141 connection_state->server_state = state;
142 connection_state->accepting_pollset = accepting_pollset;
143 connection_state->acceptor = acceptor;
144 connection_state->handshake_mgr = handshake_mgr;
Mark D. Roth1f0f23c2017-01-06 13:07:19 -0800145 grpc_handshakers_add(exec_ctx, HANDSHAKER_SERVER, state->args,
146 connection_state->handshake_mgr);
Mark D. Roth71403822016-12-02 10:51:39 -0800147 // TODO(roth): We should really get this timeout value from channel
148 // args instead of hard-coding it.
149 const gpr_timespec deadline = gpr_time_add(
150 gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(120, GPR_TIMESPAN));
Craig Tiller73122ba2016-12-05 08:16:58 -0800151 grpc_handshake_manager_do_handshake(exec_ctx, connection_state->handshake_mgr,
152 tcp, state->args, deadline, acceptor,
153 on_handshake_done, connection_state);
Mark D. Roth71403822016-12-02 10:51:39 -0800154}
155
156/* Server callback: start listening on our ports */
157static void server_start_listener(grpc_exec_ctx *exec_ctx, grpc_server *server,
158 void *arg, grpc_pollset **pollsets,
159 size_t pollset_count) {
160 server_state *state = arg;
161 gpr_mu_lock(&state->mu);
162 state->shutdown = false;
163 gpr_mu_unlock(&state->mu);
164 grpc_tcp_server_start(exec_ctx, state->tcp_server, pollsets, pollset_count,
165 on_accept, state);
166}
167
168static void tcp_server_shutdown_complete(grpc_exec_ctx *exec_ctx, void *arg,
169 grpc_error *error) {
170 server_state *state = arg;
171 /* ensure all threads have unlocked */
172 gpr_mu_lock(&state->mu);
173 grpc_closure *destroy_done = state->server_destroy_listener_done;
174 GPR_ASSERT(state->shutdown);
yang-g6da1e852017-02-16 10:34:06 -0800175 grpc_handshake_manager_pending_list_shutdown_all(
176 exec_ctx, state->pending_handshake_mgrs, GRPC_ERROR_REF(error));
Mark D. Roth71403822016-12-02 10:51:39 -0800177 gpr_mu_unlock(&state->mu);
178 // Flush queued work before destroying handshaker factory, since that
179 // may do a synchronous unref.
180 grpc_exec_ctx_flush(exec_ctx);
Mark D. Roth71403822016-12-02 10:51:39 -0800181 if (destroy_done != NULL) {
182 destroy_done->cb(exec_ctx, destroy_done->cb_arg, GRPC_ERROR_REF(error));
183 grpc_exec_ctx_flush(exec_ctx);
184 }
Craig Tiller397bff32016-12-06 15:05:59 -0800185 grpc_channel_args_destroy(exec_ctx, state->args);
Mark D. Roth71403822016-12-02 10:51:39 -0800186 gpr_mu_destroy(&state->mu);
187 gpr_free(state);
188}
189
190/* Server callback: destroy the tcp listener (so we don't generate further
191 callbacks) */
192static void server_destroy_listener(grpc_exec_ctx *exec_ctx,
193 grpc_server *server, void *arg,
194 grpc_closure *destroy_done) {
195 server_state *state = arg;
196 gpr_mu_lock(&state->mu);
197 state->shutdown = true;
198 state->server_destroy_listener_done = destroy_done;
199 grpc_tcp_server *tcp_server = state->tcp_server;
200 gpr_mu_unlock(&state->mu);
201 grpc_tcp_server_shutdown_listeners(exec_ctx, tcp_server);
202 grpc_tcp_server_unref(exec_ctx, tcp_server);
203}
204
Mark D. Roth1f0f23c2017-01-06 13:07:19 -0800205grpc_error *grpc_chttp2_server_add_port(grpc_exec_ctx *exec_ctx,
206 grpc_server *server, const char *addr,
207 grpc_channel_args *args,
208 int *port_num) {
Mark D. Roth71403822016-12-02 10:51:39 -0800209 grpc_resolved_addresses *resolved = NULL;
210 grpc_tcp_server *tcp_server = NULL;
211 size_t i;
212 size_t count = 0;
213 int port_temp;
214 grpc_error *err = GRPC_ERROR_NONE;
215 server_state *state = NULL;
Mark D. Rotha0bcfbb2016-12-02 12:10:25 -0800216 grpc_error **errors = NULL;
Mark D. Roth71403822016-12-02 10:51:39 -0800217
218 *port_num = -1;
219
220 /* resolve address */
221 err = grpc_blocking_resolve_address(addr, "https", &resolved);
222 if (err != GRPC_ERROR_NONE) {
223 goto error;
224 }
Craig Tiller6f417882017-02-16 14:09:39 -0800225 state = gpr_zalloc(sizeof(*state));
Mark D. Roth71403822016-12-02 10:51:39 -0800226 grpc_closure_init(&state->tcp_server_shutdown_complete,
Craig Tiller91031da2016-12-28 15:44:25 -0800227 tcp_server_shutdown_complete, state,
228 grpc_schedule_on_exec_ctx);
Craig Tiller73122ba2016-12-05 08:16:58 -0800229 err = grpc_tcp_server_create(exec_ctx, &state->tcp_server_shutdown_complete,
230 args, &tcp_server);
Mark D. Roth71403822016-12-02 10:51:39 -0800231 if (err != GRPC_ERROR_NONE) {
232 goto error;
233 }
234
235 state->server = server;
236 state->tcp_server = tcp_server;
237 state->args = args;
Mark D. Roth71403822016-12-02 10:51:39 -0800238 state->shutdown = true;
239 gpr_mu_init(&state->mu);
240
241 const size_t naddrs = resolved->naddrs;
Mark D. Rotha0bcfbb2016-12-02 12:10:25 -0800242 errors = gpr_malloc(sizeof(*errors) * naddrs);
Mark D. Roth71403822016-12-02 10:51:39 -0800243 for (i = 0; i < naddrs; i++) {
244 errors[i] =
245 grpc_tcp_server_add_port(tcp_server, &resolved->addrs[i], &port_temp);
246 if (errors[i] == GRPC_ERROR_NONE) {
247 if (*port_num == -1) {
248 *port_num = port_temp;
249 } else {
250 GPR_ASSERT(*port_num == port_temp);
251 }
252 count++;
253 }
254 }
255 if (count == 0) {
256 char *msg;
257 gpr_asprintf(&msg, "No address added out of total %" PRIuPTR " resolved",
258 naddrs);
259 err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, naddrs);
260 gpr_free(msg);
261 goto error;
262 } else if (count != naddrs) {
263 char *msg;
264 gpr_asprintf(&msg, "Only %" PRIuPTR
265 " addresses added out of total %" PRIuPTR " resolved",
266 count, naddrs);
267 err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, naddrs);
268 gpr_free(msg);
269
270 const char *warning_message = grpc_error_string(err);
271 gpr_log(GPR_INFO, "WARNING: %s", warning_message);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800272
Mark D. Roth71403822016-12-02 10:51:39 -0800273 /* we managed to bind some addresses: continue */
274 }
275 grpc_resolved_addresses_destroy(resolved);
276
277 /* Register with the server only upon success */
278 grpc_server_add_listener(exec_ctx, server, state, server_start_listener,
279 server_destroy_listener);
280 goto done;
281
282/* Error path: cleanup and return */
283error:
284 GPR_ASSERT(err != GRPC_ERROR_NONE);
285 if (resolved) {
286 grpc_resolved_addresses_destroy(resolved);
287 }
288 if (tcp_server) {
289 grpc_tcp_server_unref(exec_ctx, tcp_server);
Mark D. Roth0f4bbba2016-12-02 22:16:03 +0000290 } else {
Craig Tiller397bff32016-12-06 15:05:59 -0800291 grpc_channel_args_destroy(exec_ctx, args);
Mark D. Roth0f4bbba2016-12-02 22:16:03 +0000292 gpr_free(state);
Mark D. Roth71403822016-12-02 10:51:39 -0800293 }
Mark D. Roth71403822016-12-02 10:51:39 -0800294 *port_num = 0;
295
296done:
297 if (errors != NULL) {
298 for (i = 0; i < naddrs; i++) {
299 GRPC_ERROR_UNREF(errors[i]);
300 }
301 gpr_free(errors);
302 }
303 return err;
304}