Coverage Report

Created: 2023-11-12 09:30

/proc/self/cwd/source/common/network/io_socket_handle_impl.cc
Line
Count
Source (jump to first uncovered line)
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
0
constexpr int messageTypeContainsIP() {
22
#ifdef IP_RECVDSTADDR
23
  return IP_RECVDSTADDR;
24
#else
25
0
  return IP_PKTINFO;
26
0
#endif
27
0
}
28
29
0
in_addr addressFromMessage(const cmsghdr& cmsg) {
30
#ifdef IP_RECVDSTADDR
31
  return *reinterpret_cast<const in_addr*>(CMSG_DATA(&cmsg));
32
#else
33
0
  auto info = reinterpret_cast<const in_pktinfo*>(CMSG_DATA(&cmsg));
34
0
  return info->ipi_addr;
35
0
#endif
36
0
}
37
38
0
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
0
  return MSG_TRUNC;
45
0
#endif
46
0
}
47
48
} // namespace
49
50
namespace Network {
51
52
58.9k
IoSocketHandleImpl::~IoSocketHandleImpl() {
53
58.9k
  if (SOCKET_VALID(fd_)) {
54
21.2k
    IoSocketHandleImpl::close();
55
21.2k
  }
56
58.9k
}
57
58
53.8k
Api::IoCallUint64Result IoSocketHandleImpl::close() {
59
53.8k
  if (file_event_) {
60
14.5k
    file_event_.reset();
61
14.5k
  }
62
63
53.8k
  ASSERT(SOCKET_VALID(fd_));
64
53.8k
  const int rc = Api::OsSysCallsSingleton::get().close(fd_).return_value_;
65
53.8k
  SET_SOCKET_INVALID(fd_);
66
53.8k
  return {static_cast<unsigned long>(rc), Api::IoError::none()};
67
53.8k
}
68
69
Api::IoCallUint64Result IoSocketHandleImpl::readv(uint64_t max_length, Buffer::RawSlice* slices,
70
57.8k
                                                  uint64_t num_slice) {
71
57.8k
  absl::FixedArray<iovec> iov(num_slice);
72
57.8k
  uint64_t num_slices_to_read = 0;
73
57.8k
  uint64_t num_bytes_to_read = 0;
74
441k
  for (; num_slices_to_read < num_slice && num_bytes_to_read < max_length; num_slices_to_read++) {
75
384k
    iov[num_slices_to_read].iov_base = slices[num_slices_to_read].mem_;
76
384k
    const size_t slice_length = std::min(slices[num_slices_to_read].len_,
77
384k
                                         static_cast<size_t>(max_length - num_bytes_to_read));
78
384k
    iov[num_slices_to_read].iov_len = slice_length;
79
384k
    num_bytes_to_read += slice_length;
80
384k
  }
81
57.8k
  ASSERT(num_bytes_to_read <= max_length);
82
83
57.8k
  if (num_slices_to_read == 1) {
84
    // Avoid paying the VFS overhead when there is only one IO buffer to work with
85
9.70k
    return sysCallResultToIoCallResult(
86
9.70k
        Api::OsSysCallsSingleton::get().recv(fd_, iov[0].iov_base, iov[0].iov_len, 0));
87
9.70k
  }
88
89
48.1k
  auto result = sysCallResultToIoCallResult(Api::OsSysCallsSingleton::get().readv(
90
48.1k
      fd_, iov.begin(), static_cast<int>(num_slices_to_read)));
91
48.1k
  return result;
92
57.8k
}
93
94
Api::IoCallUint64Result IoSocketHandleImpl::read(Buffer::Instance& buffer,
95
57.8k
                                                 absl::optional<uint64_t> max_length_opt) {
96
57.8k
  const uint64_t max_length = max_length_opt.value_or(UINT64_MAX);
97
57.8k
  if (max_length == 0) {
98
0
    return Api::ioCallUint64ResultNoError();
99
0
  }
100
57.8k
  Buffer::Reservation reservation = buffer.reserveForRead();
101
57.8k
  Api::IoCallUint64Result result = readv(std::min(reservation.length(), max_length),
102
57.8k
                                         reservation.slices(), reservation.numSlices());
103
57.8k
  uint64_t bytes_to_commit = result.ok() ? result.return_value_ : 0;
104
57.8k
  ASSERT(bytes_to_commit <= max_length);
105
57.8k
  reservation.commit(bytes_to_commit);
106
57.8k
  return result;
107
57.8k
}
108
109
Api::IoCallUint64Result IoSocketHandleImpl::writev(const Buffer::RawSlice* slices,
110
30.6k
                                                   uint64_t num_slice) {
111
30.6k
  absl::FixedArray<iovec> iov(num_slice);
112
30.6k
  uint64_t num_slices_to_write = 0;
113
66.7k
  for (uint64_t i = 0; i < num_slice; i++) {
114
36.1k
    if (slices[i].mem_ != nullptr && slices[i].len_ != 0) {
115
35.4k
      iov[num_slices_to_write].iov_base = slices[i].mem_;
116
35.4k
      iov[num_slices_to_write].iov_len = slices[i].len_;
117
35.4k
      num_slices_to_write++;
118
35.4k
    }
119
36.1k
  }
120
30.6k
  if (num_slices_to_write == 0) {
121
1.29k
    return Api::ioCallUint64ResultNoError();
122
1.29k
  }
123
124
29.3k
  if (num_slices_to_write == 1) {
125
    // Avoid paying the VFS overhead when there is only one IO buffer to work with
126
24.1k
    return sysCallResultToIoCallResult(
127
24.1k
        Api::OsSysCallsSingleton::get().send(fd_, iov[0].iov_base, iov[0].iov_len, 0));
128
24.1k
  }
129
130
5.14k
  auto result = sysCallResultToIoCallResult(
131
5.14k
      Api::OsSysCallsSingleton::get().writev(fd_, iov.begin(), num_slices_to_write));
132
5.14k
  return result;
133
29.3k
}
134
135
30.6k
Api::IoCallUint64Result IoSocketHandleImpl::write(Buffer::Instance& buffer) {
136
30.6k
  constexpr uint64_t MaxSlices = 16;
137
30.6k
  Buffer::RawSliceVector slices = buffer.getRawSlices(MaxSlices);
138
30.6k
  Api::IoCallUint64Result result = writev(slices.begin(), slices.size());
139
30.6k
  if (result.ok() && result.return_value_ > 0) {
140
29.2k
    buffer.drain(static_cast<uint64_t>(result.return_value_));
141
29.2k
  }
142
30.6k
  return result;
143
30.6k
}
144
145
Api::IoCallUint64Result IoSocketHandleImpl::sendmsg(const Buffer::RawSlice* slices,
146
                                                    uint64_t num_slice, int flags,
147
                                                    const Address::Ip* self_ip,
148
0
                                                    const Address::Instance& peer_address) {
149
0
  const auto* address_base = dynamic_cast<const Address::InstanceBase*>(&peer_address);
150
0
  sockaddr* sock_addr = const_cast<sockaddr*>(address_base->sockAddr());
151
0
  if (sock_addr == nullptr) {
152
    // Unlikely to happen unless the wrong peer address is passed.
153
0
    return IoSocketError::ioResultSocketInvalidAddress();
154
0
  }
155
0
  absl::FixedArray<iovec> iov(num_slice);
156
0
  uint64_t num_slices_to_write = 0;
157
0
  for (uint64_t i = 0; i < num_slice; i++) {
158
0
    if (slices[i].mem_ != nullptr && slices[i].len_ != 0) {
159
0
      iov[num_slices_to_write].iov_base = slices[i].mem_;
160
0
      iov[num_slices_to_write].iov_len = slices[i].len_;
161
0
      num_slices_to_write++;
162
0
    }
163
0
  }
164
0
  if (num_slices_to_write == 0) {
165
0
    return Api::ioCallUint64ResultNoError();
166
0
  }
167
168
0
  msghdr message;
169
0
  message.msg_name = reinterpret_cast<void*>(sock_addr);
170
0
  message.msg_namelen = address_base->sockAddrLen();
171
0
  message.msg_iov = iov.begin();
172
0
  message.msg_iovlen = num_slices_to_write;
173
0
  message.msg_flags = 0;
174
0
  auto& os_syscalls = Api::OsSysCallsSingleton::get();
175
0
  if (self_ip == nullptr) {
176
0
    message.msg_control = nullptr;
177
0
    message.msg_controllen = 0;
178
0
    const Api::SysCallSizeResult result = os_syscalls.sendmsg(fd_, &message, flags);
179
0
    return sysCallResultToIoCallResult(result);
180
0
  } 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
0
}
228
229
Address::InstanceConstSharedPtr
230
0
maybeGetDstAddressFromHeader(const cmsghdr& cmsg, uint32_t self_port, os_fd_t fd, bool v6only) {
231
0
  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
0
  if (cmsg.cmsg_type == messageTypeContainsIP()) {
243
0
    sockaddr_storage ss;
244
0
    auto ipv4_addr = reinterpret_cast<sockaddr_in*>(&ss);
245
0
    memset(ipv4_addr, 0, sizeof(sockaddr_in));
246
0
    ipv4_addr->sin_family = AF_INET;
247
0
    ipv4_addr->sin_addr = addressFromMessage(cmsg);
248
0
    ipv4_addr->sin_port = htons(self_port);
249
0
    return Address::addressFromSockAddrOrDie(ss, sizeof(sockaddr_in), fd, v6only);
250
0
  }
251
252
0
  return nullptr;
253
0
}
254
255
0
absl::optional<uint32_t> maybeGetPacketsDroppedFromHeader([[maybe_unused]] const cmsghdr& cmsg) {
256
0
#ifdef SO_RXQ_OVFL
257
0
  if (cmsg.cmsg_type == SO_RXQ_OVFL) {
258
0
    return *reinterpret_cast<const uint32_t*>(CMSG_DATA(&cmsg));
259
0
  }
260
0
#endif
261
0
  return absl::nullopt;
262
0
}
263
264
Api::IoCallUint64Result IoSocketHandleImpl::recvmsg(Buffer::RawSlice* slices,
265
                                                    const uint64_t num_slice, uint32_t self_port,
266
0
                                                    RecvMsgOutput& output) {
267
0
  ASSERT(!output.msg_.empty());
268
269
0
  absl::FixedArray<char> cbuf(cmsg_space_);
270
0
  memset(cbuf.begin(), 0, cmsg_space_);
271
272
0
  absl::FixedArray<iovec> iov(num_slice);
273
0
  uint64_t num_slices_for_read = 0;
274
0
  for (uint64_t i = 0; i < num_slice; i++) {
275
0
    if (slices[i].mem_ != nullptr && slices[i].len_ != 0) {
276
0
      iov[num_slices_for_read].iov_base = slices[i].mem_;
277
0
      iov[num_slices_for_read].iov_len = slices[i].len_;
278
0
      ++num_slices_for_read;
279
0
    }
280
0
  }
281
0
  if (num_slices_for_read == 0) {
282
0
    return Api::ioCallUint64ResultNoError();
283
0
  }
284
285
0
  sockaddr_storage peer_addr;
286
0
  msghdr hdr;
287
0
  hdr.msg_name = &peer_addr;
288
0
  hdr.msg_namelen = sizeof(sockaddr_storage);
289
0
  hdr.msg_iov = iov.begin();
290
0
  hdr.msg_iovlen = num_slices_for_read;
291
0
  hdr.msg_flags = 0;
292
0
  hdr.msg_control = cbuf.begin();
293
0
  hdr.msg_controllen = cmsg_space_;
294
0
  Api::SysCallSizeResult result =
295
0
      Api::OsSysCallsSingleton::get().recvmsg(fd_, &hdr, messageTruncatedOption());
296
0
  if (result.return_value_ < 0) {
297
0
    return sysCallResultToIoCallResult(result);
298
0
  }
299
0
  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
0
  RELEASE_ASSERT((hdr.msg_flags & MSG_CTRUNC) == 0,
308
0
                 fmt::format("Incorrectly set control message length: {}", hdr.msg_controllen));
309
0
  RELEASE_ASSERT(hdr.msg_namelen > 0,
310
0
                 fmt::format("Unable to get remote address from recvmsg() for fd: {}", fd_));
311
0
  output.msg_[0].peer_address_ = Address::addressFromSockAddrOrDie(
312
0
      peer_addr, hdr.msg_namelen, fd_, socket_v6only_ || !udp_read_normalize_addresses_);
313
0
  output.msg_[0].gso_size_ = 0;
314
315
0
  if (hdr.msg_controllen > 0) {
316
    // Get overflow, local address and gso_size from control message.
317
0
    for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr); cmsg != nullptr;
318
0
         cmsg = CMSG_NXTHDR(&hdr, cmsg)) {
319
320
0
      if (output.msg_[0].local_address_ == nullptr) {
321
0
        Address::InstanceConstSharedPtr addr = maybeGetDstAddressFromHeader(
322
0
            *cmsg, self_port, fd_, socket_v6only_ || !udp_read_normalize_addresses_);
323
0
        if (addr != nullptr) {
324
          // This is a IP packet info message.
325
0
          output.msg_[0].local_address_ = std::move(addr);
326
0
          continue;
327
0
        }
328
0
      }
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
0
  }
343
344
0
  return sysCallResultToIoCallResult(result);
345
0
}
346
347
Api::IoCallUint64Result IoSocketHandleImpl::recvmmsg(RawSliceArrays& slices, uint32_t self_port,
348
0
                                                     RecvMsgOutput& output) {
349
0
  ASSERT(output.msg_.size() == slices.size());
350
0
  if (slices.empty()) {
351
0
    return sysCallResultToIoCallResult(Api::SysCallIntResult{0, SOCKET_ERROR_AGAIN});
352
0
  }
353
0
  const uint32_t num_packets_per_mmsg_call = slices.size();
354
0
  absl::FixedArray<mmsghdr> mmsg_hdr(num_packets_per_mmsg_call);
355
0
  absl::FixedArray<absl::FixedArray<struct iovec>> iovs(
356
0
      num_packets_per_mmsg_call, absl::FixedArray<struct iovec>(slices[0].size()));
357
0
  absl::FixedArray<sockaddr_storage> raw_addresses(num_packets_per_mmsg_call);
358
0
  absl::FixedArray<absl::FixedArray<char>> cbufs(num_packets_per_mmsg_call,
359
0
                                                 absl::FixedArray<char>(cmsg_space_));
360
361
0
  for (uint32_t i = 0; i < num_packets_per_mmsg_call; ++i) {
362
0
    memset(&raw_addresses[i], 0, sizeof(sockaddr_storage));
363
0
    memset(cbufs[i].data(), 0, cbufs[i].size());
364
365
0
    mmsg_hdr[i].msg_len = 0;
366
367
0
    msghdr* hdr = &mmsg_hdr[i].msg_hdr;
368
0
    hdr->msg_name = &raw_addresses[i];
369
0
    hdr->msg_namelen = sizeof(sockaddr_storage);
370
0
    ASSERT(!slices[i].empty());
371
372
0
    for (size_t j = 0; j < slices[i].size(); ++j) {
373
0
      iovs[i][j].iov_base = slices[i][j].mem_;
374
0
      iovs[i][j].iov_len = slices[i][j].len_;
375
0
    }
376
0
    hdr->msg_iov = iovs[i].data();
377
0
    hdr->msg_iovlen = slices[i].size();
378
0
    hdr->msg_control = cbufs[i].data();
379
0
    hdr->msg_controllen = cbufs[i].size();
380
0
  }
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
0
  const Api::SysCallIntResult result =
386
0
      Api::OsSysCallsSingleton::get().recvmmsg(fd_, mmsg_hdr.data(), num_packets_per_mmsg_call,
387
0
                                               messageTruncatedOption() | MSG_WAITFORONE, nullptr);
388
389
0
  if (result.return_value_ <= 0) {
390
0
    return sysCallResultToIoCallResult(result);
391
0
  }
392
393
0
  int num_packets_read = result.return_value_;
394
395
0
  for (int i = 0; i < num_packets_read; ++i) {
396
0
    msghdr& hdr = mmsg_hdr[i].msg_hdr;
397
0
    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
0
    RELEASE_ASSERT((hdr.msg_flags & MSG_CTRUNC) == 0,
405
0
                   fmt::format("Incorrectly set control message length: {}", hdr.msg_controllen));
406
0
    RELEASE_ASSERT(hdr.msg_namelen > 0,
407
0
                   fmt::format("Unable to get remote address from recvmmsg() for fd: {}", fd_));
408
409
0
    output.msg_[i].msg_len_ = mmsg_hdr[i].msg_len;
410
    // Get local and peer addresses for each packet.
411
0
    output.msg_[i].peer_address_ = Address::addressFromSockAddrOrDie(
412
0
        raw_addresses[i], hdr.msg_namelen, fd_, socket_v6only_ || !udp_read_normalize_addresses_);
413
0
    if (hdr.msg_controllen > 0) {
414
0
      struct cmsghdr* cmsg;
415
0
      for (cmsg = CMSG_FIRSTHDR(&hdr); cmsg != nullptr; cmsg = CMSG_NXTHDR(&hdr, cmsg)) {
416
0
        Address::InstanceConstSharedPtr addr = maybeGetDstAddressFromHeader(
417
0
            *cmsg, self_port, fd_, socket_v6only_ || !udp_read_normalize_addresses_);
418
0
        if (addr != nullptr) {
419
          // This is a IP packet info message.
420
0
          output.msg_[i].local_address_ = std::move(addr);
421
0
          break;
422
0
        }
423
0
      }
424
0
    }
425
0
  }
426
  // Get overflow from first packet header.
427
0
  if (output.dropped_packets_ != nullptr) {
428
0
    msghdr& hdr = mmsg_hdr[0].msg_hdr;
429
0
    if (hdr.msg_controllen > 0) {
430
0
      struct cmsghdr* cmsg;
431
0
      for (cmsg = CMSG_FIRSTHDR(&hdr); cmsg != nullptr; cmsg = CMSG_NXTHDR(&hdr, cmsg)) {
432
0
        absl::optional<uint32_t> maybe_dropped = maybeGetPacketsDroppedFromHeader(*cmsg);
433
0
        if (maybe_dropped) {
434
0
          *output.dropped_packets_ += *maybe_dropped;
435
0
        }
436
0
      }
437
0
    }
438
0
  }
439
0
  return sysCallResultToIoCallResult(result);
440
0
}
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
26.4k
Api::SysCallIntResult IoSocketHandleImpl::bind(Address::InstanceConstSharedPtr address) {
449
26.4k
  return Api::OsSysCallsSingleton::get().bind(fd_, address->sockAddr(), address->sockAddrLen());
450
26.4k
}
451
452
7.97k
Api::SysCallIntResult IoSocketHandleImpl::listen(int backlog) {
453
7.97k
  return Api::OsSysCallsSingleton::get().listen(fd_, backlog);
454
7.97k
}
455
456
13.9k
IoHandlePtr IoSocketHandleImpl::accept(struct sockaddr* addr, socklen_t* addrlen) {
457
13.9k
  auto result = Api::OsSysCallsSingleton::get().accept(fd_, addr, addrlen);
458
13.9k
  if (SOCKET_INVALID(result.return_value_)) {
459
6.96k
    return nullptr;
460
6.96k
  }
461
6.99k
  return SocketInterfaceImpl::makePlatformSpecificSocket(result.return_value_, socket_v6only_,
462
6.99k
                                                         domain_);
463
13.9k
}
464
465
7.60k
Api::SysCallIntResult IoSocketHandleImpl::connect(Address::InstanceConstSharedPtr address) {
466
7.60k
  auto sockaddr_to_use = address->sockAddr();
467
7.60k
  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
7.60k
  return Api::OsSysCallsSingleton::get().connect(fd_, sockaddr_to_use, sockaddr_len_to_use);
493
7.60k
}
494
495
38
IoHandlePtr IoSocketHandleImpl::duplicate() {
496
38
  auto result = Api::OsSysCallsSingleton::get().duplicate(fd_);
497
38
  RELEASE_ASSERT(result.return_value_ != -1,
498
38
                 fmt::format("duplicate failed for '{}': ({}) {}", fd_, result.errno_,
499
38
                             errorDetails(result.errno_)));
500
38
  return SocketInterfaceImpl::makePlatformSpecificSocket(result.return_value_, socket_v6only_,
501
38
                                                         domain_);
502
38
}
503
504
void IoSocketHandleImpl::initializeFileEvent(Event::Dispatcher& dispatcher, Event::FileReadyCb cb,
505
22.5k
                                             Event::FileTriggerType trigger, uint32_t events) {
506
22.5k
  ASSERT(file_event_ == nullptr, "Attempting to initialize two `file_event_` for the same "
507
22.5k
                                 "file descriptor. This is not allowed.");
508
22.5k
  file_event_ = dispatcher.createFileEvent(fd_, cb, trigger, events);
509
22.5k
}
510
511
46.9k
void IoSocketHandleImpl::activateFileEvents(uint32_t events) {
512
46.9k
  if (file_event_) {
513
46.9k
    file_event_->activate(events);
514
18.4E
  } else {
515
18.4E
    ENVOY_BUG(false, "Null file_event_");
516
18.4E
  }
517
46.9k
}
518
519
831
void IoSocketHandleImpl::enableFileEvents(uint32_t events) {
520
831
  if (file_event_) {
521
831
    file_event_->setEnabled(events);
522
831
  } else {
523
0
    ENVOY_BUG(false, "Null file_event_");
524
0
  }
525
831
}
526
527
46
Api::SysCallIntResult IoSocketHandleImpl::shutdown(int how) {
528
46
  return Api::OsSysCallsSingleton::get().shutdown(fd_, how);
529
46
}
530
531
} // namespace Network
532
} // namespace Envoy