blob: 3496b6094f256a4fab4b8db1f50c17b3143073b3 [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 Tiller9533d042016-03-25 17:11:06 -070038#include "src/core/lib/iomgr/tcp_client.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 Tiller8a034482016-03-28 16:09:04 -070050#include "src/core/lib/iomgr/ev_posix.h"
Craig Tiller9533d042016-03-25 17:11:06 -070051#include "src/core/lib/iomgr/iomgr_posix.h"
Craig Tiller9533d042016-03-25 17:11:06 -070052#include "src/core/lib/iomgr/sockaddr_utils.h"
53#include "src/core/lib/iomgr/socket_utils_posix.h"
54#include "src/core/lib/iomgr/tcp_posix.h"
55#include "src/core/lib/iomgr/timer.h"
56#include "src/core/lib/iomgr/unix_sockets_posix.h"
57#include "src/core/lib/support/string.h"
Craig Tillerc46beaa2016-02-24 09:17:19 -080058
Craig Tiller5e53ddb2015-09-16 10:53:15 -070059extern int grpc_tcp_trace;
60
Craig Tillera82950e2015-09-22 12:33:20 -070061typedef struct {
ctiller58393c22015-01-07 14:03:30 -080062 gpr_mu mu;
ctiller18b49ab2014-12-09 14:39:16 -080063 grpc_fd *fd;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080064 gpr_timespec deadline;
David Garcia Quintasf747bbc2015-10-04 23:09:47 -070065 grpc_timer alarm;
ctiller58393c22015-01-07 14:03:30 -080066 int refs;
Craig Tiller33825112015-09-18 07:44:19 -070067 grpc_closure write_closure;
Craig Tillerb49736822015-06-30 08:15:08 -070068 grpc_pollset_set *interested_parties;
Craig Tiller1b22b9d2015-07-20 13:42:22 -070069 char *addr_str;
Craig Tillerd1bec032015-09-18 17:29:00 -070070 grpc_endpoint **ep;
71 grpc_closure *closure;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080072} async_connect;
73
Craig Tiller27f59af2016-04-28 14:19:48 -070074static grpc_error *prepare_socket(const struct sockaddr *addr, int fd) {
75 grpc_error *err = GRPC_ERROR_NONE;
76
Craig Tiller80384bd2016-05-06 16:12:31 -070077 GPR_ASSERT(fd >= 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080078
Craig Tiller4f1d0f32016-05-06 17:12:37 -070079 err = grpc_set_socket_nonblocking(fd, 1);
80 if (err != GRPC_ERROR_NONE) goto error;
81 err = grpc_set_socket_cloexec(fd, 1);
82 if (err != GRPC_ERROR_NONE) goto error;
83 if (!grpc_is_unix_socket(addr)) {
84 err = grpc_set_socket_low_latency(fd, 1);
85 if (err != GRPC_ERROR_NONE) goto error;
Craig Tillera82950e2015-09-22 12:33:20 -070086 }
Craig Tiller4f1d0f32016-05-06 17:12:37 -070087 err = grpc_set_socket_no_sigpipe_if_possible(fd);
88 if (err != GRPC_ERROR_NONE) goto error;
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
Craig Tillerc027e772016-05-03 16:27:00 -070099static void tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) {
ctiller58393c22015-01-07 14:03:30 -0800100 int done;
101 async_connect *ac = acp;
Craig Tillera82950e2015-09-22 12:33:20 -0700102 if (grpc_tcp_trace) {
Craig Tillerc027e772016-05-03 16:27:00 -0700103 const char *str = grpc_error_string(error);
104 gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: error=%s", ac->addr_str,
105 str);
106 grpc_error_free_string(str);
Craig Tillera82950e2015-09-22 12:33:20 -0700107 }
108 gpr_mu_lock(&ac->mu);
109 if (ac->fd != NULL) {
110 grpc_fd_shutdown(exec_ctx, ac->fd);
111 }
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);
117 gpr_free(ac);
118 }
ctiller58393c22015-01-07 14:03:30 -0800119}
120
Craig Tillerc027e772016-05-03 16:27:00 -0700121static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800122 async_connect *ac = acp;
123 int so_error = 0;
124 socklen_t so_error_size;
125 int err;
ctiller58393c22015-01-07 14:03:30 -0800126 int done;
Craig Tillerd1bec032015-09-18 17:29:00 -0700127 grpc_endpoint **ep = ac->ep;
128 grpc_closure *closure = ac->closure;
Craig Tiller5553eb32015-07-21 12:28:56 -0700129 grpc_fd *fd;
130
Craig Tiller82c63eb2016-05-10 15:28:01 -0700131 GRPC_ERROR_REF(error);
132
Craig Tillera82950e2015-09-22 12:33:20 -0700133 if (grpc_tcp_trace) {
Craig Tillerc027e772016-05-03 16:27:00 -0700134 const char *str = grpc_error_string(error);
135 gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_writable: error=%s",
136 ac->addr_str, str);
137 grpc_error_free_string(str);
Craig Tillera82950e2015-09-22 12:33:20 -0700138 }
Craig Tiller5e53ddb2015-09-16 10:53:15 -0700139
Craig Tillera82950e2015-09-22 12:33:20 -0700140 gpr_mu_lock(&ac->mu);
141 GPR_ASSERT(ac->fd);
Craig Tiller5553eb32015-07-21 12:28:56 -0700142 fd = ac->fd;
143 ac->fd = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700144 gpr_mu_unlock(&ac->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800145
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700146 grpc_timer_cancel(exec_ctx, &ac->alarm);
Craig Tiller26205362015-07-21 08:21:57 -0700147
Craig Tillera82950e2015-09-22 12:33:20 -0700148 gpr_mu_lock(&ac->mu);
Mark D. Rothe65ff112016-09-09 13:48:38 -0700149 if (error != GRPC_ERROR_NONE) {
Craig Tiller27f59af2016-04-28 14:19:48 -0700150 error =
151 grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, "Timeout occurred");
Craig Tillera82950e2015-09-22 12:33:20 -0700152 goto finish;
153 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800154
Mark D. Rothe65ff112016-09-09 13:48:38 -0700155 do {
156 so_error_size = sizeof(so_error);
157 err = getsockopt(grpc_fd_wrapped_fd(fd), SOL_SOCKET, SO_ERROR, &so_error,
158 &so_error_size);
159 } while (err < 0 && errno == EINTR);
160 if (err < 0) {
161 error = GRPC_OS_ERROR(errno, "getsockopt");
162 goto finish;
163 }
164
165 switch (so_error) {
166 case 0:
167 grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd);
168 *ep = grpc_tcp_create(fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, ac->addr_str);
169 fd = NULL;
170 break;
171 case ENOBUFS:
172 /* We will get one of these errors if we have run out of
173 memory in the kernel for the data structures allocated
174 when you connect a socket. If this happens it is very
175 likely that if we wait a little bit then try again the
176 connection will work (since other programs or this
177 program will close their network connections and free up
178 memory). This does _not_ indicate that there is anything
179 wrong with the server we are connecting to, this is a
180 local problem.
181
182 If you are looking at this code, then chances are that
183 your program or another program on the same computer
184 opened too many network connections. The "easy" fix:
185 don't do that! */
186 gpr_log(GPR_ERROR, "kernel out of buffers");
187 gpr_mu_unlock(&ac->mu);
188 grpc_fd_notify_on_write(exec_ctx, fd, &ac->write_closure);
189 return;
190 case ECONNREFUSED:
191 /* This error shouldn't happen for anything other than connect(). */
192 error = GRPC_OS_ERROR(so_error, "connect");
193 break;
194 default:
195 /* We don't really know which syscall triggered the problem here,
196 so punt by reporting getsockopt(). */
197 error = GRPC_OS_ERROR(so_error, "getsockopt(SO_ERROR)");
198 break;
199 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800200
ctiller58393c22015-01-07 14:03:30 -0800201finish:
Craig Tillera82950e2015-09-22 12:33:20 -0700202 if (fd != NULL) {
203 grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd);
yang-g5d850372015-12-01 10:32:28 -0800204 grpc_fd_orphan(exec_ctx, fd, NULL, NULL, "tcp_client_orphan");
Craig Tillera82950e2015-09-22 12:33:20 -0700205 fd = NULL;
206 }
ctiller58393c22015-01-07 14:03:30 -0800207 done = (--ac->refs == 0);
Craig Tillera82950e2015-09-22 12:33:20 -0700208 gpr_mu_unlock(&ac->mu);
Craig Tiller27f59af2016-04-28 14:19:48 -0700209 if (error != GRPC_ERROR_NONE) {
210 error = grpc_error_set_str(error, GRPC_ERROR_STR_DESCRIPTION,
211 "Failed to connect to remote host");
212 error =
213 grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS, ac->addr_str);
214 }
Craig Tillera82950e2015-09-22 12:33:20 -0700215 if (done) {
216 gpr_mu_destroy(&ac->mu);
217 gpr_free(ac->addr_str);
218 gpr_free(ac);
219 }
Craig Tiller332f1b32016-05-24 13:21:21 -0700220 grpc_exec_ctx_sched(exec_ctx, closure, error, NULL);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800221}
222
Craig Tillere6282612016-04-13 14:14:34 -0700223static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx,
224 grpc_closure *closure, grpc_endpoint **ep,
225 grpc_pollset_set *interested_parties,
226 const struct sockaddr *addr,
227 size_t addr_len, gpr_timespec deadline) {
nnoble0c475f02014-12-05 15:37:39 -0800228 int fd;
229 grpc_dualstack_mode dsmode;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800230 int err;
231 async_connect *ac;
nnoble0c475f02014-12-05 15:37:39 -0800232 struct sockaddr_in6 addr6_v4mapped;
233 struct sockaddr_in addr4_copy;
Craig Tiller9bcc7512015-05-11 14:59:48 -0700234 grpc_fd *fdobj;
Craig Tillerfa275a92015-06-01 13:55:54 -0700235 char *name;
236 char *addr_str;
Craig Tiller27f59af2016-04-28 14:19:48 -0700237 grpc_error *error;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800238
Craig Tillerd1bec032015-09-18 17:29:00 -0700239 *ep = NULL;
240
nnoble0c475f02014-12-05 15:37:39 -0800241 /* Use dualstack sockets where available. */
Craig Tillera82950e2015-09-22 12:33:20 -0700242 if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
243 addr = (const struct sockaddr *)&addr6_v4mapped;
244 addr_len = sizeof(addr6_v4mapped);
245 }
nnoble0c475f02014-12-05 15:37:39 -0800246
Craig Tiller27f59af2016-04-28 14:19:48 -0700247 error = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
248 if (error != GRPC_ERROR_NONE) {
Craig Tiller332f1b32016-05-24 13:21:21 -0700249 grpc_exec_ctx_sched(exec_ctx, closure, error, NULL);
Craig Tiller27f59af2016-04-28 14:19:48 -0700250 return;
Craig Tillera82950e2015-09-22 12:33:20 -0700251 }
252 if (dsmode == GRPC_DSMODE_IPV4) {
253 /* If we got an AF_INET socket, map the address back to IPv4. */
254 GPR_ASSERT(grpc_sockaddr_is_v4mapped(addr, &addr4_copy));
255 addr = (struct sockaddr *)&addr4_copy;
256 addr_len = sizeof(addr4_copy);
257 }
Craig Tiller27f59af2016-04-28 14:19:48 -0700258 if ((error = prepare_socket(addr, fd)) != GRPC_ERROR_NONE) {
Craig Tiller332f1b32016-05-24 13:21:21 -0700259 grpc_exec_ctx_sched(exec_ctx, closure, error, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700260 return;
261 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800262
Craig Tillera82950e2015-09-22 12:33:20 -0700263 do {
264 GPR_ASSERT(addr_len < ~(socklen_t)0);
265 err = connect(fd, addr, (socklen_t)addr_len);
266 } while (err < 0 && errno == EINTR);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800267
Craig Tillera82950e2015-09-22 12:33:20 -0700268 addr_str = grpc_sockaddr_to_uri(addr);
269 gpr_asprintf(&name, "tcp-client:%s", addr_str);
Craig Tillerfa275a92015-06-01 13:55:54 -0700270
Craig Tillera82950e2015-09-22 12:33:20 -0700271 fdobj = grpc_fd_create(fd, name);
Craig Tiller9bcc7512015-05-11 14:59:48 -0700272
Craig Tillera82950e2015-09-22 12:33:20 -0700273 if (err >= 0) {
274 *ep = grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str);
Craig Tiller332f1b32016-05-24 13:21:21 -0700275 grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_NONE, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700276 goto done;
277 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800278
Craig Tillera82950e2015-09-22 12:33:20 -0700279 if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
yang-g5d850372015-12-01 10:32:28 -0800280 grpc_fd_orphan(exec_ctx, fdobj, NULL, NULL, "tcp_client_connect_error");
Craig Tiller332f1b32016-05-24 13:21:21 -0700281 grpc_exec_ctx_sched(exec_ctx, closure, GRPC_OS_ERROR(errno, "connect"),
Craig Tiller77c983d2016-05-24 13:23:14 -0700282 NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700283 goto done;
284 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800285
Craig Tillera82950e2015-09-22 12:33:20 -0700286 grpc_pollset_set_add_fd(exec_ctx, interested_parties, fdobj);
Craig Tiller4b678bd2015-06-02 16:12:24 -0700287
Craig Tillera82950e2015-09-22 12:33:20 -0700288 ac = gpr_malloc(sizeof(async_connect));
Craig Tillerd1bec032015-09-18 17:29:00 -0700289 ac->closure = closure;
290 ac->ep = ep;
Craig Tiller9bcc7512015-05-11 14:59:48 -0700291 ac->fd = fdobj;
Craig Tillerb49736822015-06-30 08:15:08 -0700292 ac->interested_parties = interested_parties;
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700293 ac->addr_str = addr_str;
294 addr_str = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700295 gpr_mu_init(&ac->mu);
ctiller58393c22015-01-07 14:03:30 -0800296 ac->refs = 2;
Craig Tiller0fcd53c2015-02-18 15:10:53 -0800297 ac->write_closure.cb = on_writable;
298 ac->write_closure.cb_arg = ac;
ctiller58393c22015-01-07 14:03:30 -0800299
Craig Tillera82950e2015-09-22 12:33:20 -0700300 if (grpc_tcp_trace) {
301 gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting",
302 ac->addr_str);
303 }
Craig Tiller5e53ddb2015-09-16 10:53:15 -0700304
Craig Tillera82950e2015-09-22 12:33:20 -0700305 gpr_mu_lock(&ac->mu);
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700306 grpc_timer_init(exec_ctx, &ac->alarm,
Craig Tillera82950e2015-09-22 12:33:20 -0700307 gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
308 tc_on_alarm, ac, gpr_now(GPR_CLOCK_MONOTONIC));
309 grpc_fd_notify_on_write(exec_ctx, ac->fd, &ac->write_closure);
310 gpr_mu_unlock(&ac->mu);
Craig Tillerfa275a92015-06-01 13:55:54 -0700311
312done:
Craig Tillera82950e2015-09-22 12:33:20 -0700313 gpr_free(name);
314 gpr_free(addr_str);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800315}
Craig Tiller0c0b60c2015-01-21 15:49:28 -0800316
Craig Tillere6282612016-04-13 14:14:34 -0700317// overridden by api_fuzzer.c
318void (*grpc_tcp_client_connect_impl)(
319 grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep,
320 grpc_pollset_set *interested_parties, const struct sockaddr *addr,
321 size_t addr_len, gpr_timespec deadline) = tcp_client_connect_impl;
322
323void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
324 grpc_endpoint **ep,
325 grpc_pollset_set *interested_parties,
326 const struct sockaddr *addr, size_t addr_len,
327 gpr_timespec deadline) {
328 grpc_tcp_client_connect_impl(exec_ctx, closure, ep, interested_parties, addr,
329 addr_len, deadline);
330}
331
Craig Tiller190d3602015-02-18 09:23:38 -0800332#endif