23 #ifdef GRPC_POSIX_SOCKET_UTILS_COMMON
25 #include <arpa/inet.h>
29 #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>
57 #ifdef GRPC_LINUX_ERRQUEUE
59 auto err = setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, &enable,
sizeof(enable));
72 int oldflags = fcntl(fd, F_GETFL, 0);
78 oldflags |= O_NONBLOCK;
80 oldflags &= ~O_NONBLOCK;
83 if (fcntl(fd, F_SETFL, oldflags) != 0) {
91 #ifdef GRPC_HAVE_SO_NOSIGPIPE
94 socklen_t intlen =
sizeof(newval);
95 if (0 != setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &val,
sizeof(val))) {
98 if (0 != getsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &newval, &intlen)) {
101 if ((newval != 0) != (val != 0)) {
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))) {
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))) {
138 return 0 == setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffer_size_bytes,
139 sizeof(buffer_size_bytes))
145 return 0 == setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buffer_size_bytes,
146 sizeof(buffer_size_bytes))
153 int oldflags = fcntl(fd, F_GETFD, 0);
159 oldflags |= FD_CLOEXEC;
161 oldflags &= ~FD_CLOEXEC;
164 if (fcntl(fd, F_SETFD, oldflags) != 0) {
173 int val = (reuse != 0);
175 socklen_t intlen =
sizeof(newval);
176 if (0 != setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val,
sizeof(val))) {
179 if (0 != getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &newval, &intlen)) {
182 if ((newval != 0) != val) {
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))) {
201 if (0 != getsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &newval, &intlen)) {
204 if ((newval != 0) != val) {
213 static int g_support_so_reuseport =
false;
215 void probe_so_reuseport_once(
void) {
216 int s =
socket(AF_INET, SOCK_STREAM, 0);
230 gpr_once_init(&g_probe_so_reuesport_once, probe_so_reuseport_once);
231 return g_support_so_reuseport;
236 int val = (low_latency != 0);
238 socklen_t intlen =
sizeof(newval);
239 if (0 != setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val,
sizeof(val))) {
242 if (0 != getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &newval, &intlen)) {
245 if ((newval != 0) != val) {
254 #define DEFAULT_CLIENT_TCP_USER_TIMEOUT_MS 20000
255 #define DEFAULT_SERVER_TCP_USER_TIMEOUT_MS 20000
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;
266 #ifndef TCP_USER_TIMEOUT
267 #define TCP_USER_TIMEOUT 18
269 #define SOCKET_SUPPORTS_TCP_USER_TIMEOUT_DEFAULT 0
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
282 static std::atomic<int> g_socket_supports_tcp_user_timeout(
283 SOCKET_SUPPORTS_TCP_USER_TIMEOUT_DEFAULT);
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;
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++) {
328 enable =
value != INT_MAX;
329 }
else if (0 == strcmp(channel_args->
args[
i].
key,
343 socklen_t
len =
sizeof(newval);
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) {
364 if (0 != setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &
timeout,
370 if (0 != getsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &newval, &
len)) {
402 const grpc_arg* socket_mutator_arg =
404 if (socket_mutator_arg ==
nullptr) {
414 static int g_ipv6_loopback_available;
416 static void probe_ipv6_once(
void) {
418 g_ipv6_loopback_available = 0;
420 gpr_log(
GPR_INFO,
"Disabling AF_INET6 sockets because socket() failed.");
422 grpc_sockaddr_in6
addr;
425 addr.sin6_addr.s6_addr[15] = 1;
426 if (bind(fd,
reinterpret_cast<grpc_sockaddr*
>(&
addr),
sizeof(
addr)) == 0) {
427 g_ipv6_loopback_available = 1;
430 "Disabling AF_INET6 sockets because ::1 is not available.");
438 return g_ipv6_loopback_available;
447 addr_str.ok() ? addr_str.value() : addr_str.status().ToString());
460 return (factory !=
nullptr)
468 const grpc_sockaddr*
addr =
469 reinterpret_cast<const grpc_sockaddr*
>(resolved_addr->
addr);
470 int family =
addr->sa_family;
476 errno = EAFNOSUPPORT;
486 return error_for_fd(*newfd, resolved_addr);
496 return error_for_fd(*newfd, resolved_addr);