chromium/third_party/grpc/src/src/core/lib/event_engine/posix_engine/tcp_socket_utils.cc

// Copyright 2022 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#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"  // IWYU pragma: keep
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/iomgr/port.h"

#ifdef GRPC_POSIX_SOCKET_UTILS_COMMON
#include <arpa/inet.h>  // IWYU pragma: keep
#ifdef GRPC_LINUX_TCP_H
#include <linux/tcp.h>
#else
#include <netinet/in.h>  // IWYU pragma: keep
#include <netinet/tcp.h>
#endif
#include <fcntl.h>
#include <sys/socket.h>
#include <unistd.h>
#endif  //  GRPC_POSIX_SOCKET_UTILS_COMMON

#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>  // IWYU pragma: keep
#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) {}

// The default values for TCP_USER_TIMEOUT are currently configured to be in
// line with the default values of KEEPALIVE_TIMEOUT as proposed in
// https://github.com/grpc/proposal/blob/master/A18-tcp-user-timeout.md */
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  // GRPC_POSIX_SOCKET_UTILS_COMMON

}  // namespace

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  // GRPC_LINUX_SOCKETUTILS

#ifdef GRPC_POSIX_SOCKET_UTILS_COMMON

void UnlinkIfUnixDomainSocket(
    const EventEngine::ResolvedAddress& resolved_addr) {}

// Instruct the kernel to wait for specified number of bytes to be received on
// the socket before generating an interrupt for packet receive. If the call
// succeeds, it returns the number of bytes (wait threshold) that was actually
// set.
absl::StatusOr<int> PosixSocketWrapper::SetSocketRcvLowat(int bytes) {}

// Set a socket to use zerocopy
absl::Status PosixSocketWrapper::SetSocketZeroCopy() {}

// Set a socket to non blocking mode
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) {}

// Set a socket to close on exec
absl::Status PosixSocketWrapper::SetSocketCloexec(int close_on_exec) {}

// set a socket to reuse old addresses
absl::Status PosixSocketWrapper::SetSocketReuseAddr(int reuse) {}

// set a socket to reuse old ports
absl::Status PosixSocketWrapper::SetSocketReusePort(int reuse) {}

bool PosixSocketWrapper::IsSocketReusePortSupported() {}

// Disable nagle algorithm
absl::Status PosixSocketWrapper::SetSocketLowLatency(int low_latency) {}

#if GPR_LINUX == 1
// For Linux, it will be detected to support TCP_USER_TIMEOUT
#ifndef TCP_USER_TIMEOUT
#define TCP_USER_TIMEOUT
#endif
#define SOCKET_SUPPORTS_TCP_USER_TIMEOUT_DEFAULT
#else
// For non-Linux, TCP_USER_TIMEOUT will be used if TCP_USER_TIMEOUT is defined.
#ifdef TCP_USER_TIMEOUT
#define SOCKET_SUPPORTS_TCP_USER_TIMEOUT_DEFAULT
#else
#define TCP_USER_TIMEOUT
#define SOCKET_SUPPORTS_TCP_USER_TIMEOUT_DEFAULT
#endif  // TCP_USER_TIMEOUT
#endif  // GPR_LINUX == 1

// Whether the socket supports TCP_USER_TIMEOUT option.
// (0: don't know, 1: support, -1: not support)
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) {}

// Set TCP_USER_TIMEOUT
void PosixSocketWrapper::TrySetSocketTcpUserTimeout(
    const PosixTcpOptions& options, bool is_client) {}

// Set a socket using a grpc_socket_mutator
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  // GRPC_POSIX_SOCKET_UTILS_COMMON

absl::StatusOr<int> PosixSocketWrapper::SetSocketRcvLowat(int /*bytes*/) {
  grpc_core::Crash("unimplemented");
}

absl::Status PosixSocketWrapper::SetSocketZeroCopy() {
  grpc_core::Crash("unimplemented");
}

absl::Status PosixSocketWrapper::SetSocketNonBlocking(int /*non_blocking*/) {
  grpc_core::Crash("unimplemented");
}

absl::Status PosixSocketWrapper::SetSocketCloexec(int /*close_on_exec*/) {
  grpc_core::Crash("unimplemented");
}

absl::Status PosixSocketWrapper::SetSocketReuseAddr(int /*reuse*/) {
  grpc_core::Crash("unimplemented");
}

absl::Status PosixSocketWrapper::SetSocketLowLatency(int /*low_latency*/) {
  grpc_core::Crash("unimplemented");
}

absl::Status PosixSocketWrapper::SetSocketReusePort(int /*reuse*/) {
  grpc_core::Crash("unimplemented");
}

void PosixSocketWrapper::ConfigureDefaultTcpUserTimeout(bool /*enable*/,
                                                        int /*timeout*/,
                                                        bool /*is_client*/) {}

void PosixSocketWrapper::TrySetSocketTcpUserTimeout(
    const PosixTcpOptions& /*options*/, bool /*is_client*/) {
  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 /*buffer_size_bytes*/) {
  grpc_core::Crash("unimplemented");
}

absl::Status PosixSocketWrapper::SetSocketRcvBuf(int /*buffer_size_bytes*/) {
  grpc_core::Crash("unimplemented");
}

absl::Status PosixSocketWrapper::SetSocketMutator(
    grpc_fd_usage /*usage*/, grpc_socket_mutator* /*mutator*/) {
  grpc_core::Crash("unimplemented");
}

absl::Status PosixSocketWrapper::ApplySocketMutatorInOptions(
    grpc_fd_usage /*usage*/, const PosixTcpOptions& /*options*/) {
  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 /*domain*/, int /*type*/, int /*protocol*/)>
    /* socket_factory */,
    const experimental::EventEngine::ResolvedAddress& /*addr*/, int /*type*/,
    int /*protocol*/, DSMode& /*dsmode*/) {
  grpc_core::Crash("unimplemented");
}

absl::StatusOr<PosixSocketWrapper::PosixSocketCreateResult>
PosixSocketWrapper::CreateAndPrepareTcpClientSocket(
    const PosixTcpOptions& /*options*/,
    const EventEngine::ResolvedAddress& /*target_addr*/) {
  grpc_core::Crash("unimplemented");
}

#endif  // GRPC_POSIX_SOCKET_UTILS_COMMON

}  // namespace experimental
}  // namespace grpc_event_engine