blob: e93d5734a07f81fcd7321fed47640ec30154c5f8 [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 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
Craig Tillera82950e2015-09-22 12:33:20 -070079 if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) ||
ahedberg43df2952016-03-18 10:46:38 -040080 (!grpc_is_unix_socket(addr) && !grpc_set_socket_low_latency(fd, 1)) ||
Craig Tillera82950e2015-09-22 12:33:20 -070081 !grpc_set_socket_no_sigpipe_if_possible(fd)) {
82 gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
83 strerror(errno));
84 goto error;
85 }
nnoble0c475f02014-12-05 15:37:39 -080086 return 1;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080087
88error:
Craig Tillera82950e2015-09-22 12:33:20 -070089 if (fd >= 0) {
90 close(fd);
91 }
nnoble0c475f02014-12-05 15:37:39 -080092 return 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080093}
94
Craig Tiller6c396862016-01-28 13:53:40 -080095static void tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, bool success) {
ctiller58393c22015-01-07 14:03:30 -080096 int done;
97 async_connect *ac = acp;
Craig Tillera82950e2015-09-22 12:33:20 -070098 if (grpc_tcp_trace) {
99 gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: success=%d", ac->addr_str,
100 success);
101 }
102 gpr_mu_lock(&ac->mu);
103 if (ac->fd != NULL) {
104 grpc_fd_shutdown(exec_ctx, ac->fd);
105 }
ctiller58393c22015-01-07 14:03:30 -0800106 done = (--ac->refs == 0);
Craig Tillera82950e2015-09-22 12:33:20 -0700107 gpr_mu_unlock(&ac->mu);
108 if (done) {
109 gpr_mu_destroy(&ac->mu);
110 gpr_free(ac->addr_str);
111 gpr_free(ac);
112 }
ctiller58393c22015-01-07 14:03:30 -0800113}
114
Craig Tiller6c396862016-01-28 13:53:40 -0800115static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, bool success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800116 async_connect *ac = acp;
117 int so_error = 0;
118 socklen_t so_error_size;
119 int err;
ctiller58393c22015-01-07 14:03:30 -0800120 int done;
Craig Tillerd1bec032015-09-18 17:29:00 -0700121 grpc_endpoint **ep = ac->ep;
122 grpc_closure *closure = ac->closure;
Craig Tiller5553eb32015-07-21 12:28:56 -0700123 grpc_fd *fd;
124
Craig Tillera82950e2015-09-22 12:33:20 -0700125 if (grpc_tcp_trace) {
126 gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_writable: success=%d",
127 ac->addr_str, success);
128 }
Craig Tiller5e53ddb2015-09-16 10:53:15 -0700129
Craig Tillera82950e2015-09-22 12:33:20 -0700130 gpr_mu_lock(&ac->mu);
131 GPR_ASSERT(ac->fd);
Craig Tiller5553eb32015-07-21 12:28:56 -0700132 fd = ac->fd;
133 ac->fd = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700134 gpr_mu_unlock(&ac->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800135
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700136 grpc_timer_cancel(exec_ctx, &ac->alarm);
Craig Tiller26205362015-07-21 08:21:57 -0700137
Craig Tillera82950e2015-09-22 12:33:20 -0700138 gpr_mu_lock(&ac->mu);
139 if (success) {
140 do {
141 so_error_size = sizeof(so_error);
Craig Tiller0a8a0172016-02-25 07:36:27 -0800142 err = getsockopt(grpc_fd_wrapped_fd(fd), SOL_SOCKET, SO_ERROR, &so_error,
143 &so_error_size);
Craig Tillera82950e2015-09-22 12:33:20 -0700144 } while (err < 0 && errno == EINTR);
145 if (err < 0) {
Craig Tiller3bf828f2015-10-05 13:36:25 -0700146 gpr_log(GPR_ERROR, "failed to connect to '%s': getsockopt(ERROR): %s",
147 ac->addr_str, strerror(errno));
Craig Tillera82950e2015-09-22 12:33:20 -0700148 goto finish;
149 } else if (so_error != 0) {
150 if (so_error == ENOBUFS) {
151 /* We will get one of these errors if we have run out of
152 memory in the kernel for the data structures allocated
153 when you connect a socket. If this happens it is very
154 likely that if we wait a little bit then try again the
155 connection will work (since other programs or this
156 program will close their network connections and free up
157 memory). This does _not_ indicate that there is anything
158 wrong with the server we are connecting to, this is a
159 local problem.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800160
Craig Tillera82950e2015-09-22 12:33:20 -0700161 If you are looking at this code, then chances are that
162 your program or another program on the same computer
163 opened too many network connections. The "easy" fix:
164 don't do that! */
165 gpr_log(GPR_ERROR, "kernel out of buffers");
166 gpr_mu_unlock(&ac->mu);
167 grpc_fd_notify_on_write(exec_ctx, fd, &ac->write_closure);
168 return;
169 } else {
170 switch (so_error) {
171 case ECONNREFUSED:
Craig Tiller3bf828f2015-10-05 13:36:25 -0700172 gpr_log(
173 GPR_ERROR,
174 "failed to connect to '%s': socket error: connection refused",
175 ac->addr_str);
Craig Tillera82950e2015-09-22 12:33:20 -0700176 break;
177 default:
Craig Tiller3bf828f2015-10-05 13:36:25 -0700178 gpr_log(GPR_ERROR, "failed to connect to '%s': socket error: %d",
179 ac->addr_str, so_error);
Craig Tillera82950e2015-09-22 12:33:20 -0700180 break;
181 }
182 goto finish;
183 }
184 } else {
185 grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd);
186 *ep = grpc_tcp_create(fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, ac->addr_str);
187 fd = NULL;
ctiller58393c22015-01-07 14:03:30 -0800188 goto finish;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800189 }
Craig Tillera82950e2015-09-22 12:33:20 -0700190 } else {
Craig Tiller3bf828f2015-10-05 13:36:25 -0700191 gpr_log(GPR_ERROR, "failed to connect to '%s': timeout occurred",
192 ac->addr_str);
Craig Tillera82950e2015-09-22 12:33:20 -0700193 goto finish;
194 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800195
yang-gb063c872015-10-07 11:40:13 -0700196 GPR_UNREACHABLE_CODE(return );
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800197
ctiller58393c22015-01-07 14:03:30 -0800198finish:
Craig Tillera82950e2015-09-22 12:33:20 -0700199 if (fd != NULL) {
200 grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd);
yang-g5d850372015-12-01 10:32:28 -0800201 grpc_fd_orphan(exec_ctx, fd, NULL, NULL, "tcp_client_orphan");
Craig Tillera82950e2015-09-22 12:33:20 -0700202 fd = NULL;
203 }
ctiller58393c22015-01-07 14:03:30 -0800204 done = (--ac->refs == 0);
Craig Tillera82950e2015-09-22 12:33:20 -0700205 gpr_mu_unlock(&ac->mu);
206 if (done) {
207 gpr_mu_destroy(&ac->mu);
208 gpr_free(ac->addr_str);
209 gpr_free(ac);
210 }
Craig Tiller6c396862016-01-28 13:53:40 -0800211 grpc_exec_ctx_enqueue(exec_ctx, closure, *ep != NULL, NULL);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800212}
213
Craig Tillere6282612016-04-13 14:14:34 -0700214static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx,
215 grpc_closure *closure, grpc_endpoint **ep,
216 grpc_pollset_set *interested_parties,
217 const struct sockaddr *addr,
218 size_t addr_len, gpr_timespec deadline) {
nnoble0c475f02014-12-05 15:37:39 -0800219 int fd;
220 grpc_dualstack_mode dsmode;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800221 int err;
222 async_connect *ac;
nnoble0c475f02014-12-05 15:37:39 -0800223 struct sockaddr_in6 addr6_v4mapped;
224 struct sockaddr_in addr4_copy;
Craig Tiller9bcc7512015-05-11 14:59:48 -0700225 grpc_fd *fdobj;
Craig Tillerfa275a92015-06-01 13:55:54 -0700226 char *name;
227 char *addr_str;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800228
Craig Tillerd1bec032015-09-18 17:29:00 -0700229 *ep = NULL;
230
nnoble0c475f02014-12-05 15:37:39 -0800231 /* Use dualstack sockets where available. */
Craig Tillera82950e2015-09-22 12:33:20 -0700232 if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
233 addr = (const struct sockaddr *)&addr6_v4mapped;
234 addr_len = sizeof(addr6_v4mapped);
235 }
nnoble0c475f02014-12-05 15:37:39 -0800236
Craig Tillera82950e2015-09-22 12:33:20 -0700237 fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
238 if (fd < 0) {
239 gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
240 }
241 if (dsmode == GRPC_DSMODE_IPV4) {
242 /* If we got an AF_INET socket, map the address back to IPv4. */
243 GPR_ASSERT(grpc_sockaddr_is_v4mapped(addr, &addr4_copy));
244 addr = (struct sockaddr *)&addr4_copy;
245 addr_len = sizeof(addr4_copy);
246 }
247 if (!prepare_socket(addr, fd)) {
Craig Tiller6c396862016-01-28 13:53:40 -0800248 grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700249 return;
250 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800251
Craig Tillera82950e2015-09-22 12:33:20 -0700252 do {
253 GPR_ASSERT(addr_len < ~(socklen_t)0);
254 err = connect(fd, addr, (socklen_t)addr_len);
255 } while (err < 0 && errno == EINTR);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800256
Craig Tillera82950e2015-09-22 12:33:20 -0700257 addr_str = grpc_sockaddr_to_uri(addr);
258 gpr_asprintf(&name, "tcp-client:%s", addr_str);
Craig Tillerfa275a92015-06-01 13:55:54 -0700259
Craig Tillera82950e2015-09-22 12:33:20 -0700260 fdobj = grpc_fd_create(fd, name);
Craig Tiller9bcc7512015-05-11 14:59:48 -0700261
Craig Tillera82950e2015-09-22 12:33:20 -0700262 if (err >= 0) {
263 *ep = grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str);
Craig Tiller6c396862016-01-28 13:53:40 -0800264 grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700265 goto done;
266 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800267
Craig Tillera82950e2015-09-22 12:33:20 -0700268 if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
269 gpr_log(GPR_ERROR, "connect error to '%s': %s", addr_str, strerror(errno));
yang-g5d850372015-12-01 10:32:28 -0800270 grpc_fd_orphan(exec_ctx, fdobj, NULL, NULL, "tcp_client_connect_error");
Craig Tiller6c396862016-01-28 13:53:40 -0800271 grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700272 goto done;
273 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800274
Craig Tillera82950e2015-09-22 12:33:20 -0700275 grpc_pollset_set_add_fd(exec_ctx, interested_parties, fdobj);
Craig Tiller4b678bd2015-06-02 16:12:24 -0700276
Craig Tillera82950e2015-09-22 12:33:20 -0700277 ac = gpr_malloc(sizeof(async_connect));
Craig Tillerd1bec032015-09-18 17:29:00 -0700278 ac->closure = closure;
279 ac->ep = ep;
Craig Tiller9bcc7512015-05-11 14:59:48 -0700280 ac->fd = fdobj;
Craig Tillerb49736822015-06-30 08:15:08 -0700281 ac->interested_parties = interested_parties;
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700282 ac->addr_str = addr_str;
283 addr_str = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700284 gpr_mu_init(&ac->mu);
ctiller58393c22015-01-07 14:03:30 -0800285 ac->refs = 2;
Craig Tiller0fcd53c2015-02-18 15:10:53 -0800286 ac->write_closure.cb = on_writable;
287 ac->write_closure.cb_arg = ac;
ctiller58393c22015-01-07 14:03:30 -0800288
Craig Tillera82950e2015-09-22 12:33:20 -0700289 if (grpc_tcp_trace) {
290 gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting",
291 ac->addr_str);
292 }
Craig Tiller5e53ddb2015-09-16 10:53:15 -0700293
Craig Tillera82950e2015-09-22 12:33:20 -0700294 gpr_mu_lock(&ac->mu);
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700295 grpc_timer_init(exec_ctx, &ac->alarm,
Craig Tillera82950e2015-09-22 12:33:20 -0700296 gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
297 tc_on_alarm, ac, gpr_now(GPR_CLOCK_MONOTONIC));
298 grpc_fd_notify_on_write(exec_ctx, ac->fd, &ac->write_closure);
299 gpr_mu_unlock(&ac->mu);
Craig Tillerfa275a92015-06-01 13:55:54 -0700300
301done:
Craig Tillera82950e2015-09-22 12:33:20 -0700302 gpr_free(name);
303 gpr_free(addr_str);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800304}
Craig Tiller0c0b60c2015-01-21 15:49:28 -0800305
Craig Tillere6282612016-04-13 14:14:34 -0700306// overridden by api_fuzzer.c
307void (*grpc_tcp_client_connect_impl)(
308 grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep,
309 grpc_pollset_set *interested_parties, const struct sockaddr *addr,
310 size_t addr_len, gpr_timespec deadline) = tcp_client_connect_impl;
311
312void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
313 grpc_endpoint **ep,
314 grpc_pollset_set *interested_parties,
315 const struct sockaddr *addr, size_t addr_len,
316 gpr_timespec deadline) {
317 grpc_tcp_client_connect_impl(exec_ctx, closure, ep, interested_parties, addr,
318 addr_len, deadline);
319}
320
Craig Tiller190d3602015-02-18 09:23:38 -0800321#endif