blob: da3e284fcf22bca25dcf6bc91543c06d995b413d [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * 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
Craig Tillerf40df232016-03-25 13:38:14 -070038#include <grpc/support/alloc.h>
39#include <grpc/support/log.h>
Craig Tiller804ff712016-05-05 16:25:40 -070040#include <grpc/support/string_util.h>
Craig Tillerf40df232016-03-25 13:38:14 -070041#include <grpc/support/sync.h>
42#include <grpc/support/useful.h>
Craig Tilleradcb92d2016-03-28 10:14:05 -070043#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
Craig Tiller9533d042016-03-25 17:11:06 -070044#include "src/core/lib/channel/channel_args.h"
Mark D. Rothdba5d272016-07-14 13:45:05 -070045#include "src/core/lib/channel/handshaker.h"
Craig Tiller9533d042016-03-25 17:11:06 -070046#include "src/core/lib/channel/http_server_filter.h"
47#include "src/core/lib/iomgr/endpoint.h"
48#include "src/core/lib/iomgr/resolve_address.h"
49#include "src/core/lib/iomgr/tcp_server.h"
Julien Boeuf8ca294e2016-05-02 14:56:30 -070050#include "src/core/lib/security/context/security_context.h"
51#include "src/core/lib/security/credentials/credentials.h"
52#include "src/core/lib/security/transport/auth_filters.h"
53#include "src/core/lib/security/transport/security_connector.h"
Craig Tiller9533d042016-03-25 17:11:06 -070054#include "src/core/lib/surface/api_trace.h"
55#include "src/core/lib/surface/server.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080056
Craig Tiller9f9d4222016-05-16 17:02:14 -070057typedef struct server_secure_state {
David Klempnerfd5d8ff2015-03-05 14:17:38 -080058 grpc_server *server;
59 grpc_tcp_server *tcp;
Julien Boeuf4f4d37c2016-02-24 22:07:36 -080060 grpc_server_security_connector *sc;
Julien Boeuffe1478f2015-08-30 21:57:38 -070061 grpc_server_credentials *creds;
Mark D. Rotha228e5f2016-07-22 09:02:15 -070062 bool is_shutdown;
David Klempnerfd5d8ff2015-03-05 14:17:38 -080063 gpr_mu mu;
64 gpr_refcount refcount;
Craig Tillerd1bec032015-09-18 17:29:00 -070065 grpc_closure destroy_closure;
Craig Tillerdfff1b82015-09-21 14:39:57 -070066 grpc_closure *destroy_callback;
Craig Tiller9f9d4222016-05-16 17:02:14 -070067} server_secure_state;
David Klempnerfd5d8ff2015-03-05 14:17:38 -080068
Craig Tiller9f9d4222016-05-16 17:02:14 -070069typedef struct server_secure_connect {
70 server_secure_state *state;
71 grpc_pollset *accepting_pollset;
Mark D. Rothdba5d272016-07-14 13:45:05 -070072 grpc_tcp_server_acceptor *acceptor;
Mark D. Rothdba5d272016-07-14 13:45:05 -070073 grpc_handshake_manager *handshake_mgr;
Mark D. Roth45015dc2016-07-15 08:48:25 -070074 // TODO(roth): Remove the following two fields when we eliminate
75 // grpc_server_security_connector_do_handshake().
76 gpr_timespec deadline;
Mark D. Rothb3ce1782016-07-20 09:25:25 -070077 grpc_channel_args *args;
Craig Tiller9f9d4222016-05-16 17:02:14 -070078} server_secure_connect;
David Klempnerfd5d8ff2015-03-05 14:17:38 -080079
Craig Tiller9f9d4222016-05-16 17:02:14 -070080static void state_ref(server_secure_state *state) { gpr_ref(&state->refcount); }
81
82static void state_unref(server_secure_state *state) {
Craig Tillera82950e2015-09-22 12:33:20 -070083 if (gpr_unref(&state->refcount)) {
84 /* ensure all threads have unlocked */
85 gpr_mu_lock(&state->mu);
86 gpr_mu_unlock(&state->mu);
87 /* clean up */
Julien Boeuf4f4d37c2016-02-24 22:07:36 -080088 GRPC_SECURITY_CONNECTOR_UNREF(&state->sc->base, "server");
Craig Tillera82950e2015-09-22 12:33:20 -070089 grpc_server_credentials_unref(state->creds);
90 gpr_free(state);
91 }
David Klempnerfd5d8ff2015-03-05 14:17:38 -080092}
93
Craig Tillera82950e2015-09-22 12:33:20 -070094static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep,
95 grpc_security_status status,
Julien Boeuf366f42c2015-12-16 22:05:46 -080096 grpc_endpoint *secure_endpoint,
97 grpc_auth_context *auth_context) {
Craig Tiller9f9d4222016-05-16 17:02:14 -070098 server_secure_connect *state = statep;
Craig Tillera82950e2015-09-22 12:33:20 -070099 if (status == GRPC_SECURITY_OK) {
yang-g5e7f08a2015-11-19 01:27:43 -0800100 if (secure_endpoint) {
Craig Tiller9f9d4222016-05-16 17:02:14 -0700101 gpr_mu_lock(&state->state->mu);
102 if (!state->state->is_shutdown) {
Mark D. Rotha228e5f2016-07-22 09:02:15 -0700103 grpc_transport *transport = grpc_create_chttp2_transport(
Craig Tiller9f9d4222016-05-16 17:02:14 -0700104 exec_ctx, grpc_server_get_channel_args(state->state->server),
yang-gd88e1d82015-12-02 13:23:33 -0800105 secure_endpoint, 0);
Craig Tiller9f9d4222016-05-16 17:02:14 -0700106 grpc_arg args_to_add[2];
107 args_to_add[0] = grpc_server_credentials_to_arg(state->state->creds);
108 args_to_add[1] = grpc_auth_context_to_arg(auth_context);
Mark D. Roth45015dc2016-07-15 08:48:25 -0700109 grpc_channel_args *args_copy = grpc_channel_args_copy_and_add(
110 state->args, args_to_add, GPR_ARRAY_SIZE(args_to_add));
Craig Tiller9f9d4222016-05-16 17:02:14 -0700111 grpc_server_setup_transport(exec_ctx, state->state->server, transport,
112 state->accepting_pollset, args_copy);
113 grpc_channel_args_destroy(args_copy);
Mark D. Roth7d9f2762016-08-04 11:06:49 -0700114 grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL);
yang-g5e7f08a2015-11-19 01:27:43 -0800115 } else {
116 /* We need to consume this here, because the server may already have
yang-g768999d2015-11-20 10:08:26 -0800117 * gone away. */
yang-g5e7f08a2015-11-19 01:27:43 -0800118 grpc_endpoint_destroy(exec_ctx, secure_endpoint);
119 }
Craig Tiller9f9d4222016-05-16 17:02:14 -0700120 gpr_mu_unlock(&state->state->mu);
David Klempnerfd5d8ff2015-03-05 14:17:38 -0800121 }
Craig Tillera82950e2015-09-22 12:33:20 -0700122 } else {
Craig Tillera82950e2015-09-22 12:33:20 -0700123 gpr_log(GPR_ERROR, "Secure transport failed with error %d", status);
124 }
Mark D. Roth45015dc2016-07-15 08:48:25 -0700125 grpc_channel_args_destroy(state->args);
Craig Tiller9f9d4222016-05-16 17:02:14 -0700126 state_unref(state->state);
127 gpr_free(state);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800128}
129
Mark D. Rothdba5d272016-07-14 13:45:05 -0700130static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint,
Mark D. Roth7d9f2762016-08-04 11:06:49 -0700131 grpc_channel_args *args,
132 gpr_slice_buffer *read_buffer, void *user_data,
Mark D. Rotha228e5f2016-07-22 09:02:15 -0700133 grpc_error *error) {
Mark D. Roth45015dc2016-07-15 08:48:25 -0700134 server_secure_connect *state = user_data;
Mark D. Rotha228e5f2016-07-22 09:02:15 -0700135 if (error != GRPC_ERROR_NONE) {
136 const char *error_str = grpc_error_string(error);
137 gpr_log(GPR_ERROR, "Handshaking failed: %s", error_str);
138 grpc_error_free_string(error_str);
139 GRPC_ERROR_UNREF(error);
Mark D. Roth7d9f2762016-08-04 11:06:49 -0700140 grpc_channel_args_destroy(args);
141 gpr_free(read_buffer);
Mark D. Rotha228e5f2016-07-22 09:02:15 -0700142 grpc_handshake_manager_shutdown(exec_ctx, state->handshake_mgr);
143 grpc_handshake_manager_destroy(exec_ctx, state->handshake_mgr);
Mark D. Rotha228e5f2016-07-22 09:02:15 -0700144 state_unref(state->state);
145 gpr_free(state);
146 return;
147 }
148 grpc_handshake_manager_destroy(exec_ctx, state->handshake_mgr);
149 state->handshake_mgr = NULL;
Mark D. Rothdba5d272016-07-14 13:45:05 -0700150 // TODO(roth, jboeuf): Convert security connector handshaking to use new
151 // handshake API, and then move the code from on_secure_handshake_done()
152 // into this function.
Mark D. Roth45015dc2016-07-15 08:48:25 -0700153 state->args = args;
Mark D. Rothdba5d272016-07-14 13:45:05 -0700154 grpc_server_security_connector_do_handshake(
Mark D. Roth7d9f2762016-08-04 11:06:49 -0700155 exec_ctx, state->state->sc, state->acceptor, endpoint, read_buffer,
156 state->deadline, on_secure_handshake_done, state);
Mark D. Rothdba5d272016-07-14 13:45:05 -0700157}
158
Dan Bornfa6b6062016-01-08 21:01:59 -0800159static void on_accept(grpc_exec_ctx *exec_ctx, void *statep, grpc_endpoint *tcp,
Craig Tiller9f9d4222016-05-16 17:02:14 -0700160 grpc_pollset *accepting_pollset,
Dan Born5d81d152016-01-12 20:29:29 -0800161 grpc_tcp_server_acceptor *acceptor) {
Craig Tiller9f9d4222016-05-16 17:02:14 -0700162 server_secure_connect *state = gpr_malloc(sizeof(*state));
163 state->state = statep;
164 state_ref(state->state);
165 state->accepting_pollset = accepting_pollset;
Mark D. Rothdba5d272016-07-14 13:45:05 -0700166 state->acceptor = acceptor;
Mark D. Roth45015dc2016-07-15 08:48:25 -0700167 state->handshake_mgr = grpc_handshake_manager_create();
Mark D. Rothdba5d272016-07-14 13:45:05 -0700168 // TODO(roth): We should really get this timeout value from channel
169 // args instead of hard-coding it.
170 state->deadline = gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
171 gpr_time_from_seconds(120, GPR_TIMESPAN));
Mark D. Roth45015dc2016-07-15 08:48:25 -0700172 grpc_handshake_manager_do_handshake(
173 exec_ctx, state->handshake_mgr, tcp,
174 grpc_server_get_channel_args(state->state->server), state->deadline,
Mark D. Roth5682a522016-07-20 09:54:41 -0700175 acceptor, on_handshake_done, state);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800176}
177
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800178/* Server callback: start listening on our ports */
Craig Tillera82950e2015-09-22 12:33:20 -0700179static void start(grpc_exec_ctx *exec_ctx, grpc_server *server, void *statep,
180 grpc_pollset **pollsets, size_t pollset_count) {
Craig Tiller9f9d4222016-05-16 17:02:14 -0700181 server_secure_state *state = statep;
Craig Tillera82950e2015-09-22 12:33:20 -0700182 grpc_tcp_server_start(exec_ctx, state->tcp, pollsets, pollset_count,
183 on_accept, state);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800184}
185
Craig Tillerf51457b2016-05-03 17:06:32 -0700186static void destroy_done(grpc_exec_ctx *exec_ctx, void *statep,
187 grpc_error *error) {
Craig Tiller9f9d4222016-05-16 17:02:14 -0700188 server_secure_state *state = statep;
Dan Bornfa6b6062016-01-08 21:01:59 -0800189 if (state->destroy_callback != NULL) {
190 state->destroy_callback->cb(exec_ctx, state->destroy_callback->cb_arg,
Craig Tillerf707d622016-05-06 14:26:12 -0700191 GRPC_ERROR_REF(error));
Dan Bornfa6b6062016-01-08 21:01:59 -0800192 }
Julien Boeuf4f4d37c2016-02-24 22:07:36 -0800193 grpc_server_security_connector_shutdown(exec_ctx, state->sc);
Craig Tillera82950e2015-09-22 12:33:20 -0700194 state_unref(state);
Craig Tiller12d7e1f2015-06-03 07:54:48 -0700195}
196
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800197/* Server callback: destroy the tcp listener (so we don't generate further
198 callbacks) */
Craig Tillera82950e2015-09-22 12:33:20 -0700199static void destroy(grpc_exec_ctx *exec_ctx, grpc_server *server, void *statep,
200 grpc_closure *callback) {
Craig Tiller9f9d4222016-05-16 17:02:14 -0700201 server_secure_state *state = statep;
Nicolas "Pixel" Noble04a841f2015-06-23 01:57:21 +0200202 grpc_tcp_server *tcp;
Craig Tillera82950e2015-09-22 12:33:20 -0700203 gpr_mu_lock(&state->mu);
Mark D. Rotha228e5f2016-07-22 09:02:15 -0700204 state->is_shutdown = true;
Craig Tillerdfff1b82015-09-21 14:39:57 -0700205 state->destroy_callback = callback;
Nicolas "Pixel" Noble04a841f2015-06-23 01:57:21 +0200206 tcp = state->tcp;
Craig Tillera82950e2015-09-22 12:33:20 -0700207 gpr_mu_unlock(&state->mu);
yang-g9275d402016-07-11 16:51:39 -0700208 grpc_tcp_server_shutdown_listeners(exec_ctx, tcp);
Dan Bornfa6b6062016-01-08 21:01:59 -0800209 grpc_tcp_server_unref(exec_ctx, tcp);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800210}
211
Craig Tillera82950e2015-09-22 12:33:20 -0700212int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
213 grpc_server_credentials *creds) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800214 grpc_resolved_addresses *resolved = NULL;
215 grpc_tcp_server *tcp = NULL;
Craig Tiller9f9d4222016-05-16 17:02:14 -0700216 server_secure_state *state = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800217 size_t i;
Craig Tiller13c09402016-06-15 09:41:33 -0700218 size_t count = 0;
murgatroid99c896e192015-01-21 11:36:23 -0800219 int port_num = -1;
220 int port_temp;
Craig Tiller759026c2015-02-22 23:09:45 -0800221 grpc_security_status status = GRPC_SECURITY_ERROR;
Julien Boeuf4f4d37c2016-02-24 22:07:36 -0800222 grpc_server_security_connector *sc = NULL;
Craig Tillerf5768a62015-09-22 10:54:34 -0700223 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Craig Tiller5b15afd2016-05-04 15:00:14 -0700224 grpc_error *err = GRPC_ERROR_NONE;
David Garcia Quintas6d0b4d22016-05-12 14:28:36 -0700225 grpc_error **errors = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800226
Craig Tiller4de3e4f2015-10-05 08:55:50 -0700227 GRPC_API_TRACE(
228 "grpc_server_add_secure_http2_port("
229 "server=%p, addr=%s, creds=%p)",
230 3, (server, addr, creds));
Masood Malekghassemi76c3d742015-08-19 18:22:53 -0700231
Craig Tiller759026c2015-02-22 23:09:45 -0800232 /* create security context */
Craig Tillerf5f29042016-06-03 11:29:55 -0700233 if (creds == NULL) {
234 err = GRPC_ERROR_CREATE(
235 "No credentials specified for secure server port (creds==NULL)");
236 goto error;
237 }
Craig Tillera82950e2015-09-22 12:33:20 -0700238 status = grpc_server_credentials_create_security_connector(creds, &sc);
239 if (status != GRPC_SECURITY_OK) {
Craig Tiller80384bd2016-05-06 16:12:31 -0700240 char *msg;
241 gpr_asprintf(&msg,
242 "Unable to create secure server with credentials of type %s.",
243 creds->type);
244 err = grpc_error_set_int(GRPC_ERROR_CREATE(msg),
245 GRPC_ERROR_INT_SECURITY_STATUS, status);
246 gpr_free(msg);
Craig Tiller759026c2015-02-22 23:09:45 -0800247 goto error;
Craig Tillera82950e2015-09-22 12:33:20 -0700248 }
yang-gdd7c1ae2015-11-23 14:29:09 -0800249 sc->channel_args = grpc_server_get_channel_args(server);
Craig Tiller759026c2015-02-22 23:09:45 -0800250
251 /* resolve address */
Craig Tiller2b782d82016-05-04 16:29:57 -0700252 err = grpc_blocking_resolve_address(addr, "https", &resolved);
253 if (err != GRPC_ERROR_NONE) {
Craig Tillera82950e2015-09-22 12:33:20 -0700254 goto error;
255 }
Dan Bornfa6b6062016-01-08 21:01:59 -0800256 state = gpr_malloc(sizeof(*state));
257 memset(state, 0, sizeof(*state));
258 grpc_closure_init(&state->destroy_closure, destroy_done, state);
Craig Tilleref962642016-05-18 22:57:17 -0700259 err = grpc_tcp_server_create(&state->destroy_closure,
260 grpc_server_get_channel_args(server), &tcp);
Craig Tiller2b782d82016-05-04 16:29:57 -0700261 if (err != GRPC_ERROR_NONE) {
Craig Tillera82950e2015-09-22 12:33:20 -0700262 goto error;
263 }
Craig Tiller45724b32015-09-22 10:42:19 -0700264
yang-g9356b472016-02-02 22:33:43 -0800265 state->server = server;
266 state->tcp = tcp;
267 state->sc = sc;
268 state->creds = grpc_server_credentials_ref(creds);
Mark D. Rotha228e5f2016-07-22 09:02:15 -0700269 state->is_shutdown = false;
yang-g9356b472016-02-02 22:33:43 -0800270 gpr_mu_init(&state->mu);
271 gpr_ref_init(&state->refcount, 1);
272
David Garcia Quintas6d0b4d22016-05-12 14:28:36 -0700273 errors = gpr_malloc(sizeof(*errors) * resolved->naddrs);
Craig Tillera82950e2015-09-22 12:33:20 -0700274 for (i = 0; i < resolved->naddrs; i++) {
Craig Tiller0b5857f2016-05-04 10:58:06 -0700275 errors[i] = grpc_tcp_server_add_port(
Craig Tillera82950e2015-09-22 12:33:20 -0700276 tcp, (struct sockaddr *)&resolved->addrs[i].addr,
Craig Tiller5b15afd2016-05-04 15:00:14 -0700277 resolved->addrs[i].len, &port_temp);
Craig Tiller0b5857f2016-05-04 10:58:06 -0700278 if (errors[i] == GRPC_ERROR_NONE) {
Craig Tillera82950e2015-09-22 12:33:20 -0700279 if (port_num == -1) {
280 port_num = port_temp;
281 } else {
282 GPR_ASSERT(port_num == port_temp);
283 }
284 count++;
Craig Tiller45724b32015-09-22 10:42:19 -0700285 }
Craig Tillera82950e2015-09-22 12:33:20 -0700286 }
287 if (count == 0) {
Craig Tiller804ff712016-05-05 16:25:40 -0700288 char *msg;
Craig Tiller13c09402016-06-15 09:41:33 -0700289 gpr_asprintf(&msg, "No address added out of total %" PRIuPTR " resolved",
Craig Tiller804ff712016-05-05 16:25:40 -0700290 resolved->naddrs);
291 err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, resolved->naddrs);
Craig Tillerd9c58962016-05-12 13:28:04 -0700292 gpr_free(msg);
Craig Tillera82950e2015-09-22 12:33:20 -0700293 goto error;
Craig Tiller804ff712016-05-05 16:25:40 -0700294 } else if (count != resolved->naddrs) {
295 char *msg;
Craig Tiller13c09402016-06-15 09:41:33 -0700296 gpr_asprintf(&msg, "Only %" PRIuPTR
297 " addresses added out of total %" PRIuPTR " resolved",
Craig Tiller804ff712016-05-05 16:25:40 -0700298 count, resolved->naddrs);
299 err = GRPC_ERROR_CREATE_REFERENCING(msg, errors, resolved->naddrs);
300 gpr_free(msg);
301
302 const char *warning_message = grpc_error_string(err);
303 gpr_log(GPR_INFO, "WARNING: %s", warning_message);
304 grpc_error_free_string(warning_message);
305 /* we managed to bind some addresses: continue */
306 } else {
307 for (i = 0; i < resolved->naddrs; i++) {
Craig Tillerf707d622016-05-06 14:26:12 -0700308 GRPC_ERROR_UNREF(errors[i]);
Craig Tiller804ff712016-05-05 16:25:40 -0700309 }
Craig Tillera82950e2015-09-22 12:33:20 -0700310 }
Craig Tiller804ff712016-05-05 16:25:40 -0700311 gpr_free(errors);
Craig Tillerd9c58962016-05-12 13:28:04 -0700312 errors = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700313 grpc_resolved_addresses_destroy(resolved);
Craig Tiller45724b32015-09-22 10:42:19 -0700314
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800315 /* Register with the server only upon success */
Craig Tillera82950e2015-09-22 12:33:20 -0700316 grpc_server_add_listener(&exec_ctx, server, state, start, destroy);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800317
Craig Tillera82950e2015-09-22 12:33:20 -0700318 grpc_exec_ctx_finish(&exec_ctx);
murgatroid99c896e192015-01-21 11:36:23 -0800319 return port_num;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800320
321/* Error path: cleanup and return */
322error:
Craig Tiller5b15afd2016-05-04 15:00:14 -0700323 GPR_ASSERT(err != GRPC_ERROR_NONE);
Craig Tillerd9c58962016-05-12 13:28:04 -0700324 if (errors != NULL) {
325 for (i = 0; i < resolved->naddrs; i++) {
326 GRPC_ERROR_UNREF(errors[i]);
327 }
328 gpr_free(errors);
329 }
Craig Tillera82950e2015-09-22 12:33:20 -0700330 if (resolved) {
331 grpc_resolved_addresses_destroy(resolved);
332 }
333 if (tcp) {
Dan Bornfa6b6062016-01-08 21:01:59 -0800334 grpc_tcp_server_unref(&exec_ctx, tcp);
yang-g9356b472016-02-02 22:33:43 -0800335 } else {
336 if (sc) {
Julien Boeuf4f4d37c2016-02-24 22:07:36 -0800337 GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "server");
yang-g9356b472016-02-02 22:33:43 -0800338 }
339 if (state) {
340 gpr_free(state);
341 }
Craig Tillera82950e2015-09-22 12:33:20 -0700342 }
343 grpc_exec_ctx_finish(&exec_ctx);
Craig Tiller80384bd2016-05-06 16:12:31 -0700344 const char *msg = grpc_error_string(err);
345 GRPC_ERROR_UNREF(err);
346 gpr_log(GPR_ERROR, "%s", msg);
347 grpc_error_free_string(msg);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800348 return 0;
Craig Tiller190d3602015-02-18 09:23:38 -0800349}