blob: 5b7d99ce401f90f6fdc6c4e8a1369fd0a970b979 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller06059952015-02-18 08:34:56 -08003 * Copyright 2015, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * 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 <grpc/grpc.h>
35
Craig Tiller759026c2015-02-22 23:09:45 -080036#include <string.h>
37
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080038#include "src/core/channel/http_filter.h"
39#include "src/core/channel/http_server_filter.h"
David Klempnerfd5d8ff2015-03-05 14:17:38 -080040#include "src/core/iomgr/endpoint.h"
ctiller18b49ab2014-12-09 14:39:16 -080041#include "src/core/iomgr/resolve_address.h"
42#include "src/core/iomgr/tcp_server.h"
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -070043#include "src/core/security/credentials.h"
44#include "src/core/security/security_connector.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080045#include "src/core/security/secure_transport_setup.h"
46#include "src/core/surface/server.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080047#include "src/core/transport/chttp2_transport.h"
48#include <grpc/support/alloc.h>
49#include <grpc/support/log.h>
David Klempnerfd5d8ff2015-03-05 14:17:38 -080050#include <grpc/support/sync.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080051#include <grpc/support/useful.h>
52
David Klempnerfd5d8ff2015-03-05 14:17:38 -080053typedef struct grpc_server_secure_state {
54 grpc_server *server;
55 grpc_tcp_server *tcp;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -070056 grpc_security_connector *sc;
David Klempnerfd5d8ff2015-03-05 14:17:38 -080057 int is_shutdown;
58 gpr_mu mu;
59 gpr_refcount refcount;
60} grpc_server_secure_state;
61
62static void state_ref(grpc_server_secure_state *state) {
63 gpr_ref(&state->refcount);
64}
65
66static void state_unref(grpc_server_secure_state *state) {
67 if (gpr_unref(&state->refcount)) {
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -070068 grpc_security_connector_unref(state->sc);
David Klempnerfd5d8ff2015-03-05 14:17:38 -080069 gpr_free(state);
70 }
71}
72
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080073static grpc_transport_setup_result setup_transport(void *server,
74 grpc_transport *transport,
75 grpc_mdctx *mdctx) {
76 static grpc_channel_filter const *extra_filters[] = {&grpc_http_server_filter,
77 &grpc_http_filter};
78 return grpc_server_setup_transport(server, transport, extra_filters,
79 GPR_ARRAY_SIZE(extra_filters), mdctx);
80}
81
David Klempnerfd5d8ff2015-03-05 14:17:38 -080082static void on_secure_transport_setup_done(void *statep,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080083 grpc_security_status status,
84 grpc_endpoint *secure_endpoint) {
David Klempnerfd5d8ff2015-03-05 14:17:38 -080085 grpc_server_secure_state *state = statep;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080086 if (status == GRPC_SECURITY_OK) {
David Klempnerfd5d8ff2015-03-05 14:17:38 -080087 gpr_mu_lock(&state->mu);
88 if (!state->is_shutdown) {
Craig Tillerc02c1d82015-04-07 16:21:55 -070089 grpc_create_chttp2_transport(setup_transport, state->server,
90 grpc_server_get_channel_args(state->server),
91 secure_endpoint, NULL, 0,
92 grpc_mdctx_create(), 0);
David Klempnerfd5d8ff2015-03-05 14:17:38 -080093 } else {
94 /* We need to consume this here, because the server may already have gone
95 * away. */
96 grpc_endpoint_destroy(secure_endpoint);
97 }
98 gpr_mu_unlock(&state->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080099 } else {
100 gpr_log(GPR_ERROR, "Secure transport failed with error %d", status);
101 }
David Klempnerfd5d8ff2015-03-05 14:17:38 -0800102 state_unref(state);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800103}
104
David Klempnerfd5d8ff2015-03-05 14:17:38 -0800105static void on_accept(void *statep, grpc_endpoint *tcp) {
106 grpc_server_secure_state *state = statep;
David Klempnerfd5d8ff2015-03-05 14:17:38 -0800107 state_ref(state);
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700108 grpc_setup_secure_transport(state->sc, tcp, on_secure_transport_setup_done,
Craig Tillerc02c1d82015-04-07 16:21:55 -0700109 state);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800110}
111
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800112/* Server callback: start listening on our ports */
David Klempnerfd5d8ff2015-03-05 14:17:38 -0800113static void start(grpc_server *server, void *statep, grpc_pollset **pollsets,
Craig Tiller20bc56d2015-02-12 09:02:56 -0800114 size_t pollset_count) {
David Klempnerfd5d8ff2015-03-05 14:17:38 -0800115 grpc_server_secure_state *state = statep;
116 grpc_tcp_server_start(state->tcp, pollsets, pollset_count, on_accept, state);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800117}
118
119/* Server callback: destroy the tcp listener (so we don't generate further
120 callbacks) */
David Klempnerfd5d8ff2015-03-05 14:17:38 -0800121static void destroy(grpc_server *server, void *statep) {
122 grpc_server_secure_state *state = statep;
123 gpr_mu_lock(&state->mu);
124 state->is_shutdown = 1;
Craig Tillerc02c1d82015-04-07 16:21:55 -0700125 grpc_tcp_server_destroy(state->tcp, grpc_server_listener_destroy_done,
126 server);
David Klempnerfd5d8ff2015-03-05 14:17:38 -0800127 gpr_mu_unlock(&state->mu);
128 state_unref(state);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800129}
130
Craig Tillerc02c1d82015-04-07 16:21:55 -0700131int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
132 grpc_server_credentials *creds) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800133 grpc_resolved_addresses *resolved = NULL;
134 grpc_tcp_server *tcp = NULL;
David Klempnerfd5d8ff2015-03-05 14:17:38 -0800135 grpc_server_secure_state *state = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800136 size_t i;
Nicolas "Pixel" Noble213ed912015-01-30 02:11:35 +0100137 unsigned count = 0;
murgatroid99c896e192015-01-21 11:36:23 -0800138 int port_num = -1;
139 int port_temp;
Craig Tiller759026c2015-02-22 23:09:45 -0800140 grpc_security_status status = GRPC_SECURITY_ERROR;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700141 grpc_security_connector *sc = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800142
Craig Tiller759026c2015-02-22 23:09:45 -0800143 /* create security context */
144 if (creds == NULL) goto error;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700145 status = grpc_server_credentials_create_security_connector(creds, &sc);
Craig Tiller759026c2015-02-22 23:09:45 -0800146 if (status != GRPC_SECURITY_OK) {
147 gpr_log(GPR_ERROR,
148 "Unable to create secure server with credentials of type %s.",
149 creds->type);
150 goto error;
151 }
152
153 /* resolve address */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800154 resolved = grpc_blocking_resolve_address(addr, "https");
155 if (!resolved) {
156 goto error;
157 }
158
ctiller18b49ab2014-12-09 14:39:16 -0800159 tcp = grpc_tcp_server_create();
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800160 if (!tcp) {
161 goto error;
162 }
163
164 for (i = 0; i < resolved->naddrs; i++) {
murgatroid99c896e192015-01-21 11:36:23 -0800165 port_temp = grpc_tcp_server_add_port(
166 tcp, (struct sockaddr *)&resolved->addrs[i].addr,
167 resolved->addrs[i].len);
168 if (port_temp >= 0) {
169 if (port_num == -1) {
170 port_num = port_temp;
171 } else {
172 GPR_ASSERT(port_num == port_temp);
173 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800174 count++;
175 }
176 }
177 if (count == 0) {
178 gpr_log(GPR_ERROR, "No address added out of total %d resolved",
179 resolved->naddrs);
180 goto error;
181 }
182 if (count != resolved->naddrs) {
183 gpr_log(GPR_ERROR, "Only %d addresses added out of total %d resolved",
184 count, resolved->naddrs);
Nicolas "Pixel" Noble213ed912015-01-30 02:11:35 +0100185 /* if it's an error, don't we want to goto error; here ? */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800186 }
187 grpc_resolved_addresses_destroy(resolved);
188
David Klempnerfd5d8ff2015-03-05 14:17:38 -0800189 state = gpr_malloc(sizeof(*state));
190 state->server = server;
191 state->tcp = tcp;
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700192 state->sc = sc;
David Klempnerfd5d8ff2015-03-05 14:17:38 -0800193 state->is_shutdown = 0;
194 gpr_mu_init(&state->mu);
195 gpr_ref_init(&state->refcount, 1);
Craig Tiller759026c2015-02-22 23:09:45 -0800196
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800197 /* Register with the server only upon success */
David Klempnerfd5d8ff2015-03-05 14:17:38 -0800198 grpc_server_add_listener(server, state, start, destroy);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800199
murgatroid99c896e192015-01-21 11:36:23 -0800200 return port_num;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800201
202/* Error path: cleanup and return */
203error:
Julien Boeuf7d1d9ca2015-04-17 14:38:48 -0700204 if (sc) {
205 grpc_security_connector_unref(sc);
Craig Tiller759026c2015-02-22 23:09:45 -0800206 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800207 if (resolved) {
208 grpc_resolved_addresses_destroy(resolved);
209 }
210 if (tcp) {
Craig Tilleraec96aa2015-04-07 14:32:15 -0700211 grpc_tcp_server_destroy(tcp, NULL, NULL);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800212 }
Craig Tiller60a5bfc2015-03-05 17:02:17 -0800213 if (state) {
214 gpr_free(state);
Craig Tiller759026c2015-02-22 23:09:45 -0800215 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800216 return 0;
Craig Tiller190d3602015-02-18 09:23:38 -0800217}