blob: 3dff6240654092178d89d10a407be123569375c5 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2015 gRPC authors.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * 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
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * 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.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080016 *
17 */
18
murgatroid9954070892016-08-08 17:01:18 -070019#include "src/core/lib/iomgr/port.h"
Craig Tiller0c0b60c2015-01-21 15:49:28 -080020
murgatroid99623dd4f2016-08-08 17:31:27 -070021#ifdef GRPC_POSIX_SOCKET
Craig Tiller0c0b60c2015-01-21 15:49:28 -080022
Craig Tiller86958762016-09-23 12:05:34 -070023#include "src/core/lib/iomgr/tcp_client_posix.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080024
25#include <errno.h>
nnoble0c475f02014-12-05 15:37:39 -080026#include <netinet/in.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080027#include <string.h>
28#include <unistd.h>
29
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080030#include <grpc/support/alloc.h>
31#include <grpc/support/log.h>
Masood Malekghassemi701af602015-06-03 15:01:17 -070032#include <grpc/support/string_util.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080033#include <grpc/support/time.h>
34
Craig Tiller86958762016-09-23 12:05:34 -070035#include "src/core/lib/channel/channel_args.h"
Mark D. Rothdbdf4952018-01-18 11:21:12 -080036#include "src/core/lib/gpr/string.h"
Craig Tiller8a034482016-03-28 16:09:04 -070037#include "src/core/lib/iomgr/ev_posix.h"
Craig Tiller9533d042016-03-25 17:11:06 -070038#include "src/core/lib/iomgr/iomgr_posix.h"
Craig Tiller9533d042016-03-25 17:11:06 -070039#include "src/core/lib/iomgr/sockaddr_utils.h"
Yuchen Zengde3daf52016-10-13 17:26:26 -070040#include "src/core/lib/iomgr/socket_mutator.h"
Craig Tiller9533d042016-03-25 17:11:06 -070041#include "src/core/lib/iomgr/socket_utils_posix.h"
42#include "src/core/lib/iomgr/tcp_posix.h"
43#include "src/core/lib/iomgr/timer.h"
44#include "src/core/lib/iomgr/unix_sockets_posix.h"
Craig Tillerc46beaa2016-02-24 09:17:19 -080045
Craig Tiller694580f2017-10-18 14:48:14 -070046extern grpc_core::TraceFlag grpc_tcp_trace;
Craig Tiller5e53ddb2015-09-16 10:53:15 -070047
Craig Tillera82950e2015-09-22 12:33:20 -070048typedef struct {
ctiller58393c22015-01-07 14:03:30 -080049 gpr_mu mu;
Craig Tillerbaa14a92017-11-03 09:09:36 -070050 grpc_fd* fd;
David Garcia Quintasf747bbc2015-10-04 23:09:47 -070051 grpc_timer alarm;
Masood Malekghassemib5b43722017-01-05 15:07:26 -080052 grpc_closure on_alarm;
ctiller58393c22015-01-07 14:03:30 -080053 int refs;
Craig Tiller33825112015-09-18 07:44:19 -070054 grpc_closure write_closure;
Craig Tillerbaa14a92017-11-03 09:09:36 -070055 grpc_pollset_set* interested_parties;
56 char* addr_str;
57 grpc_endpoint** ep;
58 grpc_closure* closure;
59 grpc_channel_args* channel_args;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080060} async_connect;
61
Craig Tillerbaa14a92017-11-03 09:09:36 -070062static grpc_error* prepare_socket(const grpc_resolved_address* addr, int fd,
63 const grpc_channel_args* channel_args) {
64 grpc_error* err = GRPC_ERROR_NONE;
Craig Tiller27f59af2016-04-28 14:19:48 -070065
Craig Tiller80384bd2016-05-06 16:12:31 -070066 GPR_ASSERT(fd >= 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080067
Craig Tiller4f1d0f32016-05-06 17:12:37 -070068 err = grpc_set_socket_nonblocking(fd, 1);
69 if (err != GRPC_ERROR_NONE) goto error;
70 err = grpc_set_socket_cloexec(fd, 1);
71 if (err != GRPC_ERROR_NONE) goto error;
72 if (!grpc_is_unix_socket(addr)) {
73 err = grpc_set_socket_low_latency(fd, 1);
74 if (err != GRPC_ERROR_NONE) goto error;
Craig Tillera82950e2015-09-22 12:33:20 -070075 }
Craig Tiller4f1d0f32016-05-06 17:12:37 -070076 err = grpc_set_socket_no_sigpipe_if_possible(fd);
77 if (err != GRPC_ERROR_NONE) goto error;
Yuchen Zeng929f4c62016-10-10 16:02:43 -070078 if (channel_args) {
79 for (size_t i = 0; i < channel_args->num_args; i++) {
Yuchen Zenga4f708a2016-10-11 18:36:24 -070080 if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_SOCKET_MUTATOR)) {
81 GPR_ASSERT(channel_args->args[i].type == GRPC_ARG_POINTER);
Craig Tillerbaa14a92017-11-03 09:09:36 -070082 grpc_socket_mutator* mutator =
83 (grpc_socket_mutator*)channel_args->args[i].value.pointer.p;
Yuchen Zenga4f708a2016-10-11 18:36:24 -070084 err = grpc_set_socket_with_mutator(fd, mutator);
Yuchen Zeng929f4c62016-10-10 16:02:43 -070085 if (err != GRPC_ERROR_NONE) goto error;
Yuchen Zeng929f4c62016-10-10 16:02:43 -070086 }
87 }
88 }
Craig Tiller27f59af2016-04-28 14:19:48 -070089 goto done;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080090
91error:
Craig Tillera82950e2015-09-22 12:33:20 -070092 if (fd >= 0) {
93 close(fd);
94 }
Craig Tiller27f59af2016-04-28 14:19:48 -070095done:
96 return err;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080097}
98
Yash Tibrewal8cf14702017-12-06 09:47:54 -080099static void tc_on_alarm(void* acp, grpc_error* error) {
ctiller58393c22015-01-07 14:03:30 -0800100 int done;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700101 async_connect* ac = (async_connect*)acp;
Craig Tiller6014e8a2017-10-16 13:50:29 -0700102 if (grpc_tcp_trace.enabled()) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700103 const char* str = grpc_error_string(error);
Craig Tillerc027e772016-05-03 16:27:00 -0700104 gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: error=%s", ac->addr_str,
105 str);
Craig Tillera82950e2015-09-22 12:33:20 -0700106 }
107 gpr_mu_lock(&ac->mu);
Craig Tiller4782d922017-11-10 09:53:21 -0800108 if (ac->fd != nullptr) {
Yash Tibrewal0ee75742017-10-13 16:07:13 -0700109 grpc_fd_shutdown(
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800110 ac->fd, GRPC_ERROR_CREATE_FROM_STATIC_STRING("connect() timed out"));
Craig Tillera82950e2015-09-22 12:33:20 -0700111 }
ctiller58393c22015-01-07 14:03:30 -0800112 done = (--ac->refs == 0);
Craig Tillera82950e2015-09-22 12:33:20 -0700113 gpr_mu_unlock(&ac->mu);
114 if (done) {
115 gpr_mu_destroy(&ac->mu);
116 gpr_free(ac->addr_str);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800117 grpc_channel_args_destroy(ac->channel_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700118 gpr_free(ac);
119 }
ctiller58393c22015-01-07 14:03:30 -0800120}
121
Craig Tillerbaa14a92017-11-03 09:09:36 -0700122grpc_endpoint* grpc_tcp_client_create_from_fd(
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800123 grpc_fd* fd, const grpc_channel_args* channel_args, const char* addr_str) {
124 return grpc_tcp_create(fd, channel_args, addr_str);
Craig Tiller86958762016-09-23 12:05:34 -0700125}
126
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800127static void on_writable(void* acp, grpc_error* error) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700128 async_connect* ac = (async_connect*)acp;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800129 int so_error = 0;
130 socklen_t so_error_size;
131 int err;
ctiller58393c22015-01-07 14:03:30 -0800132 int done;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700133 grpc_endpoint** ep = ac->ep;
134 grpc_closure* closure = ac->closure;
135 grpc_fd* fd;
Craig Tiller5553eb32015-07-21 12:28:56 -0700136
Craig Tiller82c63eb2016-05-10 15:28:01 -0700137 GRPC_ERROR_REF(error);
138
Craig Tiller6014e8a2017-10-16 13:50:29 -0700139 if (grpc_tcp_trace.enabled()) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700140 const char* str = grpc_error_string(error);
Craig Tillerc027e772016-05-03 16:27:00 -0700141 gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_writable: error=%s",
142 ac->addr_str, str);
Craig Tillera82950e2015-09-22 12:33:20 -0700143 }
Craig Tiller5e53ddb2015-09-16 10:53:15 -0700144
Craig Tillera82950e2015-09-22 12:33:20 -0700145 gpr_mu_lock(&ac->mu);
146 GPR_ASSERT(ac->fd);
Craig Tiller5553eb32015-07-21 12:28:56 -0700147 fd = ac->fd;
Craig Tiller4782d922017-11-10 09:53:21 -0800148 ac->fd = nullptr;
Craig Tillera82950e2015-09-22 12:33:20 -0700149 gpr_mu_unlock(&ac->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800150
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800151 grpc_timer_cancel(&ac->alarm);
Craig Tiller26205362015-07-21 08:21:57 -0700152
Craig Tillera82950e2015-09-22 12:33:20 -0700153 gpr_mu_lock(&ac->mu);
Mark D. Rothe65ff112016-09-09 13:48:38 -0700154 if (error != GRPC_ERROR_NONE) {
Craig Tiller27f59af2016-04-28 14:19:48 -0700155 error =
ncteisen4b36a3d2017-03-13 19:08:06 -0700156 grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR,
157 grpc_slice_from_static_string("Timeout occurred"));
Craig Tillera82950e2015-09-22 12:33:20 -0700158 goto finish;
159 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800160
Mark D. Rothe65ff112016-09-09 13:48:38 -0700161 do {
162 so_error_size = sizeof(so_error);
163 err = getsockopt(grpc_fd_wrapped_fd(fd), SOL_SOCKET, SO_ERROR, &so_error,
164 &so_error_size);
165 } while (err < 0 && errno == EINTR);
166 if (err < 0) {
167 error = GRPC_OS_ERROR(errno, "getsockopt");
168 goto finish;
169 }
170
171 switch (so_error) {
172 case 0:
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800173 grpc_pollset_set_del_fd(ac->interested_parties, fd);
174 *ep = grpc_tcp_client_create_from_fd(fd, ac->channel_args, ac->addr_str);
Craig Tiller4782d922017-11-10 09:53:21 -0800175 fd = nullptr;
Mark D. Rothe65ff112016-09-09 13:48:38 -0700176 break;
177 case ENOBUFS:
178 /* We will get one of these errors if we have run out of
179 memory in the kernel for the data structures allocated
180 when you connect a socket. If this happens it is very
181 likely that if we wait a little bit then try again the
182 connection will work (since other programs or this
183 program will close their network connections and free up
184 memory). This does _not_ indicate that there is anything
185 wrong with the server we are connecting to, this is a
186 local problem.
187
188 If you are looking at this code, then chances are that
189 your program or another program on the same computer
190 opened too many network connections. The "easy" fix:
191 don't do that! */
192 gpr_log(GPR_ERROR, "kernel out of buffers");
193 gpr_mu_unlock(&ac->mu);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800194 grpc_fd_notify_on_write(fd, &ac->write_closure);
Mark D. Rothe65ff112016-09-09 13:48:38 -0700195 return;
196 case ECONNREFUSED:
197 /* This error shouldn't happen for anything other than connect(). */
198 error = GRPC_OS_ERROR(so_error, "connect");
199 break;
200 default:
201 /* We don't really know which syscall triggered the problem here,
202 so punt by reporting getsockopt(). */
203 error = GRPC_OS_ERROR(so_error, "getsockopt(SO_ERROR)");
204 break;
205 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800206
ctiller58393c22015-01-07 14:03:30 -0800207finish:
Craig Tiller4782d922017-11-10 09:53:21 -0800208 if (fd != nullptr) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800209 grpc_pollset_set_del_fd(ac->interested_parties, fd);
210 grpc_fd_orphan(fd, nullptr, nullptr, false /* already_closed */,
Yuchen Zengd40a7ae2017-07-12 15:59:56 -0700211 "tcp_client_orphan");
Craig Tiller4782d922017-11-10 09:53:21 -0800212 fd = nullptr;
Craig Tillera82950e2015-09-22 12:33:20 -0700213 }
ctiller58393c22015-01-07 14:03:30 -0800214 done = (--ac->refs == 0);
David Garcia Quintas4ef4c382017-12-19 09:34:18 -0800215 // Create a copy of the data from "ac" to be accessed after the unlock, as
216 // "ac" and its contents may be deallocated by the time they are read.
217 const grpc_slice addr_str_slice = grpc_slice_from_copied_string(ac->addr_str);
218 gpr_mu_unlock(&ac->mu);
Craig Tiller27f59af2016-04-28 14:19:48 -0700219 if (error != GRPC_ERROR_NONE) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700220 char* error_descr;
ncteisenbbb38012017-03-10 14:58:43 -0800221 grpc_slice str;
222 bool ret = grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &str);
223 GPR_ASSERT(ret);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700224 char* desc = grpc_slice_to_c_string(str);
ncteisenbbb38012017-03-10 14:58:43 -0800225 gpr_asprintf(&error_descr, "Failed to connect to remote host: %s", desc);
ncteisen4b36a3d2017-03-13 19:08:06 -0700226 error = grpc_error_set_str(error, GRPC_ERROR_STR_DESCRIPTION,
227 grpc_slice_from_copied_string(error_descr));
David Garcia Quintas19badff2016-11-20 20:17:46 -0800228 gpr_free(error_descr);
ncteisenbbb38012017-03-10 14:58:43 -0800229 gpr_free(desc);
ncteisen4b36a3d2017-03-13 19:08:06 -0700230 error = grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS,
David Garcia Quintasc41bbd32017-12-19 14:59:41 -0800231 addr_str_slice /* takes ownership */);
232 } else {
David Garcia Quintas4ef4c382017-12-19 09:34:18 -0800233 grpc_slice_unref(addr_str_slice);
Craig Tiller27f59af2016-04-28 14:19:48 -0700234 }
Craig Tillera82950e2015-09-22 12:33:20 -0700235 if (done) {
David Garcia Quintas4ef4c382017-12-19 09:34:18 -0800236 // This is safe even outside the lock, because "done", the sentinel, is
237 // populated *inside* the lock.
Craig Tillera82950e2015-09-22 12:33:20 -0700238 gpr_mu_destroy(&ac->mu);
239 gpr_free(ac->addr_str);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800240 grpc_channel_args_destroy(ac->channel_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700241 gpr_free(ac);
242 }
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800243 GRPC_CLOSURE_SCHED(closure, error);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800244}
245
Dan Bornbdf63912017-11-17 14:31:00 -0800246grpc_error* grpc_tcp_client_prepare_fd(const grpc_channel_args* channel_args,
247 const grpc_resolved_address* addr,
248 grpc_resolved_address* mapped_addr,
249 grpc_fd** fdobj) {
nnoble0c475f02014-12-05 15:37:39 -0800250 grpc_dualstack_mode dsmode;
Dan Bornbdf63912017-11-17 14:31:00 -0800251 int fd;
252 grpc_error* error;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700253 char* name;
254 char* addr_str;
Dan Bornbdf63912017-11-17 14:31:00 -0800255 *fdobj = nullptr;
256 /* Use dualstack sockets where available. Set mapped to v6 or v4 mapped to
257 v6. */
258 if (!grpc_sockaddr_to_v4mapped(addr, mapped_addr)) {
259 /* addr is v4 mapped to v6 or v6. */
260 memcpy(mapped_addr, addr, sizeof(*mapped_addr));
Craig Tillera82950e2015-09-22 12:33:20 -0700261 }
Dan Bornbdf63912017-11-17 14:31:00 -0800262 error =
263 grpc_create_dualstack_socket(mapped_addr, SOCK_STREAM, 0, &dsmode, &fd);
Craig Tiller27f59af2016-04-28 14:19:48 -0700264 if (error != GRPC_ERROR_NONE) {
Dan Bornbdf63912017-11-17 14:31:00 -0800265 return error;
Craig Tillera82950e2015-09-22 12:33:20 -0700266 }
267 if (dsmode == GRPC_DSMODE_IPV4) {
Dan Bornbdf63912017-11-17 14:31:00 -0800268 /* Original addr is either v4 or v4 mapped to v6. Set mapped_addr to v4. */
269 if (!grpc_sockaddr_is_v4mapped(addr, mapped_addr)) {
270 memcpy(mapped_addr, addr, sizeof(*mapped_addr));
271 }
Craig Tillera82950e2015-09-22 12:33:20 -0700272 }
Dan Bornbdf63912017-11-17 14:31:00 -0800273 if ((error = prepare_socket(mapped_addr, fd, channel_args)) !=
274 GRPC_ERROR_NONE) {
275 return error;
Craig Tillera82950e2015-09-22 12:33:20 -0700276 }
Dan Bornbdf63912017-11-17 14:31:00 -0800277 addr_str = grpc_sockaddr_to_uri(mapped_addr);
278 gpr_asprintf(&name, "tcp-client:%s", addr_str);
279 *fdobj = grpc_fd_create(fd, name);
280 gpr_free(name);
281 gpr_free(addr_str);
282 return GRPC_ERROR_NONE;
283}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800284
Dan Bornbdf63912017-11-17 14:31:00 -0800285void grpc_tcp_client_create_from_prepared_fd(
286 grpc_pollset_set* interested_parties, grpc_closure* closure, grpc_fd* fdobj,
287 const grpc_channel_args* channel_args, const grpc_resolved_address* addr,
288 grpc_millis deadline, grpc_endpoint** ep) {
289 const int fd = grpc_fd_wrapped_fd(fdobj);
290 int err;
291 async_connect* ac;
Craig Tillera82950e2015-09-22 12:33:20 -0700292 do {
murgatroid997871f732016-09-23 13:49:05 -0700293 GPR_ASSERT(addr->len < ~(socklen_t)0);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700294 err = connect(fd, (const struct sockaddr*)addr->addr, (socklen_t)addr->len);
Craig Tillera82950e2015-09-22 12:33:20 -0700295 } while (err < 0 && errno == EINTR);
Craig Tillera82950e2015-09-22 12:33:20 -0700296 if (err >= 0) {
Dan Bornbdf63912017-11-17 14:31:00 -0800297 char* addr_str = grpc_sockaddr_to_uri(addr);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800298 *ep = grpc_tcp_client_create_from_fd(fdobj, channel_args, addr_str);
Dan Bornbdf63912017-11-17 14:31:00 -0800299 gpr_free(addr_str);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800300 GRPC_CLOSURE_SCHED(closure, GRPC_ERROR_NONE);
Dan Bornbdf63912017-11-17 14:31:00 -0800301 return;
Craig Tillera82950e2015-09-22 12:33:20 -0700302 }
Craig Tillera82950e2015-09-22 12:33:20 -0700303 if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800304 grpc_fd_orphan(fdobj, nullptr, nullptr, false /* already_closed */,
305 "tcp_client_connect_error");
306 GRPC_CLOSURE_SCHED(closure, GRPC_OS_ERROR(errno, "connect"));
Dan Bornbdf63912017-11-17 14:31:00 -0800307 return;
Craig Tillera82950e2015-09-22 12:33:20 -0700308 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800309
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800310 grpc_pollset_set_add_fd(interested_parties, fdobj);
Craig Tiller4b678bd2015-06-02 16:12:24 -0700311
Craig Tillerbaa14a92017-11-03 09:09:36 -0700312 ac = (async_connect*)gpr_malloc(sizeof(async_connect));
Craig Tillerd1bec032015-09-18 17:29:00 -0700313 ac->closure = closure;
314 ac->ep = ep;
Craig Tiller9bcc7512015-05-11 14:59:48 -0700315 ac->fd = fdobj;
Craig Tillerb49736822015-06-30 08:15:08 -0700316 ac->interested_parties = interested_parties;
Dan Bornbdf63912017-11-17 14:31:00 -0800317 ac->addr_str = grpc_sockaddr_to_uri(addr);
Craig Tillera82950e2015-09-22 12:33:20 -0700318 gpr_mu_init(&ac->mu);
ctiller58393c22015-01-07 14:03:30 -0800319 ac->refs = 2;
ncteisen274bbbe2017-06-08 14:57:11 -0700320 GRPC_CLOSURE_INIT(&ac->write_closure, on_writable, ac,
Craig Tillerd6887e02016-12-29 10:11:40 -0800321 grpc_schedule_on_exec_ctx);
Craig Tiller86958762016-09-23 12:05:34 -0700322 ac->channel_args = grpc_channel_args_copy(channel_args);
ctiller58393c22015-01-07 14:03:30 -0800323
Craig Tiller6014e8a2017-10-16 13:50:29 -0700324 if (grpc_tcp_trace.enabled()) {
Craig Tiller6c8383a2017-05-05 16:54:42 +0000325 gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting fd %p",
326 ac->addr_str, fdobj);
Craig Tillera82950e2015-09-22 12:33:20 -0700327 }
Craig Tiller5e53ddb2015-09-16 10:53:15 -0700328
Craig Tillera82950e2015-09-22 12:33:20 -0700329 gpr_mu_lock(&ac->mu);
ncteisen274bbbe2017-06-08 14:57:11 -0700330 GRPC_CLOSURE_INIT(&ac->on_alarm, tc_on_alarm, ac, grpc_schedule_on_exec_ctx);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800331 grpc_timer_init(&ac->alarm, deadline, &ac->on_alarm);
332 grpc_fd_notify_on_write(ac->fd, &ac->write_closure);
Craig Tillera82950e2015-09-22 12:33:20 -0700333 gpr_mu_unlock(&ac->mu);
Dan Bornbdf63912017-11-17 14:31:00 -0800334}
Craig Tillerfa275a92015-06-01 13:55:54 -0700335
Dan Bornbdf63912017-11-17 14:31:00 -0800336static void tcp_client_connect_impl(grpc_closure* closure, grpc_endpoint** ep,
337 grpc_pollset_set* interested_parties,
338 const grpc_channel_args* channel_args,
339 const grpc_resolved_address* addr,
340 grpc_millis deadline) {
341 grpc_resolved_address mapped_addr;
342 grpc_fd* fdobj = nullptr;
343 grpc_error* error;
344 *ep = nullptr;
345 if ((error = grpc_tcp_client_prepare_fd(channel_args, addr, &mapped_addr,
346 &fdobj)) != GRPC_ERROR_NONE) {
347 GRPC_CLOSURE_SCHED(closure, error);
348 return;
349 }
350 grpc_tcp_client_create_from_prepared_fd(interested_parties, closure, fdobj,
351 channel_args, &mapped_addr, deadline,
352 ep);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800353}
Craig Tiller0c0b60c2015-01-21 15:49:28 -0800354
Craig Tillere6282612016-04-13 14:14:34 -0700355// overridden by api_fuzzer.c
356void (*grpc_tcp_client_connect_impl)(
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800357 grpc_closure* closure, grpc_endpoint** ep,
Craig Tillerbaa14a92017-11-03 09:09:36 -0700358 grpc_pollset_set* interested_parties, const grpc_channel_args* channel_args,
359 const grpc_resolved_address* addr,
Craig Tillerdc3998e2017-05-12 09:55:30 -0700360 grpc_millis deadline) = tcp_client_connect_impl;
Craig Tillere6282612016-04-13 14:14:34 -0700361
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800362void grpc_tcp_client_connect(grpc_closure* closure, grpc_endpoint** ep,
Craig Tillerbaa14a92017-11-03 09:09:36 -0700363 grpc_pollset_set* interested_parties,
364 const grpc_channel_args* channel_args,
365 const grpc_resolved_address* addr,
Craig Tillerdc3998e2017-05-12 09:55:30 -0700366 grpc_millis deadline) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800367 grpc_tcp_client_connect_impl(closure, ep, interested_parties, channel_args,
368 addr, deadline);
Craig Tillere6282612016-04-13 14:14:34 -0700369}
370
Craig Tiller190d3602015-02-18 09:23:38 -0800371#endif