blob: 6c82f47d719eed71339fa0076cee02ebc318bfa8 [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
Craig Tiller0c0b60c2015-01-21 15:49:28 -080034#include <grpc/support/port_platform.h>
35
36#ifdef GPR_POSIX_SOCKET
37
Craig Tiller86958762016-09-23 12:05:34 -070038#include "src/core/lib/iomgr/tcp_client_posix.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080039
40#include <errno.h>
nnoble0c475f02014-12-05 15:37:39 -080041#include <netinet/in.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080042#include <string.h>
43#include <unistd.h>
44
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080045#include <grpc/support/alloc.h>
46#include <grpc/support/log.h>
Masood Malekghassemi701af602015-06-03 15:01:17 -070047#include <grpc/support/string_util.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080048#include <grpc/support/time.h>
49
Craig Tiller86958762016-09-23 12:05:34 -070050#include "src/core/lib/channel/channel_args.h"
Craig Tiller8a034482016-03-28 16:09:04 -070051#include "src/core/lib/iomgr/ev_posix.h"
Craig Tiller9533d042016-03-25 17:11:06 -070052#include "src/core/lib/iomgr/iomgr_posix.h"
Craig Tiller9533d042016-03-25 17:11:06 -070053#include "src/core/lib/iomgr/sockaddr_utils.h"
54#include "src/core/lib/iomgr/socket_utils_posix.h"
55#include "src/core/lib/iomgr/tcp_posix.h"
56#include "src/core/lib/iomgr/timer.h"
57#include "src/core/lib/iomgr/unix_sockets_posix.h"
58#include "src/core/lib/support/string.h"
Craig Tillerc46beaa2016-02-24 09:17:19 -080059
Craig Tiller5e53ddb2015-09-16 10:53:15 -070060extern int grpc_tcp_trace;
61
Craig Tillera82950e2015-09-22 12:33:20 -070062typedef struct {
ctiller58393c22015-01-07 14:03:30 -080063 gpr_mu mu;
ctiller18b49ab2014-12-09 14:39:16 -080064 grpc_fd *fd;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080065 gpr_timespec deadline;
David Garcia Quintasf747bbc2015-10-04 23:09:47 -070066 grpc_timer alarm;
ctiller58393c22015-01-07 14:03:30 -080067 int refs;
Craig Tiller33825112015-09-18 07:44:19 -070068 grpc_closure write_closure;
Craig Tillerb49736822015-06-30 08:15:08 -070069 grpc_pollset_set *interested_parties;
Craig Tiller1b22b9d2015-07-20 13:42:22 -070070 char *addr_str;
Craig Tillerd1bec032015-09-18 17:29:00 -070071 grpc_endpoint **ep;
72 grpc_closure *closure;
Craig Tiller86958762016-09-23 12:05:34 -070073 grpc_channel_args *channel_args;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080074} async_connect;
75
Craig Tiller27f59af2016-04-28 14:19:48 -070076static grpc_error *prepare_socket(const struct sockaddr *addr, int fd) {
77 grpc_error *err = GRPC_ERROR_NONE;
78
Craig Tiller80384bd2016-05-06 16:12:31 -070079 GPR_ASSERT(fd >= 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080080
Craig Tiller4f1d0f32016-05-06 17:12:37 -070081 err = grpc_set_socket_nonblocking(fd, 1);
82 if (err != GRPC_ERROR_NONE) goto error;
83 err = grpc_set_socket_cloexec(fd, 1);
84 if (err != GRPC_ERROR_NONE) goto error;
85 if (!grpc_is_unix_socket(addr)) {
86 err = grpc_set_socket_low_latency(fd, 1);
87 if (err != GRPC_ERROR_NONE) goto error;
Craig Tillera82950e2015-09-22 12:33:20 -070088 }
Craig Tiller4f1d0f32016-05-06 17:12:37 -070089 err = grpc_set_socket_no_sigpipe_if_possible(fd);
90 if (err != GRPC_ERROR_NONE) goto error;
Craig Tiller27f59af2016-04-28 14:19:48 -070091 goto done;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080092
93error:
Craig Tillera82950e2015-09-22 12:33:20 -070094 if (fd >= 0) {
95 close(fd);
96 }
Craig Tiller27f59af2016-04-28 14:19:48 -070097done:
98 return err;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080099}
100
Craig Tillerc027e772016-05-03 16:27:00 -0700101static void tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) {
ctiller58393c22015-01-07 14:03:30 -0800102 int done;
103 async_connect *ac = acp;
Craig Tillera82950e2015-09-22 12:33:20 -0700104 if (grpc_tcp_trace) {
Craig Tillerc027e772016-05-03 16:27:00 -0700105 const char *str = grpc_error_string(error);
106 gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: error=%s", ac->addr_str,
107 str);
108 grpc_error_free_string(str);
Craig Tillera82950e2015-09-22 12:33:20 -0700109 }
110 gpr_mu_lock(&ac->mu);
111 if (ac->fd != NULL) {
112 grpc_fd_shutdown(exec_ctx, ac->fd);
113 }
ctiller58393c22015-01-07 14:03:30 -0800114 done = (--ac->refs == 0);
Craig Tillera82950e2015-09-22 12:33:20 -0700115 gpr_mu_unlock(&ac->mu);
116 if (done) {
117 gpr_mu_destroy(&ac->mu);
118 gpr_free(ac->addr_str);
Craig Tiller86958762016-09-23 12:05:34 -0700119 grpc_channel_args_destroy(ac->channel_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700120 gpr_free(ac);
121 }
ctiller58393c22015-01-07 14:03:30 -0800122}
123
Craig Tiller86958762016-09-23 12:05:34 -0700124grpc_endpoint *grpc_tcp_client_create_from_fd(
125 grpc_exec_ctx *exec_ctx, grpc_fd *fd, const grpc_channel_args *channel_args,
126 const char *addr_str) {
127 size_t tcp_read_chunk_size = GRPC_TCP_DEFAULT_READ_SLICE_SIZE;
Craig Tilleref6b9762016-09-28 08:37:51 -0700128 grpc_buffer_pool *buffer_pool = grpc_buffer_pool_create(NULL);
Craig Tiller86958762016-09-23 12:05:34 -0700129 if (channel_args != NULL) {
130 for (size_t i = 0; i < channel_args->num_args; i++) {
131 if (0 ==
132 strcmp(channel_args->args[i].key, GRPC_ARG_TCP_READ_CHUNK_SIZE)) {
133 grpc_integer_options options = {(int)tcp_read_chunk_size, 1,
134 8 * 1024 * 1024};
135 tcp_read_chunk_size = (size_t)grpc_channel_arg_get_integer(
136 &channel_args->args[i], options);
137 } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_BUFFER_POOL)) {
138 grpc_buffer_pool_internal_unref(exec_ctx, buffer_pool);
139 buffer_pool = grpc_buffer_pool_internal_ref(
140 channel_args->args[i].value.pointer.p);
141 }
142 }
143 }
144
145 grpc_endpoint *ep =
146 grpc_tcp_create(fd, buffer_pool, tcp_read_chunk_size, addr_str);
147 grpc_buffer_pool_internal_unref(exec_ctx, buffer_pool);
148 return ep;
149}
150
Craig Tillerc027e772016-05-03 16:27:00 -0700151static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800152 async_connect *ac = acp;
153 int so_error = 0;
154 socklen_t so_error_size;
155 int err;
ctiller58393c22015-01-07 14:03:30 -0800156 int done;
Craig Tillerd1bec032015-09-18 17:29:00 -0700157 grpc_endpoint **ep = ac->ep;
158 grpc_closure *closure = ac->closure;
Craig Tiller5553eb32015-07-21 12:28:56 -0700159 grpc_fd *fd;
160
Craig Tiller82c63eb2016-05-10 15:28:01 -0700161 GRPC_ERROR_REF(error);
162
Craig Tillera82950e2015-09-22 12:33:20 -0700163 if (grpc_tcp_trace) {
Craig Tillerc027e772016-05-03 16:27:00 -0700164 const char *str = grpc_error_string(error);
165 gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_writable: error=%s",
166 ac->addr_str, str);
167 grpc_error_free_string(str);
Craig Tillera82950e2015-09-22 12:33:20 -0700168 }
Craig Tiller5e53ddb2015-09-16 10:53:15 -0700169
Craig Tillera82950e2015-09-22 12:33:20 -0700170 gpr_mu_lock(&ac->mu);
171 GPR_ASSERT(ac->fd);
Craig Tiller5553eb32015-07-21 12:28:56 -0700172 fd = ac->fd;
173 ac->fd = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700174 gpr_mu_unlock(&ac->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800175
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700176 grpc_timer_cancel(exec_ctx, &ac->alarm);
Craig Tiller26205362015-07-21 08:21:57 -0700177
Craig Tillera82950e2015-09-22 12:33:20 -0700178 gpr_mu_lock(&ac->mu);
Mark D. Rothe65ff112016-09-09 13:48:38 -0700179 if (error != GRPC_ERROR_NONE) {
Craig Tiller27f59af2016-04-28 14:19:48 -0700180 error =
181 grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, "Timeout occurred");
Craig Tillera82950e2015-09-22 12:33:20 -0700182 goto finish;
183 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800184
Mark D. Rothe65ff112016-09-09 13:48:38 -0700185 do {
186 so_error_size = sizeof(so_error);
187 err = getsockopt(grpc_fd_wrapped_fd(fd), SOL_SOCKET, SO_ERROR, &so_error,
188 &so_error_size);
189 } while (err < 0 && errno == EINTR);
190 if (err < 0) {
191 error = GRPC_OS_ERROR(errno, "getsockopt");
192 goto finish;
193 }
194
195 switch (so_error) {
196 case 0:
197 grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd);
Craig Tillerd88c4612016-09-29 10:35:38 -0700198 *ep = grpc_tcp_client_create_from_fd(exec_ctx, fd, ac->channel_args,
199 +ac->addr_str);
Mark D. Rothe65ff112016-09-09 13:48:38 -0700200 fd = NULL;
201 break;
202 case ENOBUFS:
203 /* We will get one of these errors if we have run out of
204 memory in the kernel for the data structures allocated
205 when you connect a socket. If this happens it is very
206 likely that if we wait a little bit then try again the
207 connection will work (since other programs or this
208 program will close their network connections and free up
209 memory). This does _not_ indicate that there is anything
210 wrong with the server we are connecting to, this is a
211 local problem.
212
213 If you are looking at this code, then chances are that
214 your program or another program on the same computer
215 opened too many network connections. The "easy" fix:
216 don't do that! */
217 gpr_log(GPR_ERROR, "kernel out of buffers");
218 gpr_mu_unlock(&ac->mu);
219 grpc_fd_notify_on_write(exec_ctx, fd, &ac->write_closure);
220 return;
221 case ECONNREFUSED:
222 /* This error shouldn't happen for anything other than connect(). */
223 error = GRPC_OS_ERROR(so_error, "connect");
224 break;
225 default:
226 /* We don't really know which syscall triggered the problem here,
227 so punt by reporting getsockopt(). */
228 error = GRPC_OS_ERROR(so_error, "getsockopt(SO_ERROR)");
229 break;
230 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800231
ctiller58393c22015-01-07 14:03:30 -0800232finish:
Craig Tillera82950e2015-09-22 12:33:20 -0700233 if (fd != NULL) {
234 grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd);
yang-g5d850372015-12-01 10:32:28 -0800235 grpc_fd_orphan(exec_ctx, fd, NULL, NULL, "tcp_client_orphan");
Craig Tillera82950e2015-09-22 12:33:20 -0700236 fd = NULL;
237 }
ctiller58393c22015-01-07 14:03:30 -0800238 done = (--ac->refs == 0);
Craig Tillera82950e2015-09-22 12:33:20 -0700239 gpr_mu_unlock(&ac->mu);
Craig Tiller27f59af2016-04-28 14:19:48 -0700240 if (error != GRPC_ERROR_NONE) {
241 error = grpc_error_set_str(error, GRPC_ERROR_STR_DESCRIPTION,
242 "Failed to connect to remote host");
243 error =
244 grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS, ac->addr_str);
245 }
Craig Tillera82950e2015-09-22 12:33:20 -0700246 if (done) {
247 gpr_mu_destroy(&ac->mu);
248 gpr_free(ac->addr_str);
Craig Tiller287928c2016-09-23 16:04:30 -0700249 grpc_channel_args_destroy(ac->channel_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700250 gpr_free(ac);
251 }
Craig Tiller332f1b32016-05-24 13:21:21 -0700252 grpc_exec_ctx_sched(exec_ctx, closure, error, NULL);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800253}
254
Craig Tillere6282612016-04-13 14:14:34 -0700255static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx,
256 grpc_closure *closure, grpc_endpoint **ep,
257 grpc_pollset_set *interested_parties,
Craig Tiller86958762016-09-23 12:05:34 -0700258 const grpc_channel_args *channel_args,
Craig Tillere6282612016-04-13 14:14:34 -0700259 const struct sockaddr *addr,
260 size_t addr_len, gpr_timespec deadline) {
nnoble0c475f02014-12-05 15:37:39 -0800261 int fd;
262 grpc_dualstack_mode dsmode;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800263 int err;
264 async_connect *ac;
nnoble0c475f02014-12-05 15:37:39 -0800265 struct sockaddr_in6 addr6_v4mapped;
266 struct sockaddr_in addr4_copy;
Craig Tiller9bcc7512015-05-11 14:59:48 -0700267 grpc_fd *fdobj;
Craig Tillerfa275a92015-06-01 13:55:54 -0700268 char *name;
269 char *addr_str;
Craig Tiller27f59af2016-04-28 14:19:48 -0700270 grpc_error *error;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800271
Craig Tillerd1bec032015-09-18 17:29:00 -0700272 *ep = NULL;
273
nnoble0c475f02014-12-05 15:37:39 -0800274 /* Use dualstack sockets where available. */
Craig Tillera82950e2015-09-22 12:33:20 -0700275 if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
276 addr = (const struct sockaddr *)&addr6_v4mapped;
277 addr_len = sizeof(addr6_v4mapped);
278 }
nnoble0c475f02014-12-05 15:37:39 -0800279
Craig Tiller27f59af2016-04-28 14:19:48 -0700280 error = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
281 if (error != GRPC_ERROR_NONE) {
Craig Tiller332f1b32016-05-24 13:21:21 -0700282 grpc_exec_ctx_sched(exec_ctx, closure, error, NULL);
Craig Tiller27f59af2016-04-28 14:19:48 -0700283 return;
Craig Tillera82950e2015-09-22 12:33:20 -0700284 }
285 if (dsmode == GRPC_DSMODE_IPV4) {
286 /* If we got an AF_INET socket, map the address back to IPv4. */
287 GPR_ASSERT(grpc_sockaddr_is_v4mapped(addr, &addr4_copy));
288 addr = (struct sockaddr *)&addr4_copy;
289 addr_len = sizeof(addr4_copy);
290 }
Craig Tiller27f59af2016-04-28 14:19:48 -0700291 if ((error = prepare_socket(addr, fd)) != GRPC_ERROR_NONE) {
Craig Tiller332f1b32016-05-24 13:21:21 -0700292 grpc_exec_ctx_sched(exec_ctx, closure, error, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700293 return;
294 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800295
Craig Tillera82950e2015-09-22 12:33:20 -0700296 do {
297 GPR_ASSERT(addr_len < ~(socklen_t)0);
298 err = connect(fd, addr, (socklen_t)addr_len);
299 } while (err < 0 && errno == EINTR);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800300
Craig Tillera82950e2015-09-22 12:33:20 -0700301 addr_str = grpc_sockaddr_to_uri(addr);
302 gpr_asprintf(&name, "tcp-client:%s", addr_str);
Craig Tillerfa275a92015-06-01 13:55:54 -0700303
Craig Tillera82950e2015-09-22 12:33:20 -0700304 fdobj = grpc_fd_create(fd, name);
Craig Tiller9bcc7512015-05-11 14:59:48 -0700305
Craig Tillera82950e2015-09-22 12:33:20 -0700306 if (err >= 0) {
Craig Tiller86958762016-09-23 12:05:34 -0700307 *ep =
308 grpc_tcp_client_create_from_fd(exec_ctx, fdobj, channel_args, addr_str);
Craig Tiller332f1b32016-05-24 13:21:21 -0700309 grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_NONE, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700310 goto done;
311 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800312
Craig Tillera82950e2015-09-22 12:33:20 -0700313 if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
yang-g5d850372015-12-01 10:32:28 -0800314 grpc_fd_orphan(exec_ctx, fdobj, NULL, NULL, "tcp_client_connect_error");
Craig Tiller332f1b32016-05-24 13:21:21 -0700315 grpc_exec_ctx_sched(exec_ctx, closure, GRPC_OS_ERROR(errno, "connect"),
Craig Tiller77c983d2016-05-24 13:23:14 -0700316 NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700317 goto done;
318 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800319
Craig Tillera82950e2015-09-22 12:33:20 -0700320 grpc_pollset_set_add_fd(exec_ctx, interested_parties, fdobj);
Craig Tiller4b678bd2015-06-02 16:12:24 -0700321
Craig Tillera82950e2015-09-22 12:33:20 -0700322 ac = gpr_malloc(sizeof(async_connect));
Craig Tillerd1bec032015-09-18 17:29:00 -0700323 ac->closure = closure;
324 ac->ep = ep;
Craig Tiller9bcc7512015-05-11 14:59:48 -0700325 ac->fd = fdobj;
Craig Tillerb49736822015-06-30 08:15:08 -0700326 ac->interested_parties = interested_parties;
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700327 ac->addr_str = addr_str;
328 addr_str = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700329 gpr_mu_init(&ac->mu);
ctiller58393c22015-01-07 14:03:30 -0800330 ac->refs = 2;
Craig Tiller0fcd53c2015-02-18 15:10:53 -0800331 ac->write_closure.cb = on_writable;
332 ac->write_closure.cb_arg = ac;
Craig Tiller86958762016-09-23 12:05:34 -0700333 ac->channel_args = grpc_channel_args_copy(channel_args);
ctiller58393c22015-01-07 14:03:30 -0800334
Craig Tillera82950e2015-09-22 12:33:20 -0700335 if (grpc_tcp_trace) {
336 gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting",
337 ac->addr_str);
338 }
Craig Tiller5e53ddb2015-09-16 10:53:15 -0700339
Craig Tillera82950e2015-09-22 12:33:20 -0700340 gpr_mu_lock(&ac->mu);
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700341 grpc_timer_init(exec_ctx, &ac->alarm,
Craig Tillera82950e2015-09-22 12:33:20 -0700342 gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
343 tc_on_alarm, ac, gpr_now(GPR_CLOCK_MONOTONIC));
344 grpc_fd_notify_on_write(exec_ctx, ac->fd, &ac->write_closure);
345 gpr_mu_unlock(&ac->mu);
Craig Tillerfa275a92015-06-01 13:55:54 -0700346
347done:
Craig Tillera82950e2015-09-22 12:33:20 -0700348 gpr_free(name);
349 gpr_free(addr_str);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800350}
Craig Tiller0c0b60c2015-01-21 15:49:28 -0800351
Craig Tillere6282612016-04-13 14:14:34 -0700352// overridden by api_fuzzer.c
353void (*grpc_tcp_client_connect_impl)(
354 grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep,
Craig Tiller86958762016-09-23 12:05:34 -0700355 grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args,
Craig Tillere34c2852016-09-23 09:43:32 -0700356 const struct sockaddr *addr, size_t addr_len,
357 gpr_timespec deadline) = tcp_client_connect_impl;
Craig Tillere6282612016-04-13 14:14:34 -0700358
359void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
360 grpc_endpoint **ep,
361 grpc_pollset_set *interested_parties,
Craig Tiller86958762016-09-23 12:05:34 -0700362 const grpc_channel_args *channel_args,
Craig Tillere6282612016-04-13 14:14:34 -0700363 const struct sockaddr *addr, size_t addr_len,
364 gpr_timespec deadline) {
Craig Tillere34c2852016-09-23 09:43:32 -0700365 grpc_tcp_client_connect_impl(exec_ctx, closure, ep, interested_parties,
Craig Tiller86958762016-09-23 12:05:34 -0700366 channel_args, addr, addr_len, deadline);
Craig Tillere6282612016-04-13 14:14:34 -0700367}
368
Craig Tiller190d3602015-02-18 09:23:38 -0800369#endif