3 * Copyright 2015 gRPC authors.
5 * 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
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * 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.
19 #include <grpc/support/port_platform.h>
21 #include "src/core/lib/iomgr/port.h"
23 #ifdef GRPC_POSIX_SOCKET_UTILS_COMMON
25 #include "src/core/lib/iomgr/socket_utils.h"
26 #include "src/core/lib/iomgr/socket_utils_posix.h"
28 #include <arpa/inet.h>
32 #include <netinet/in.h>
33 #include <netinet/tcp.h>
36 #include <sys/socket.h>
37 #include <sys/types.h>
40 #include <grpc/support/alloc.h>
41 #include <grpc/support/log.h>
42 #include <grpc/support/sync.h>
44 #include "src/core/lib/channel/channel_args.h"
45 #include "src/core/lib/gpr/host_port.h"
46 #include "src/core/lib/gpr/string.h"
47 #include "src/core/lib/iomgr/sockaddr.h"
48 #include "src/core/lib/iomgr/sockaddr_utils.h"
50 /* set a socket to non blocking mode */
51 grpc_error* grpc_set_socket_nonblocking(int fd, int non_blocking) {
52 int oldflags = fcntl(fd, F_GETFL, 0);
54 return GRPC_OS_ERROR(errno, "fcntl");
58 oldflags |= O_NONBLOCK;
60 oldflags &= ~O_NONBLOCK;
63 if (fcntl(fd, F_SETFL, oldflags) != 0) {
64 return GRPC_OS_ERROR(errno, "fcntl");
67 return GRPC_ERROR_NONE;
70 grpc_error* grpc_set_socket_no_sigpipe_if_possible(int fd) {
71 #ifdef GRPC_HAVE_SO_NOSIGPIPE
74 socklen_t intlen = sizeof(newval);
75 if (0 != setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(val))) {
76 return GRPC_OS_ERROR(errno, "setsockopt(SO_NOSIGPIPE)");
78 if (0 != getsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &newval, &intlen)) {
79 return GRPC_OS_ERROR(errno, "getsockopt(SO_NOSIGPIPE)");
81 if ((newval != 0) != (val != 0)) {
82 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to set SO_NOSIGPIPE");
85 return GRPC_ERROR_NONE;
88 grpc_error* grpc_set_socket_ip_pktinfo_if_possible(int fd) {
89 #ifdef GRPC_HAVE_IP_PKTINFO
91 if (0 != setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &get_local_ip,
92 sizeof(get_local_ip))) {
93 return GRPC_OS_ERROR(errno, "setsockopt(IP_PKTINFO)");
96 return GRPC_ERROR_NONE;
99 grpc_error* grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd) {
100 #ifdef GRPC_HAVE_IPV6_RECVPKTINFO
101 int get_local_ip = 1;
102 if (0 != setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &get_local_ip,
103 sizeof(get_local_ip))) {
104 return GRPC_OS_ERROR(errno, "setsockopt(IPV6_RECVPKTINFO)");
107 return GRPC_ERROR_NONE;
110 grpc_error* grpc_set_socket_sndbuf(int fd, int buffer_size_bytes) {
111 return 0 == setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffer_size_bytes,
112 sizeof(buffer_size_bytes))
114 : GRPC_OS_ERROR(errno, "setsockopt(SO_SNDBUF)");
117 grpc_error* grpc_set_socket_rcvbuf(int fd, int buffer_size_bytes) {
118 return 0 == setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buffer_size_bytes,
119 sizeof(buffer_size_bytes))
121 : GRPC_OS_ERROR(errno, "setsockopt(SO_RCVBUF)");
124 /* set a socket to close on exec */
125 grpc_error* grpc_set_socket_cloexec(int fd, int close_on_exec) {
126 int oldflags = fcntl(fd, F_GETFD, 0);
128 return GRPC_OS_ERROR(errno, "fcntl");
132 oldflags |= FD_CLOEXEC;
134 oldflags &= ~FD_CLOEXEC;
137 if (fcntl(fd, F_SETFD, oldflags) != 0) {
138 return GRPC_OS_ERROR(errno, "fcntl");
141 return GRPC_ERROR_NONE;
144 /* set a socket to reuse old addresses */
145 grpc_error* grpc_set_socket_reuse_addr(int fd, int reuse) {
146 int val = (reuse != 0);
148 socklen_t intlen = sizeof(newval);
149 if (0 != setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) {
150 return GRPC_OS_ERROR(errno, "setsockopt(SO_REUSEADDR)");
152 if (0 != getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &newval, &intlen)) {
153 return GRPC_OS_ERROR(errno, "getsockopt(SO_REUSEADDR)");
155 if ((newval != 0) != val) {
156 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to set SO_REUSEADDR");
159 return GRPC_ERROR_NONE;
162 /* set a socket to reuse old addresses */
163 grpc_error* grpc_set_socket_reuse_port(int fd, int reuse) {
165 return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
166 "SO_REUSEPORT unavailable on compiling system");
168 int val = (reuse != 0);
170 socklen_t intlen = sizeof(newval);
171 if (0 != setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val))) {
172 return GRPC_OS_ERROR(errno, "setsockopt(SO_REUSEPORT)");
174 if (0 != getsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &newval, &intlen)) {
175 return GRPC_OS_ERROR(errno, "getsockopt(SO_REUSEPORT)");
177 if ((newval != 0) != val) {
178 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to set SO_REUSEPORT");
181 return GRPC_ERROR_NONE;
185 static gpr_once g_probe_so_reuesport_once = GPR_ONCE_INIT;
186 static int g_support_so_reuseport = false;
188 void probe_so_reuseport_once(void) {
189 #ifndef GPR_MANYLINUX1
190 int s = socket(AF_INET, SOCK_STREAM, 0);
192 /* This might be an ipv6-only environment in which case 'socket(AF_INET,..)'
193 call would fail. Try creating IPv6 socket in that case */
194 s = socket(AF_INET6, SOCK_STREAM, 0);
197 g_support_so_reuseport = GRPC_LOG_IF_ERROR(
198 "check for SO_REUSEPORT", grpc_set_socket_reuse_port(s, 1));
204 bool grpc_is_socket_reuse_port_supported() {
205 gpr_once_init(&g_probe_so_reuesport_once, probe_so_reuseport_once);
206 return g_support_so_reuseport;
210 grpc_error* grpc_set_socket_low_latency(int fd, int low_latency) {
211 int val = (low_latency != 0);
213 socklen_t intlen = sizeof(newval);
214 if (0 != setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val))) {
215 return GRPC_OS_ERROR(errno, "setsockopt(TCP_NODELAY)");
217 if (0 != getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &newval, &intlen)) {
218 return GRPC_OS_ERROR(errno, "getsockopt(TCP_NODELAY)");
220 if ((newval != 0) != val) {
221 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to set TCP_NODELAY");
223 return GRPC_ERROR_NONE;
226 /* The default values for TCP_USER_TIMEOUT are currently configured to be in
227 * line with the default values of KEEPALIVE_TIMEOUT as proposed in
228 * https://github.com/grpc/proposal/blob/master/A18-tcp-user-timeout.md */
229 #define DEFAULT_CLIENT_TCP_USER_TIMEOUT_MS 20000 /* 20 seconds */
230 #define DEFAULT_SERVER_TCP_USER_TIMEOUT_MS 20000 /* 20 seconds */
232 static int g_default_client_tcp_user_timeout_ms =
233 DEFAULT_CLIENT_TCP_USER_TIMEOUT_MS;
234 static int g_default_server_tcp_user_timeout_ms =
235 DEFAULT_SERVER_TCP_USER_TIMEOUT_MS;
236 static bool g_default_client_tcp_user_timeout_enabled = false;
237 static bool g_default_server_tcp_user_timeout_enabled = true;
239 void config_default_tcp_user_timeout(bool enable, int timeout, bool is_client) {
241 g_default_client_tcp_user_timeout_enabled = enable;
243 g_default_client_tcp_user_timeout_ms = timeout;
246 g_default_server_tcp_user_timeout_enabled = enable;
248 g_default_server_tcp_user_timeout_ms = timeout;
253 /* Set TCP_USER_TIMEOUT */
254 grpc_error* grpc_set_socket_tcp_user_timeout(
255 int fd, const grpc_channel_args* channel_args, bool is_client) {
256 #ifdef GRPC_HAVE_TCP_USER_TIMEOUT
260 enable = g_default_client_tcp_user_timeout_enabled;
261 timeout = g_default_client_tcp_user_timeout_ms;
263 enable = g_default_server_tcp_user_timeout_enabled;
264 timeout = g_default_server_tcp_user_timeout_ms;
267 for (unsigned int i = 0; i < channel_args->num_args; i++) {
268 if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_KEEPALIVE_TIME_MS)) {
269 const int value = grpc_channel_arg_get_integer(
270 &channel_args->args[i], grpc_integer_options{0, 1, INT_MAX});
271 /* Continue using default if value is 0 */
275 /* Disable if value is INT_MAX */
276 enable = value != INT_MAX;
277 } else if (0 == strcmp(channel_args->args[i].key,
278 GRPC_ARG_KEEPALIVE_TIMEOUT_MS)) {
279 const int value = grpc_channel_arg_get_integer(
280 &channel_args->args[i], grpc_integer_options{0, 1, INT_MAX});
281 /* Continue using default if value is 0 */
290 extern grpc_core::TraceFlag grpc_tcp_trace;
291 if (grpc_tcp_trace.enabled()) {
292 gpr_log(GPR_INFO, "Enabling TCP_USER_TIMEOUT with a timeout of %d ms",
296 socklen_t len = sizeof(newval);
297 if (0 != setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout,
299 gpr_log(GPR_ERROR, "setsockopt(TCP_USER_TIMEOUT) %s", strerror(errno));
300 return GRPC_ERROR_NONE;
302 if (0 != getsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &newval, &len)) {
303 gpr_log(GPR_ERROR, "getsockopt(TCP_USER_TIMEOUT) %s", strerror(errno));
304 return GRPC_ERROR_NONE;
306 if (newval != timeout) {
307 /* Do not fail on failing to set TCP_USER_TIMEOUT for now. */
308 gpr_log(GPR_ERROR, "Failed to set TCP_USER_TIMEOUT");
309 return GRPC_ERROR_NONE;
313 extern grpc_core::TraceFlag grpc_tcp_trace;
314 if (grpc_tcp_trace.enabled()) {
315 gpr_log(GPR_INFO, "TCP_USER_TIMEOUT not supported for this platform");
317 #endif /* GRPC_HAVE_TCP_USER_TIMEOUT */
318 return GRPC_ERROR_NONE;
321 /* set a socket using a grpc_socket_mutator */
322 grpc_error* grpc_set_socket_with_mutator(int fd, grpc_socket_mutator* mutator) {
324 if (!grpc_socket_mutator_mutate_fd(mutator, fd)) {
325 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("grpc_socket_mutator failed.");
327 return GRPC_ERROR_NONE;
330 static gpr_once g_probe_ipv6_once = GPR_ONCE_INIT;
331 static int g_ipv6_loopback_available;
333 static void probe_ipv6_once(void) {
334 int fd = socket(AF_INET6, SOCK_STREAM, 0);
335 g_ipv6_loopback_available = 0;
337 gpr_log(GPR_INFO, "Disabling AF_INET6 sockets because socket() failed.");
339 grpc_sockaddr_in6 addr;
340 memset(&addr, 0, sizeof(addr));
341 addr.sin6_family = AF_INET6;
342 addr.sin6_addr.s6_addr[15] = 1; /* [::1]:0 */
343 if (bind(fd, reinterpret_cast<grpc_sockaddr*>(&addr), sizeof(addr)) == 0) {
344 g_ipv6_loopback_available = 1;
347 "Disabling AF_INET6 sockets because ::1 is not available.");
353 int grpc_ipv6_loopback_available(void) {
354 gpr_once_init(&g_probe_ipv6_once, probe_ipv6_once);
355 return g_ipv6_loopback_available;
358 /* This should be 0 in production, but it may be enabled for testing or
359 debugging purposes, to simulate an environment where IPv6 sockets can't
361 int grpc_forbid_dualstack_sockets_for_testing = 0;
363 static int set_socket_dualstack(int fd) {
364 if (!grpc_forbid_dualstack_sockets_for_testing) {
366 return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off));
368 /* Force an IPv6-only socket, for testing purposes. */
370 setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
375 static grpc_error* error_for_fd(int fd, const grpc_resolved_address* addr) {
376 if (fd >= 0) return GRPC_ERROR_NONE;
378 grpc_sockaddr_to_string(&addr_str, addr, 0);
379 grpc_error* err = grpc_error_set_str(GRPC_OS_ERROR(errno, "socket"),
380 GRPC_ERROR_STR_TARGET_ADDRESS,
381 grpc_slice_from_copied_string(addr_str));
386 grpc_error* grpc_create_dualstack_socket(
387 const grpc_resolved_address* resolved_addr, int type, int protocol,
388 grpc_dualstack_mode* dsmode, int* newfd) {
389 return grpc_create_dualstack_socket_using_factory(
390 nullptr, resolved_addr, type, protocol, dsmode, newfd);
393 static int create_socket(grpc_socket_factory* factory, int domain, int type,
395 return (factory != nullptr)
396 ? grpc_socket_factory_socket(factory, domain, type, protocol)
397 : socket(domain, type, protocol);
400 grpc_error* grpc_create_dualstack_socket_using_factory(
401 grpc_socket_factory* factory, const grpc_resolved_address* resolved_addr,
402 int type, int protocol, grpc_dualstack_mode* dsmode, int* newfd) {
403 const grpc_sockaddr* addr =
404 reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr);
405 int family = addr->sa_family;
406 if (family == AF_INET6) {
407 if (grpc_ipv6_loopback_available()) {
408 *newfd = create_socket(factory, family, type, protocol);
411 errno = EAFNOSUPPORT;
413 /* Check if we've got a valid dualstack socket. */
414 if (*newfd >= 0 && set_socket_dualstack(*newfd)) {
415 *dsmode = GRPC_DSMODE_DUALSTACK;
416 return GRPC_ERROR_NONE;
418 /* If this isn't an IPv4 address, then return whatever we've got. */
419 if (!grpc_sockaddr_is_v4mapped(resolved_addr, nullptr)) {
420 *dsmode = GRPC_DSMODE_IPV6;
421 return error_for_fd(*newfd, resolved_addr);
423 /* Fall back to AF_INET. */
429 *dsmode = family == AF_INET ? GRPC_DSMODE_IPV4 : GRPC_DSMODE_NONE;
430 *newfd = create_socket(factory, family, type, protocol);
431 return error_for_fd(*newfd, resolved_addr);
434 uint16_t grpc_htons(uint16_t hostshort) { return htons(hostshort); }
436 uint16_t grpc_ntohs(uint16_t netshort) { return ntohs(netshort); }
438 uint32_t grpc_htonl(uint32_t hostlong) { return htonl(hostlong); }
440 uint32_t grpc_ntohl(uint32_t netlong) { return ntohl(netlong); }
442 int grpc_inet_pton(int af, const char* src, void* dst) {
443 return inet_pton(af, src, dst);
446 const char* grpc_inet_ntop(int af, const void* src, char* dst, size_t size) {
447 GPR_ASSERT(size <= (socklen_t)-1);
448 return inet_ntop(af, src, dst, static_cast<socklen_t>(size));