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
|