Line data Source code
1 : #include "io_socket_handle_base_impl.h"
2 :
3 : #include "envoy/buffer/buffer.h"
4 : #include "envoy/common/exception.h"
5 : #include "envoy/event/dispatcher.h"
6 :
7 : #include "source/common/api/os_sys_calls_impl.h"
8 : #include "source/common/common/assert.h"
9 : #include "source/common/common/utility.h"
10 : #include "source/common/network/address_impl.h"
11 : #include "source/common/network/io_socket_error_impl.h"
12 : #include "source/common/network/io_socket_handle_impl.h"
13 : #include "source/common/network/socket_interface_impl.h"
14 :
15 : namespace Envoy {
16 : namespace Network {
17 :
18 : IoSocketHandleBaseImpl::IoSocketHandleBaseImpl(os_fd_t fd, bool socket_v6only,
19 : absl::optional<int> domain)
20 7792 : : fd_(fd), socket_v6only_(socket_v6only), domain_(domain) {}
21 :
22 7792 : IoSocketHandleBaseImpl::~IoSocketHandleBaseImpl() {
23 7792 : if (SOCKET_VALID(fd_)) {
24 : // The TLS slot has been shut down by this moment with IoUring wiped out, thus
25 : // better use this posix system call instead of IoSocketHandleBaseImpl::close().
26 0 : ::close(fd_);
27 0 : }
28 7792 : }
29 :
30 47837 : bool IoSocketHandleBaseImpl::isOpen() const { return SOCKET_VALID(fd_); }
31 :
32 330 : bool IoSocketHandleBaseImpl::supportsMmsg() const {
33 330 : return Api::OsSysCallsSingleton::get().supportsMmsg();
34 330 : }
35 :
36 26 : bool IoSocketHandleBaseImpl::supportsUdpGro() const {
37 26 : return Api::OsSysCallsSingleton::get().supportsUdpGro();
38 26 : }
39 :
40 : Api::SysCallIntResult IoSocketHandleBaseImpl::setOption(int level, int optname, const void* optval,
41 3958 : socklen_t optlen) {
42 3958 : return Api::OsSysCallsSingleton::get().setsockopt(fd_, level, optname, optval, optlen);
43 3958 : }
44 :
45 : Api::SysCallIntResult IoSocketHandleBaseImpl::getOption(int level, int optname, void* optval,
46 1178 : socklen_t* optlen) {
47 1178 : return Api::OsSysCallsSingleton::get().getsockopt(fd_, level, optname, optval, optlen);
48 1178 : }
49 :
50 : Api::SysCallIntResult IoSocketHandleBaseImpl::ioctl(unsigned long control_code, void* in_buffer,
51 : unsigned long in_buffer_len, void* out_buffer,
52 : unsigned long out_buffer_len,
53 0 : unsigned long* bytes_returned) {
54 0 : return Api::OsSysCallsSingleton::get().ioctl(fd_, control_code, in_buffer, in_buffer_len,
55 0 : out_buffer, out_buffer_len, bytes_returned);
56 0 : }
57 :
58 91 : Api::SysCallIntResult IoSocketHandleBaseImpl::setBlocking(bool blocking) {
59 91 : return Api::OsSysCallsSingleton::get().setsocketblocking(fd_, blocking);
60 91 : }
61 :
62 0 : absl::optional<int> IoSocketHandleBaseImpl::domain() { return domain_; }
63 :
64 2125 : Address::InstanceConstSharedPtr IoSocketHandleBaseImpl::localAddress() {
65 2125 : sockaddr_storage ss;
66 2125 : socklen_t ss_len = sizeof(ss);
67 2125 : memset(&ss, 0, ss_len);
68 2125 : auto& os_sys_calls = Api::OsSysCallsSingleton::get();
69 2125 : Api::SysCallIntResult result =
70 2125 : os_sys_calls.getsockname(fd_, reinterpret_cast<sockaddr*>(&ss), &ss_len);
71 2125 : if (result.return_value_ != 0) {
72 0 : throwEnvoyExceptionOrPanic(fmt::format("getsockname failed for '{}': ({}) {}", fd_,
73 0 : result.errno_, errorDetails(result.errno_)));
74 0 : }
75 2125 : return Address::addressFromSockAddrOrThrow(ss, ss_len, socket_v6only_);
76 2125 : }
77 :
78 0 : Address::InstanceConstSharedPtr IoSocketHandleBaseImpl::peerAddress() {
79 0 : sockaddr_storage ss;
80 0 : socklen_t ss_len = sizeof(ss);
81 0 : memset(&ss, 0, ss_len);
82 0 : auto& os_sys_calls = Api::OsSysCallsSingleton::get();
83 0 : Api::SysCallIntResult result =
84 0 : os_sys_calls.getpeername(fd_, reinterpret_cast<sockaddr*>(&ss), &ss_len);
85 0 : if (result.return_value_ != 0) {
86 0 : throwEnvoyExceptionOrPanic(
87 0 : fmt::format("getpeername failed for '{}': {}", fd_, errorDetails(result.errno_)));
88 0 : }
89 :
90 0 : if (static_cast<unsigned int>(ss_len) >=
91 0 : (offsetof(sockaddr_storage, ss_family) + sizeof(ss.ss_family)) &&
92 0 : ss.ss_family == AF_UNIX) {
93 : // For Unix domain sockets, can't find out the peer name, but it should match our own
94 : // name for the socket (i.e. the path should match, barring any namespace or other
95 : // mechanisms to hide things, of which there are many).
96 0 : ss_len = sizeof(ss);
97 0 : result = os_sys_calls.getsockname(fd_, reinterpret_cast<sockaddr*>(&ss), &ss_len);
98 0 : if (result.return_value_ != 0) {
99 0 : throwEnvoyExceptionOrPanic(
100 0 : fmt::format("getsockname failed for '{}': {}", fd_, errorDetails(result.errno_)));
101 0 : }
102 0 : }
103 0 : return Address::addressFromSockAddrOrThrow(ss, ss_len, socket_v6only_);
104 0 : }
105 :
106 1315 : absl::optional<std::chrono::milliseconds> IoSocketHandleBaseImpl::lastRoundTripTime() {
107 1315 : Api::EnvoyTcpInfo info;
108 1315 : auto result = Api::OsSysCallsSingleton::get().socketTcpInfo(fd_, &info);
109 1315 : if (!result.return_value_) {
110 0 : return {};
111 0 : }
112 1315 : return std::chrono::duration_cast<std::chrono::milliseconds>(info.tcpi_rtt);
113 1315 : }
114 :
115 0 : absl::optional<uint64_t> IoSocketHandleBaseImpl::congestionWindowInBytes() const {
116 0 : Api::EnvoyTcpInfo info;
117 0 : auto result = Api::OsSysCallsSingleton::get().socketTcpInfo(fd_, &info);
118 0 : if (!result.return_value_) {
119 0 : return {};
120 0 : }
121 0 : return info.tcpi_snd_cwnd;
122 0 : }
123 :
124 0 : absl::optional<std::string> IoSocketHandleBaseImpl::interfaceName() {
125 0 : auto& os_syscalls_singleton = Api::OsSysCallsSingleton::get();
126 0 : if (!os_syscalls_singleton.supportsGetifaddrs()) {
127 0 : return absl::nullopt;
128 0 : }
129 :
130 0 : Address::InstanceConstSharedPtr socket_address = localAddress();
131 0 : if (!socket_address || socket_address->type() != Address::Type::Ip) {
132 0 : return absl::nullopt;
133 0 : }
134 :
135 0 : Api::InterfaceAddressVector interface_addresses{};
136 0 : const Api::SysCallIntResult rc = os_syscalls_singleton.getifaddrs(interface_addresses);
137 0 : RELEASE_ASSERT(!rc.return_value_, fmt::format("getifaddrs error: {}", rc.errno_));
138 :
139 0 : absl::optional<std::string> selected_interface_name{};
140 0 : for (const auto& interface_address : interface_addresses) {
141 0 : if (!interface_address.interface_addr_) {
142 0 : continue;
143 0 : }
144 :
145 0 : if (socket_address->ip()->version() == interface_address.interface_addr_->ip()->version()) {
146 : // Compare address _without port_.
147 : // TODO: create common addressAsStringWithoutPort method to simplify code here.
148 0 : absl::uint128 socket_address_value;
149 0 : absl::uint128 interface_address_value;
150 0 : switch (socket_address->ip()->version()) {
151 0 : case Address::IpVersion::v4:
152 0 : socket_address_value = socket_address->ip()->ipv4()->address();
153 0 : interface_address_value = interface_address.interface_addr_->ip()->ipv4()->address();
154 0 : break;
155 0 : case Address::IpVersion::v6:
156 0 : socket_address_value = socket_address->ip()->ipv6()->address();
157 0 : interface_address_value = interface_address.interface_addr_->ip()->ipv6()->address();
158 0 : break;
159 0 : default:
160 0 : ENVOY_BUG(false, fmt::format("unexpected IP family {}",
161 0 : static_cast<int>(socket_address->ip()->version())));
162 0 : }
163 :
164 0 : if (socket_address_value == interface_address_value) {
165 0 : selected_interface_name = interface_address.interface_name_;
166 0 : break;
167 0 : }
168 0 : }
169 0 : }
170 :
171 0 : return selected_interface_name;
172 0 : }
173 :
174 : } // namespace Network
175 : } // namespace Envoy
|