diff --git a/src/core/lib/event_engine/posix_engine/file_descriptors.cc b/src/core/lib/event_engine/posix_engine/file_descriptors.cc index 6708044fe28d2..cf95de7a7dc55 100644 --- a/src/core/lib/event_engine/posix_engine/file_descriptors.cc +++ b/src/core/lib/event_engine/posix_engine/file_descriptors.cc @@ -386,16 +386,15 @@ IF_POSIX_SOCKET(Int64Result FileDescriptors::SendMsg( int flags), { return Int64Wrap(sendmsg(fd.fd(), message, flags)); }) -IF_POSIX_SOCKET(Int64Result FileDescriptors::WriteV(const FileDescriptor& fd, - const struct iovec* iov, - int iovcnt), - { -#if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) - return Int64Wrap(writev(fd.fd(), iov, iovcnt)); +Int64Result FileDescriptors::WriteV(const FileDescriptor& fd, + const struct iovec* iov, int iovcnt) { +#if defined(GRPC_POSIX_SOCKET) && GRPC_ARES == 1 && \ + defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) + return Int64Wrap(writev(fd.fd(), iov, iovcnt)); #else // GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) - grpc_core::Crash("Not available"); + grpc_core::Crash("Not available"); #endif // GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) - }) +} // // Epoll @@ -593,74 +592,84 @@ absl::Status FileDescriptors::SetSocketZeroCopy(const FileDescriptor& fd) { } // Set a socket to non blocking mode -absl::Status FileDescriptors::SetSocketNonBlocking(const FileDescriptor& fd, - int non_blocking) { - int oldflags = fcntl(fd.fd(), F_GETFL, 0); - if (oldflags < 0) { - return absl::Status(absl::StatusCode::kInternal, +IF_POSIX_SOCKET(absl::Status FileDescriptors::SetSocketNonBlocking( + const FileDescriptor& fd, int non_blocking), + { + int oldflags = fcntl(fd.fd(), F_GETFL, 0); + if (oldflags < 0) { + return absl::Status( + absl::StatusCode::kInternal, absl::StrCat("fcntl: ", grpc_core::StrError(errno))); - } + } - if (non_blocking) { - oldflags |= O_NONBLOCK; - } else { - oldflags &= ~O_NONBLOCK; - } + if (non_blocking) { + oldflags |= O_NONBLOCK; + } else { + oldflags &= ~O_NONBLOCK; + } - if (fcntl(fd.fd(), F_SETFL, oldflags) != 0) { - return absl::Status(absl::StatusCode::kInternal, + if (fcntl(fd.fd(), F_SETFL, oldflags) != 0) { + return absl::Status( + absl::StatusCode::kInternal, absl::StrCat("fcntl: ", grpc_core::StrError(errno))); - } + } - return absl::OkStatus(); -} + return absl::OkStatus(); + }) // Set a socket to close on exec -absl::Status FileDescriptors::SetSocketCloexec(const FileDescriptor& fd, - int close_on_exec) { - int oldflags = fcntl(fd.fd(), F_GETFD, 0); - if (oldflags < 0) { - return absl::Status(absl::StatusCode::kInternal, +IF_POSIX_SOCKET(absl::Status FileDescriptors::SetSocketCloexec( + const FileDescriptor& fd, int close_on_exec), + { + int oldflags = fcntl(fd.fd(), F_GETFD, 0); + if (oldflags < 0) { + return absl::Status( + absl::StatusCode::kInternal, absl::StrCat("fcntl: ", grpc_core::StrError(errno))); - } + } - if (close_on_exec) { - oldflags |= FD_CLOEXEC; - } else { - oldflags &= ~FD_CLOEXEC; - } + if (close_on_exec) { + oldflags |= FD_CLOEXEC; + } else { + oldflags &= ~FD_CLOEXEC; + } - if (fcntl(fd.fd(), F_SETFD, oldflags) != 0) { - return absl::Status(absl::StatusCode::kInternal, + if (fcntl(fd.fd(), F_SETFD, oldflags) != 0) { + return absl::Status( + absl::StatusCode::kInternal, absl::StrCat("fcntl: ", grpc_core::StrError(errno))); - } + } - return absl::OkStatus(); -} + return absl::OkStatus(); + }) // set a socket to reuse old addresses -absl::Status FileDescriptors::SetSocketReuseAddr(const FileDescriptor& fd, - int reuse) { - int val = (reuse != 0); - int newval; - socklen_t intlen = sizeof(newval); - if (0 != setsockopt(fd.fd(), SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) { - return absl::Status( - absl::StatusCode::kInternal, - absl::StrCat("setsockopt(SO_REUSEADDR): ", grpc_core::StrError(errno))); - } - if (0 != getsockopt(fd.fd(), SOL_SOCKET, SO_REUSEADDR, &newval, &intlen)) { - return absl::Status( - absl::StatusCode::kInternal, - absl::StrCat("getsockopt(SO_REUSEADDR): ", grpc_core::StrError(errno))); - } - if ((newval != 0) != val) { - return absl::Status(absl::StatusCode::kInternal, - "Failed to set SO_REUSEADDR"); - } +IF_POSIX_SOCKET( + absl::Status FileDescriptors::SetSocketReuseAddr(const FileDescriptor& fd, + int reuse), + { + int val = (reuse != 0); + int newval; + socklen_t intlen = sizeof(newval); + if (0 != + setsockopt(fd.fd(), SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) { + return absl::Status(absl::StatusCode::kInternal, + absl::StrCat("setsockopt(SO_REUSEADDR): ", + grpc_core::StrError(errno))); + } + if (0 != + getsockopt(fd.fd(), SOL_SOCKET, SO_REUSEADDR, &newval, &intlen)) { + return absl::Status(absl::StatusCode::kInternal, + absl::StrCat("getsockopt(SO_REUSEADDR): ", + grpc_core::StrError(errno))); + } + if ((newval != 0) != val) { + return absl::Status(absl::StatusCode::kInternal, + "Failed to set SO_REUSEADDR"); + } - return absl::OkStatus(); -} + return absl::OkStatus(); + }) // Disable nagle algorithm IF_POSIX_SOCKET( @@ -703,39 +712,42 @@ int FileDescriptors::ConfigureSocket(const FileDescriptor& fd, int type) { } // Set Differentiated Services Code Point (DSCP) -absl::Status FileDescriptors::SetSocketDscp(const FileDescriptor& fd, - int dscp) { - if (dscp == PosixTcpOptions::kDscpNotSet) { - return absl::OkStatus(); - } - // The TOS/TrafficClass byte consists of following bits: - // | 7 6 5 4 3 2 | 1 0 | - // | DSCP | ECN | - int newval = dscp << 2; - int val; - socklen_t intlen = sizeof(val); - int fdesc = fd.fd(); - // Get ECN bits from current IP_TOS value unless IPv6 only - if (0 == getsockopt(fdesc, IPPROTO_IP, IP_TOS, &val, &intlen)) { - newval |= (val & 0x3); - if (0 != setsockopt(fdesc, IPPROTO_IP, IP_TOS, &newval, sizeof(newval))) { - return absl::Status( - absl::StatusCode::kInternal, - absl::StrCat("setsockopt(IP_TOS): ", grpc_core::StrError(errno))); - } - } - // Get ECN from current Traffic Class value if IPv6 is available - if (0 == getsockopt(fdesc, IPPROTO_IPV6, IPV6_TCLASS, &val, &intlen)) { - newval |= (val & 0x3); - if (0 != - setsockopt(fdesc, IPPROTO_IPV6, IPV6_TCLASS, &newval, sizeof(newval))) { - return absl::Status(absl::StatusCode::kInternal, - absl::StrCat("setsockopt(IPV6_TCLASS): ", - grpc_core::StrError(errno))); - } - } - return absl::OkStatus(); -} +IF_POSIX_SOCKET( + absl::Status FileDescriptors::SetSocketDscp(const FileDescriptor& fd, + int dscp), + { + if (dscp == PosixTcpOptions::kDscpNotSet) { + return absl::OkStatus(); + } + // The TOS/TrafficClass byte consists of following bits: + // | 7 6 5 4 3 2 | 1 0 | + // | DSCP | ECN | + int newval = dscp << 2; + int val; + socklen_t intlen = sizeof(val); + int fdesc = fd.fd(); + // Get ECN bits from current IP_TOS value unless IPv6 only + if (0 == getsockopt(fdesc, IPPROTO_IP, IP_TOS, &val, &intlen)) { + newval |= (val & 0x3); + if (0 != + setsockopt(fdesc, IPPROTO_IP, IP_TOS, &newval, sizeof(newval))) { + return absl::Status( + absl::StatusCode::kInternal, + absl::StrCat("setsockopt(IP_TOS): ", grpc_core::StrError(errno))); + } + } + // Get ECN from current Traffic Class value if IPv6 is available + if (0 == getsockopt(fdesc, IPPROTO_IPV6, IPV6_TCLASS, &val, &intlen)) { + newval |= (val & 0x3); + if (0 != setsockopt(fdesc, IPPROTO_IPV6, IPV6_TCLASS, &newval, + sizeof(newval))) { + return absl::Status(absl::StatusCode::kInternal, + absl::StrCat("setsockopt(IPV6_TCLASS): ", + grpc_core::StrError(errno))); + } + } + return absl::OkStatus(); + }) // set a socket to reuse old ports absl::Status FileDescriptors::SetSocketReusePort(const FileDescriptor& fd, @@ -794,85 +806,93 @@ absl::Status FileDescriptors::SetSocketIpv6RecvPktInfoIfPossible( return absl::OkStatus(); } -absl::Status FileDescriptors::SetSocketSndBuf(const FileDescriptor& fd, - int buffer_size_bytes) { - int f = fd.fd(); - return 0 == setsockopt(f, SOL_SOCKET, SO_SNDBUF, &buffer_size_bytes, - sizeof(buffer_size_bytes)) - ? absl::OkStatus() - : absl::Status(absl::StatusCode::kInternal, - absl::StrCat("setsockopt(SO_SNDBUF): ", - grpc_core::StrError(errno))); -} +IF_POSIX_SOCKET( + absl::Status FileDescriptors::SetSocketSndBuf(const FileDescriptor& fd, + int buffer_size_bytes), + { + int f = fd.fd(); + return 0 == setsockopt(f, SOL_SOCKET, SO_SNDBUF, &buffer_size_bytes, + sizeof(buffer_size_bytes)) + ? absl::OkStatus() + : absl::Status(absl::StatusCode::kInternal, + absl::StrCat("setsockopt(SO_SNDBUF): ", + grpc_core::StrError(errno))); + }) -absl::Status FileDescriptors::SetSocketRcvBuf(const FileDescriptor& fd, - int buffer_size_bytes) { - int f = fd.fd(); - return 0 == setsockopt(f, SOL_SOCKET, SO_RCVBUF, &buffer_size_bytes, - sizeof(buffer_size_bytes)) - ? absl::OkStatus() - : absl::Status(absl::StatusCode::kInternal, - absl::StrCat("setsockopt(SO_RCVBUF): ", - grpc_core::StrError(errno))); -} +IF_POSIX_SOCKET( + absl::Status FileDescriptors::SetSocketRcvBuf(const FileDescriptor& fd, + int buffer_size_bytes), + { + int f = fd.fd(); + return 0 == setsockopt(f, SOL_SOCKET, SO_RCVBUF, &buffer_size_bytes, + sizeof(buffer_size_bytes)) + ? absl::OkStatus() + : absl::Status(absl::StatusCode::kInternal, + absl::StrCat("setsockopt(SO_RCVBUF): ", + grpc_core::StrError(errno))); + }) // Set TCP_USER_TIMEOUT -void FileDescriptors::TrySetSocketTcpUserTimeout(const FileDescriptor& fd, - const PosixTcpOptions& options, - bool is_client) { - if (g_socket_supports_tcp_user_timeout.load() < 0) { - return; - } - bool enable = is_client ? kDefaultClientUserTimeoutEnabled - : kDefaultServerUserTimeoutEnabled; - int timeout = - is_client ? kDefaultClientUserTimeoutMs : kDefaultServerUserTimeoutMs; - if (options.keep_alive_time_ms > 0) { - enable = options.keep_alive_time_ms != INT_MAX; - } - if (options.keep_alive_timeout_ms > 0) { - timeout = options.keep_alive_timeout_ms; - } - if (enable) { - int newval; - socklen_t len = sizeof(newval); - int f = fd.fd(); - // If this is the first time to use TCP_USER_TIMEOUT, try to check - // if it is available. - if (g_socket_supports_tcp_user_timeout.load() == 0) { - if (0 != getsockopt(f, IPPROTO_TCP, TCP_USER_TIMEOUT, &newval, &len)) { - // This log is intentionally not protected behind a flag, so that users - // know that TCP_USER_TIMEOUT is not being used. - GRPC_TRACE_LOG(tcp, INFO) - << "TCP_USER_TIMEOUT is not available. TCP_USER_TIMEOUT " - "won't be used thereafter"; - g_socket_supports_tcp_user_timeout.store(-1); - } else { - GRPC_TRACE_LOG(tcp, INFO) - << "TCP_USER_TIMEOUT is available. TCP_USER_TIMEOUT will be " - "used thereafter"; - g_socket_supports_tcp_user_timeout.store(1); - } - } - if (g_socket_supports_tcp_user_timeout.load() > 0) { - if (0 != setsockopt(f, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout, - sizeof(timeout))) { - LOG(ERROR) << "setsockopt(TCP_USER_TIMEOUT) " - << grpc_core::StrError(errno); +IF_POSIX_SOCKET( + void FileDescriptors::TrySetSocketTcpUserTimeout( + const FileDescriptor& fd, const PosixTcpOptions& options, + bool is_client), + { + if (g_socket_supports_tcp_user_timeout.load() < 0) { return; } - if (0 != getsockopt(f, IPPROTO_TCP, TCP_USER_TIMEOUT, &newval, &len)) { - LOG(ERROR) << "getsockopt(TCP_USER_TIMEOUT) " - << grpc_core::StrError(errno); - return; + bool enable = is_client ? kDefaultClientUserTimeoutEnabled + : kDefaultServerUserTimeoutEnabled; + int timeout = + is_client ? kDefaultClientUserTimeoutMs : kDefaultServerUserTimeoutMs; + if (options.keep_alive_time_ms > 0) { + enable = options.keep_alive_time_ms != INT_MAX; } - if (newval != timeout) { - // Do not fail on failing to set TCP_USER_TIMEOUT - LOG(ERROR) << "Failed to set TCP_USER_TIMEOUT"; - return; + if (options.keep_alive_timeout_ms > 0) { + timeout = options.keep_alive_timeout_ms; } - } - } -} + if (enable) { + int newval; + socklen_t len = sizeof(newval); + int f = fd.fd(); + // If this is the first time to use TCP_USER_TIMEOUT, try to check + // if it is available. + if (g_socket_supports_tcp_user_timeout.load() == 0) { + if (0 != + getsockopt(f, IPPROTO_TCP, TCP_USER_TIMEOUT, &newval, &len)) { + // This log is intentionally not protected behind a flag, so that + // users know that TCP_USER_TIMEOUT is not being used. + GRPC_TRACE_LOG(tcp, INFO) + << "TCP_USER_TIMEOUT is not available. TCP_USER_TIMEOUT " + "won't be used thereafter"; + g_socket_supports_tcp_user_timeout.store(-1); + } else { + GRPC_TRACE_LOG(tcp, INFO) + << "TCP_USER_TIMEOUT is available. TCP_USER_TIMEOUT will be " + "used thereafter"; + g_socket_supports_tcp_user_timeout.store(1); + } + } + if (g_socket_supports_tcp_user_timeout.load() > 0) { + if (0 != setsockopt(f, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout, + sizeof(timeout))) { + LOG(ERROR) << "setsockopt(TCP_USER_TIMEOUT) " + << grpc_core::StrError(errno); + return; + } + if (0 != + getsockopt(f, IPPROTO_TCP, TCP_USER_TIMEOUT, &newval, &len)) { + LOG(ERROR) << "getsockopt(TCP_USER_TIMEOUT) " + << grpc_core::StrError(errno); + return; + } + if (newval != timeout) { + // Do not fail on failing to set TCP_USER_TIMEOUT + LOG(ERROR) << "Failed to set TCP_USER_TIMEOUT"; + return; + } + } + } + }) } // namespace grpc_event_engine::experimental \ No newline at end of file