blob: 392eda999ee2086b2afbcad06b8656e8f1d187c2 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller06059952015-02-18 08:34:56 -08003 * 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
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
ctiller58393c22015-01-07 14:03:30 -080045#include "src/core/iomgr/alarm.h"
46#include "src/core/iomgr/iomgr_posix.h"
47#include "src/core/iomgr/pollset_posix.h"
ctiller18b49ab2014-12-09 14:39:16 -080048#include "src/core/iomgr/sockaddr_utils.h"
49#include "src/core/iomgr/socket_utils_posix.h"
50#include "src/core/iomgr/tcp_posix.h"
Craig Tillerfa275a92015-06-01 13:55:54 -070051#include "src/core/support/string.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080052#include <grpc/support/alloc.h>
53#include <grpc/support/log.h>
Masood Malekghassemi701af602015-06-03 15:01:17 -070054#include <grpc/support/string_util.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080055#include <grpc/support/time.h>
56
57typedef struct {
58 void (*cb)(void *arg, grpc_endpoint *tcp);
59 void *cb_arg;
ctiller58393c22015-01-07 14:03:30 -080060 gpr_mu mu;
ctiller18b49ab2014-12-09 14:39:16 -080061 grpc_fd *fd;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080062 gpr_timespec deadline;
ctiller58393c22015-01-07 14:03:30 -080063 grpc_alarm alarm;
64 int refs;
Craig Tiller0fcd53c2015-02-18 15:10:53 -080065 grpc_iomgr_closure write_closure;
Craig Tillerb49736822015-06-30 08:15:08 -070066 grpc_pollset_set *interested_parties;
Craig Tiller1b22b9d2015-07-20 13:42:22 -070067 char *addr_str;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080068} async_connect;
69
Craig Tillerd209ed02015-02-13 23:18:15 -080070static int prepare_socket(const struct sockaddr *addr, int fd) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080071 if (fd < 0) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080072 goto error;
73 }
74
75 if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) ||
Craig Tiller2da02962015-05-06 16:14:25 -070076 (addr->sa_family != AF_UNIX && !grpc_set_socket_low_latency(fd, 1)) ||
77 !grpc_set_socket_no_sigpipe_if_possible(fd)) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080078 gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
79 strerror(errno));
80 goto error;
81 }
82
nnoble0c475f02014-12-05 15:37:39 -080083 return 1;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080084
85error:
86 if (fd >= 0) {
87 close(fd);
88 }
nnoble0c475f02014-12-05 15:37:39 -080089 return 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080090}
91
ctiller58393c22015-01-07 14:03:30 -080092static void on_alarm(void *acp, int success) {
93 int done;
94 async_connect *ac = acp;
95 gpr_mu_lock(&ac->mu);
96 if (ac->fd != NULL && success) {
97 grpc_fd_shutdown(ac->fd);
98 }
99 done = (--ac->refs == 0);
100 gpr_mu_unlock(&ac->mu);
101 if (done) {
102 gpr_mu_destroy(&ac->mu);
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700103 gpr_free(ac->addr_str);
ctiller58393c22015-01-07 14:03:30 -0800104 gpr_free(ac);
105 }
106}
107
108static void on_writable(void *acp, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800109 async_connect *ac = acp;
110 int so_error = 0;
111 socklen_t so_error_size;
112 int err;
ctiller58393c22015-01-07 14:03:30 -0800113 int fd = ac->fd->fd;
114 int done;
115 grpc_endpoint *ep = NULL;
116 void (*cb)(void *arg, grpc_endpoint *tcp) = ac->cb;
117 void *cb_arg = ac->cb_arg;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800118
Craig Tiller26205362015-07-21 08:21:57 -0700119 grpc_alarm_cancel(&ac->alarm);
120
Craig Tiller71bf1be2015-07-09 14:51:24 -0700121 gpr_mu_lock(&ac->mu);
ctiller58393c22015-01-07 14:03:30 -0800122 if (success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800123 do {
124 so_error_size = sizeof(so_error);
125 err = getsockopt(fd, SOL_SOCKET, SO_ERROR, &so_error, &so_error_size);
126 } while (err < 0 && errno == EINTR);
127 if (err < 0) {
128 gpr_log(GPR_ERROR, "getsockopt(ERROR): %s", strerror(errno));
ctiller58393c22015-01-07 14:03:30 -0800129 goto finish;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800130 } else if (so_error != 0) {
131 if (so_error == ENOBUFS) {
132 /* We will get one of these errors if we have run out of
133 memory in the kernel for the data structures allocated
134 when you connect a socket. If this happens it is very
135 likely that if we wait a little bit then try again the
136 connection will work (since other programs or this
137 program will close their network connections and free up
138 memory). This does _not_ indicate that there is anything
139 wrong with the server we are connecting to, this is a
140 local problem.
141
142 If you are looking at this code, then chances are that
143 your program or another program on the same computer
144 opened too many network connections. The "easy" fix:
145 don't do that! */
146 gpr_log(GPR_ERROR, "kernel out of buffers");
Craig Tiller71bf1be2015-07-09 14:51:24 -0700147 gpr_mu_unlock(&ac->mu);
Craig Tiller0fcd53c2015-02-18 15:10:53 -0800148 grpc_fd_notify_on_write(ac->fd, &ac->write_closure);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800149 return;
150 } else {
ctillerccd27fd2014-12-11 09:12:02 -0800151 switch (so_error) {
152 case ECONNREFUSED:
153 gpr_log(GPR_ERROR, "socket error: connection refused");
154 break;
155 default:
156 gpr_log(GPR_ERROR, "socket error: %d", so_error);
157 break;
158 }
ctiller58393c22015-01-07 14:03:30 -0800159 goto finish;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800160 }
161 } else {
Craig Tillerb49736822015-06-30 08:15:08 -0700162 grpc_pollset_set_del_fd(ac->interested_parties, ac->fd);
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700163 ep = grpc_tcp_create(ac->fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE,
164 ac->addr_str);
ctiller58393c22015-01-07 14:03:30 -0800165 goto finish;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800166 }
167 } else {
ctiller58393c22015-01-07 14:03:30 -0800168 gpr_log(GPR_ERROR, "on_writable failed during connect");
169 goto finish;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800170 }
171
172 abort();
173
ctiller58393c22015-01-07 14:03:30 -0800174finish:
Craig Tiller71bf1be2015-07-09 14:51:24 -0700175 if (ep == NULL) {
Craig Tillerb49736822015-06-30 08:15:08 -0700176 grpc_pollset_set_del_fd(ac->interested_parties, ac->fd);
Craig Tiller4b678bd2015-06-02 16:12:24 -0700177 grpc_fd_orphan(ac->fd, NULL, "tcp_client_orphan");
Craig Tiller71bf1be2015-07-09 14:51:24 -0700178 } else {
179 ac->fd = NULL;
ctiller58393c22015-01-07 14:03:30 -0800180 }
181 done = (--ac->refs == 0);
182 gpr_mu_unlock(&ac->mu);
183 if (done) {
184 gpr_mu_destroy(&ac->mu);
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700185 gpr_free(ac->addr_str);
ctiller58393c22015-01-07 14:03:30 -0800186 gpr_free(ac);
187 }
188 cb(cb_arg, ep);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800189}
190
191void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep),
Craig Tiller8ed24e22015-05-08 09:59:51 -0700192 void *arg, grpc_pollset_set *interested_parties,
193 const struct sockaddr *addr, int addr_len,
194 gpr_timespec deadline) {
nnoble0c475f02014-12-05 15:37:39 -0800195 int fd;
196 grpc_dualstack_mode dsmode;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800197 int err;
198 async_connect *ac;
nnoble0c475f02014-12-05 15:37:39 -0800199 struct sockaddr_in6 addr6_v4mapped;
200 struct sockaddr_in addr4_copy;
Craig Tiller9bcc7512015-05-11 14:59:48 -0700201 grpc_fd *fdobj;
Craig Tillerfa275a92015-06-01 13:55:54 -0700202 char *name;
203 char *addr_str;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800204
nnoble0c475f02014-12-05 15:37:39 -0800205 /* Use dualstack sockets where available. */
206 if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
207 addr = (const struct sockaddr *)&addr6_v4mapped;
208 addr_len = sizeof(addr6_v4mapped);
209 }
210
211 fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800212 if (fd < 0) {
nnoble0c475f02014-12-05 15:37:39 -0800213 gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
214 }
215 if (dsmode == GRPC_DSMODE_IPV4) {
216 /* If we got an AF_INET socket, map the address back to IPv4. */
217 GPR_ASSERT(grpc_sockaddr_is_v4mapped(addr, &addr4_copy));
218 addr = (struct sockaddr *)&addr4_copy;
219 addr_len = sizeof(addr4_copy);
220 }
Craig Tillerae7fe922015-02-13 23:16:32 -0800221 if (!prepare_socket(addr, fd)) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800222 cb(arg, NULL);
223 return;
224 }
225
226 do {
nnoble0c475f02014-12-05 15:37:39 -0800227 err = connect(fd, addr, addr_len);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800228 } while (err < 0 && errno == EINTR);
229
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700230 addr_str = grpc_sockaddr_to_uri(addr);
Craig Tillerfa275a92015-06-01 13:55:54 -0700231 gpr_asprintf(&name, "tcp-client:%s", addr_str);
232
Craig Tiller8e0b08a2015-06-01 17:04:17 -0700233 fdobj = grpc_fd_create(fd, name);
Craig Tiller9bcc7512015-05-11 14:59:48 -0700234
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800235 if (err >= 0) {
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700236 cb(arg, grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str));
Craig Tillerfa275a92015-06-01 13:55:54 -0700237 goto done;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800238 }
239
240 if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
Craig Tiller4b678bd2015-06-02 16:12:24 -0700241 gpr_log(GPR_ERROR, "connect error to '%s': %s", addr_str, strerror(errno));
242 grpc_fd_orphan(fdobj, NULL, "tcp_client_connect_error");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800243 cb(arg, NULL);
Craig Tillerfa275a92015-06-01 13:55:54 -0700244 goto done;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800245 }
246
Craig Tiller4b678bd2015-06-02 16:12:24 -0700247 grpc_pollset_set_add_fd(interested_parties, fdobj);
248
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800249 ac = gpr_malloc(sizeof(async_connect));
250 ac->cb = cb;
251 ac->cb_arg = arg;
Craig Tiller9bcc7512015-05-11 14:59:48 -0700252 ac->fd = fdobj;
Craig Tillerb49736822015-06-30 08:15:08 -0700253 ac->interested_parties = interested_parties;
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700254 ac->addr_str = addr_str;
255 addr_str = NULL;
ctiller58393c22015-01-07 14:03:30 -0800256 gpr_mu_init(&ac->mu);
257 ac->refs = 2;
Craig Tiller0fcd53c2015-02-18 15:10:53 -0800258 ac->write_closure.cb = on_writable;
259 ac->write_closure.cb_arg = ac;
ctiller58393c22015-01-07 14:03:30 -0800260
Craig Tiller0317b3d2015-06-01 21:57:03 -0700261 gpr_mu_lock(&ac->mu);
Craig Tiller6a7626c2015-07-19 22:21:41 -0700262 grpc_alarm_init(&ac->alarm, gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
263 on_alarm, ac, gpr_now(GPR_CLOCK_MONOTONIC));
Craig Tiller0317b3d2015-06-01 21:57:03 -0700264 grpc_fd_notify_on_write(ac->fd, &ac->write_closure);
265 gpr_mu_unlock(&ac->mu);
Craig Tillerfa275a92015-06-01 13:55:54 -0700266
267done:
268 gpr_free(name);
269 gpr_free(addr_str);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800270}
Craig Tiller0c0b60c2015-01-21 15:49:28 -0800271
Craig Tiller190d3602015-02-18 09:23:38 -0800272#endif