/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 |