blob: b04e1dbb6886f95dbf02a7981dbe33fec9864a7f [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tillera93a25f2016-01-28 13:55:49 -08003 * Copyright 2015-2016, 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
ctiller18b49ab2014-12-09 14:39:16 -080038#include "src/core/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 Tiller69b093b2016-02-25 19:04:07 -080050#include "src/core/iomgr/iomgr_posix.h"
51#include "src/core/iomgr/pollset_posix.h"
52#include "src/core/iomgr/pollset_set_posix.h"
53#include "src/core/iomgr/sockaddr_utils.h"
54#include "src/core/iomgr/socket_utils_posix.h"
55#include "src/core/iomgr/tcp_posix.h"
56#include "src/core/iomgr/timer.h"
57#include "src/core/support/string.h"
58
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 Tillera82950e2015-09-22 12:33:20 -070074static int prepare_socket(const struct sockaddr *addr, int fd) {
75 if (fd < 0) {
76 goto error;
77 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080078
ahedberg803931d2016-03-11 17:24:12 -050079#ifdef GPR_HAVE_UNIX_SOCKET
Craig Tillera82950e2015-09-22 12:33:20 -070080 if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) ||
81 (addr->sa_family != AF_UNIX && !grpc_set_socket_low_latency(fd, 1)) ||
82 !grpc_set_socket_no_sigpipe_if_possible(fd)) {
83 gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
84 strerror(errno));
85 goto error;
86 }
ahedberg803931d2016-03-11 17:24:12 -050087#else
88 if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) ||
89 !grpc_set_socket_low_latency(fd, 1) ||
90 !grpc_set_socket_no_sigpipe_if_possible(fd)) {
91 gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
92 strerror(errno));
93 goto error;
94 }
95#endif
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080096
nnoble0c475f02014-12-05 15:37:39 -080097 return 1;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080098
99error:
Craig Tillera82950e2015-09-22 12:33:20 -0700100 if (fd >= 0) {
101 close(fd);
102 }
nnoble0c475f02014-12-05 15:37:39 -0800103 return 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800104}
105
Craig Tiller6c396862016-01-28 13:53:40 -0800106static void tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, bool success) {
ctiller58393c22015-01-07 14:03:30 -0800107 int done;
108 async_connect *ac = acp;
Craig Tillera82950e2015-09-22 12:33:20 -0700109 if (grpc_tcp_trace) {
110 gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: success=%d", ac->addr_str,
111 success);
112 }
113 gpr_mu_lock(&ac->mu);
114 if (ac->fd != NULL) {
115 grpc_fd_shutdown(exec_ctx, ac->fd);
116 }
ctiller58393c22015-01-07 14:03:30 -0800117 done = (--ac->refs == 0);
Craig Tillera82950e2015-09-22 12:33:20 -0700118 gpr_mu_unlock(&ac->mu);
119 if (done) {
120 gpr_mu_destroy(&ac->mu);
121 gpr_free(ac->addr_str);
122 gpr_free(ac);
123 }
ctiller58393c22015-01-07 14:03:30 -0800124}
125
Craig Tiller6c396862016-01-28 13:53:40 -0800126static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, bool success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800127 async_connect *ac = acp;
128 int so_error = 0;
129 socklen_t so_error_size;
130 int err;
ctiller58393c22015-01-07 14:03:30 -0800131 int done;
Craig Tillerd1bec032015-09-18 17:29:00 -0700132 grpc_endpoint **ep = ac->ep;
133 grpc_closure *closure = ac->closure;
Craig Tiller5553eb32015-07-21 12:28:56 -0700134 grpc_fd *fd;
135
Craig Tillera82950e2015-09-22 12:33:20 -0700136 if (grpc_tcp_trace) {
137 gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_writable: success=%d",
138 ac->addr_str, success);
139 }
Craig Tiller5e53ddb2015-09-16 10:53:15 -0700140
Craig Tillera82950e2015-09-22 12:33:20 -0700141 gpr_mu_lock(&ac->mu);
142 GPR_ASSERT(ac->fd);
Craig Tiller5553eb32015-07-21 12:28:56 -0700143 fd = ac->fd;
144 ac->fd = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700145 gpr_mu_unlock(&ac->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800146
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700147 grpc_timer_cancel(exec_ctx, &ac->alarm);
Craig Tiller26205362015-07-21 08:21:57 -0700148
Craig Tillera82950e2015-09-22 12:33:20 -0700149 gpr_mu_lock(&ac->mu);
150 if (success) {
151 do {
152 so_error_size = sizeof(so_error);
153 err = getsockopt(fd->fd, SOL_SOCKET, SO_ERROR, &so_error, &so_error_size);
154 } while (err < 0 && errno == EINTR);
155 if (err < 0) {
Craig Tiller3bf828f2015-10-05 13:36:25 -0700156 gpr_log(GPR_ERROR, "failed to connect to '%s': getsockopt(ERROR): %s",
157 ac->addr_str, strerror(errno));
Craig Tillera82950e2015-09-22 12:33:20 -0700158 goto finish;
159 } else if (so_error != 0) {
160 if (so_error == ENOBUFS) {
161 /* We will get one of these errors if we have run out of
162 memory in the kernel for the data structures allocated
163 when you connect a socket. If this happens it is very
164 likely that if we wait a little bit then try again the
165 connection will work (since other programs or this
166 program will close their network connections and free up
167 memory). This does _not_ indicate that there is anything
168 wrong with the server we are connecting to, this is a
169 local problem.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800170
Craig Tillera82950e2015-09-22 12:33:20 -0700171 If you are looking at this code, then chances are that
172 your program or another program on the same computer
173 opened too many network connections. The "easy" fix:
174 don't do that! */
175 gpr_log(GPR_ERROR, "kernel out of buffers");
176 gpr_mu_unlock(&ac->mu);
177 grpc_fd_notify_on_write(exec_ctx, fd, &ac->write_closure);
178 return;
179 } else {
180 switch (so_error) {
181 case ECONNREFUSED:
Craig Tiller3bf828f2015-10-05 13:36:25 -0700182 gpr_log(
183 GPR_ERROR,
184 "failed to connect to '%s': socket error: connection refused",
185 ac->addr_str);
Craig Tillera82950e2015-09-22 12:33:20 -0700186 break;
187 default:
Craig Tiller3bf828f2015-10-05 13:36:25 -0700188 gpr_log(GPR_ERROR, "failed to connect to '%s': socket error: %d",
189 ac->addr_str, so_error);
Craig Tillera82950e2015-09-22 12:33:20 -0700190 break;
191 }
192 goto finish;
193 }
194 } else {
195 grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd);
196 *ep = grpc_tcp_create(fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, ac->addr_str);
197 fd = NULL;
ctiller58393c22015-01-07 14:03:30 -0800198 goto finish;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800199 }
Craig Tillera82950e2015-09-22 12:33:20 -0700200 } else {
Craig Tiller3bf828f2015-10-05 13:36:25 -0700201 gpr_log(GPR_ERROR, "failed to connect to '%s': timeout occurred",
202 ac->addr_str);
Craig Tillera82950e2015-09-22 12:33:20 -0700203 goto finish;
204 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800205
yang-gb063c872015-10-07 11:40:13 -0700206 GPR_UNREACHABLE_CODE(return );
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800207
ctiller58393c22015-01-07 14:03:30 -0800208finish:
Craig Tillera82950e2015-09-22 12:33:20 -0700209 if (fd != NULL) {
210 grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd);
yang-g5d850372015-12-01 10:32:28 -0800211 grpc_fd_orphan(exec_ctx, fd, NULL, NULL, "tcp_client_orphan");
Craig Tillera82950e2015-09-22 12:33:20 -0700212 fd = NULL;
213 }
ctiller58393c22015-01-07 14:03:30 -0800214 done = (--ac->refs == 0);
Craig Tillera82950e2015-09-22 12:33:20 -0700215 gpr_mu_unlock(&ac->mu);
216 if (done) {
217 gpr_mu_destroy(&ac->mu);
218 gpr_free(ac->addr_str);
219 gpr_free(ac);
220 }
Craig Tiller6c396862016-01-28 13:53:40 -0800221 grpc_exec_ctx_enqueue(exec_ctx, closure, *ep != NULL, NULL);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800222}
223
Craig Tillera82950e2015-09-22 12:33:20 -0700224void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
225 grpc_endpoint **ep,
226 grpc_pollset_set *interested_parties,
227 const struct sockaddr *addr, size_t addr_len,
228 gpr_timespec deadline) {
nnoble0c475f02014-12-05 15:37:39 -0800229 int fd;
230 grpc_dualstack_mode dsmode;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800231 int err;
232 async_connect *ac;
nnoble0c475f02014-12-05 15:37:39 -0800233 struct sockaddr_in6 addr6_v4mapped;
234 struct sockaddr_in addr4_copy;
Craig Tiller9bcc7512015-05-11 14:59:48 -0700235 grpc_fd *fdobj;
Craig Tillerfa275a92015-06-01 13:55:54 -0700236 char *name;
237 char *addr_str;
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 Tillera82950e2015-09-22 12:33:20 -0700247 fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
248 if (fd < 0) {
249 gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
250 }
251 if (dsmode == GRPC_DSMODE_IPV4) {
252 /* If we got an AF_INET socket, map the address back to IPv4. */
253 GPR_ASSERT(grpc_sockaddr_is_v4mapped(addr, &addr4_copy));
254 addr = (struct sockaddr *)&addr4_copy;
255 addr_len = sizeof(addr4_copy);
256 }
257 if (!prepare_socket(addr, fd)) {
Craig Tiller6c396862016-01-28 13:53:40 -0800258 grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700259 return;
260 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800261
Craig Tillera82950e2015-09-22 12:33:20 -0700262 do {
263 GPR_ASSERT(addr_len < ~(socklen_t)0);
264 err = connect(fd, addr, (socklen_t)addr_len);
265 } while (err < 0 && errno == EINTR);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800266
Craig Tillera82950e2015-09-22 12:33:20 -0700267 addr_str = grpc_sockaddr_to_uri(addr);
268 gpr_asprintf(&name, "tcp-client:%s", addr_str);
Craig Tillerfa275a92015-06-01 13:55:54 -0700269
Craig Tillera82950e2015-09-22 12:33:20 -0700270 fdobj = grpc_fd_create(fd, name);
Craig Tiller9bcc7512015-05-11 14:59:48 -0700271
Craig Tillera82950e2015-09-22 12:33:20 -0700272 if (err >= 0) {
273 *ep = grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str);
Craig Tiller6c396862016-01-28 13:53:40 -0800274 grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700275 goto done;
276 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800277
Craig Tillera82950e2015-09-22 12:33:20 -0700278 if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
279 gpr_log(GPR_ERROR, "connect error to '%s': %s", addr_str, strerror(errno));
yang-g5d850372015-12-01 10:32:28 -0800280 grpc_fd_orphan(exec_ctx, fdobj, NULL, NULL, "tcp_client_connect_error");
Craig Tiller6c396862016-01-28 13:53:40 -0800281 grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700282 goto done;
283 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800284
Craig Tillera82950e2015-09-22 12:33:20 -0700285 grpc_pollset_set_add_fd(exec_ctx, interested_parties, fdobj);
Craig Tiller4b678bd2015-06-02 16:12:24 -0700286
Craig Tillera82950e2015-09-22 12:33:20 -0700287 ac = gpr_malloc(sizeof(async_connect));
Craig Tillerd1bec032015-09-18 17:29:00 -0700288 ac->closure = closure;
289 ac->ep = ep;
Craig Tiller9bcc7512015-05-11 14:59:48 -0700290 ac->fd = fdobj;
Craig Tillerb49736822015-06-30 08:15:08 -0700291 ac->interested_parties = interested_parties;
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700292 ac->addr_str = addr_str;
293 addr_str = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700294 gpr_mu_init(&ac->mu);
ctiller58393c22015-01-07 14:03:30 -0800295 ac->refs = 2;
Craig Tiller0fcd53c2015-02-18 15:10:53 -0800296 ac->write_closure.cb = on_writable;
297 ac->write_closure.cb_arg = ac;
ctiller58393c22015-01-07 14:03:30 -0800298
Craig Tillera82950e2015-09-22 12:33:20 -0700299 if (grpc_tcp_trace) {
300 gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting",
301 ac->addr_str);
302 }
Craig Tiller5e53ddb2015-09-16 10:53:15 -0700303
Craig Tillera82950e2015-09-22 12:33:20 -0700304 gpr_mu_lock(&ac->mu);
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700305 grpc_timer_init(exec_ctx, &ac->alarm,
Craig Tillera82950e2015-09-22 12:33:20 -0700306 gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
307 tc_on_alarm, ac, gpr_now(GPR_CLOCK_MONOTONIC));
308 grpc_fd_notify_on_write(exec_ctx, ac->fd, &ac->write_closure);
309 gpr_mu_unlock(&ac->mu);
Craig Tillerfa275a92015-06-01 13:55:54 -0700310
311done:
Craig Tillera82950e2015-09-22 12:33:20 -0700312 gpr_free(name);
313 gpr_free(addr_str);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800314}
Craig Tiller0c0b60c2015-01-21 15:49:28 -0800315
Craig Tiller190d3602015-02-18 09:23:38 -0800316#endif