LCOV - code coverage report
Current view: top level - source/common/network - socket_impl.cc (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 50 86 58.1 %
Date: 2024-01-05 06:35:25 Functions: 8 12 66.7 %

          Line data    Source code
       1             : #include "source/common/network/socket_impl.h"
       2             : 
       3             : #include "envoy/common/exception.h"
       4             : #include "envoy/network/socket_interface.h"
       5             : 
       6             : #include "source/common/api/os_sys_calls_impl.h"
       7             : #include "source/common/common/utility.h"
       8             : 
       9             : namespace Envoy {
      10             : namespace Network {
      11             : 
      12             : SocketImpl::SocketImpl(Socket::Type sock_type,
      13             :                        const Address::InstanceConstSharedPtr& address_for_io_handle,
      14             :                        const Address::InstanceConstSharedPtr& remote_address,
      15             :                        const SocketCreationOptions& options)
      16             :     : io_handle_(ioHandleForAddr(sock_type, address_for_io_handle, options)),
      17             :       connection_info_provider_(
      18             :           std::make_shared<ConnectionInfoSetterImpl>(nullptr, remote_address)),
      19         515 :       sock_type_(sock_type), addr_type_(address_for_io_handle->type()) {}
      20             : 
      21             : SocketImpl::SocketImpl(IoHandlePtr&& io_handle,
      22             :                        const Address::InstanceConstSharedPtr& local_address,
      23             :                        const Address::InstanceConstSharedPtr& remote_address)
      24             :     : io_handle_(std::move(io_handle)),
      25             :       connection_info_provider_(
      26             :           std::make_shared<ConnectionInfoSetterImpl>(local_address, remote_address)),
      27        3504 :       sock_type_(Network::Socket::Type::Stream) {
      28             : 
      29        3504 :   if (connection_info_provider_->localAddress() != nullptr) {
      30        2176 :     addr_type_ = connection_info_provider_->localAddress()->type();
      31        2176 :     return;
      32        2176 :   }
      33             : 
      34        1328 :   if (connection_info_provider_->remoteAddress() != nullptr) {
      35        1328 :     addr_type_ = connection_info_provider_->remoteAddress()->type();
      36        1328 :     return;
      37        1328 :   }
      38             : 
      39             :   // Should not happen but some tests inject -1 fds
      40           0 :   if (!io_handle_->isOpen()) {
      41           0 :     return;
      42           0 :   }
      43             : 
      44           0 :   auto domain = io_handle_->domain();
      45             :   // This should never happen in practice but too many tests inject fake fds ...
      46           0 :   if (!domain.has_value()) {
      47           0 :     return;
      48           0 :   }
      49             : 
      50           0 :   addr_type_ = *domain == AF_UNIX ? Address::Type::Pipe : Address::Type::Ip;
      51           0 : }
      52             : 
      53        1317 : Api::SysCallIntResult SocketImpl::bind(Network::Address::InstanceConstSharedPtr address) {
      54        1317 :   Api::SysCallIntResult bind_result;
      55             : 
      56        1317 :   if (address->type() == Address::Type::Pipe) {
      57           5 :     const Address::Pipe* pipe = address->pipe();
      58           5 :     const auto* pipe_sa = reinterpret_cast<const sockaddr_un*>(address->sockAddr());
      59           5 :     bool abstract_namespace = address->pipe()->abstractNamespace();
      60           5 :     if (!abstract_namespace) {
      61             :       // Try to unlink an existing filesystem object at the requested path. Ignore
      62             :       // errors -- it's fine if the path doesn't exist, and if it exists but can't
      63             :       // be unlinked then `::bind()` will generate a reasonable errno.
      64           0 :       unlink(pipe_sa->sun_path);
      65           0 :     }
      66             :     // Not storing a reference to syscalls singleton because of unit test mocks
      67           5 :     bind_result = io_handle_->bind(address);
      68           5 :     if (pipe->mode() != 0 && !abstract_namespace && bind_result.return_value_ == 0) {
      69           0 :       auto set_permissions = Api::OsSysCallsSingleton::get().chmod(pipe_sa->sun_path, pipe->mode());
      70           0 :       if (set_permissions.return_value_ != 0) {
      71           0 :         throwEnvoyExceptionOrPanic(fmt::format("Failed to create socket with mode {}: {}",
      72           0 :                                                std::to_string(pipe->mode()),
      73           0 :                                                errorDetails(set_permissions.errno_)));
      74           0 :       }
      75           0 :     }
      76           5 :     return bind_result;
      77           5 :   }
      78             : 
      79        1312 :   bind_result = io_handle_->bind(address);
      80        1312 :   if (bind_result.return_value_ == 0 && address->ip()->port() == 0) {
      81         797 :     connection_info_provider_->setLocalAddress(io_handle_->localAddress());
      82         797 :   }
      83        1312 :   return bind_result;
      84        1317 : }
      85             : 
      86           0 : Api::SysCallIntResult SocketImpl::listen(int backlog) { return io_handle_->listen(backlog); }
      87             : 
      88        1328 : Api::SysCallIntResult SocketImpl::connect(const Network::Address::InstanceConstSharedPtr address) {
      89        1328 :   auto result = io_handle_->connect(address);
      90        1328 :   if (address->type() == Address::Type::Ip) {
      91        1328 :     connection_info_provider_->setLocalAddress(io_handle_->localAddress());
      92        1328 :   }
      93        1328 :   return result;
      94        1328 : }
      95             : 
      96             : Api::SysCallIntResult SocketImpl::setSocketOption(int level, int optname, const void* optval,
      97        3443 :                                                   socklen_t optlen) {
      98        3443 :   return io_handle_->setOption(level, optname, optval, optlen);
      99        3443 : }
     100             : 
     101             : Api::SysCallIntResult SocketImpl::getSocketOption(int level, int optname, void* optval,
     102        1178 :                                                   socklen_t* optlen) const {
     103        1178 :   return io_handle_->getOption(level, optname, optval, optlen);
     104        1178 : }
     105             : 
     106             : Api::SysCallIntResult SocketImpl::ioctl(unsigned long control_code, void* in_buffer,
     107             :                                         unsigned long in_buffer_len, void* out_buffer,
     108             :                                         unsigned long out_buffer_len,
     109           0 :                                         unsigned long* bytes_returned) {
     110           0 :   return io_handle_->ioctl(control_code, in_buffer, in_buffer_len, out_buffer, out_buffer_len,
     111           0 :                            bytes_returned);
     112           0 : }
     113             : 
     114          91 : Api::SysCallIntResult SocketImpl::setBlockingForTest(bool blocking) {
     115          91 :   return io_handle_->setBlocking(blocking);
     116          91 : }
     117             : 
     118        1212 : absl::optional<Address::IpVersion> SocketImpl::ipVersion() const {
     119        1212 :   if (addr_type_ == Address::Type::Ip) {
     120             :     // Always hit after socket is initialized, i.e., accepted or connected
     121        1212 :     if (connection_info_provider_->localAddress() != nullptr) {
     122        1212 :       return connection_info_provider_->localAddress()->ip()->version();
     123        1212 :     } else {
     124           0 :       auto domain = io_handle_->domain();
     125           0 :       if (!domain.has_value()) {
     126           0 :         return absl::nullopt;
     127           0 :       }
     128           0 :       if (*domain == AF_INET) {
     129           0 :         return Address::IpVersion::v4;
     130           0 :       } else if (*domain == AF_INET6) {
     131           0 :         return Address::IpVersion::v6;
     132           0 :       } else {
     133           0 :         return absl::nullopt;
     134           0 :       }
     135           0 :     }
     136        1212 :   }
     137           0 :   return absl::nullopt;
     138        1212 : }
     139             : 
     140             : } // namespace Network
     141             : } // namespace Envoy

Generated by: LCOV version 1.15