Bitcoin ABC 0.32.12
P2P Digital Currency
sock.cpp
Go to the documentation of this file.
1// Copyright (c) 2020-2021 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 <common/system.h>
8#include <compat/compat.h>
9#include <logging.h>
10#include <tinyformat.h>
11#include <util/syserror.h>
13#include <util/time.h>
14
15#include <codecvt>
16#include <cwchar>
17#include <locale>
18#include <memory>
19#include <stdexcept>
20#include <string>
21
22#ifdef USE_POLL
23#include <poll.h>
24#endif
25
26static inline bool IOErrorIsPermanent(int err) {
27 return err != WSAEAGAIN && err != WSAEINTR && err != WSAEWOULDBLOCK &&
28 err != WSAEINPROGRESS;
29}
30
31Sock::Sock(SOCKET s) : m_socket(s) {}
32
33Sock::Sock(Sock &&other) {
34 m_socket = other.m_socket;
35 other.m_socket = INVALID_SOCKET;
36}
37
39 Close();
40}
41
43 Close();
44 m_socket = other.m_socket;
45 other.m_socket = INVALID_SOCKET;
46 return *this;
47}
48
49ssize_t Sock::Send(const void *data, size_t len, int flags) const {
50 return send(m_socket, static_cast<const char *>(data), len, flags);
51}
52
53ssize_t Sock::Recv(void *buf, size_t len, int flags) const {
54 return recv(m_socket, static_cast<char *>(buf), len, flags);
55}
56
57int Sock::Connect(const sockaddr *addr, socklen_t addr_len) const {
58 return connect(m_socket, addr, addr_len);
59}
60
61int Sock::Bind(const sockaddr *addr, socklen_t addr_len) const {
62 return bind(m_socket, addr, addr_len);
63}
64
65int Sock::Listen(int backlog) const {
66 return listen(m_socket, backlog);
67}
68
69std::unique_ptr<Sock> Sock::Accept(sockaddr *addr, socklen_t *addr_len) const {
70#ifdef WIN32
71 static constexpr auto err = INVALID_SOCKET;
72#else
73 static constexpr auto err = SOCKET_ERROR;
74#endif
75
76 std::unique_ptr<Sock> sock;
77
78 const auto socket = accept(m_socket, addr, addr_len);
79 if (socket != err) {
80 try {
81 sock = std::make_unique<Sock>(socket);
82 } catch (const std::exception &) {
83#ifdef WIN32
84 closesocket(socket);
85#else
86 close(socket);
87#endif
88 }
89 }
90
91 return sock;
92}
93
94int Sock::GetSockOpt(int level, int opt_name, void *opt_val,
95 socklen_t *opt_len) const {
96 return getsockopt(m_socket, level, opt_name, static_cast<char *>(opt_val),
97 opt_len);
98}
99
100int Sock::SetSockOpt(int level, int opt_name, const void *opt_val,
101 socklen_t opt_len) const {
102 return setsockopt(m_socket, level, opt_name,
103 static_cast<const char *>(opt_val), opt_len);
104}
105
106int Sock::GetSockName(sockaddr *name, socklen_t *name_len) const {
107 return getsockname(m_socket, name, name_len);
108}
109
111#ifdef WIN32
112 u_long on{1};
113 if (ioctlsocket(m_socket, FIONBIO, &on) == SOCKET_ERROR) {
114 return false;
115 }
116#else
117 const int flags{fcntl(m_socket, F_GETFL, 0)};
118 if (flags == SOCKET_ERROR) {
119 return false;
120 }
121 if (fcntl(m_socket, F_SETFL, flags | O_NONBLOCK) == SOCKET_ERROR) {
122 return false;
123 }
124#endif
125 return true;
126}
127
128bool Sock::IsSelectable() const {
129#if defined(USE_POLL) || defined(WIN32)
130 return true;
131#else
132 return m_socket < FD_SETSIZE;
133#endif
134}
135
136bool Sock::Wait(std::chrono::milliseconds timeout, Event requested,
137 Event *occurred) const {
138 // We need a `shared_ptr` owning `this` for `WaitMany()`, but don't want
139 // `this` to be destroyed when the `shared_ptr` goes out of scope at the
140 // end of this function. Create it with a custom noop deleter.
141 std::shared_ptr<const Sock> shared{this, [](const Sock *) {}};
142
143 EventsPerSock events_per_sock{std::make_pair(shared, Events{requested})};
144
145 if (!WaitMany(timeout, events_per_sock)) {
146 return false;
147 }
148
149 if (occurred != nullptr) {
150 *occurred = events_per_sock.begin()->second.occurred;
151 }
152
153 return true;
154}
155
156bool Sock::WaitMany(std::chrono::milliseconds timeout,
157 EventsPerSock &events_per_sock) const {
158#ifdef USE_POLL
159 std::vector<pollfd> pfds;
160 for (const auto &[sock, events] : events_per_sock) {
161 pfds.emplace_back();
162 auto &pfd = pfds.back();
163 pfd.fd = sock->m_socket;
164 if (events.requested & RECV) {
165 pfd.events |= POLLIN;
166 }
167 if (events.requested & SEND) {
168 pfd.events |= POLLOUT;
169 }
170 }
171
172 if (poll(pfds.data(), pfds.size(), count_milliseconds(timeout)) ==
173 SOCKET_ERROR) {
174 return false;
175 }
176
177 assert(pfds.size() == events_per_sock.size());
178 size_t i{0};
179 for (auto &[sock, events] : events_per_sock) {
180 assert(sock->m_socket == static_cast<SOCKET>(pfds[i].fd));
181 events.occurred = 0;
182 if (pfds[i].revents & POLLIN) {
183 events.occurred |= RECV;
184 }
185 if (pfds[i].revents & POLLOUT) {
186 events.occurred |= SEND;
187 }
188 if (pfds[i].revents & (POLLERR | POLLHUP)) {
189 events.occurred |= ERR;
190 }
191 ++i;
192 }
193
194 return true;
195#else
196 fd_set recv;
197 fd_set send;
198 fd_set err;
199 FD_ZERO(&recv);
200 FD_ZERO(&send);
201 FD_ZERO(&err);
202 SOCKET socket_max{0};
203
204 for (const auto &[sock, events] : events_per_sock) {
205 if (!sock->IsSelectable()) {
206 return false;
207 }
208 const auto &s = sock->m_socket;
209 if (events.requested & RECV) {
210 FD_SET(s, &recv);
211 }
212 if (events.requested & SEND) {
213 FD_SET(s, &send);
214 }
215 FD_SET(s, &err);
216 socket_max = std::max(socket_max, s);
217 }
218
219 timeval tv = MillisToTimeval(timeout);
220
221 if (select(socket_max + 1, &recv, &send, &err, &tv) == SOCKET_ERROR) {
222 return false;
223 }
224
225 for (auto &[sock, events] : events_per_sock) {
226 const auto &s = sock->m_socket;
227 events.occurred = 0;
228 if (FD_ISSET(s, &recv)) {
229 events.occurred |= RECV;
230 }
231 if (FD_ISSET(s, &send)) {
232 events.occurred |= SEND;
233 }
234 if (FD_ISSET(s, &err)) {
235 events.occurred |= ERR;
236 }
237 }
238
239 return true;
240#endif /* USE_POLL */
241}
242
243// Used in the seeder only.
244int Sock::WaitReadableOrException(timeval *timeout) const {
245 fd_set fdsetRecv;
246 fd_set fdsetError;
247 FD_ZERO(&fdsetRecv);
248 FD_ZERO(&fdsetError);
249 FD_SET(m_socket, &fdsetRecv);
250 FD_SET(m_socket, &fdsetError);
251 return select(m_socket + 1, &fdsetRecv, nullptr, &fdsetError, timeout);
252}
253
254void Sock::SendComplete(const std::string &data,
255 std::chrono::milliseconds timeout,
256 CThreadInterrupt &interrupt) const {
257 const auto deadline = GetTime<std::chrono::milliseconds>() + timeout;
258 size_t sent{0};
259
260 for (;;) {
261 const ssize_t ret{
262 Send(data.data() + sent, data.size() - sent, MSG_NOSIGNAL)};
263
264 if (ret > 0) {
265 sent += static_cast<size_t>(ret);
266 if (sent == data.size()) {
267 break;
268 }
269 } else {
270 const int err{WSAGetLastError()};
271 if (IOErrorIsPermanent(err)) {
272 throw std::runtime_error(
273 strprintf("send(): %s", NetworkErrorString(err)));
274 }
275 }
276
277 const auto now = GetTime<std::chrono::milliseconds>();
278
279 if (now >= deadline) {
280 throw std::runtime_error(
281 strprintf("Send timeout (sent only %u of %u bytes before that)",
282 sent, data.size()));
283 }
284
285 if (interrupt) {
286 throw std::runtime_error(strprintf(
287 "Send interrupted (sent only %u of %u bytes before that)", sent,
288 data.size()));
289 }
290
291 // Wait for a short while (or the socket to become ready for sending)
292 // before retrying if nothing was sent.
293 const auto wait_time = std::min(
294 deadline - now, std::chrono::milliseconds{MAX_WAIT_FOR_IO});
295 Wait(wait_time, SEND);
296 }
297}
298
299std::string Sock::RecvUntilTerminator(uint8_t terminator,
300 std::chrono::milliseconds timeout,
301 CThreadInterrupt &interrupt,
302 size_t max_data) const {
303 const auto deadline = GetTime<std::chrono::milliseconds>() + timeout;
304 std::string data;
305 bool terminator_found{false};
306
307 // We must not consume any bytes past the terminator from the socket.
308 // One option is to read one byte at a time and check if we have read a
309 // terminator. However that is very slow. Instead, we peek at what is in the
310 // socket and only read as many bytes as possible without crossing the
311 // terminator. Reading 64 MiB of random data with 262526 terminator chars
312 // takes 37 seconds to read one byte at a time VS 0.71 seconds with the
313 // "peek" solution below. Reading one byte at a time is about 50 times
314 // slower.
315
316 for (;;) {
317 if (data.size() >= max_data) {
318 throw std::runtime_error(
319 strprintf("Received too many bytes without a terminator (%u)",
320 data.size()));
321 }
322
323 char buf[512];
324
325 const ssize_t peek_ret{
326 Recv(buf, std::min(sizeof(buf), max_data - data.size()), MSG_PEEK)};
327
328 switch (peek_ret) {
329 case -1: {
330 const int err{WSAGetLastError()};
331 if (IOErrorIsPermanent(err)) {
332 throw std::runtime_error(
333 strprintf("recv(): %s", NetworkErrorString(err)));
334 }
335 break;
336 }
337 case 0:
338 throw std::runtime_error(
339 "Connection unexpectedly closed by peer");
340 default:
341 auto end = buf + peek_ret;
342 auto terminator_pos = std::find(buf, end, terminator);
343 terminator_found = terminator_pos != end;
344
345 const size_t try_len{terminator_found
346 ? terminator_pos - buf + 1
347 : static_cast<size_t>(peek_ret)};
348
349 const ssize_t read_ret{Recv(buf, try_len, 0)};
350
351 if (read_ret < 0 || static_cast<size_t>(read_ret) != try_len) {
352 throw std::runtime_error(
353 strprintf("recv() returned %u bytes on attempt to read "
354 "%u bytes but previous "
355 "peek claimed %u bytes are available",
356 read_ret, try_len, peek_ret));
357 }
358
359 // Don't include the terminator in the output.
360 const size_t append_len{terminator_found ? try_len - 1
361 : try_len};
362
363 data.append(buf, buf + append_len);
364
365 if (terminator_found) {
366 return data;
367 }
368 }
369
370 const auto now = GetTime<std::chrono::milliseconds>();
371
372 if (now >= deadline) {
373 throw std::runtime_error(
374 strprintf("Receive timeout (received %u bytes without "
375 "terminator before that)",
376 data.size()));
377 }
378
379 if (interrupt) {
380 throw std::runtime_error(
381 strprintf("Receive interrupted (received %u bytes without "
382 "terminator before that)",
383 data.size()));
384 }
385
386 // Wait for a short while (or the socket to become ready for reading)
387 // before retrying.
388 const auto wait_time = std::min(
389 deadline - now, std::chrono::milliseconds{MAX_WAIT_FOR_IO});
390 Wait(wait_time, RECV);
391 }
392}
393
394bool Sock::IsConnected(std::string &errmsg) const {
395 if (m_socket == INVALID_SOCKET) {
396 errmsg = "not connected";
397 return false;
398 }
399
400 char c;
401 switch (Recv(&c, sizeof(c), MSG_PEEK)) {
402 case -1: {
403 const int err = WSAGetLastError();
404 if (IOErrorIsPermanent(err)) {
405 errmsg = NetworkErrorString(err);
406 return false;
407 }
408 return true;
409 }
410 case 0:
411 errmsg = "closed";
412 return false;
413 default:
414 return true;
415 }
416}
417
419 if (m_socket == INVALID_SOCKET) {
420 return;
421 }
422#ifdef WIN32
423 int ret = closesocket(m_socket);
424#else
425 int ret = close(m_socket);
426#endif
427 if (ret) {
428 LogPrintf("Error closing socket %d: %s\n", m_socket,
430 }
432}
433
435 return m_socket == s;
436};
437
438std::string NetworkErrorString(int err) {
439#ifdef WIN32
440 return Win32ErrorString(err);
441#else
442 // On BSD sockets implementations, NetworkErrorString is the same as
443 // SysErrorString.
444 return SysErrorString(err);
445#endif
446}
int flags
Definition: bitcoin-tx.cpp:546
A helper class for interruptible sleeps.
RAII helper class that manages a socket and closes it automatically when it goes out of scope.
Definition: sock.h:27
virtual std::unique_ptr< Sock > Accept(sockaddr *addr, socklen_t *addr_len) const
accept(2) wrapper.
Definition: sock.cpp:69
virtual ssize_t Send(const void *data, size_t len, int flags) const
send(2) wrapper.
Definition: sock.cpp:49
static constexpr Event SEND
If passed to Wait(), then it will wait for readiness to send to the socket.
Definition: sock.h:165
int WaitReadableOrException(timeval *timeout) const
Wait until the socket is readable or has an exceptional condition, or the timeout expires,...
Definition: sock.cpp:244
SOCKET m_socket
Contained socket.
Definition: sock.h:300
Sock & operator=(const Sock &)=delete
Copy assignment operator, disabled because closing the same socket twice is undesirable.
virtual void SendComplete(const std::string &data, std::chrono::milliseconds timeout, CThreadInterrupt &interrupt) const
Send the given data, retrying on transient errors.
Definition: sock.cpp:254
virtual int Bind(const sockaddr *addr, socklen_t addr_len) const
bind(2) wrapper.
Definition: sock.cpp:61
virtual bool Wait(std::chrono::milliseconds timeout, Event requested, Event *occurred=nullptr) const
Wait for readiness for input (recv) or output (send).
Definition: sock.cpp:136
virtual ~Sock()
Destructor, close the socket or do nothing if empty.
Definition: sock.cpp:38
uint8_t Event
Definition: sock.h:153
virtual int GetSockName(sockaddr *name, socklen_t *name_len) const
getsockname(2) wrapper.
Definition: sock.cpp:106
void Close()
Close m_socket if it is not INVALID_SOCKET.
Definition: sock.cpp:418
virtual bool WaitMany(std::chrono::milliseconds timeout, EventsPerSock &events_per_sock) const
Same as Wait(), but wait on many sockets within the same timeout.
Definition: sock.cpp:156
static constexpr Event ERR
Ignored if passed to Wait(), but could be set in the occurred events if an exceptional condition has ...
Definition: sock.h:172
virtual bool IsConnected(std::string &errmsg) const
Check if still connected.
Definition: sock.cpp:394
virtual int SetSockOpt(int level, int opt_name, const void *opt_val, socklen_t opt_len) const
setsockopt(2) wrapper.
Definition: sock.cpp:100
static constexpr Event RECV
If passed to Wait(), then it will wait for readiness to read from the socket.
Definition: sock.h:159
virtual int GetSockOpt(int level, int opt_name, void *opt_val, socklen_t *opt_len) const
getsockopt(2) wrapper.
Definition: sock.cpp:94
virtual int Connect(const sockaddr *addr, socklen_t addr_len) const
connect(2) wrapper.
Definition: sock.cpp:57
virtual ssize_t Recv(void *buf, size_t len, int flags) const
recv(2) wrapper.
Definition: sock.cpp:53
Sock()=delete
virtual std::string RecvUntilTerminator(uint8_t terminator, std::chrono::milliseconds timeout, CThreadInterrupt &interrupt, size_t max_data) const
Read from socket until a terminator character is encountered.
Definition: sock.cpp:299
virtual int Listen(int backlog) const
listen(2) wrapper.
Definition: sock.cpp:65
virtual bool SetNonBlocking() const
Set the non-blocking option on the socket.
Definition: sock.cpp:110
std::unordered_map< std::shared_ptr< const Sock >, Events, HashSharedPtrSock, EqualSharedPtrSock > EventsPerSock
On which socket to wait for what events in WaitMany().
Definition: sock.h:229
virtual bool IsSelectable() const
Check if the underlying socket can be used for select(2) (or the Wait() method).
Definition: sock.cpp:128
bool operator==(SOCKET s) const
Check if the internal socket is equal to s.
Definition: sock.cpp:434
#define INVALID_SOCKET
Definition: compat.h:65
#define WSAEWOULDBLOCK
Definition: compat.h:59
#define SOCKET_ERROR
Definition: compat.h:66
#define WSAGetLastError()
Definition: compat.h:57
#define MSG_NOSIGNAL
Definition: compat.h:122
unsigned int SOCKET
Definition: compat.h:55
#define WSAEINPROGRESS
Definition: compat.h:63
#define WSAEINTR
Definition: compat.h:62
#define WSAEAGAIN
Definition: compat.h:60
#define LogPrintf(...)
Definition: logging.h:424
const char * name
Definition: rest.cpp:47
static RPCHelpMan send()
Definition: rpcwallet.cpp:4206
static bool IOErrorIsPermanent(int err)
Definition: sock.cpp:26
std::string NetworkErrorString(int err)
Return readable error string for a network error code.
Definition: sock.cpp:438
static constexpr auto MAX_WAIT_FOR_IO
Maximum time to wait for I/O readiness.
Definition: sock.h:21
Auxiliary requested/occurred events to wait for in WaitMany().
Definition: sock.h:194
std::string SysErrorString(int err)
Return system error string from errno value.
Definition: syserror.cpp:20
struct timeval MillisToTimeval(int64_t nTimeout)
Convert milliseconds to a struct timeval for e.g.
Definition: time.cpp:130
constexpr int64_t count_milliseconds(std::chrono::milliseconds t)
Definition: time.h:62
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1202
assert(!tx.IsCoinBase())