Branch data Line data Source code
1 : : // Copyright (c) 2020-present The Bitcoin Core developers
2 : : // Distributed under the MIT software license, see the accompanying
3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 : :
5 : : #include <util/sock.h>
6 : :
7 : : #include <compat/compat.h>
8 : : #include <span.h>
9 : : #include <tinyformat.h>
10 : : #include <util/check.h>
11 : : #include <util/log.h>
12 : : #include <util/syserror.h>
13 : : #include <util/threadinterrupt.h>
14 : : #include <util/time.h>
15 : :
16 : : #include <algorithm>
17 : : #include <compare>
18 : : #include <exception>
19 : : #include <limits>
20 : : #include <memory>
21 : : #include <stdexcept>
22 : : #include <string>
23 : : #include <utility>
24 : : #include <vector>
25 : :
26 : : #ifdef USE_POLL
27 : : #include <poll.h>
28 : : #endif
29 : :
30 : 62 : Sock::Sock(SOCKET s) : m_socket(s) {}
31 : :
32 : 3 : Sock::Sock(Sock&& other)
33 : : {
34 : 3 : m_socket = other.m_socket;
35 : 3 : other.m_socket = INVALID_SOCKET;
36 : 3 : }
37 : :
38 : 74 : Sock::~Sock() { Close(); }
39 : :
40 : 4 : Sock& Sock::operator=(Sock&& other)
41 : : {
42 : 4 : Close();
43 : 4 : m_socket = other.m_socket;
44 : 4 : other.m_socket = INVALID_SOCKET;
45 : 4 : return *this;
46 : : }
47 : :
48 : 5 : ssize_t Sock::Send(const void* data, size_t len, int flags) const
49 : : {
50 : 5 : return send(m_socket, static_cast<const char*>(data), len, flags);
51 : : }
52 : :
53 : 4 : ssize_t Sock::Recv(void* buf, size_t len, int flags) const
54 : : {
55 [ + - ]: 4 : return recv(m_socket, static_cast<char*>(buf), len, flags);
56 : : }
57 : :
58 : 4 : int Sock::Connect(const sockaddr* addr, socklen_t addr_len) const
59 : : {
60 : 4 : return connect(m_socket, addr, addr_len);
61 : : }
62 : :
63 : 3 : int Sock::Bind(const sockaddr* addr, socklen_t addr_len) const
64 : : {
65 : 3 : return bind(m_socket, addr, addr_len);
66 : : }
67 : :
68 : 3 : int Sock::Listen(int backlog) const
69 : : {
70 : 3 : return listen(m_socket, backlog);
71 : : }
72 : :
73 : 3 : std::unique_ptr<Sock> Sock::Accept(sockaddr* addr, socklen_t* addr_len) const
74 : : {
75 : : #ifdef WIN32
76 : : static constexpr auto accept_error = INVALID_SOCKET;
77 : : #else
78 : 3 : static constexpr auto accept_error = SOCKET_ERROR;
79 : : #endif
80 : :
81 : 3 : std::unique_ptr<Sock> sock;
82 : :
83 [ + - ]: 3 : const auto socket = accept(m_socket, addr, addr_len);
84 [ + - ]: 3 : if (socket != accept_error) {
85 : 3 : try {
86 [ + - ]: 6 : sock = std::make_unique<Sock>(socket);
87 [ - - ]: 0 : } catch (const std::exception&) {
88 : : #ifdef WIN32
89 : : closesocket(socket);
90 : : #else
91 [ - - ]: 0 : close(socket);
92 : : #endif
93 : 0 : }
94 : : }
95 : :
96 : 3 : return sock;
97 : 0 : }
98 : :
99 : 1 : int Sock::GetSockOpt(int level, int opt_name, void* opt_val, socklen_t* opt_len) const
100 : : {
101 : 1 : return getsockopt(m_socket, level, opt_name, static_cast<char*>(opt_val), opt_len);
102 : : }
103 : :
104 : 1 : int Sock::SetSockOpt(int level, int opt_name, const void* opt_val, socklen_t opt_len) const
105 : : {
106 : 1 : return setsockopt(m_socket, level, opt_name, static_cast<const char*>(opt_val), opt_len);
107 : : }
108 : :
109 : 3 : int Sock::GetSockName(sockaddr* name, socklen_t* name_len) const
110 : : {
111 : 3 : return getsockname(m_socket, name, name_len);
112 : : }
113 : :
114 : 1 : bool Sock::SetNonBlocking() const
115 : : {
116 : : #ifdef WIN32
117 : : u_long on{1};
118 : : if (ioctlsocket(m_socket, FIONBIO, &on) == SOCKET_ERROR) {
119 : : return false;
120 : : }
121 : : #else
122 : 1 : const int flags{fcntl(m_socket, F_GETFL, 0)};
123 [ + - ]: 1 : if (flags == SOCKET_ERROR) {
124 : : return false;
125 : : }
126 [ - + ]: 1 : if (fcntl(m_socket, F_SETFL, flags | O_NONBLOCK) == SOCKET_ERROR) {
127 : 0 : return false;
128 : : }
129 : : #endif
130 : : return true;
131 : : }
132 : :
133 : 1 : bool Sock::IsSelectable() const
134 : : {
135 : : #if defined(USE_POLL) || defined(WIN32)
136 : 1 : return true;
137 : : #else
138 : : return m_socket < FD_SETSIZE;
139 : : #endif
140 : : }
141 : :
142 : 3 : bool Sock::Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred) const
143 : : {
144 : : // We need a `shared_ptr` holding `this` for `WaitMany()`, but don't want
145 : : // `this` to be destroyed when the `shared_ptr` goes out of scope at the
146 : : // end of this function.
147 : : // Create it with an aliasing shared_ptr that points to `this` without
148 : : // owning it.
149 [ - + ]: 3 : std::shared_ptr<const Sock> shared{std::shared_ptr<const Sock>{}, this};
150 : :
151 [ - + + + : 9 : EventsPerSock events_per_sock{std::make_pair(shared, Events{requested})};
- + - - -
- ]
152 : :
153 [ + - + - ]: 3 : if (!WaitMany(timeout, events_per_sock)) {
154 : : return false;
155 : : }
156 : :
157 [ + + ]: 3 : if (occurred != nullptr) {
158 : 1 : *occurred = events_per_sock.begin()->second.occurred;
159 : : }
160 : :
161 : : return true;
162 [ - + ]: 6 : }
163 : :
164 : 3 : bool Sock::WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock) const
165 : : {
166 : : // poll() takes the timeout as an int and select() rejects very large values on
167 : : // some systems (e.g. macOS), so cap it at INT_MAX milliseconds (~24.8 days).
168 : 3 : timeout = std::min(timeout, std::chrono::milliseconds{std::numeric_limits<int>::max()});
169 : :
170 : : #ifdef USE_POLL
171 : 3 : std::vector<pollfd> pfds;
172 [ + + + - ]: 6 : for (const auto& [sock, events] : events_per_sock) {
173 [ + - ]: 3 : pfds.emplace_back();
174 : 3 : auto& pfd = pfds.back();
175 [ + - ]: 3 : pfd.fd = sock->m_socket;
176 [ + - ]: 3 : if (events.requested & RecvEvent) {
177 : 3 : pfd.events |= POLLIN;
178 : : }
179 [ + + ]: 3 : if (events.requested & SendEvent) {
180 : 1 : pfd.events |= POLLOUT;
181 : : }
182 : : }
183 : :
184 [ - + + - : 6 : if (poll(pfds.data(), pfds.size(), count_milliseconds(timeout)) == SOCKET_ERROR) {
+ - ]
185 : : return false;
186 : : }
187 : :
188 [ - + - + ]: 3 : assert(pfds.size() == events_per_sock.size());
189 : 3 : size_t i{0};
190 [ + + - + ]: 6 : for (auto& [sock, events] : events_per_sock) {
191 [ - + ]: 3 : assert(sock->m_socket == static_cast<SOCKET>(pfds[i].fd));
192 : 3 : events.occurred = 0;
193 [ + - ]: 3 : if (pfds[i].revents & POLLIN) {
194 : 3 : events.occurred |= RecvEvent;
195 : : }
196 [ + + ]: 3 : if (pfds[i].revents & POLLOUT) {
197 : 1 : events.occurred |= SendEvent;
198 : : }
199 [ + + ]: 3 : if (pfds[i].revents & (POLLERR | POLLHUP)) {
200 : 1 : events.occurred |= ErrorEvent;
201 : : }
202 : 3 : ++i;
203 : : }
204 : :
205 : : return true;
206 : : #else
207 : : fd_set recv;
208 : : fd_set send;
209 : : fd_set err;
210 : : FD_ZERO(&recv);
211 : : FD_ZERO(&send);
212 : : FD_ZERO(&err);
213 : : SOCKET socket_max{0};
214 : :
215 : : for (const auto& [sock, events] : events_per_sock) {
216 : : if (!sock->IsSelectable()) {
217 : : return false;
218 : : }
219 : : const auto& s = sock->m_socket;
220 : : if (events.requested & RecvEvent) {
221 : : FD_SET(s, &recv);
222 : : }
223 : : if (events.requested & SendEvent) {
224 : : FD_SET(s, &send);
225 : : }
226 : : FD_SET(s, &err);
227 : : socket_max = std::max(socket_max, s);
228 : : }
229 : :
230 : : timeval tv = MillisToTimeval(timeout);
231 : :
232 : : if (select(socket_max + 1, &recv, &send, &err, &tv) == SOCKET_ERROR) {
233 : : return false;
234 : : }
235 : :
236 : : for (auto& [sock, events] : events_per_sock) {
237 : : const auto& s = sock->m_socket;
238 : : events.occurred = 0;
239 : : if (FD_ISSET(s, &recv)) {
240 : : events.occurred |= RecvEvent;
241 : : }
242 : : if (FD_ISSET(s, &send)) {
243 : : events.occurred |= SendEvent;
244 : : }
245 : : if (FD_ISSET(s, &err)) {
246 : : events.occurred |= ErrorEvent;
247 : : }
248 : : }
249 : :
250 : : return true;
251 : : #endif /* USE_POLL */
252 : 3 : }
253 : :
254 : 34 : void Sock::SendComplete(std::span<const unsigned char> data,
255 : : std::chrono::milliseconds timeout,
256 : : CThreadInterrupt& interrupt) const
257 : : {
258 : 34 : const auto deadline = GetTime<std::chrono::milliseconds>() + timeout;
259 : 34 : size_t sent{0};
260 : :
261 : 34 : for (;;) {
262 : 34 : const ssize_t ret{Send(data.data() + sent, data.size() - sent, MSG_NOSIGNAL)};
263 : :
264 [ + - ]: 34 : if (ret > 0) {
265 : 34 : sent += static_cast<size_t>(ret);
266 [ - + ]: 34 : if (sent == data.size()) {
267 : : break;
268 : : }
269 : : } else {
270 : 0 : const int err{WSAGetLastError()};
271 [ # # ]: 0 : if (IOErrorIsPermanent(err)) {
272 [ # # # # : 0 : throw std::runtime_error(strprintf("send(): %s", NetworkErrorString(err)));
# # ]
273 : : }
274 : : }
275 : :
276 : 0 : const auto now = GetTime<std::chrono::milliseconds>();
277 : :
278 [ # # ]: 0 : if (now >= deadline) {
279 [ # # ]: 0 : throw std::runtime_error(strprintf(
280 [ # # # # ]: 0 : "Send timeout (sent only %u of %u bytes before that)", sent, data.size()));
281 : : }
282 : :
283 [ # # ]: 0 : if (interrupt) {
284 [ # # ]: 0 : throw std::runtime_error(strprintf(
285 [ # # # # ]: 0 : "Send interrupted (sent only %u of %u bytes before that)", sent, data.size()));
286 : : }
287 : :
288 : : // Wait for a short while (or the socket to become ready for sending) before retrying
289 : : // if nothing was sent.
290 : 0 : const auto wait_time = std::min(deadline - now, std::chrono::milliseconds{MAX_WAIT_FOR_IO});
291 : 0 : (void)Wait(wait_time, SendEvent);
292 : 0 : }
293 : 34 : }
294 : :
295 : 34 : void Sock::SendComplete(std::span<const char> data,
296 : : std::chrono::milliseconds timeout,
297 : : CThreadInterrupt& interrupt) const
298 : : {
299 : 34 : SendComplete(MakeUCharSpan(data), timeout, interrupt);
300 : 34 : }
301 : :
302 : 38 : std::string Sock::RecvUntilTerminator(uint8_t terminator,
303 : : std::chrono::milliseconds timeout,
304 : : CThreadInterrupt& interrupt,
305 : : size_t max_data) const
306 : : {
307 : 38 : const auto deadline = GetTime<std::chrono::milliseconds>() + timeout;
308 : 38 : std::string data;
309 : 38 : bool terminator_found{false};
310 : :
311 : : // We must not consume any bytes past the terminator from the socket.
312 : : // One option is to read one byte at a time and check if we have read a terminator.
313 : : // However that is very slow. Instead, we peek at what is in the socket and only read
314 : : // as many bytes as possible without crossing the terminator.
315 : : // Reading 64 MiB of random data with 262526 terminator chars takes 37 seconds to read
316 : : // one byte at a time VS 0.71 seconds with the "peek" solution below. Reading one byte
317 : : // at a time is about 50 times slower.
318 : :
319 : 169 : for (;;) {
320 [ - + + + ]: 169 : if (data.size() >= max_data) {
321 : 2 : throw std::runtime_error(
322 [ - + + - : 4 : strprintf("Received too many bytes without a terminator (%u)", data.size()));
+ - ]
323 : : }
324 : :
325 : 167 : char buf[512];
326 : :
327 [ + + + - ]: 333 : const ssize_t peek_ret{Recv(buf, std::min(sizeof(buf), max_data - data.size()), MSG_PEEK)};
328 : :
329 [ - - + ]: 167 : switch (peek_ret) {
330 : 0 : case -1: {
331 : 0 : const int err{WSAGetLastError()};
332 [ # # ]: 0 : if (IOErrorIsPermanent(err)) {
333 [ # # # # : 0 : throw std::runtime_error(strprintf("recv(): %s", NetworkErrorString(err)));
# # ]
334 : : }
335 : : break;
336 : : }
337 : 0 : case 0:
338 [ # # ]: 0 : throw std::runtime_error("Connection unexpectedly closed by peer");
339 : 167 : default:
340 : 167 : auto end = buf + peek_ret;
341 : 167 : auto terminator_pos = std::find(buf, end, terminator);
342 : 167 : terminator_found = terminator_pos != end;
343 : :
344 [ + + ]: 167 : const size_t try_len{terminator_found ? terminator_pos - buf + 1 :
345 : : static_cast<size_t>(peek_ret)};
346 : :
347 [ + - ]: 167 : const ssize_t read_ret{Recv(buf, try_len, 0)};
348 : :
349 [ + - - + ]: 167 : if (read_ret < 0 || static_cast<size_t>(read_ret) != try_len) {
350 : 0 : throw std::runtime_error(
351 [ # # ]: 0 : strprintf("recv() returned %u bytes on attempt to read %u bytes but previous "
352 : : "peek claimed %u bytes are available",
353 [ # # ]: 0 : read_ret, try_len, peek_ret));
354 : : }
355 : :
356 : : // Don't include the terminator in the output.
357 [ + + ]: 167 : const size_t append_len{terminator_found ? try_len - 1 : try_len};
358 : :
359 [ + - ]: 167 : data.append(buf, buf + append_len);
360 : :
361 [ + + ]: 167 : if (terminator_found) {
362 : 36 : return data;
363 : : }
364 : : }
365 : :
366 : 131 : const auto now = GetTime<std::chrono::milliseconds>();
367 : :
368 [ - + ]: 131 : if (now >= deadline) {
369 : 0 : throw std::runtime_error(strprintf(
370 [ # # # # : 0 : "Receive timeout (received %u bytes without terminator before that)", data.size()));
# # ]
371 : : }
372 : :
373 [ + - - + ]: 131 : if (interrupt) {
374 : 0 : throw std::runtime_error(strprintf(
375 : : "Receive interrupted (received %u bytes without terminator before that)",
376 [ # # # # : 0 : data.size()));
# # ]
377 : : }
378 : :
379 : : // Wait for a short while (or the socket to become ready for reading) before retrying.
380 [ + - ]: 131 : const auto wait_time = std::min(deadline - now, std::chrono::milliseconds{MAX_WAIT_FOR_IO});
381 [ + - ]: 131 : (void)Wait(wait_time, RecvEvent);
382 : : }
383 : 2 : }
384 : :
385 : 0 : bool Sock::IsConnected(std::string& errmsg) const
386 : : {
387 [ # # ]: 0 : if (m_socket == INVALID_SOCKET) {
388 : 0 : errmsg = "not connected";
389 : 0 : return false;
390 : : }
391 : :
392 : 0 : char c;
393 [ # # # ]: 0 : switch (Recv(&c, sizeof(c), MSG_PEEK)) {
394 : 0 : case -1: {
395 : 0 : const int err = WSAGetLastError();
396 [ # # ]: 0 : if (IOErrorIsPermanent(err)) {
397 : 0 : errmsg = NetworkErrorString(err);
398 : 0 : return false;
399 : : }
400 : : return true;
401 : : }
402 : 0 : case 0:
403 : 0 : errmsg = "closed";
404 : 0 : return false;
405 : : default:
406 : : return true;
407 : : }
408 : : }
409 : :
410 : 69 : void Sock::Close()
411 : : {
412 [ + + ]: 69 : if (m_socket == INVALID_SOCKET) {
413 : : return;
414 : : }
415 : : #ifdef WIN32
416 : : int ret = closesocket(m_socket);
417 : : #else
418 : 14 : int ret = close(m_socket);
419 : : #endif
420 [ - + ]: 14 : if (ret) {
421 [ # # ]: 0 : LogWarning("Error closing socket %d: %s", m_socket, NetworkErrorString(WSAGetLastError()));
422 : : }
423 : 14 : m_socket = INVALID_SOCKET;
424 : : }
425 : :
426 : 4 : bool Sock::operator==(SOCKET s) const
427 : : {
428 : 4 : return m_socket == s;
429 : : };
430 : :
431 : 2 : std::string NetworkErrorString(int err)
432 : : {
433 : : #if defined(WIN32)
434 : : return Win32ErrorString(err);
435 : : #else
436 : : // On BSD sockets implementations, NetworkErrorString is the same as SysErrorString.
437 : 2 : return SysErrorString(err);
438 : : #endif
439 : : }
|