LCOV - code coverage report
Current view: top level - source/common/network - io_socket_handle_impl.cc (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 297 388 76.5 %
Date: 2024-01-05 06:35:25 Functions: 23 24 95.8 %

          Line data    Source code
       1             : #include "source/common/network/io_socket_handle_impl.h"
       2             : 
       3             : #include "envoy/buffer/buffer.h"
       4             : 
       5             : #include "source/common/api/os_sys_calls_impl.h"
       6             : #include "source/common/common/utility.h"
       7             : #include "source/common/event/file_event_impl.h"
       8             : #include "source/common/network/address_impl.h"
       9             : #include "source/common/network/socket_interface_impl.h"
      10             : 
      11             : #include "absl/container/fixed_array.h"
      12             : #include "absl/types/optional.h"
      13             : 
      14             : using Envoy::Api::SysCallIntResult;
      15             : using Envoy::Api::SysCallSizeResult;
      16             : 
      17             : namespace Envoy {
      18             : 
      19             : namespace {
      20             : 
      21         668 : constexpr int messageTypeContainsIP() {
      22             : #ifdef IP_RECVDSTADDR
      23             :   return IP_RECVDSTADDR;
      24             : #else
      25         668 :   return IP_PKTINFO;
      26         668 : #endif
      27         668 : }
      28             : 
      29         668 : in_addr addressFromMessage(const cmsghdr& cmsg) {
      30             : #ifdef IP_RECVDSTADDR
      31             :   return *reinterpret_cast<const in_addr*>(CMSG_DATA(&cmsg));
      32             : #else
      33         668 :   auto info = reinterpret_cast<const in_pktinfo*>(CMSG_DATA(&cmsg));
      34         668 :   return info->ipi_addr;
      35         668 : #endif
      36         668 : }
      37             : 
      38         504 : constexpr int messageTruncatedOption() {
      39             : #if defined(__APPLE__)
      40             :   // OSX does not support passing `MSG_TRUNC` to recvmsg and recvmmsg. This does not effect
      41             :   // functionality and it primarily used for logging.
      42             :   return 0;
      43             : #else
      44         504 :   return MSG_TRUNC;
      45         504 : #endif
      46         504 : }
      47             : 
      48             : } // namespace
      49             : 
      50             : namespace Network {
      51             : 
      52        7792 : IoSocketHandleImpl::~IoSocketHandleImpl() {
      53        7792 :   if (SOCKET_VALID(fd_)) {
      54        4034 :     IoSocketHandleImpl::close();
      55        4034 :   }
      56        7792 : }
      57             : 
      58        7397 : Api::IoCallUint64Result IoSocketHandleImpl::close() {
      59        7397 :   if (file_event_) {
      60        2643 :     file_event_.reset();
      61        2643 :   }
      62             : 
      63        7397 :   ASSERT(SOCKET_VALID(fd_));
      64        7397 :   const int rc = Api::OsSysCallsSingleton::get().close(fd_).return_value_;
      65        7397 :   SET_SOCKET_INVALID(fd_);
      66        7397 :   return {static_cast<unsigned long>(rc), Api::IoError::none()};
      67        7397 : }
      68             : 
      69             : Api::IoCallUint64Result IoSocketHandleImpl::readv(uint64_t max_length, Buffer::RawSlice* slices,
      70        6796 :                                                   uint64_t num_slice) {
      71        6796 :   absl::FixedArray<iovec> iov(num_slice);
      72        6796 :   uint64_t num_slices_to_read = 0;
      73        6796 :   uint64_t num_bytes_to_read = 0;
      74       43897 :   for (; num_slices_to_read < num_slice && num_bytes_to_read < max_length; num_slices_to_read++) {
      75       37101 :     iov[num_slices_to_read].iov_base = slices[num_slices_to_read].mem_;
      76       37101 :     const size_t slice_length = std::min(slices[num_slices_to_read].len_,
      77       37101 :                                          static_cast<size_t>(max_length - num_bytes_to_read));
      78       37101 :     iov[num_slices_to_read].iov_len = slice_length;
      79       37101 :     num_bytes_to_read += slice_length;
      80       37101 :   }
      81        6796 :   ASSERT(num_bytes_to_read <= max_length);
      82             : 
      83        6796 :   if (num_slices_to_read == 1) {
      84             :     // Avoid paying the VFS overhead when there is only one IO buffer to work with
      85        2403 :     return sysCallResultToIoCallResult(
      86        2403 :         Api::OsSysCallsSingleton::get().recv(fd_, iov[0].iov_base, iov[0].iov_len, 0));
      87        2403 :   }
      88             : 
      89        4393 :   auto result = sysCallResultToIoCallResult(Api::OsSysCallsSingleton::get().readv(
      90        4393 :       fd_, iov.begin(), static_cast<int>(num_slices_to_read)));
      91        4393 :   return result;
      92        6796 : }
      93             : 
      94             : Api::IoCallUint64Result IoSocketHandleImpl::read(Buffer::Instance& buffer,
      95        6798 :                                                  absl::optional<uint64_t> max_length_opt) {
      96        6798 :   const uint64_t max_length = max_length_opt.value_or(UINT64_MAX);
      97        6798 :   if (max_length == 0) {
      98           0 :     return Api::ioCallUint64ResultNoError();
      99           0 :   }
     100        6798 :   Buffer::Reservation reservation = buffer.reserveForRead();
     101        6798 :   Api::IoCallUint64Result result = readv(std::min(reservation.length(), max_length),
     102        6798 :                                          reservation.slices(), reservation.numSlices());
     103        6798 :   uint64_t bytes_to_commit = result.ok() ? result.return_value_ : 0;
     104        6798 :   ASSERT(bytes_to_commit <= max_length);
     105        6798 :   reservation.commit(bytes_to_commit);
     106        6798 :   return result;
     107        6798 : }
     108             : 
     109             : Api::IoCallUint64Result IoSocketHandleImpl::writev(const Buffer::RawSlice* slices,
     110        5657 :                                                    uint64_t num_slice) {
     111        5657 :   absl::FixedArray<iovec> iov(num_slice);
     112        5657 :   uint64_t num_slices_to_write = 0;
     113       12040 :   for (uint64_t i = 0; i < num_slice; i++) {
     114        6384 :     if (slices[i].mem_ != nullptr && slices[i].len_ != 0) {
     115        5986 :       iov[num_slices_to_write].iov_base = slices[i].mem_;
     116        5986 :       iov[num_slices_to_write].iov_len = slices[i].len_;
     117        5986 :       num_slices_to_write++;
     118        5986 :     }
     119        6383 :   }
     120        5657 :   if (num_slices_to_write == 0) {
     121         796 :     return Api::ioCallUint64ResultNoError();
     122         796 :   }
     123             : 
     124        4861 :   if (num_slices_to_write == 1) {
     125             :     // Avoid paying the VFS overhead when there is only one IO buffer to work with
     126        4383 :     return sysCallResultToIoCallResult(
     127        4383 :         Api::OsSysCallsSingleton::get().send(fd_, iov[0].iov_base, iov[0].iov_len, 0));
     128        4383 :   }
     129             : 
     130         478 :   auto result = sysCallResultToIoCallResult(
     131         478 :       Api::OsSysCallsSingleton::get().writev(fd_, iov.begin(), num_slices_to_write));
     132         478 :   return result;
     133        4861 : }
     134             : 
     135        5658 : Api::IoCallUint64Result IoSocketHandleImpl::write(Buffer::Instance& buffer) {
     136        5658 :   constexpr uint64_t MaxSlices = 16;
     137        5658 :   Buffer::RawSliceVector slices = buffer.getRawSlices(MaxSlices);
     138        5658 :   Api::IoCallUint64Result result = writev(slices.begin(), slices.size());
     139        5658 :   if (result.ok() && result.return_value_ > 0) {
     140        4793 :     buffer.drain(static_cast<uint64_t>(result.return_value_));
     141        4793 :   }
     142        5658 :   return result;
     143        5658 : }
     144             : 
     145             : Api::IoCallUint64Result IoSocketHandleImpl::sendmsg(const Buffer::RawSlice* slices,
     146             :                                                     uint64_t num_slice, int flags,
     147             :                                                     const Address::Ip* self_ip,
     148         668 :                                                     const Address::Instance& peer_address) {
     149         668 :   const auto* address_base = dynamic_cast<const Address::InstanceBase*>(&peer_address);
     150         668 :   sockaddr* sock_addr = const_cast<sockaddr*>(address_base->sockAddr());
     151         668 :   if (sock_addr == nullptr) {
     152             :     // Unlikely to happen unless the wrong peer address is passed.
     153           0 :     return IoSocketError::ioResultSocketInvalidAddress();
     154           0 :   }
     155         668 :   absl::FixedArray<iovec> iov(num_slice);
     156         668 :   uint64_t num_slices_to_write = 0;
     157        1336 :   for (uint64_t i = 0; i < num_slice; i++) {
     158         668 :     if (slices[i].mem_ != nullptr && slices[i].len_ != 0) {
     159         668 :       iov[num_slices_to_write].iov_base = slices[i].mem_;
     160         668 :       iov[num_slices_to_write].iov_len = slices[i].len_;
     161         668 :       num_slices_to_write++;
     162         668 :     }
     163         668 :   }
     164         668 :   if (num_slices_to_write == 0) {
     165           0 :     return Api::ioCallUint64ResultNoError();
     166           0 :   }
     167             : 
     168         668 :   msghdr message;
     169         668 :   message.msg_name = reinterpret_cast<void*>(sock_addr);
     170         668 :   message.msg_namelen = address_base->sockAddrLen();
     171         668 :   message.msg_iov = iov.begin();
     172         668 :   message.msg_iovlen = num_slices_to_write;
     173         668 :   message.msg_flags = 0;
     174         668 :   auto& os_syscalls = Api::OsSysCallsSingleton::get();
     175         668 :   if (self_ip == nullptr) {
     176         668 :     message.msg_control = nullptr;
     177         668 :     message.msg_controllen = 0;
     178         668 :     const Api::SysCallSizeResult result = os_syscalls.sendmsg(fd_, &message, flags);
     179         668 :     return sysCallResultToIoCallResult(result);
     180         668 :   } else {
     181           0 :     const size_t space_v6 = CMSG_SPACE(sizeof(in6_pktinfo));
     182           0 :     const size_t space_v4 = CMSG_SPACE(sizeof(in_pktinfo));
     183             : 
     184             :     // FreeBSD only needs in_addr size, but allocates more to unify code in two platforms.
     185           0 :     const size_t cmsg_space = (self_ip->version() == Address::IpVersion::v4) ? space_v4 : space_v6;
     186             :     // kSpaceForIp should be big enough to hold both IPv4 and IPv6 packet info.
     187           0 :     absl::FixedArray<char> cbuf(cmsg_space);
     188           0 :     memset(cbuf.begin(), 0, cmsg_space);
     189             : 
     190           0 :     message.msg_control = cbuf.begin();
     191           0 :     message.msg_controllen = cmsg_space;
     192           0 :     cmsghdr* const cmsg = CMSG_FIRSTHDR(&message);
     193           0 :     RELEASE_ASSERT(cmsg != nullptr, fmt::format("cbuf with size {} is not enough, cmsghdr size {}",
     194           0 :                                                 sizeof(cbuf), sizeof(cmsghdr)));
     195           0 :     if (self_ip->version() == Address::IpVersion::v4) {
     196           0 :       cmsg->cmsg_level = IPPROTO_IP;
     197           0 : #ifndef IP_SENDSRCADDR
     198           0 :       cmsg->cmsg_len = CMSG_LEN(sizeof(in_pktinfo));
     199           0 :       cmsg->cmsg_type = IP_PKTINFO;
     200           0 :       auto pktinfo = reinterpret_cast<in_pktinfo*>(CMSG_DATA(cmsg));
     201           0 :       pktinfo->ipi_ifindex = 0;
     202             : #ifdef WIN32
     203             :       pktinfo->ipi_addr.s_addr = self_ip->ipv4()->address();
     204             : #else
     205           0 :       pktinfo->ipi_spec_dst.s_addr = self_ip->ipv4()->address();
     206           0 : #endif
     207             : #else
     208             :       cmsg->cmsg_type = IP_SENDSRCADDR;
     209             :       cmsg->cmsg_len = CMSG_LEN(sizeof(in_addr));
     210             :       *(reinterpret_cast<struct in_addr*>(CMSG_DATA(cmsg))).s_addr = self_ip->ipv4()->address();
     211             : #endif
     212           0 :     } else if (self_ip->version() == Address::IpVersion::v6) {
     213           0 :       cmsg->cmsg_len = CMSG_LEN(sizeof(in6_pktinfo));
     214           0 :       cmsg->cmsg_level = IPPROTO_IPV6;
     215           0 :       cmsg->cmsg_type = IPV6_PKTINFO;
     216           0 :       auto pktinfo = reinterpret_cast<in6_pktinfo*>(CMSG_DATA(cmsg));
     217           0 :       pktinfo->ipi6_ifindex = 0;
     218           0 :       *(reinterpret_cast<absl::uint128*>(pktinfo->ipi6_addr.s6_addr)) = self_ip->ipv6()->address();
     219           0 :     }
     220           0 :     const Api::SysCallSizeResult result = os_syscalls.sendmsg(fd_, &message, flags);
     221           0 :     if (result.return_value_ < 0 && result.errno_ == SOCKET_ERROR_INVAL) {
     222           0 :       ENVOY_LOG(error, fmt::format("EINVAL error. Socket is open: {}, IPv{}.", isOpen(),
     223           0 :                                    self_ip->version() == Address::IpVersion::v6 ? 6 : 4));
     224           0 :     }
     225           0 :     return sysCallResultToIoCallResult(result);
     226           0 :   }
     227         668 : }
     228             : 
     229             : Address::InstanceConstSharedPtr
     230         668 : maybeGetDstAddressFromHeader(const cmsghdr& cmsg, uint32_t self_port, os_fd_t fd, bool v6only) {
     231         668 :   if (cmsg.cmsg_type == IPV6_PKTINFO) {
     232           0 :     auto info = reinterpret_cast<const in6_pktinfo*>(CMSG_DATA(&cmsg));
     233           0 :     sockaddr_storage ss;
     234           0 :     auto ipv6_addr = reinterpret_cast<sockaddr_in6*>(&ss);
     235           0 :     memset(ipv6_addr, 0, sizeof(sockaddr_in6));
     236           0 :     ipv6_addr->sin6_family = AF_INET6;
     237           0 :     ipv6_addr->sin6_addr = info->ipi6_addr;
     238           0 :     ipv6_addr->sin6_port = htons(self_port);
     239           0 :     return Address::addressFromSockAddrOrDie(ss, sizeof(sockaddr_in6), fd, v6only);
     240           0 :   }
     241             : 
     242         668 :   if (cmsg.cmsg_type == messageTypeContainsIP()) {
     243         668 :     sockaddr_storage ss;
     244         668 :     auto ipv4_addr = reinterpret_cast<sockaddr_in*>(&ss);
     245         668 :     memset(ipv4_addr, 0, sizeof(sockaddr_in));
     246         668 :     ipv4_addr->sin_family = AF_INET;
     247         668 :     ipv4_addr->sin_addr = addressFromMessage(cmsg);
     248         668 :     ipv4_addr->sin_port = htons(self_port);
     249         668 :     return Address::addressFromSockAddrOrDie(ss, sizeof(sockaddr_in), fd, v6only);
     250         668 :   }
     251             : 
     252           0 :   return nullptr;
     253         668 : }
     254             : 
     255          42 : absl::optional<uint32_t> maybeGetPacketsDroppedFromHeader([[maybe_unused]] const cmsghdr& cmsg) {
     256          42 : #ifdef SO_RXQ_OVFL
     257          42 :   if (cmsg.cmsg_type == SO_RXQ_OVFL) {
     258           0 :     return *reinterpret_cast<const uint32_t*>(CMSG_DATA(&cmsg));
     259           0 :   }
     260          42 : #endif
     261          42 :   return absl::nullopt;
     262          42 : }
     263             : 
     264             : Api::IoCallUint64Result IoSocketHandleImpl::recvmsg(Buffer::RawSlice* slices,
     265             :                                                     const uint64_t num_slice, uint32_t self_port,
     266         420 :                                                     RecvMsgOutput& output) {
     267         420 :   ASSERT(!output.msg_.empty());
     268             : 
     269         420 :   absl::FixedArray<char> cbuf(cmsg_space_);
     270         420 :   memset(cbuf.begin(), 0, cmsg_space_);
     271             : 
     272         420 :   absl::FixedArray<iovec> iov(num_slice);
     273         420 :   uint64_t num_slices_for_read = 0;
     274         840 :   for (uint64_t i = 0; i < num_slice; i++) {
     275         420 :     if (slices[i].mem_ != nullptr && slices[i].len_ != 0) {
     276         420 :       iov[num_slices_for_read].iov_base = slices[i].mem_;
     277         420 :       iov[num_slices_for_read].iov_len = slices[i].len_;
     278         420 :       ++num_slices_for_read;
     279         420 :     }
     280         420 :   }
     281         420 :   if (num_slices_for_read == 0) {
     282           0 :     return Api::ioCallUint64ResultNoError();
     283           0 :   }
     284             : 
     285         420 :   sockaddr_storage peer_addr;
     286         420 :   msghdr hdr;
     287         420 :   hdr.msg_name = &peer_addr;
     288         420 :   hdr.msg_namelen = sizeof(sockaddr_storage);
     289         420 :   hdr.msg_iov = iov.begin();
     290         420 :   hdr.msg_iovlen = num_slices_for_read;
     291         420 :   hdr.msg_flags = 0;
     292         420 :   hdr.msg_control = cbuf.begin();
     293         420 :   hdr.msg_controllen = cmsg_space_;
     294         420 :   Api::SysCallSizeResult result =
     295         420 :       Api::OsSysCallsSingleton::get().recvmsg(fd_, &hdr, messageTruncatedOption());
     296         420 :   if (result.return_value_ < 0) {
     297          49 :     return sysCallResultToIoCallResult(result);
     298          49 :   }
     299         371 :   if ((hdr.msg_flags & MSG_TRUNC) != 0) {
     300           0 :     ENVOY_LOG_MISC(debug, "Dropping truncated UDP packet with size: {}.", result.return_value_);
     301           0 :     result.return_value_ = 0;
     302           0 :     (*output.dropped_packets_)++;
     303           0 :     output.msg_[0].truncated_and_dropped_ = true;
     304           0 :     return sysCallResultToIoCallResult(result);
     305           0 :   }
     306             : 
     307         371 :   RELEASE_ASSERT((hdr.msg_flags & MSG_CTRUNC) == 0,
     308         371 :                  fmt::format("Incorrectly set control message length: {}", hdr.msg_controllen));
     309         371 :   RELEASE_ASSERT(hdr.msg_namelen > 0,
     310         371 :                  fmt::format("Unable to get remote address from recvmsg() for fd: {}", fd_));
     311         371 :   output.msg_[0].peer_address_ = Address::addressFromSockAddrOrDie(
     312         371 :       peer_addr, hdr.msg_namelen, fd_, socket_v6only_ || !udp_read_normalize_addresses_);
     313         371 :   output.msg_[0].gso_size_ = 0;
     314             : 
     315         371 :   if (hdr.msg_controllen > 0) {
     316             :     // Get overflow, local address and gso_size from control message.
     317         742 :     for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr); cmsg != nullptr;
     318         371 :          cmsg = CMSG_NXTHDR(&hdr, cmsg)) {
     319             : 
     320         371 :       if (output.msg_[0].local_address_ == nullptr) {
     321         371 :         Address::InstanceConstSharedPtr addr = maybeGetDstAddressFromHeader(
     322         371 :             *cmsg, self_port, fd_, socket_v6only_ || !udp_read_normalize_addresses_);
     323         371 :         if (addr != nullptr) {
     324             :           // This is a IP packet info message.
     325         371 :           output.msg_[0].local_address_ = std::move(addr);
     326         371 :           continue;
     327         371 :         }
     328         371 :       }
     329           0 :       if (output.dropped_packets_ != nullptr) {
     330           0 :         absl::optional<uint32_t> maybe_dropped = maybeGetPacketsDroppedFromHeader(*cmsg);
     331           0 :         if (maybe_dropped) {
     332           0 :           *output.dropped_packets_ += *maybe_dropped;
     333           0 :           continue;
     334           0 :         }
     335           0 :       }
     336           0 : #ifdef UDP_GRO
     337           0 :       if (cmsg->cmsg_level == SOL_UDP && cmsg->cmsg_type == UDP_GRO) {
     338           0 :         output.msg_[0].gso_size_ = *reinterpret_cast<uint16_t*>(CMSG_DATA(cmsg));
     339           0 :       }
     340           0 : #endif
     341           0 :     }
     342         371 :   }
     343             : 
     344         371 :   return sysCallResultToIoCallResult(result);
     345         371 : }
     346             : 
     347             : Api::IoCallUint64Result IoSocketHandleImpl::recvmmsg(RawSliceArrays& slices, uint32_t self_port,
     348          84 :                                                      RecvMsgOutput& output) {
     349          84 :   ASSERT(output.msg_.size() == slices.size());
     350          84 :   if (slices.empty()) {
     351           0 :     return sysCallResultToIoCallResult(Api::SysCallIntResult{0, SOCKET_ERROR_AGAIN});
     352           0 :   }
     353          84 :   const uint32_t num_packets_per_mmsg_call = slices.size();
     354          84 :   absl::FixedArray<mmsghdr> mmsg_hdr(num_packets_per_mmsg_call);
     355          84 :   absl::FixedArray<absl::FixedArray<struct iovec>> iovs(
     356          84 :       num_packets_per_mmsg_call, absl::FixedArray<struct iovec>(slices[0].size()));
     357          84 :   absl::FixedArray<sockaddr_storage> raw_addresses(num_packets_per_mmsg_call);
     358          84 :   absl::FixedArray<absl::FixedArray<char>> cbufs(num_packets_per_mmsg_call,
     359          84 :                                                  absl::FixedArray<char>(cmsg_space_));
     360             : 
     361        1428 :   for (uint32_t i = 0; i < num_packets_per_mmsg_call; ++i) {
     362        1344 :     memset(&raw_addresses[i], 0, sizeof(sockaddr_storage));
     363        1344 :     memset(cbufs[i].data(), 0, cbufs[i].size());
     364             : 
     365        1344 :     mmsg_hdr[i].msg_len = 0;
     366             : 
     367        1344 :     msghdr* hdr = &mmsg_hdr[i].msg_hdr;
     368        1344 :     hdr->msg_name = &raw_addresses[i];
     369        1344 :     hdr->msg_namelen = sizeof(sockaddr_storage);
     370        1344 :     ASSERT(!slices[i].empty());
     371             : 
     372        2688 :     for (size_t j = 0; j < slices[i].size(); ++j) {
     373        1344 :       iovs[i][j].iov_base = slices[i][j].mem_;
     374        1344 :       iovs[i][j].iov_len = slices[i][j].len_;
     375        1344 :     }
     376        1344 :     hdr->msg_iov = iovs[i].data();
     377        1344 :     hdr->msg_iovlen = slices[i].size();
     378        1344 :     hdr->msg_control = cbufs[i].data();
     379        1344 :     hdr->msg_controllen = cbufs[i].size();
     380        1344 :   }
     381             : 
     382             :   // Set MSG_WAITFORONE so that recvmmsg will not waiting for
     383             :   // |num_packets_per_mmsg_call| packets to arrive before returning when the
     384             :   // socket is a blocking socket.
     385          84 :   const Api::SysCallIntResult result =
     386          84 :       Api::OsSysCallsSingleton::get().recvmmsg(fd_, mmsg_hdr.data(), num_packets_per_mmsg_call,
     387          84 :                                                messageTruncatedOption() | MSG_WAITFORONE, nullptr);
     388             : 
     389          84 :   if (result.return_value_ <= 0) {
     390          42 :     return sysCallResultToIoCallResult(result);
     391          42 :   }
     392             : 
     393          42 :   int num_packets_read = result.return_value_;
     394             : 
     395         339 :   for (int i = 0; i < num_packets_read; ++i) {
     396         297 :     msghdr& hdr = mmsg_hdr[i].msg_hdr;
     397         297 :     if ((hdr.msg_flags & MSG_TRUNC) != 0) {
     398           0 :       ENVOY_LOG_MISC(debug, "Dropping truncated UDP packet with size: {}.", mmsg_hdr[i].msg_len);
     399           0 :       (*output.dropped_packets_)++;
     400           0 :       output.msg_[i].truncated_and_dropped_ = true;
     401           0 :       continue;
     402           0 :     }
     403             : 
     404         297 :     RELEASE_ASSERT((hdr.msg_flags & MSG_CTRUNC) == 0,
     405         297 :                    fmt::format("Incorrectly set control message length: {}", hdr.msg_controllen));
     406         297 :     RELEASE_ASSERT(hdr.msg_namelen > 0,
     407         297 :                    fmt::format("Unable to get remote address from recvmmsg() for fd: {}", fd_));
     408             : 
     409         297 :     output.msg_[i].msg_len_ = mmsg_hdr[i].msg_len;
     410             :     // Get local and peer addresses for each packet.
     411         297 :     output.msg_[i].peer_address_ = Address::addressFromSockAddrOrDie(
     412         297 :         raw_addresses[i], hdr.msg_namelen, fd_, socket_v6only_ || !udp_read_normalize_addresses_);
     413         297 :     if (hdr.msg_controllen > 0) {
     414         297 :       struct cmsghdr* cmsg;
     415         297 :       for (cmsg = CMSG_FIRSTHDR(&hdr); cmsg != nullptr; cmsg = CMSG_NXTHDR(&hdr, cmsg)) {
     416         297 :         Address::InstanceConstSharedPtr addr = maybeGetDstAddressFromHeader(
     417         297 :             *cmsg, self_port, fd_, socket_v6only_ || !udp_read_normalize_addresses_);
     418         297 :         if (addr != nullptr) {
     419             :           // This is a IP packet info message.
     420         297 :           output.msg_[i].local_address_ = std::move(addr);
     421         297 :           break;
     422         297 :         }
     423         297 :       }
     424         297 :     }
     425         297 :   }
     426             :   // Get overflow from first packet header.
     427          42 :   if (output.dropped_packets_ != nullptr) {
     428          42 :     msghdr& hdr = mmsg_hdr[0].msg_hdr;
     429          42 :     if (hdr.msg_controllen > 0) {
     430          42 :       struct cmsghdr* cmsg;
     431          84 :       for (cmsg = CMSG_FIRSTHDR(&hdr); cmsg != nullptr; cmsg = CMSG_NXTHDR(&hdr, cmsg)) {
     432          42 :         absl::optional<uint32_t> maybe_dropped = maybeGetPacketsDroppedFromHeader(*cmsg);
     433          42 :         if (maybe_dropped) {
     434           0 :           *output.dropped_packets_ += *maybe_dropped;
     435           0 :         }
     436          42 :       }
     437          42 :     }
     438          42 :   }
     439          42 :   return sysCallResultToIoCallResult(result);
     440          42 : }
     441             : 
     442           0 : Api::IoCallUint64Result IoSocketHandleImpl::recv(void* buffer, size_t length, int flags) {
     443           0 :   const Api::SysCallSizeResult result =
     444           0 :       Api::OsSysCallsSingleton::get().recv(fd_, buffer, length, flags);
     445           0 :   return sysCallResultToIoCallResult(result);
     446           0 : }
     447             : 
     448        1317 : Api::SysCallIntResult IoSocketHandleImpl::bind(Address::InstanceConstSharedPtr address) {
     449        1317 :   return Api::OsSysCallsSingleton::get().bind(fd_, address->sockAddr(), address->sockAddrLen());
     450        1317 : }
     451             : 
     452         607 : Api::SysCallIntResult IoSocketHandleImpl::listen(int backlog) {
     453         607 :   return Api::OsSysCallsSingleton::get().listen(fd_, backlog);
     454         607 : }
     455             : 
     456        2612 : IoHandlePtr IoSocketHandleImpl::accept(struct sockaddr* addr, socklen_t* addrlen) {
     457        2612 :   auto result = Api::OsSysCallsSingleton::get().accept(fd_, addr, addrlen);
     458        2612 :   if (SOCKET_INVALID(result.return_value_)) {
     459        1297 :     return nullptr;
     460        1297 :   }
     461        1315 :   return SocketInterfaceImpl::makePlatformSpecificSocket(result.return_value_, socket_v6only_,
     462        1315 :                                                          domain_);
     463        2612 : }
     464             : 
     465        1328 : Api::SysCallIntResult IoSocketHandleImpl::connect(Address::InstanceConstSharedPtr address) {
     466        1328 :   auto sockaddr_to_use = address->sockAddr();
     467        1328 :   auto sockaddr_len_to_use = address->sockAddrLen();
     468             : #if defined(__APPLE__) || defined(__ANDROID_API__)
     469             :   sockaddr_in6 sin6;
     470             :   if (sockaddr_to_use->sa_family == AF_INET && Address::forceV6()) {
     471             :     const sockaddr_in& sin4 = reinterpret_cast<const sockaddr_in&>(*sockaddr_to_use);
     472             : 
     473             :     // Android always uses IPv6 dual stack. Convert IPv4 to the IPv6 mapped address when
     474             :     // connecting.
     475             :     memset(&sin6, 0, sizeof(sin6));
     476             :     sin6.sin6_family = AF_INET6;
     477             :     sin6.sin6_port = sin4.sin_port;
     478             : #if defined(__ANDROID_API__)
     479             :     sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
     480             :     sin6.sin6_addr.s6_addr32[3] = sin4.sin_addr.s_addr;
     481             : #elif defined(__APPLE__)
     482             :     sin6.sin6_addr.__u6_addr.__u6_addr32[2] = htonl(0xffff);
     483             :     sin6.sin6_addr.__u6_addr.__u6_addr32[3] = sin4.sin_addr.s_addr;
     484             : #endif
     485             :     ASSERT(IN6_IS_ADDR_V4MAPPED(&sin6.sin6_addr));
     486             : 
     487             :     sockaddr_to_use = reinterpret_cast<sockaddr*>(&sin6);
     488             :     sockaddr_len_to_use = sizeof(sin6);
     489             :   }
     490             : #endif
     491             : 
     492        1328 :   return Api::OsSysCallsSingleton::get().connect(fd_, sockaddr_to_use, sockaddr_len_to_use);
     493        1328 : }
     494             : 
     495          18 : IoHandlePtr IoSocketHandleImpl::duplicate() {
     496          18 :   auto result = Api::OsSysCallsSingleton::get().duplicate(fd_);
     497          18 :   RELEASE_ASSERT(result.return_value_ != -1,
     498          18 :                  fmt::format("duplicate failed for '{}': ({}) {}", fd_, result.errno_,
     499          18 :                              errorDetails(result.errno_)));
     500          18 :   return SocketInterfaceImpl::makePlatformSpecificSocket(result.return_value_, socket_v6only_,
     501          18 :                                                          domain_);
     502          18 : }
     503             : 
     504             : void IoSocketHandleImpl::initializeFileEvent(Event::Dispatcher& dispatcher, Event::FileReadyCb cb,
     505        3341 :                                              Event::FileTriggerType trigger, uint32_t events) {
     506        3341 :   ASSERT(file_event_ == nullptr, "Attempting to initialize two `file_event_` for the same "
     507        3341 :                                  "file descriptor. This is not allowed.");
     508        3341 :   file_event_ = dispatcher.createFileEvent(fd_, cb, trigger, events);
     509        3341 : }
     510             : 
     511        7016 : void IoSocketHandleImpl::activateFileEvents(uint32_t events) {
     512        7016 :   if (file_event_) {
     513        7016 :     file_event_->activate(events);
     514        7016 :   } else {
     515           0 :     ENVOY_BUG(false, "Null file_event_");
     516           0 :   }
     517        7016 : }
     518             : 
     519         670 : void IoSocketHandleImpl::enableFileEvents(uint32_t events) {
     520         670 :   if (file_event_) {
     521         670 :     file_event_->setEnabled(events);
     522         670 :   } else {
     523           0 :     ENVOY_BUG(false, "Null file_event_");
     524           0 :   }
     525         670 : }
     526             : 
     527         252 : Api::SysCallIntResult IoSocketHandleImpl::shutdown(int how) {
     528         252 :   return Api::OsSysCallsSingleton::get().shutdown(fd_, how);
     529         252 : }
     530             : 
     531             : } // namespace Network
     532             : } // namespace Envoy

Generated by: LCOV version 1.15