LCOV - code coverage report
Current view: top level - source/common/network - io_socket_handle_base_impl.cc (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 36 120 30.0 %
Date: 2024-01-05 06:35:25 Functions: 10 15 66.7 %

          Line data    Source code
       1             : #include "io_socket_handle_base_impl.h"
       2             : 
       3             : #include "envoy/buffer/buffer.h"
       4             : #include "envoy/common/exception.h"
       5             : #include "envoy/event/dispatcher.h"
       6             : 
       7             : #include "source/common/api/os_sys_calls_impl.h"
       8             : #include "source/common/common/assert.h"
       9             : #include "source/common/common/utility.h"
      10             : #include "source/common/network/address_impl.h"
      11             : #include "source/common/network/io_socket_error_impl.h"
      12             : #include "source/common/network/io_socket_handle_impl.h"
      13             : #include "source/common/network/socket_interface_impl.h"
      14             : 
      15             : namespace Envoy {
      16             : namespace Network {
      17             : 
      18             : IoSocketHandleBaseImpl::IoSocketHandleBaseImpl(os_fd_t fd, bool socket_v6only,
      19             :                                                absl::optional<int> domain)
      20        7792 :     : fd_(fd), socket_v6only_(socket_v6only), domain_(domain) {}
      21             : 
      22        7792 : IoSocketHandleBaseImpl::~IoSocketHandleBaseImpl() {
      23        7792 :   if (SOCKET_VALID(fd_)) {
      24             :     // The TLS slot has been shut down by this moment with IoUring wiped out, thus
      25             :     // better use this posix system call instead of IoSocketHandleBaseImpl::close().
      26           0 :     ::close(fd_);
      27           0 :   }
      28        7792 : }
      29             : 
      30       47837 : bool IoSocketHandleBaseImpl::isOpen() const { return SOCKET_VALID(fd_); }
      31             : 
      32         330 : bool IoSocketHandleBaseImpl::supportsMmsg() const {
      33         330 :   return Api::OsSysCallsSingleton::get().supportsMmsg();
      34         330 : }
      35             : 
      36          26 : bool IoSocketHandleBaseImpl::supportsUdpGro() const {
      37          26 :   return Api::OsSysCallsSingleton::get().supportsUdpGro();
      38          26 : }
      39             : 
      40             : Api::SysCallIntResult IoSocketHandleBaseImpl::setOption(int level, int optname, const void* optval,
      41        3958 :                                                         socklen_t optlen) {
      42        3958 :   return Api::OsSysCallsSingleton::get().setsockopt(fd_, level, optname, optval, optlen);
      43        3958 : }
      44             : 
      45             : Api::SysCallIntResult IoSocketHandleBaseImpl::getOption(int level, int optname, void* optval,
      46        1178 :                                                         socklen_t* optlen) {
      47        1178 :   return Api::OsSysCallsSingleton::get().getsockopt(fd_, level, optname, optval, optlen);
      48        1178 : }
      49             : 
      50             : Api::SysCallIntResult IoSocketHandleBaseImpl::ioctl(unsigned long control_code, void* in_buffer,
      51             :                                                     unsigned long in_buffer_len, void* out_buffer,
      52             :                                                     unsigned long out_buffer_len,
      53           0 :                                                     unsigned long* bytes_returned) {
      54           0 :   return Api::OsSysCallsSingleton::get().ioctl(fd_, control_code, in_buffer, in_buffer_len,
      55           0 :                                                out_buffer, out_buffer_len, bytes_returned);
      56           0 : }
      57             : 
      58          91 : Api::SysCallIntResult IoSocketHandleBaseImpl::setBlocking(bool blocking) {
      59          91 :   return Api::OsSysCallsSingleton::get().setsocketblocking(fd_, blocking);
      60          91 : }
      61             : 
      62           0 : absl::optional<int> IoSocketHandleBaseImpl::domain() { return domain_; }
      63             : 
      64        2125 : Address::InstanceConstSharedPtr IoSocketHandleBaseImpl::localAddress() {
      65        2125 :   sockaddr_storage ss;
      66        2125 :   socklen_t ss_len = sizeof(ss);
      67        2125 :   memset(&ss, 0, ss_len);
      68        2125 :   auto& os_sys_calls = Api::OsSysCallsSingleton::get();
      69        2125 :   Api::SysCallIntResult result =
      70        2125 :       os_sys_calls.getsockname(fd_, reinterpret_cast<sockaddr*>(&ss), &ss_len);
      71        2125 :   if (result.return_value_ != 0) {
      72           0 :     throwEnvoyExceptionOrPanic(fmt::format("getsockname failed for '{}': ({}) {}", fd_,
      73           0 :                                            result.errno_, errorDetails(result.errno_)));
      74           0 :   }
      75        2125 :   return Address::addressFromSockAddrOrThrow(ss, ss_len, socket_v6only_);
      76        2125 : }
      77             : 
      78           0 : Address::InstanceConstSharedPtr IoSocketHandleBaseImpl::peerAddress() {
      79           0 :   sockaddr_storage ss;
      80           0 :   socklen_t ss_len = sizeof(ss);
      81           0 :   memset(&ss, 0, ss_len);
      82           0 :   auto& os_sys_calls = Api::OsSysCallsSingleton::get();
      83           0 :   Api::SysCallIntResult result =
      84           0 :       os_sys_calls.getpeername(fd_, reinterpret_cast<sockaddr*>(&ss), &ss_len);
      85           0 :   if (result.return_value_ != 0) {
      86           0 :     throwEnvoyExceptionOrPanic(
      87           0 :         fmt::format("getpeername failed for '{}': {}", fd_, errorDetails(result.errno_)));
      88           0 :   }
      89             : 
      90           0 :   if (static_cast<unsigned int>(ss_len) >=
      91           0 :           (offsetof(sockaddr_storage, ss_family) + sizeof(ss.ss_family)) &&
      92           0 :       ss.ss_family == AF_UNIX) {
      93             :     // For Unix domain sockets, can't find out the peer name, but it should match our own
      94             :     // name for the socket (i.e. the path should match, barring any namespace or other
      95             :     // mechanisms to hide things, of which there are many).
      96           0 :     ss_len = sizeof(ss);
      97           0 :     result = os_sys_calls.getsockname(fd_, reinterpret_cast<sockaddr*>(&ss), &ss_len);
      98           0 :     if (result.return_value_ != 0) {
      99           0 :       throwEnvoyExceptionOrPanic(
     100           0 :           fmt::format("getsockname failed for '{}': {}", fd_, errorDetails(result.errno_)));
     101           0 :     }
     102           0 :   }
     103           0 :   return Address::addressFromSockAddrOrThrow(ss, ss_len, socket_v6only_);
     104           0 : }
     105             : 
     106        1315 : absl::optional<std::chrono::milliseconds> IoSocketHandleBaseImpl::lastRoundTripTime() {
     107        1315 :   Api::EnvoyTcpInfo info;
     108        1315 :   auto result = Api::OsSysCallsSingleton::get().socketTcpInfo(fd_, &info);
     109        1315 :   if (!result.return_value_) {
     110           0 :     return {};
     111           0 :   }
     112        1315 :   return std::chrono::duration_cast<std::chrono::milliseconds>(info.tcpi_rtt);
     113        1315 : }
     114             : 
     115           0 : absl::optional<uint64_t> IoSocketHandleBaseImpl::congestionWindowInBytes() const {
     116           0 :   Api::EnvoyTcpInfo info;
     117           0 :   auto result = Api::OsSysCallsSingleton::get().socketTcpInfo(fd_, &info);
     118           0 :   if (!result.return_value_) {
     119           0 :     return {};
     120           0 :   }
     121           0 :   return info.tcpi_snd_cwnd;
     122           0 : }
     123             : 
     124           0 : absl::optional<std::string> IoSocketHandleBaseImpl::interfaceName() {
     125           0 :   auto& os_syscalls_singleton = Api::OsSysCallsSingleton::get();
     126           0 :   if (!os_syscalls_singleton.supportsGetifaddrs()) {
     127           0 :     return absl::nullopt;
     128           0 :   }
     129             : 
     130           0 :   Address::InstanceConstSharedPtr socket_address = localAddress();
     131           0 :   if (!socket_address || socket_address->type() != Address::Type::Ip) {
     132           0 :     return absl::nullopt;
     133           0 :   }
     134             : 
     135           0 :   Api::InterfaceAddressVector interface_addresses{};
     136           0 :   const Api::SysCallIntResult rc = os_syscalls_singleton.getifaddrs(interface_addresses);
     137           0 :   RELEASE_ASSERT(!rc.return_value_, fmt::format("getifaddrs error: {}", rc.errno_));
     138             : 
     139           0 :   absl::optional<std::string> selected_interface_name{};
     140           0 :   for (const auto& interface_address : interface_addresses) {
     141           0 :     if (!interface_address.interface_addr_) {
     142           0 :       continue;
     143           0 :     }
     144             : 
     145           0 :     if (socket_address->ip()->version() == interface_address.interface_addr_->ip()->version()) {
     146             :       // Compare address _without port_.
     147             :       // TODO: create common addressAsStringWithoutPort method to simplify code here.
     148           0 :       absl::uint128 socket_address_value;
     149           0 :       absl::uint128 interface_address_value;
     150           0 :       switch (socket_address->ip()->version()) {
     151           0 :       case Address::IpVersion::v4:
     152           0 :         socket_address_value = socket_address->ip()->ipv4()->address();
     153           0 :         interface_address_value = interface_address.interface_addr_->ip()->ipv4()->address();
     154           0 :         break;
     155           0 :       case Address::IpVersion::v6:
     156           0 :         socket_address_value = socket_address->ip()->ipv6()->address();
     157           0 :         interface_address_value = interface_address.interface_addr_->ip()->ipv6()->address();
     158           0 :         break;
     159           0 :       default:
     160           0 :         ENVOY_BUG(false, fmt::format("unexpected IP family {}",
     161           0 :                                      static_cast<int>(socket_address->ip()->version())));
     162           0 :       }
     163             : 
     164           0 :       if (socket_address_value == interface_address_value) {
     165           0 :         selected_interface_name = interface_address.interface_name_;
     166           0 :         break;
     167           0 :       }
     168           0 :     }
     169           0 :   }
     170             : 
     171           0 :   return selected_interface_name;
     172           0 : }
     173             : 
     174             : } // namespace Network
     175             : } // namespace Envoy

Generated by: LCOV version 1.15