#include <grpc/support/port_platform.h>
#include "src/core/lib/event_engine/posix_engine/tcp_socket_utils.h"
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include "absl/cleanup/cleanup.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include <grpc/event_engine/event_engine.h>
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/crash.h"
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET_UTILS_COMMON
#include <arpa/inet.h>
#ifdef GRPC_LINUX_TCP_H
#include <linux/tcp.h>
#else
#include <netinet/in.h>
#include <netinet/tcp.h>
#endif
#include <fcntl.h>
#include <sys/socket.h>
#include <unistd.h>
#endif
#include <atomic>
#include <cstring>
#include "absl/status/status.h"
#include <grpc/support/log.h>
#include "src/core/lib/event_engine/tcp_socket_utils.h"
#include "src/core/lib/gprpp/status_helper.h"
#include "src/core/lib/gprpp/strerror.h"
#ifdef GRPC_HAVE_UNIX_SOCKET
#include <sys/stat.h>
#include <sys/un.h>
#endif
namespace grpc_event_engine {
namespace experimental {
namespace {
int AdjustValue(int default_value, int min_value, int max_value,
absl::optional<int> actual_value) { … }
int kDefaultClientUserTimeoutMs = …;
int kDefaultServerUserTimeoutMs = …;
bool kDefaultClientUserTimeoutEnabled = …;
bool kDefaultServerUserTimeoutEnabled = …;
#ifdef GRPC_POSIX_SOCKET_UTILS_COMMON
absl::Status ErrorForFd(
int fd, const experimental::EventEngine::ResolvedAddress& addr) { … }
int CreateSocket(std::function<int(int, int, int)> socket_factory, int family,
int type, int protocol) { … }
absl::Status PrepareTcpClientSocket(PosixSocketWrapper sock,
const EventEngine::ResolvedAddress& addr,
const PosixTcpOptions& options) { … }
#endif
}
PosixTcpOptions TcpOptionsFromEndpointConfig(const EndpointConfig& config) { … }
#ifdef GRPC_POSIX_SOCKETUTILS
int Accept4(int sockfd,
grpc_event_engine::experimental::EventEngine::ResolvedAddress& addr,
int nonblock, int cloexec) {
int fd, flags;
EventEngine::ResolvedAddress peer_addr;
socklen_t len = EventEngine::ResolvedAddress::MAX_SIZE_BYTES;
fd = accept(sockfd, const_cast<sockaddr*>(peer_addr.address()), &len);
if (fd >= 0) {
if (nonblock) {
flags = fcntl(fd, F_GETFL, 0);
if (flags < 0) goto close_and_error;
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0) goto close_and_error;
}
if (cloexec) {
flags = fcntl(fd, F_GETFD, 0);
if (flags < 0) goto close_and_error;
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != 0) goto close_and_error;
}
}
addr = EventEngine::ResolvedAddress(peer_addr.address(), len);
return fd;
close_and_error:
close(fd);
return -1;
}
#elif GRPC_LINUX_SOCKETUTILS
int Accept4(int sockfd,
grpc_event_engine::experimental::EventEngine::ResolvedAddress& addr,
int nonblock, int cloexec) { … }
#endif
#ifdef GRPC_POSIX_SOCKET_UTILS_COMMON
void UnlinkIfUnixDomainSocket(
const EventEngine::ResolvedAddress& resolved_addr) { … }
absl::StatusOr<int> PosixSocketWrapper::SetSocketRcvLowat(int bytes) { … }
absl::Status PosixSocketWrapper::SetSocketZeroCopy() { … }
absl::Status PosixSocketWrapper::SetSocketNonBlocking(int non_blocking) { … }
absl::Status PosixSocketWrapper::SetSocketNoSigpipeIfPossible() { … }
absl::Status PosixSocketWrapper::SetSocketIpPktInfoIfPossible() { … }
absl::Status PosixSocketWrapper::SetSocketIpv6RecvPktInfoIfPossible() { … }
absl::Status PosixSocketWrapper::SetSocketSndBuf(int buffer_size_bytes) { … }
absl::Status PosixSocketWrapper::SetSocketRcvBuf(int buffer_size_bytes) { … }
absl::Status PosixSocketWrapper::SetSocketCloexec(int close_on_exec) { … }
absl::Status PosixSocketWrapper::SetSocketReuseAddr(int reuse) { … }
absl::Status PosixSocketWrapper::SetSocketReusePort(int reuse) { … }
bool PosixSocketWrapper::IsSocketReusePortSupported() { … }
absl::Status PosixSocketWrapper::SetSocketLowLatency(int low_latency) { … }
#if GPR_LINUX == 1
#ifndef TCP_USER_TIMEOUT
#define TCP_USER_TIMEOUT …
#endif
#define SOCKET_SUPPORTS_TCP_USER_TIMEOUT_DEFAULT …
#else
#ifdef TCP_USER_TIMEOUT
#define SOCKET_SUPPORTS_TCP_USER_TIMEOUT_DEFAULT …
#else
#define TCP_USER_TIMEOUT …
#define SOCKET_SUPPORTS_TCP_USER_TIMEOUT_DEFAULT …
#endif
#endif
static std::atomic<int> g_socket_supports_tcp_user_timeout(
SOCKET_SUPPORTS_TCP_USER_TIMEOUT_DEFAULT);
void PosixSocketWrapper::ConfigureDefaultTcpUserTimeout(bool enable,
int timeout,
bool is_client) { … }
void PosixSocketWrapper::TrySetSocketTcpUserTimeout(
const PosixTcpOptions& options, bool is_client) { … }
absl::Status PosixSocketWrapper::SetSocketMutator(
grpc_fd_usage usage, grpc_socket_mutator* mutator) { … }
absl::Status PosixSocketWrapper::ApplySocketMutatorInOptions(
grpc_fd_usage usage, const PosixTcpOptions& options) { … }
bool PosixSocketWrapper::SetSocketDualStack() { … }
bool PosixSocketWrapper::IsIpv6LoopbackAvailable() { … }
absl::StatusOr<EventEngine::ResolvedAddress>
PosixSocketWrapper::LocalAddress() { … }
absl::StatusOr<EventEngine::ResolvedAddress> PosixSocketWrapper::PeerAddress() { … }
absl::StatusOr<std::string> PosixSocketWrapper::LocalAddressString() { … }
absl::StatusOr<std::string> PosixSocketWrapper::PeerAddressString() { … }
absl::StatusOr<PosixSocketWrapper> PosixSocketWrapper::CreateDualStackSocket(
std::function<int(int, int, int)> socket_factory,
const experimental::EventEngine::ResolvedAddress& addr, int type,
int protocol, PosixSocketWrapper::DSMode& dsmode) { … }
absl::StatusOr<PosixSocketWrapper::PosixSocketCreateResult>
PosixSocketWrapper::CreateAndPrepareTcpClientSocket(
const PosixTcpOptions& options,
const EventEngine::ResolvedAddress& target_addr) { … }
#else
absl::StatusOr<int> PosixSocketWrapper::SetSocketRcvLowat(int ) {
grpc_core::Crash("unimplemented");
}
absl::Status PosixSocketWrapper::SetSocketZeroCopy() {
grpc_core::Crash("unimplemented");
}
absl::Status PosixSocketWrapper::SetSocketNonBlocking(int ) {
grpc_core::Crash("unimplemented");
}
absl::Status PosixSocketWrapper::SetSocketCloexec(int ) {
grpc_core::Crash("unimplemented");
}
absl::Status PosixSocketWrapper::SetSocketReuseAddr(int ) {
grpc_core::Crash("unimplemented");
}
absl::Status PosixSocketWrapper::SetSocketLowLatency(int ) {
grpc_core::Crash("unimplemented");
}
absl::Status PosixSocketWrapper::SetSocketReusePort(int ) {
grpc_core::Crash("unimplemented");
}
void PosixSocketWrapper::ConfigureDefaultTcpUserTimeout(bool ,
int ,
bool ) {}
void PosixSocketWrapper::TrySetSocketTcpUserTimeout(
const PosixTcpOptions& , bool ) {
grpc_core::Crash("unimplemented");
}
absl::Status PosixSocketWrapper::SetSocketNoSigpipeIfPossible() {
grpc_core::Crash("unimplemented");
}
absl::Status PosixSocketWrapper::SetSocketIpPktInfoIfPossible() {
grpc_core::Crash("unimplemented");
}
absl::Status PosixSocketWrapper::SetSocketIpv6RecvPktInfoIfPossible() {
grpc_core::Crash("unimplemented");
}
absl::Status PosixSocketWrapper::SetSocketSndBuf(int ) {
grpc_core::Crash("unimplemented");
}
absl::Status PosixSocketWrapper::SetSocketRcvBuf(int ) {
grpc_core::Crash("unimplemented");
}
absl::Status PosixSocketWrapper::SetSocketMutator(
grpc_fd_usage , grpc_socket_mutator* ) {
grpc_core::Crash("unimplemented");
}
absl::Status PosixSocketWrapper::ApplySocketMutatorInOptions(
grpc_fd_usage , const PosixTcpOptions& ) {
grpc_core::Crash("unimplemented");
}
bool PosixSocketWrapper::SetSocketDualStack() {
grpc_core::Crash("unimplemented");
}
bool PosixSocketWrapper::IsSocketReusePortSupported() {
grpc_core::Crash("unimplemented");
}
bool PosixSocketWrapper::IsIpv6LoopbackAvailable() {
grpc_core::Crash("unimplemented");
}
absl::StatusOr<PosixSocketWrapper> PosixSocketWrapper::CreateDualStackSocket(
std::function<int(int , int , int )>
,
const experimental::EventEngine::ResolvedAddress& , int ,
int , DSMode& ) {
grpc_core::Crash("unimplemented");
}
absl::StatusOr<PosixSocketWrapper::PosixSocketCreateResult>
PosixSocketWrapper::CreateAndPrepareTcpClientSocket(
const PosixTcpOptions& ,
const EventEngine::ResolvedAddress& ) {
grpc_core::Crash("unimplemented");
}
#endif
}
}