Skip to content

Commit a1be084

Browse files
committed
Merge #20788: net: add RAII socket and use it instead of bare SOCKET
615ba0e test: add Sock unit tests (Vasil Dimov) 7bd21ce style: rename hSocket to sock (Vasil Dimov) 04ae846 net: use Sock in InterruptibleRecv() and Socks5() (Vasil Dimov) ba9d732 net: add RAII socket and use it instead of bare SOCKET (Vasil Dimov) dec9b5e net: move CloseSocket() from netbase to util/sock (Vasil Dimov) aa17a44 net: move MillisToTimeval() from netbase to util/time (Vasil Dimov) Pull request description: Introduce a class to manage the lifetime of a socket - when the object that contains the socket goes out of scope, the underlying socket will be closed. In addition, the new `Sock` class has a `Send()`, `Recv()` and `Wait()` methods that can be overridden by unit tests to mock the socket operations. The `Wait()` method also hides the `#ifdef USE_POLL poll() #else select() #endif` technique from higher level code. ACKs for top commit: laanwj: Re-ACK 615ba0e jonatack: re-ACK 615ba0e Tree-SHA512: 3003e6bc0259295ca0265ccdeb1522ee25b4abe66d32e6ceaa51b55e0a999df7ddee765f86ce558a788c1953ee2009bfa149b09d494593f7d799c0d7d930bee8
2 parents 685c16f + 615ba0e commit a1be084

File tree

11 files changed

+527
-147
lines changed

11 files changed

+527
-147
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ BITCOIN_CORE_H = \
243243
util/rbf.h \
244244
util/ref.h \
245245
util/settings.h \
246+
util/sock.h \
246247
util/spanparsing.h \
247248
util/string.h \
248249
util/system.h \
@@ -559,6 +560,7 @@ libbitcoin_util_a_SOURCES = \
559560
util/fees.cpp \
560561
util/getuniquepath.cpp \
561562
util/hasher.cpp \
563+
util/sock.cpp \
562564
util/system.cpp \
563565
util/message.cpp \
564566
util/moneystr.cpp \

src/Makefile.test.include

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ BITCOIN_TESTS =\
124124
test/sighash_tests.cpp \
125125
test/sigopcount_tests.cpp \
126126
test/skiplist_tests.cpp \
127+
test/sock_tests.cpp \
127128
test/streams_tests.cpp \
128129
test/sync_tests.cpp \
129130
test/system_tests.cpp \

src/net.cpp

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <protocol.h>
2121
#include <random.h>
2222
#include <scheduler.h>
23+
#include <util/sock.h>
2324
#include <util/strencodings.h>
2425
#include <util/translation.h>
2526

@@ -429,51 +430,53 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
429430

430431
// Connect
431432
bool connected = false;
432-
SOCKET hSocket = INVALID_SOCKET;
433+
std::unique_ptr<Sock> sock;
433434
proxyType proxy;
434435
if (addrConnect.IsValid()) {
435436
bool proxyConnectionFailed = false;
436437

437438
if (GetProxy(addrConnect.GetNetwork(), proxy)) {
438-
hSocket = CreateSocket(proxy.proxy);
439-
if (hSocket == INVALID_SOCKET) {
439+
sock = CreateSock(proxy.proxy);
440+
if (!sock) {
440441
return nullptr;
441442
}
442-
connected = ConnectThroughProxy(proxy, addrConnect.ToStringIP(), addrConnect.GetPort(), hSocket, nConnectTimeout, proxyConnectionFailed);
443+
connected = ConnectThroughProxy(proxy, addrConnect.ToStringIP(), addrConnect.GetPort(),
444+
*sock, nConnectTimeout, proxyConnectionFailed);
443445
} else {
444446
// no proxy needed (none set for target network)
445-
hSocket = CreateSocket(addrConnect);
446-
if (hSocket == INVALID_SOCKET) {
447+
sock = CreateSock(addrConnect);
448+
if (!sock) {
447449
return nullptr;
448450
}
449-
connected = ConnectSocketDirectly(addrConnect, hSocket, nConnectTimeout, conn_type == ConnectionType::MANUAL);
451+
connected = ConnectSocketDirectly(addrConnect, sock->Get(), nConnectTimeout,
452+
conn_type == ConnectionType::MANUAL);
450453
}
451454
if (!proxyConnectionFailed) {
452455
// If a connection to the node was attempted, and failure (if any) is not caused by a problem connecting to
453456
// the proxy, mark this as an attempt.
454457
addrman.Attempt(addrConnect, fCountFailure);
455458
}
456459
} else if (pszDest && GetNameProxy(proxy)) {
457-
hSocket = CreateSocket(proxy.proxy);
458-
if (hSocket == INVALID_SOCKET) {
460+
sock = CreateSock(proxy.proxy);
461+
if (!sock) {
459462
return nullptr;
460463
}
461464
std::string host;
462465
int port = default_port;
463466
SplitHostPort(std::string(pszDest), port, host);
464467
bool proxyConnectionFailed;
465-
connected = ConnectThroughProxy(proxy, host, port, hSocket, nConnectTimeout, proxyConnectionFailed);
468+
connected = ConnectThroughProxy(proxy, host, port, *sock, nConnectTimeout,
469+
proxyConnectionFailed);
466470
}
467471
if (!connected) {
468-
CloseSocket(hSocket);
469472
return nullptr;
470473
}
471474

472475
// Add node
473476
NodeId id = GetNewNodeId();
474477
uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
475-
CAddress addr_bind = GetBindAddress(hSocket);
476-
CNode* pnode = new CNode(id, nLocalServices, hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", conn_type);
478+
CAddress addr_bind = GetBindAddress(sock->Get());
479+
CNode* pnode = new CNode(id, nLocalServices, sock->Release(), addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", conn_type);
477480
pnode->AddRef();
478481

479482
// We're making a new connection, harvest entropy from the time (and our peer count)
@@ -2188,53 +2191,50 @@ bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError,
21882191
return false;
21892192
}
21902193

2191-
SOCKET hListenSocket = CreateSocket(addrBind);
2192-
if (hListenSocket == INVALID_SOCKET)
2193-
{
2194+
std::unique_ptr<Sock> sock = CreateSock(addrBind);
2195+
if (!sock) {
21942196
strError = strprintf(Untranslated("Error: Couldn't open socket for incoming connections (socket returned error %s)"), NetworkErrorString(WSAGetLastError()));
21952197
LogPrintf("%s\n", strError.original);
21962198
return false;
21972199
}
21982200

21992201
// Allow binding if the port is still in TIME_WAIT state after
22002202
// the program was closed and restarted.
2201-
setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (sockopt_arg_type)&nOne, sizeof(int));
2203+
setsockopt(sock->Get(), SOL_SOCKET, SO_REUSEADDR, (sockopt_arg_type)&nOne, sizeof(int));
22022204

22032205
// some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
22042206
// and enable it by default or not. Try to enable it, if possible.
22052207
if (addrBind.IsIPv6()) {
22062208
#ifdef IPV6_V6ONLY
2207-
setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (sockopt_arg_type)&nOne, sizeof(int));
2209+
setsockopt(sock->Get(), IPPROTO_IPV6, IPV6_V6ONLY, (sockopt_arg_type)&nOne, sizeof(int));
22082210
#endif
22092211
#ifdef WIN32
22102212
int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
2211-
setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
2213+
setsockopt(sock->Get(), IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
22122214
#endif
22132215
}
22142216

2215-
if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
2217+
if (::bind(sock->Get(), (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
22162218
{
22172219
int nErr = WSAGetLastError();
22182220
if (nErr == WSAEADDRINUSE)
22192221
strError = strprintf(_("Unable to bind to %s on this computer. %s is probably already running."), addrBind.ToString(), PACKAGE_NAME);
22202222
else
22212223
strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToString(), NetworkErrorString(nErr));
22222224
LogPrintf("%s\n", strError.original);
2223-
CloseSocket(hListenSocket);
22242225
return false;
22252226
}
22262227
LogPrintf("Bound to %s\n", addrBind.ToString());
22272228

22282229
// Listen for incoming connections
2229-
if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
2230+
if (listen(sock->Get(), SOMAXCONN) == SOCKET_ERROR)
22302231
{
22312232
strError = strprintf(_("Error: Listening for incoming connections failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError()));
22322233
LogPrintf("%s\n", strError.original);
2233-
CloseSocket(hListenSocket);
22342234
return false;
22352235
}
22362236

2237-
vhListenSocket.push_back(ListenSocket(hListenSocket, permissions));
2237+
vhListenSocket.push_back(ListenSocket(sock->Release(), permissions));
22382238
return true;
22392239
}
22402240

0 commit comments

Comments
 (0)