Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 1 | /* |
| 2 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 3 | * Copyright 2015 gRPC authors. |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 4 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 5 | * 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. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 8 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 10 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 11 | * 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. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 16 | * |
| 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 Tiller | e3593d9 | 2017-04-03 14:51:02 -0700 | [diff] [blame] | 31 | #include "src/core/ext/filters/http/server/http_server_filter.h" |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 32 | #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. Roth | 1f0f23c | 2017-01-06 13:07:19 -0800 | [diff] [blame] | 35 | #include "src/core/lib/channel/handshaker_registry.h" |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 36 | #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 Tiller | 6822a7a | 2016-12-06 19:28:52 -0800 | [diff] [blame] | 39 | #include "src/core/lib/slice/slice_internal.h" |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 40 | #include "src/core/lib/surface/api_trace.h" |
| 41 | #include "src/core/lib/surface/server.h" |
| 42 | |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 43 | typedef struct { |
| 44 | grpc_server *server; |
| 45 | grpc_tcp_server *tcp_server; |
| 46 | grpc_channel_args *args; |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 47 | gpr_mu mu; |
| 48 | bool shutdown; |
| 49 | grpc_closure tcp_server_shutdown_complete; |
| 50 | grpc_closure *server_destroy_listener_done; |
yang-g | 6da1e85 | 2017-02-16 10:34:06 -0800 | [diff] [blame] | 51 | grpc_handshake_manager *pending_handshake_mgrs; |
Yash Tibrewal | a495220 | 2017-09-13 10:53:28 -0700 | [diff] [blame] | 52 | } server_state; |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 53 | |
| 54 | typedef struct { |
Yash Tibrewal | a495220 | 2017-09-13 10:53:28 -0700 | [diff] [blame] | 55 | server_state *svr_state; |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 56 | grpc_pollset *accepting_pollset; |
| 57 | grpc_tcp_server_acceptor *acceptor; |
| 58 | grpc_handshake_manager *handshake_mgr; |
| 59 | } server_connection_state; |
| 60 | |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 61 | static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, |
| 62 | grpc_error *error) { |
Yash Tibrewal | ca3c1c0 | 2017-09-07 22:47:16 -0700 | [diff] [blame] | 63 | grpc_handshaker_args *args = (grpc_handshaker_args *)arg; |
| 64 | server_connection_state *connection_state = |
| 65 | (server_connection_state *)args->user_data; |
Yash Tibrewal | a495220 | 2017-09-13 10:53:28 -0700 | [diff] [blame] | 66 | gpr_mu_lock(&connection_state->svr_state->mu); |
| 67 | if (error != GRPC_ERROR_NONE || connection_state->svr_state->shutdown) { |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 68 | const char *error_str = grpc_error_string(error); |
David Garcia Quintas | c3fc834 | 2017-04-21 15:01:18 -0700 | [diff] [blame] | 69 | gpr_log(GPR_DEBUG, "Handshaking failed: %s", error_str); |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 70 | |
Mark D. Roth | 0ee1dbb | 2016-12-09 09:57:20 -0800 | [diff] [blame] | 71 | if (error == GRPC_ERROR_NONE && args->endpoint != NULL) { |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 72 | // 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 Tiller | cda759d | 2017-01-27 11:37:37 -0800 | [diff] [blame] | 78 | grpc_endpoint_shutdown(exec_ctx, args->endpoint, GRPC_ERROR_NONE); |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 79 | grpc_endpoint_destroy(exec_ctx, args->endpoint); |
Craig Tiller | 397bff3 | 2016-12-06 15:05:59 -0800 | [diff] [blame] | 80 | grpc_channel_args_destroy(exec_ctx, args->args); |
Craig Tiller | 6822a7a | 2016-12-06 19:28:52 -0800 | [diff] [blame] | 81 | grpc_slice_buffer_destroy_internal(exec_ctx, args->read_buffer); |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 82 | gpr_free(args->read_buffer); |
| 83 | } |
| 84 | } else { |
Mark D. Roth | 3059828 | 2016-12-07 07:13:58 -0800 | [diff] [blame] | 85 | // 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. Roth | cc527cf | 2016-12-06 10:43:12 -0800 | [diff] [blame] | 88 | 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 Tibrewal | a495220 | 2017-09-13 10:53:28 -0700 | [diff] [blame] | 92 | exec_ctx, connection_state->svr_state->server, transport, |
Mark D. Roth | cc527cf | 2016-12-06 10:43:12 -0800 | [diff] [blame] | 93 | connection_state->accepting_pollset, args->args); |
| 94 | grpc_chttp2_transport_start_reading(exec_ctx, transport, |
| 95 | args->read_buffer); |
Craig Tiller | 1a7c57b | 2016-12-12 06:38:13 -0800 | [diff] [blame] | 96 | grpc_channel_args_destroy(exec_ctx, args->args); |
Mark D. Roth | cc527cf | 2016-12-06 10:43:12 -0800 | [diff] [blame] | 97 | } |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 98 | } |
yang-g | 6da1e85 | 2017-02-16 10:34:06 -0800 | [diff] [blame] | 99 | grpc_handshake_manager_pending_list_remove( |
Yash Tibrewal | a495220 | 2017-09-13 10:53:28 -0700 | [diff] [blame] | 100 | &connection_state->svr_state->pending_handshake_mgrs, |
yang-g | 6da1e85 | 2017-02-16 10:34:06 -0800 | [diff] [blame] | 101 | connection_state->handshake_mgr); |
Yash Tibrewal | a495220 | 2017-09-13 10:53:28 -0700 | [diff] [blame] | 102 | gpr_mu_unlock(&connection_state->svr_state->mu); |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 103 | grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr); |
Yash Tibrewal | a495220 | 2017-09-13 10:53:28 -0700 | [diff] [blame] | 104 | grpc_tcp_server_unref(exec_ctx, connection_state->svr_state->tcp_server); |
Mark D. Roth | eed3815 | 2016-12-08 13:59:13 -0800 | [diff] [blame] | 105 | gpr_free(connection_state->acceptor); |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 106 | gpr_free(connection_state); |
| 107 | } |
| 108 | |
| 109 | static 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 Tibrewal | a495220 | 2017-09-13 10:53:28 -0700 | [diff] [blame] | 112 | server_state *state = (server_state *)arg; |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 113 | gpr_mu_lock(&state->mu); |
| 114 | if (state->shutdown) { |
| 115 | gpr_mu_unlock(&state->mu); |
Makarand Dharmapurikar | 9c156da | 2017-05-18 10:32:13 -0700 | [diff] [blame] | 116 | grpc_endpoint_shutdown(exec_ctx, tcp, GRPC_ERROR_NONE); |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 117 | grpc_endpoint_destroy(exec_ctx, tcp); |
Mark D. Roth | 96ba68d | 2016-12-09 17:21:26 +0000 | [diff] [blame] | 118 | gpr_free(acceptor); |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 119 | return; |
| 120 | } |
| 121 | grpc_handshake_manager *handshake_mgr = grpc_handshake_manager_create(); |
yang-g | 6da1e85 | 2017-02-16 10:34:06 -0800 | [diff] [blame] | 122 | grpc_handshake_manager_pending_list_add(&state->pending_handshake_mgrs, |
| 123 | handshake_mgr); |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 124 | gpr_mu_unlock(&state->mu); |
| 125 | grpc_tcp_server_ref(state->tcp_server); |
| 126 | server_connection_state *connection_state = |
Yash Tibrewal | bc130da | 2017-09-12 22:44:08 -0700 | [diff] [blame] | 127 | (server_connection_state *)gpr_malloc(sizeof(*connection_state)); |
Yash Tibrewal | a495220 | 2017-09-13 10:53:28 -0700 | [diff] [blame] | 128 | connection_state->svr_state = state; |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 129 | connection_state->accepting_pollset = accepting_pollset; |
| 130 | connection_state->acceptor = acceptor; |
| 131 | connection_state->handshake_mgr = handshake_mgr; |
Mark D. Roth | 1f0f23c | 2017-01-06 13:07:19 -0800 | [diff] [blame] | 132 | grpc_handshakers_add(exec_ctx, HANDSHAKER_SERVER, state->args, |
| 133 | connection_state->handshake_mgr); |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 134 | // 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 Tiller | 73122ba | 2016-12-05 08:16:58 -0800 | [diff] [blame] | 138 | 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. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 141 | } |
| 142 | |
| 143 | /* Server callback: start listening on our ports */ |
| 144 | static void server_start_listener(grpc_exec_ctx *exec_ctx, grpc_server *server, |
| 145 | void *arg, grpc_pollset **pollsets, |
| 146 | size_t pollset_count) { |
Yash Tibrewal | a495220 | 2017-09-13 10:53:28 -0700 | [diff] [blame] | 147 | server_state *state = (server_state *)arg; |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 148 | 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 | |
| 155 | static void tcp_server_shutdown_complete(grpc_exec_ctx *exec_ctx, void *arg, |
| 156 | grpc_error *error) { |
Yash Tibrewal | a495220 | 2017-09-13 10:53:28 -0700 | [diff] [blame] | 157 | server_state *state = (server_state *)arg; |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 158 | /* 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-g | 6da1e85 | 2017-02-16 10:34:06 -0800 | [diff] [blame] | 162 | grpc_handshake_manager_pending_list_shutdown_all( |
| 163 | exec_ctx, state->pending_handshake_mgrs, GRPC_ERROR_REF(error)); |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 164 | 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. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 168 | 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 Tiller | 397bff3 | 2016-12-06 15:05:59 -0800 | [diff] [blame] | 172 | grpc_channel_args_destroy(exec_ctx, state->args); |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 173 | 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) */ |
| 179 | static void server_destroy_listener(grpc_exec_ctx *exec_ctx, |
| 180 | grpc_server *server, void *arg, |
| 181 | grpc_closure *destroy_done) { |
Yash Tibrewal | a495220 | 2017-09-13 10:53:28 -0700 | [diff] [blame] | 182 | server_state *state = (server_state *)arg; |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 183 | 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. Roth | 1f0f23c | 2017-01-06 13:07:19 -0800 | [diff] [blame] | 192 | grpc_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. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 196 | 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 Tibrewal | a495220 | 2017-09-13 10:53:28 -0700 | [diff] [blame] | 202 | server_state *state = NULL; |
Mark D. Roth | a0bcfbb | 2016-12-02 12:10:25 -0800 | [diff] [blame] | 203 | grpc_error **errors = NULL; |
Yash Tibrewal | 533d118 | 2017-09-18 10:48:22 -0700 | [diff] [blame^] | 204 | size_t naddrs = 0; |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 205 | |
| 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 Tibrewal | a495220 | 2017-09-13 10:53:28 -0700 | [diff] [blame] | 213 | state = (server_state *)gpr_zalloc(sizeof(*state)); |
ncteisen | 274bbbe | 2017-06-08 14:57:11 -0700 | [diff] [blame] | 214 | GRPC_CLOSURE_INIT(&state->tcp_server_shutdown_complete, |
Craig Tiller | 91031da | 2016-12-28 15:44:25 -0800 | [diff] [blame] | 215 | tcp_server_shutdown_complete, state, |
| 216 | grpc_schedule_on_exec_ctx); |
Craig Tiller | 73122ba | 2016-12-05 08:16:58 -0800 | [diff] [blame] | 217 | err = grpc_tcp_server_create(exec_ctx, &state->tcp_server_shutdown_complete, |
| 218 | args, &tcp_server); |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 219 | 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. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 226 | state->shutdown = true; |
| 227 | gpr_mu_init(&state->mu); |
| 228 | |
Yash Tibrewal | 533d118 | 2017-09-18 10:48:22 -0700 | [diff] [blame^] | 229 | naddrs = resolved->naddrs; |
Yash Tibrewal | ca3c1c0 | 2017-09-07 22:47:16 -0700 | [diff] [blame] | 230 | errors = (grpc_error **)gpr_malloc(sizeof(*errors) * naddrs); |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 231 | 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); |
ncteisen | 4b36a3d | 2017-03-13 19:08:06 -0700 | [diff] [blame] | 247 | err = GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(msg, errors, naddrs); |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 248 | 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); |
ncteisen | 4b36a3d | 2017-03-13 19:08:06 -0700 | [diff] [blame] | 255 | err = GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(msg, errors, naddrs); |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 256 | gpr_free(msg); |
| 257 | |
| 258 | const char *warning_message = grpc_error_string(err); |
| 259 | gpr_log(GPR_INFO, "WARNING: %s", warning_message); |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 260 | |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 261 | /* 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 */ |
| 271 | error: |
| 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. Roth | 0f4bbba | 2016-12-02 22:16:03 +0000 | [diff] [blame] | 278 | } else { |
Craig Tiller | 397bff3 | 2016-12-06 15:05:59 -0800 | [diff] [blame] | 279 | grpc_channel_args_destroy(exec_ctx, args); |
Mark D. Roth | 0f4bbba | 2016-12-02 22:16:03 +0000 | [diff] [blame] | 280 | gpr_free(state); |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 281 | } |
Mark D. Roth | 7140382 | 2016-12-02 10:51:39 -0800 | [diff] [blame] | 282 | *port_num = 0; |
| 283 | |
| 284 | done: |
| 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 | } |