blob: af0b9e5b0b621586b4f004e91311dbd3e74da982 [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"
49#include "src/core/lib/channel/http_server_filter.h"
50#include "src/core/lib/iomgr/endpoint.h"
51#include "src/core/lib/iomgr/resolve_address.h"
52#include "src/core/lib/iomgr/tcp_server.h"
53#include "src/core/lib/surface/api_trace.h"
54#include "src/core/lib/surface/server.h"
55
Mark D. Roth65b79c82016-12-06 07:20:20 -080056void grpc_chttp2_server_handshaker_factory_add_handshakers(
Mark D. Roth71403822016-12-02 10:51:39 -080057 grpc_exec_ctx *exec_ctx,
58 grpc_chttp2_server_handshaker_factory *handshaker_factory,
59 grpc_handshake_manager *handshake_mgr) {
60 if (handshaker_factory != NULL) {
Mark D. Roth65b79c82016-12-06 07:20:20 -080061 handshaker_factory->vtable->add_handshakers(exec_ctx, handshaker_factory,
62 handshake_mgr);
Mark D. Roth71403822016-12-02 10:51:39 -080063 }
64}
65
66void grpc_chttp2_server_handshaker_factory_destroy(
67 grpc_exec_ctx *exec_ctx,
68 grpc_chttp2_server_handshaker_factory *handshaker_factory) {
69 if (handshaker_factory != NULL) {
70 handshaker_factory->vtable->destroy(exec_ctx, handshaker_factory);
71 }
72}
73
Mark D. Roth71403822016-12-02 10:51:39 -080074typedef struct pending_handshake_manager_node {
75 grpc_handshake_manager *handshake_mgr;
76 struct pending_handshake_manager_node *next;
77} pending_handshake_manager_node;
78
79typedef struct {
80 grpc_server *server;
81 grpc_tcp_server *tcp_server;
82 grpc_channel_args *args;
83 grpc_chttp2_server_handshaker_factory *handshaker_factory;
84 gpr_mu mu;
85 bool shutdown;
86 grpc_closure tcp_server_shutdown_complete;
87 grpc_closure *server_destroy_listener_done;
88 pending_handshake_manager_node *pending_handshake_mgrs;
89} server_state;
90
91typedef struct {
92 server_state *server_state;
93 grpc_pollset *accepting_pollset;
94 grpc_tcp_server_acceptor *acceptor;
95 grpc_handshake_manager *handshake_mgr;
96} server_connection_state;
97
98static void pending_handshake_manager_add_locked(
99 server_state *state, grpc_handshake_manager *handshake_mgr) {
100 pending_handshake_manager_node *node = gpr_malloc(sizeof(*node));
101 node->handshake_mgr = handshake_mgr;
102 node->next = state->pending_handshake_mgrs;
103 state->pending_handshake_mgrs = node;
104}
105
106static void pending_handshake_manager_remove_locked(
107 server_state *state, grpc_handshake_manager *handshake_mgr) {
108 pending_handshake_manager_node **prev_node = &state->pending_handshake_mgrs;
109 for (pending_handshake_manager_node *node = state->pending_handshake_mgrs;
110 node != NULL; node = node->next) {
111 if (node->handshake_mgr == handshake_mgr) {
112 *prev_node = node->next;
113 gpr_free(node);
114 break;
115 }
116 prev_node = &node->next;
117 }
118}
119
120static void pending_handshake_manager_shutdown_locked(grpc_exec_ctx *exec_ctx,
121 server_state *state) {
122 pending_handshake_manager_node *prev_node = NULL;
123 for (pending_handshake_manager_node *node = state->pending_handshake_mgrs;
124 node != NULL; node = node->next) {
125 grpc_handshake_manager_shutdown(exec_ctx, node->handshake_mgr);
126 gpr_free(prev_node);
127 prev_node = node;
128 }
129 gpr_free(prev_node);
130 state->pending_handshake_mgrs = NULL;
131}
132
133static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
134 grpc_error *error) {
135 grpc_handshaker_args *args = arg;
136 server_connection_state *connection_state = args->user_data;
137 gpr_mu_lock(&connection_state->server_state->mu);
138 if (error != GRPC_ERROR_NONE || connection_state->server_state->shutdown) {
139 const char *error_str = grpc_error_string(error);
140 gpr_log(GPR_ERROR, "Handshaking failed: %s", error_str);
141 grpc_error_free_string(error_str);
142 if (error == GRPC_ERROR_NONE) {
143 // We were shut down after handshaking completed successfully, so
144 // destroy the endpoint here.
145 // TODO(ctiller): It is currently necessary to shutdown endpoints
146 // before destroying them, even if we know that there are no
147 // pending read/write callbacks. This should be fixed, at which
148 // point this can be removed.
149 grpc_endpoint_shutdown(exec_ctx, args->endpoint);
150 grpc_endpoint_destroy(exec_ctx, args->endpoint);
151 grpc_channel_args_destroy(args->args);
152 grpc_slice_buffer_destroy(args->read_buffer);
153 gpr_free(args->read_buffer);
154 }
155 } else {
156 grpc_transport *transport =
157 grpc_create_chttp2_transport(exec_ctx, args->args, args->endpoint, 0);
158 grpc_server_setup_transport(
159 exec_ctx, connection_state->server_state->server, transport,
160 connection_state->accepting_pollset, args->args);
161 grpc_chttp2_transport_start_reading(exec_ctx, transport, args->read_buffer);
162 grpc_channel_args_destroy(args->args);
163 }
164 pending_handshake_manager_remove_locked(connection_state->server_state,
165 connection_state->handshake_mgr);
166 gpr_mu_unlock(&connection_state->server_state->mu);
167 grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr);
168 grpc_tcp_server_unref(exec_ctx, connection_state->server_state->tcp_server);
Mark D. Rotheed38152016-12-08 13:59:13 -0800169 gpr_free(connection_state->acceptor);
Mark D. Roth71403822016-12-02 10:51:39 -0800170 gpr_free(connection_state);
171}
172
173static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
174 grpc_pollset *accepting_pollset,
175 grpc_tcp_server_acceptor *acceptor) {
176 server_state *state = arg;
177 gpr_mu_lock(&state->mu);
178 if (state->shutdown) {
179 gpr_mu_unlock(&state->mu);
180 grpc_endpoint_destroy(exec_ctx, tcp);
Mark D. Roth96ba68d2016-12-09 17:21:26 +0000181 gpr_free(acceptor);
Mark D. Roth71403822016-12-02 10:51:39 -0800182 return;
183 }
184 grpc_handshake_manager *handshake_mgr = grpc_handshake_manager_create();
185 pending_handshake_manager_add_locked(state, handshake_mgr);
186 gpr_mu_unlock(&state->mu);
187 grpc_tcp_server_ref(state->tcp_server);
188 server_connection_state *connection_state =
189 gpr_malloc(sizeof(*connection_state));
190 connection_state->server_state = state;
191 connection_state->accepting_pollset = accepting_pollset;
192 connection_state->acceptor = acceptor;
193 connection_state->handshake_mgr = handshake_mgr;
Mark D. Roth65b79c82016-12-06 07:20:20 -0800194 grpc_chttp2_server_handshaker_factory_add_handshakers(
Mark D. Roth71403822016-12-02 10:51:39 -0800195 exec_ctx, state->handshaker_factory, connection_state->handshake_mgr);
196 // TODO(roth): We should really get this timeout value from channel
197 // args instead of hard-coding it.
198 const gpr_timespec deadline = gpr_time_add(
199 gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(120, GPR_TIMESPAN));
Craig Tiller73122ba2016-12-05 08:16:58 -0800200 grpc_handshake_manager_do_handshake(exec_ctx, connection_state->handshake_mgr,
201 tcp, state->args, deadline, acceptor,
202 on_handshake_done, connection_state);
Mark D. Roth71403822016-12-02 10:51:39 -0800203}
204
205/* Server callback: start listening on our ports */
206static void server_start_listener(grpc_exec_ctx *exec_ctx, grpc_server *server,
207 void *arg, grpc_pollset **pollsets,
208 size_t pollset_count) {
209 server_state *state = arg;
210 gpr_mu_lock(&state->mu);
211 state->shutdown = false;
212 gpr_mu_unlock(&state->mu);
213 grpc_tcp_server_start(exec_ctx, state->tcp_server, pollsets, pollset_count,
214 on_accept, state);
215}
216
217static void tcp_server_shutdown_complete(grpc_exec_ctx *exec_ctx, void *arg,
218 grpc_error *error) {
219 server_state *state = arg;
220 /* ensure all threads have unlocked */
221 gpr_mu_lock(&state->mu);
222 grpc_closure *destroy_done = state->server_destroy_listener_done;
223 GPR_ASSERT(state->shutdown);
224 pending_handshake_manager_shutdown_locked(exec_ctx, state);
225 gpr_mu_unlock(&state->mu);
226 // Flush queued work before destroying handshaker factory, since that
227 // may do a synchronous unref.
228 grpc_exec_ctx_flush(exec_ctx);
229 grpc_chttp2_server_handshaker_factory_destroy(exec_ctx,
230 state->handshaker_factory);
231 if (destroy_done != NULL) {
232 destroy_done->cb(exec_ctx, destroy_done->cb_arg, GRPC_ERROR_REF(error));
233 grpc_exec_ctx_flush(exec_ctx);
234 }
235 grpc_channel_args_destroy(state->args);
236 gpr_mu_destroy(&state->mu);
237 gpr_free(state);
238}
239
240/* Server callback: destroy the tcp listener (so we don't generate further
241 callbacks) */
242static void server_destroy_listener(grpc_exec_ctx *exec_ctx,
243 grpc_server *server, void *arg,
244 grpc_closure *destroy_done) {
245 server_state *state = arg;
246 gpr_mu_lock(&state->mu);
247 state->shutdown = true;
248 state->server_destroy_listener_done = destroy_done;
249 grpc_tcp_server *tcp_server = state->tcp_server;
250 gpr_mu_unlock(&state->mu);
251 grpc_tcp_server_shutdown_listeners(exec_ctx, tcp_server);
252 grpc_tcp_server_unref(exec_ctx, tcp_server);
253}
254
255grpc_error *grpc_chttp2_server_add_port(
256 grpc_exec_ctx *exec_ctx, grpc_server *server, const char *addr,
257 grpc_channel_args *args,
258 grpc_chttp2_server_handshaker_factory *handshaker_factory, int *port_num) {
259 grpc_resolved_addresses *resolved = NULL;
260 grpc_tcp_server *tcp_server = NULL;
261 size_t i;
262 size_t count = 0;
263 int port_temp;
264 grpc_error *err = GRPC_ERROR_NONE;
265 server_state *state = NULL;
Mark D. Rotha0bcfbb2016-12-02 12:10:25 -0800266 grpc_error **errors = NULL;
Mark D. Roth71403822016-12-02 10:51:39 -0800267
268 *port_num = -1;
269
270 /* resolve address */
271 err = grpc_blocking_resolve_address(addr, "https", &resolved);
272 if (err != GRPC_ERROR_NONE) {
273 goto error;
274 }
275 state = gpr_malloc(sizeof(*state));
276 memset(state, 0, sizeof(*state));
277 grpc_closure_init(&state->tcp_server_shutdown_complete,
278 tcp_server_shutdown_complete, state);
Craig Tiller73122ba2016-12-05 08:16:58 -0800279 err = grpc_tcp_server_create(exec_ctx, &state->tcp_server_shutdown_complete,
280 args, &tcp_server);
Mark D. Roth71403822016-12-02 10:51:39 -0800281 if (err != GRPC_ERROR_NONE) {
282 goto error;
283 }
284
285 state->server = server;
286 state->tcp_server = tcp_server;
287 state->args = args;
288 state->handshaker_factory = handshaker_factory;
289 state->shutdown = true;
290 gpr_mu_init(&state->mu);
291
292 const size_t naddrs = resolved->naddrs;
Mark D. Rotha0bcfbb2016-12-02 12:10:25 -0800293 errors = gpr_malloc(sizeof(*errors) * naddrs);
Mark D. Roth71403822016-12-02 10:51:39 -0800294 for (i = 0; i < naddrs; i++) {
295 errors[i] =
296 grpc_tcp_server_add_port(tcp_server, &resolved->addrs[i], &port_temp);
297 if (errors[i] == GRPC_ERROR_NONE) {
298 if (*port_num == -1) {
299 *port_num = port_temp;
300 } else {
301 GPR_ASSERT(*port_num == port_temp);
302 }
303 count++;
304 }
305 }
306 if (count == 0) {
307 char *msg;
308 gpr_asprintf(&msg, "No address added out of total %" PRIuPTR " resolved",
309 naddrs);
310 err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, naddrs);
311 gpr_free(msg);
312 goto error;
313 } else if (count != naddrs) {
314 char *msg;
315 gpr_asprintf(&msg, "Only %" PRIuPTR
316 " addresses added out of total %" PRIuPTR " resolved",
317 count, naddrs);
318 err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, naddrs);
319 gpr_free(msg);
320
321 const char *warning_message = grpc_error_string(err);
322 gpr_log(GPR_INFO, "WARNING: %s", warning_message);
323 grpc_error_free_string(warning_message);
324 /* we managed to bind some addresses: continue */
325 }
326 grpc_resolved_addresses_destroy(resolved);
327
328 /* Register with the server only upon success */
329 grpc_server_add_listener(exec_ctx, server, state, server_start_listener,
330 server_destroy_listener);
331 goto done;
332
333/* Error path: cleanup and return */
334error:
335 GPR_ASSERT(err != GRPC_ERROR_NONE);
336 if (resolved) {
337 grpc_resolved_addresses_destroy(resolved);
338 }
339 if (tcp_server) {
340 grpc_tcp_server_unref(exec_ctx, tcp_server);
Mark D. Roth0f4bbba2016-12-02 22:16:03 +0000341 } else {
Mark D. Rotha0bb3742016-12-02 22:27:26 +0000342 grpc_channel_args_destroy(args);
343 grpc_chttp2_server_handshaker_factory_destroy(exec_ctx, handshaker_factory);
Mark D. Roth0f4bbba2016-12-02 22:16:03 +0000344 gpr_free(state);
Mark D. Roth71403822016-12-02 10:51:39 -0800345 }
Mark D. Roth71403822016-12-02 10:51:39 -0800346 *port_num = 0;
347
348done:
349 if (errors != NULL) {
350 for (i = 0; i < naddrs; i++) {
351 GRPC_ERROR_UNREF(errors[i]);
352 }
353 gpr_free(errors);
354 }
355 return err;
356}