aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCory Fields <cory-nospam-@coryfields.com>2017-10-02 16:37:36 -0400
committerCory Fields <cory-nospam-@coryfields.com>2017-12-12 15:25:25 -0500
commitdf3bcf89e49ec951baa3778a2452c0d1237ec053 (patch)
tree0af136d9b3eca5554799df19171567e2b6118085
parent9e3b2f576bb368a0857e808dcbd24b2dcb8bef2d (diff)
downloadbitcoin-df3bcf89e49ec951baa3778a2452c0d1237ec053.tar.xz
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.
-rw-r--r--src/netbase.cpp32
-rw-r--r--src/netbase.h4
2 files changed, 6 insertions, 30 deletions
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 1635957b7f..74ea6b19cf 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -317,12 +317,11 @@ std::string Socks5ErrorString(uint8_t err)
}
/** Connect using SOCKS5 (as described in RFC1928) */
-static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, SOCKET& hSocket)
+static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, const SOCKET& hSocket)
{
IntrRecvError recvr;
LogPrint(BCLog::NET, "SOCKS5 connecting %s\n", strDest);
if (strDest.size() > 255) {
- CloseSocket(hSocket);
return error("Hostname too long");
}
// Accepted authentication methods
@@ -338,17 +337,14 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
}
ssize_t ret = send(hSocket, (const char*)vSocks5Init.data(), vSocks5Init.size(), MSG_NOSIGNAL);
if (ret != (ssize_t)vSocks5Init.size()) {
- CloseSocket(hSocket);
return error("Error sending to proxy");
}
uint8_t pchRet1[2];
if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
- CloseSocket(hSocket);
LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port);
return false;
}
if (pchRet1[0] != SOCKSVersion::SOCKS5) {
- CloseSocket(hSocket);
return error("Proxy failed to initialize");
}
if (pchRet1[1] == SOCKS5Method::USER_PASS && auth) {
@@ -363,23 +359,19 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
vAuth.insert(vAuth.end(), auth->password.begin(), auth->password.end());
ret = send(hSocket, (const char*)vAuth.data(), vAuth.size(), MSG_NOSIGNAL);
if (ret != (ssize_t)vAuth.size()) {
- CloseSocket(hSocket);
return error("Error sending authentication to proxy");
}
LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password);
uint8_t pchRetA[2];
if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
- CloseSocket(hSocket);
return error("Error reading proxy authentication response");
}
if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
- CloseSocket(hSocket);
return error("Proxy authentication unsuccessful");
}
} else if (pchRet1[1] == SOCKS5Method::NOAUTH) {
// Perform no authentication
} else {
- CloseSocket(hSocket);
return error("Proxy requested wrong authentication method %02x", pchRet1[1]);
}
std::vector<uint8_t> vSocks5;
@@ -393,12 +385,10 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
vSocks5.push_back((port >> 0) & 0xFF);
ret = send(hSocket, (const char*)vSocks5.data(), vSocks5.size(), MSG_NOSIGNAL);
if (ret != (ssize_t)vSocks5.size()) {
- CloseSocket(hSocket);
return error("Error sending to proxy");
}
uint8_t pchRet2[4];
if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
- CloseSocket(hSocket);
if (recvr == IntrRecvError::Timeout) {
/* If a timeout happens here, this effectively means we timed out while connecting
* 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
}
}
if (pchRet2[0] != SOCKSVersion::SOCKS5) {
- CloseSocket(hSocket);
return error("Proxy failed to accept request");
}
if (pchRet2[1] != SOCKS5Reply::SUCCEEDED) {
// Failures to connect to a peer that are not proxy errors
- CloseSocket(hSocket);
LogPrintf("Socks5() connect to %s:%d failed: %s\n", strDest, port, Socks5ErrorString(pchRet2[1]));
return false;
}
if (pchRet2[2] != 0x00) { // Reserved field must be 0
- CloseSocket(hSocket);
return error("Error: malformed proxy response");
}
uint8_t pchRet3[256];
@@ -431,21 +418,18 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
{
recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket);
if (recvr != IntrRecvError::OK) {
- CloseSocket(hSocket);
return error("Error reading from proxy");
}
int nRecv = pchRet3[0];
recvr = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
break;
}
- default: CloseSocket(hSocket); return error("Error: malformed proxy response");
+ default: return error("Error: malformed proxy response");
}
if (recvr != IntrRecvError::OK) {
- CloseSocket(hSocket);
return error("Error reading from proxy");
}
if ((recvr = InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
- CloseSocket(hSocket);
return error("Error reading from proxy");
}
LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest);
@@ -488,7 +472,7 @@ SOCKET CreateSocket(const CService &addrConnect)
return hSocket;
}
-bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocket, int nTimeout)
+bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocket, int nTimeout)
{
struct sockaddr_storage sockaddr;
socklen_t len = sizeof(sockaddr);
@@ -498,7 +482,6 @@ bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocket, int nTi
}
if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString());
- CloseSocket(hSocket);
return false;
}
if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
@@ -515,13 +498,11 @@ bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocket, int nTi
if (nRet == 0)
{
LogPrint(BCLog::NET, "connection to %s timeout\n", addrConnect.ToString());
- CloseSocket(hSocket);
return false;
}
if (nRet == SOCKET_ERROR)
{
LogPrintf("select() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
- CloseSocket(hSocket);
return false;
}
socklen_t nRetSize = sizeof(nRet);
@@ -532,13 +513,11 @@ bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocket, int nTi
#endif
{
LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
- CloseSocket(hSocket);
return false;
}
if (nRet != 0)
{
LogPrintf("connect() to %s failed after select(): %s\n", addrConnect.ToString(), NetworkErrorString(nRet));
- CloseSocket(hSocket);
return false;
}
}
@@ -549,7 +528,6 @@ bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocket, int nTi
#endif
{
LogPrintf("connect() to %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
- CloseSocket(hSocket);
return false;
}
}
@@ -604,7 +582,7 @@ bool IsProxy(const CNetAddr &addr) {
return false;
}
-bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, SOCKET& hSocket, int nTimeout, bool *outProxyConnectionFailed)
+bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, const SOCKET& hSocket, int nTimeout, bool *outProxyConnectionFailed)
{
// first connect to proxy server
if (!ConnectSocketDirectly(proxy.proxy, hSocket, nTimeout)) {
@@ -618,12 +596,10 @@ bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int
static std::atomic_int counter(0);
random_auth.username = random_auth.password = strprintf("%i", counter++);
if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket)) {
- CloseSocket(hSocket);
return false;
}
} else {
if (!Socks5(strDest, (unsigned short)port, 0, hSocket)) {
- CloseSocket(hSocket);
return false;
}
}
diff --git a/src/netbase.h b/src/netbase.h
index 59945ea97d..52e920b3d8 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -52,8 +52,8 @@ bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault,
CService LookupNumeric(const char *pszName, int portDefault = 0);
bool LookupSubNet(const char *pszName, CSubNet& subnet);
SOCKET CreateSocket(const CService &addrConnect);
-bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int nTimeout);
-bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed);
+bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocketRet, int nTimeout);
+bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, const SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed);
/** Return readable error string for a network error code */
std::string NetworkErrorString(int err);
/** Close socket and set hSocket to INVALID_SOCKET */