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 #ifdef GRPC_LINUX_TCP_H
34 #include <linux/tcp.h>
36 #include <netinet/tcp.h>
40 #include <sys/socket.h>
41 #include <sys/types.h>
46 #include <grpc/support/alloc.h>
47 #include <grpc/support/log.h>
48 #include <grpc/support/sync.h>
50 #include "src/core/lib/channel/channel_args.h"
51 #include "src/core/lib/gpr/string.h"
52 #include "src/core/lib/iomgr/sockaddr.h"
53 #include "src/core/lib/iomgr/sockaddr_utils.h"
55 /* set a socket to use zerocopy */
56 grpc_error* grpc_set_socket_zerocopy(int fd) {
57 #ifdef GRPC_LINUX_ERRQUEUE
59 auto err = setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, &enable, sizeof(enable));
61 return GRPC_OS_ERROR(errno, "setsockopt(SO_ZEROCOPY)");
63 return GRPC_ERROR_NONE;
66 return GRPC_OS_ERROR(ENOSYS, "setsockopt(SO_ZEROCOPY)");
70 /* set a socket to non blocking mode */
71 grpc_error* grpc_set_socket_nonblocking(int fd, int non_blocking) {
72 int oldflags = fcntl(fd, F_GETFL, 0);
74 return GRPC_OS_ERROR(errno, "fcntl");
78 oldflags |= O_NONBLOCK;
80 oldflags &= ~O_NONBLOCK;
83 if (fcntl(fd, F_SETFL, oldflags) != 0) {
84 return GRPC_OS_ERROR(errno, "fcntl");
87 return GRPC_ERROR_NONE;
90 grpc_error* grpc_set_socket_no_sigpipe_if_possible(int fd) {
91 #ifdef GRPC_HAVE_SO_NOSIGPIPE
94 socklen_t intlen = sizeof(newval);
95 if (0 != setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(val))) {
96 return GRPC_OS_ERROR(errno, "setsockopt(SO_NOSIGPIPE)");
98 if (0 != getsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &newval, &intlen)) {
99 return GRPC_OS_ERROR(errno, "getsockopt(SO_NOSIGPIPE)");
101 if ((newval != 0) != (val != 0)) {
102 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to set SO_NOSIGPIPE");
105 // Avoid unused parameter warning for conditional parameter
108 return GRPC_ERROR_NONE;
111 grpc_error* grpc_set_socket_ip_pktinfo_if_possible(int fd) {
112 // Use conditionally-important parameter to avoid warning
114 #ifdef GRPC_HAVE_IP_PKTINFO
115 int get_local_ip = 1;
116 if (0 != setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &get_local_ip,
117 sizeof(get_local_ip))) {
118 return GRPC_OS_ERROR(errno, "setsockopt(IP_PKTINFO)");
121 return GRPC_ERROR_NONE;
124 grpc_error* grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd) {
125 // Use conditionally-important parameter to avoid warning
127 #ifdef GRPC_HAVE_IPV6_RECVPKTINFO
128 int get_local_ip = 1;
129 if (0 != setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &get_local_ip,
130 sizeof(get_local_ip))) {
131 return GRPC_OS_ERROR(errno, "setsockopt(IPV6_RECVPKTINFO)");
134 return GRPC_ERROR_NONE;
137 grpc_error* grpc_set_socket_sndbuf(int fd, int buffer_size_bytes) {
138 return 0 == setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffer_size_bytes,
139 sizeof(buffer_size_bytes))
141 : GRPC_OS_ERROR(errno, "setsockopt(SO_SNDBUF)");
144 grpc_error* grpc_set_socket_rcvbuf(int fd, int buffer_size_bytes) {
145 return 0 == setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buffer_size_bytes,
146 sizeof(buffer_size_bytes))
148 : GRPC_OS_ERROR(errno, "setsockopt(SO_RCVBUF)");
151 /* set a socket to close on exec */
152 grpc_error* grpc_set_socket_cloexec(int fd, int close_on_exec) {
153 int oldflags = fcntl(fd, F_GETFD, 0);
155 return GRPC_OS_ERROR(errno, "fcntl");
159 oldflags |= FD_CLOEXEC;
161 oldflags &= ~FD_CLOEXEC;
164 if (fcntl(fd, F_SETFD, oldflags) != 0) {
165 return GRPC_OS_ERROR(errno, "fcntl");
168 return GRPC_ERROR_NONE;
171 /* set a socket to reuse old addresses */
172 grpc_error* grpc_set_socket_reuse_addr(int fd, int reuse) {
173 int val = (reuse != 0);
175 socklen_t intlen = sizeof(newval);
176 if (0 != setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) {
177 return GRPC_OS_ERROR(errno, "setsockopt(SO_REUSEADDR)");
179 if (0 != getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &newval, &intlen)) {
180 return GRPC_OS_ERROR(errno, "getsockopt(SO_REUSEADDR)");
182 if ((newval != 0) != val) {
183 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to set SO_REUSEADDR");
186 return GRPC_ERROR_NONE;
189 /* set a socket to reuse old addresses */
190 grpc_error* grpc_set_socket_reuse_port(int fd, int reuse) {
192 return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
193 "SO_REUSEPORT unavailable on compiling system");
195 int val = (reuse != 0);
197 socklen_t intlen = sizeof(newval);
198 if (0 != setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val))) {
199 return GRPC_OS_ERROR(errno, "setsockopt(SO_REUSEPORT)");
201 if (0 != getsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &newval, &intlen)) {
202 return GRPC_OS_ERROR(errno, "getsockopt(SO_REUSEPORT)");
204 if ((newval != 0) != val) {
205 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to set SO_REUSEPORT");
208 return GRPC_ERROR_NONE;
212 static gpr_once g_probe_so_reuesport_once = GPR_ONCE_INIT;
213 static int g_support_so_reuseport = false;
215 void probe_so_reuseport_once(void) {
216 int s = socket(AF_INET, SOCK_STREAM, 0);
218 /* This might be an ipv6-only environment in which case 'socket(AF_INET,..)'
219 call would fail. Try creating IPv6 socket in that case */
220 s = socket(AF_INET6, SOCK_STREAM, 0);
223 g_support_so_reuseport = GRPC_LOG_IF_ERROR(
224 "check for SO_REUSEPORT", grpc_set_socket_reuse_port(s, 1));
229 bool grpc_is_socket_reuse_port_supported() {
230 gpr_once_init(&g_probe_so_reuesport_once, probe_so_reuseport_once);
231 return g_support_so_reuseport;
235 grpc_error* grpc_set_socket_low_latency(int fd, int low_latency) {
236 int val = (low_latency != 0);
238 socklen_t intlen = sizeof(newval);
239 if (0 != setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val))) {
240 return GRPC_OS_ERROR(errno, "setsockopt(TCP_NODELAY)");
242 if (0 != getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &newval, &intlen)) {
243 return GRPC_OS_ERROR(errno, "getsockopt(TCP_NODELAY)");
245 if ((newval != 0) != val) {
246 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to set TCP_NODELAY");
248 return GRPC_ERROR_NONE;
251 /* The default values for TCP_USER_TIMEOUT are currently configured to be in
252 * line with the default values of KEEPALIVE_TIMEOUT as proposed in
253 * https://github.com/grpc/proposal/blob/master/A18-tcp-user-timeout.md */
254 #define DEFAULT_CLIENT_TCP_USER_TIMEOUT_MS 20000 /* 20 seconds */
255 #define DEFAULT_SERVER_TCP_USER_TIMEOUT_MS 20000 /* 20 seconds */
257 static int g_default_client_tcp_user_timeout_ms =
258 DEFAULT_CLIENT_TCP_USER_TIMEOUT_MS;
259 static int g_default_server_tcp_user_timeout_ms =
260 DEFAULT_SERVER_TCP_USER_TIMEOUT_MS;
261 static bool g_default_client_tcp_user_timeout_enabled = false;
262 static bool g_default_server_tcp_user_timeout_enabled = true;
265 // For Linux, it will be detected to support TCP_USER_TIMEOUT
266 #ifndef TCP_USER_TIMEOUT
267 #define TCP_USER_TIMEOUT 18
269 #define SOCKET_SUPPORTS_TCP_USER_TIMEOUT_DEFAULT 0
271 // For non-Linux, TCP_USER_TIMEOUT will be used if TCP_USER_TIMEOUT is defined.
272 #ifdef TCP_USER_TIMEOUT
273 #define SOCKET_SUPPORTS_TCP_USER_TIMEOUT_DEFAULT 0
275 #define TCP_USER_TIMEOUT 0
276 #define SOCKET_SUPPORTS_TCP_USER_TIMEOUT_DEFAULT -1
277 #endif // TCP_USER_TIMEOUT
278 #endif // GPR_LINUX == 1
280 // Whether the socket supports TCP_USER_TIMEOUT option.
281 // (0: don't know, 1: support, -1: not support)
282 static std::atomic<int> g_socket_supports_tcp_user_timeout(
283 SOCKET_SUPPORTS_TCP_USER_TIMEOUT_DEFAULT);
285 void config_default_tcp_user_timeout(bool enable, int timeout, bool is_client) {
287 g_default_client_tcp_user_timeout_enabled = enable;
289 g_default_client_tcp_user_timeout_ms = timeout;
292 g_default_server_tcp_user_timeout_enabled = enable;
294 g_default_server_tcp_user_timeout_ms = timeout;
299 /* Set TCP_USER_TIMEOUT */
300 grpc_error* grpc_set_socket_tcp_user_timeout(
301 int fd, const grpc_channel_args* channel_args, bool is_client) {
302 // Use conditionally-important parameter to avoid warning
306 extern grpc_core::TraceFlag grpc_tcp_trace;
307 if (g_socket_supports_tcp_user_timeout.load() >= 0) {
311 enable = g_default_client_tcp_user_timeout_enabled;
312 timeout = g_default_client_tcp_user_timeout_ms;
314 enable = g_default_server_tcp_user_timeout_enabled;
315 timeout = g_default_server_tcp_user_timeout_ms;
318 for (unsigned int i = 0; i < channel_args->num_args; i++) {
320 strcmp(channel_args->args[i].key, GRPC_ARG_KEEPALIVE_TIME_MS)) {
321 const int value = grpc_channel_arg_get_integer(
322 &channel_args->args[i], grpc_integer_options{0, 1, INT_MAX});
323 /* Continue using default if value is 0 */
327 /* Disable if value is INT_MAX */
328 enable = value != INT_MAX;
329 } else if (0 == strcmp(channel_args->args[i].key,
330 GRPC_ARG_KEEPALIVE_TIMEOUT_MS)) {
331 const int value = grpc_channel_arg_get_integer(
332 &channel_args->args[i], grpc_integer_options{0, 1, INT_MAX});
333 /* Continue using default if value is 0 */
343 socklen_t len = sizeof(newval);
344 // If this is the first time to use TCP_USER_TIMEOUT, try to check
345 // if it is available.
346 if (g_socket_supports_tcp_user_timeout.load() == 0) {
347 if (0 != getsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &newval, &len)) {
349 "TCP_USER_TIMEOUT is not available. TCP_USER_TIMEOUT won't "
350 "be used thereafter");
351 g_socket_supports_tcp_user_timeout.store(-1);
354 "TCP_USER_TIMEOUT is available. TCP_USER_TIMEOUT will be "
356 g_socket_supports_tcp_user_timeout.store(1);
359 if (g_socket_supports_tcp_user_timeout.load() > 0) {
360 if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) {
361 gpr_log(GPR_INFO, "Enabling TCP_USER_TIMEOUT with a timeout of %d ms",
364 if (0 != setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout,
366 gpr_log(GPR_ERROR, "setsockopt(TCP_USER_TIMEOUT) %s",
368 return GRPC_ERROR_NONE;
370 if (0 != getsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &newval, &len)) {
371 gpr_log(GPR_ERROR, "getsockopt(TCP_USER_TIMEOUT) %s",
373 return GRPC_ERROR_NONE;
375 if (newval != timeout) {
376 /* Do not fail on failing to set TCP_USER_TIMEOUT for now. */
377 gpr_log(GPR_ERROR, "Failed to set TCP_USER_TIMEOUT");
378 return GRPC_ERROR_NONE;
383 if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) {
384 gpr_log(GPR_INFO, "TCP_USER_TIMEOUT not supported for this platform");
387 return GRPC_ERROR_NONE;
390 /* set a socket using a grpc_socket_mutator */
391 grpc_error* grpc_set_socket_with_mutator(int fd, grpc_socket_mutator* mutator) {
393 if (!grpc_socket_mutator_mutate_fd(mutator, fd)) {
394 return GRPC_ERROR_CREATE_FROM_STATIC_STRING("grpc_socket_mutator failed.");
396 return GRPC_ERROR_NONE;
399 grpc_error* grpc_apply_socket_mutator_in_args(int fd,
400 const grpc_channel_args* args) {
401 const grpc_arg* socket_mutator_arg =
402 grpc_channel_args_find(args, GRPC_ARG_SOCKET_MUTATOR);
403 if (socket_mutator_arg == nullptr) {
404 return GRPC_ERROR_NONE;
406 GPR_DEBUG_ASSERT(socket_mutator_arg->type == GRPC_ARG_POINTER);
407 grpc_socket_mutator* mutator =
408 static_cast<grpc_socket_mutator*>(socket_mutator_arg->value.pointer.p);
409 return grpc_set_socket_with_mutator(fd, mutator);
412 static gpr_once g_probe_ipv6_once = GPR_ONCE_INIT;
413 static int g_ipv6_loopback_available;
415 static void probe_ipv6_once(void) {
416 int fd = socket(AF_INET6, SOCK_STREAM, 0);
417 g_ipv6_loopback_available = 0;
419 gpr_log(GPR_INFO, "Disabling AF_INET6 sockets because socket() failed.");
421 grpc_sockaddr_in6 addr;
422 memset(&addr, 0, sizeof(addr));
423 addr.sin6_family = AF_INET6;
424 addr.sin6_addr.s6_addr[15] = 1; /* [::1]:0 */
425 if (bind(fd, reinterpret_cast<grpc_sockaddr*>(&addr), sizeof(addr)) == 0) {
426 g_ipv6_loopback_available = 1;
429 "Disabling AF_INET6 sockets because ::1 is not available.");
435 int grpc_ipv6_loopback_available(void) {
436 gpr_once_init(&g_probe_ipv6_once, probe_ipv6_once);
437 return g_ipv6_loopback_available;
440 static grpc_error* error_for_fd(int fd, const grpc_resolved_address* addr) {
441 if (fd >= 0) return GRPC_ERROR_NONE;
442 std::string addr_str = grpc_sockaddr_to_string(addr, false);
443 grpc_error* err = grpc_error_set_str(
444 GRPC_OS_ERROR(errno, "socket"), GRPC_ERROR_STR_TARGET_ADDRESS,
445 grpc_slice_from_copied_string(addr_str.c_str()));
449 grpc_error* grpc_create_dualstack_socket(
450 const grpc_resolved_address* resolved_addr, int type, int protocol,
451 grpc_dualstack_mode* dsmode, int* newfd) {
452 return grpc_create_dualstack_socket_using_factory(
453 nullptr, resolved_addr, type, protocol, dsmode, newfd);
456 static int create_socket(grpc_socket_factory* factory, int domain, int type,
458 return (factory != nullptr)
459 ? grpc_socket_factory_socket(factory, domain, type, protocol)
460 : socket(domain, type, protocol);
463 grpc_error* grpc_create_dualstack_socket_using_factory(
464 grpc_socket_factory* factory, const grpc_resolved_address* resolved_addr,
465 int type, int protocol, grpc_dualstack_mode* dsmode, int* newfd) {
466 const grpc_sockaddr* addr =
467 reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr);
468 int family = addr->sa_family;
469 if (family == AF_INET6) {
470 if (grpc_ipv6_loopback_available()) {
471 *newfd = create_socket(factory, family, type, protocol);
474 errno = EAFNOSUPPORT;
476 /* Check if we've got a valid dualstack socket. */
477 if (*newfd >= 0 && grpc_set_socket_dualstack(*newfd)) {
478 *dsmode = GRPC_DSMODE_DUALSTACK;
479 return GRPC_ERROR_NONE;
481 /* If this isn't an IPv4 address, then return whatever we've got. */
482 if (!grpc_sockaddr_is_v4mapped(resolved_addr, nullptr)) {
483 *dsmode = GRPC_DSMODE_IPV6;
484 return error_for_fd(*newfd, resolved_addr);
486 /* Fall back to AF_INET. */
492 *dsmode = family == AF_INET ? GRPC_DSMODE_IPV4 : GRPC_DSMODE_NONE;
493 *newfd = create_socket(factory, family, type, protocol);
494 return error_for_fd(*newfd, resolved_addr);
497 uint16_t grpc_htons(uint16_t hostshort) { return htons(hostshort); }
499 uint16_t grpc_ntohs(uint16_t netshort) { return ntohs(netshort); }
501 uint32_t grpc_htonl(uint32_t hostlong) { return htonl(hostlong); }
503 uint32_t grpc_ntohl(uint32_t netlong) { return ntohl(netlong); }
505 int grpc_inet_pton(int af, const char* src, void* dst) {
506 return inet_pton(af, src, dst);
509 const char* grpc_inet_ntop(int af, const void* src, char* dst, size_t size) {
510 GPR_ASSERT(size <= (socklen_t)-1);
511 return inet_ntop(af, src, dst, static_cast<socklen_t>(size));