Skip to content

Commit df3bcf8

Browse files
committed
net: pass socket closing responsibility up to caller for outgoing connections
This allows const references to be passed around, making it clear where the socket may and may not be invalidated.
1 parent 9e3b2f5 commit df3bcf8

File tree

2 files changed

+6
-30
lines changed

2 files changed

+6
-30
lines changed

src/netbase.cpp

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -317,12 +317,11 @@ std::string Socks5ErrorString(uint8_t err)
317317
}
318318

319319
/** Connect using SOCKS5 (as described in RFC1928) */
320-
static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, SOCKET& hSocket)
320+
static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, const SOCKET& hSocket)
321321
{
322322
IntrRecvError recvr;
323323
LogPrint(BCLog::NET, "SOCKS5 connecting %s\n", strDest);
324324
if (strDest.size() > 255) {
325-
CloseSocket(hSocket);
326325
return error("Hostname too long");
327326
}
328327
// Accepted authentication methods
@@ -338,17 +337,14 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
338337
}
339338
ssize_t ret = send(hSocket, (const char*)vSocks5Init.data(), vSocks5Init.size(), MSG_NOSIGNAL);
340339
if (ret != (ssize_t)vSocks5Init.size()) {
341-
CloseSocket(hSocket);
342340
return error("Error sending to proxy");
343341
}
344342
uint8_t pchRet1[2];
345343
if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
346-
CloseSocket(hSocket);
347344
LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port);
348345
return false;
349346
}
350347
if (pchRet1[0] != SOCKSVersion::SOCKS5) {
351-
CloseSocket(hSocket);
352348
return error("Proxy failed to initialize");
353349
}
354350
if (pchRet1[1] == SOCKS5Method::USER_PASS && auth) {
@@ -363,23 +359,19 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
363359
vAuth.insert(vAuth.end(), auth->password.begin(), auth->password.end());
364360
ret = send(hSocket, (const char*)vAuth.data(), vAuth.size(), MSG_NOSIGNAL);
365361
if (ret != (ssize_t)vAuth.size()) {
366-
CloseSocket(hSocket);
367362
return error("Error sending authentication to proxy");
368363
}
369364
LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password);
370365
uint8_t pchRetA[2];
371366
if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
372-
CloseSocket(hSocket);
373367
return error("Error reading proxy authentication response");
374368
}
375369
if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
376-
CloseSocket(hSocket);
377370
return error("Proxy authentication unsuccessful");
378371
}
379372
} else if (pchRet1[1] == SOCKS5Method::NOAUTH) {
380373
// Perform no authentication
381374
} else {
382-
CloseSocket(hSocket);
383375
return error("Proxy requested wrong authentication method %02x", pchRet1[1]);
384376
}
385377
std::vector<uint8_t> vSocks5;
@@ -393,12 +385,10 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
393385
vSocks5.push_back((port >> 0) & 0xFF);
394386
ret = send(hSocket, (const char*)vSocks5.data(), vSocks5.size(), MSG_NOSIGNAL);
395387
if (ret != (ssize_t)vSocks5.size()) {
396-
CloseSocket(hSocket);
397388
return error("Error sending to proxy");
398389
}
399390
uint8_t pchRet2[4];
400391
if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
401-
CloseSocket(hSocket);
402392
if (recvr == IntrRecvError::Timeout) {
403393
/* If a timeout happens here, this effectively means we timed out while connecting
404394
* to the remote node. This is very common for Tor, so do not print an
@@ -409,17 +399,14 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
409399
}
410400
}
411401
if (pchRet2[0] != SOCKSVersion::SOCKS5) {
412-
CloseSocket(hSocket);
413402
return error("Proxy failed to accept request");
414403
}
415404
if (pchRet2[1] != SOCKS5Reply::SUCCEEDED) {
416405
// Failures to connect to a peer that are not proxy errors
417-
CloseSocket(hSocket);
418406
LogPrintf("Socks5() connect to %s:%d failed: %s\n", strDest, port, Socks5ErrorString(pchRet2[1]));
419407
return false;
420408
}
421409
if (pchRet2[2] != 0x00) { // Reserved field must be 0
422-
CloseSocket(hSocket);
423410
return error("Error: malformed proxy response");
424411
}
425412
uint8_t pchRet3[256];
@@ -431,21 +418,18 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
431418
{
432419
recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket);
433420
if (recvr != IntrRecvError::OK) {
434-
CloseSocket(hSocket);
435421
return error("Error reading from proxy");
436422
}
437423
int nRecv = pchRet3[0];
438424
recvr = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
439425
break;
440426
}
441-
default: CloseSocket(hSocket); return error("Error: malformed proxy response");
427+
default: return error("Error: malformed proxy response");
442428
}
443429
if (recvr != IntrRecvError::OK) {
444-
CloseSocket(hSocket);
445430
return error("Error reading from proxy");
446431
}
447432
if ((recvr = InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
448-
CloseSocket(hSocket);
449433
return error("Error reading from proxy");
450434
}
451435
LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest);
@@ -488,7 +472,7 @@ SOCKET CreateSocket(const CService &addrConnect)
488472
return hSocket;
489473
}
490474

491-
bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocket, int nTimeout)
475+
bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocket, int nTimeout)
492476
{
493477
struct sockaddr_storage sockaddr;
494478
socklen_t len = sizeof(sockaddr);
@@ -498,7 +482,6 @@ bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocket, int nTi
498482
}
499483
if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
500484
LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString());
501-
CloseSocket(hSocket);
502485
return false;
503486
}
504487
if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
@@ -515,13 +498,11 @@ bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocket, int nTi
515498
if (nRet == 0)
516499
{
517500
LogPrint(BCLog::NET, "connection to %s timeout\n", addrConnect.ToString());
518-
CloseSocket(hSocket);
519501
return false;
520502
}
521503
if (nRet == SOCKET_ERROR)
522504
{
523505
LogPrintf("select() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
524-
CloseSocket(hSocket);
525506
return false;
526507
}
527508
socklen_t nRetSize = sizeof(nRet);
@@ -532,13 +513,11 @@ bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocket, int nTi
532513
#endif
533514
{
534515
LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
535-
CloseSocket(hSocket);
536516
return false;
537517
}
538518
if (nRet != 0)
539519
{
540520
LogPrintf("connect() to %s failed after select(): %s\n", addrConnect.ToString(), NetworkErrorString(nRet));
541-
CloseSocket(hSocket);
542521
return false;
543522
}
544523
}
@@ -549,7 +528,6 @@ bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocket, int nTi
549528
#endif
550529
{
551530
LogPrintf("connect() to %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
552-
CloseSocket(hSocket);
553531
return false;
554532
}
555533
}
@@ -604,7 +582,7 @@ bool IsProxy(const CNetAddr &addr) {
604582
return false;
605583
}
606584

607-
bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, SOCKET& hSocket, int nTimeout, bool *outProxyConnectionFailed)
585+
bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, const SOCKET& hSocket, int nTimeout, bool *outProxyConnectionFailed)
608586
{
609587
// first connect to proxy server
610588
if (!ConnectSocketDirectly(proxy.proxy, hSocket, nTimeout)) {
@@ -618,12 +596,10 @@ bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int
618596
static std::atomic_int counter(0);
619597
random_auth.username = random_auth.password = strprintf("%i", counter++);
620598
if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket)) {
621-
CloseSocket(hSocket);
622599
return false;
623600
}
624601
} else {
625602
if (!Socks5(strDest, (unsigned short)port, 0, hSocket)) {
626-
CloseSocket(hSocket);
627603
return false;
628604
}
629605
}

src/netbase.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault,
5252
CService LookupNumeric(const char *pszName, int portDefault = 0);
5353
bool LookupSubNet(const char *pszName, CSubNet& subnet);
5454
SOCKET CreateSocket(const CService &addrConnect);
55-
bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int nTimeout);
56-
bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed);
55+
bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocketRet, int nTimeout);
56+
bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, const SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed);
5757
/** Return readable error string for a network error code */
5858
std::string NetworkErrorString(int err);
5959
/** Close socket and set hSocket to INVALID_SOCKET */

0 commit comments

Comments
 (0)