net: split socket creation out of connection

Also, check for the correct error during socket creation
This commit is contained in:
Cory Fields 2017-09-18 18:45:51 -04:00
parent 6f01dcf638
commit 1729c29ded
3 changed files with 44 additions and 17 deletions

View File

@ -417,16 +417,30 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
if (addrConnect.IsValid()) { if (addrConnect.IsValid()) {
bool proxyConnectionFailed = false; bool proxyConnectionFailed = false;
if (GetProxy(addrConnect.GetNetwork(), proxy)) if (GetProxy(addrConnect.GetNetwork(), proxy)) {
hSocket = CreateSocket(proxy.proxy);
if (hSocket == INVALID_SOCKET) {
return nullptr;
}
connected = ConnectThroughProxy(proxy, addrConnect.ToStringIP(), addrConnect.GetPort(), hSocket, nConnectTimeout, &proxyConnectionFailed); connected = ConnectThroughProxy(proxy, addrConnect.ToStringIP(), addrConnect.GetPort(), hSocket, nConnectTimeout, &proxyConnectionFailed);
else // no proxy needed (none set for target network) } else {
// no proxy needed (none set for target network)
hSocket = CreateSocket(addrConnect);
if (hSocket == INVALID_SOCKET) {
return nullptr;
}
connected = ConnectSocketDirectly(addrConnect, hSocket, nConnectTimeout); connected = ConnectSocketDirectly(addrConnect, hSocket, nConnectTimeout);
}
if (!proxyConnectionFailed) { if (!proxyConnectionFailed) {
// If a connection to the node was attempted, and failure (if any) is not caused by a problem connecting to // If a connection to the node was attempted, and failure (if any) is not caused by a problem connecting to
// the proxy, mark this as an attempt. // the proxy, mark this as an attempt.
addrman.Attempt(addrConnect, fCountFailure); addrman.Attempt(addrConnect, fCountFailure);
} }
} else if (pszDest && GetNameProxy(proxy)) { } else if (pszDest && GetNameProxy(proxy)) {
hSocket = CreateSocket(proxy.proxy);
if (hSocket == INVALID_SOCKET) {
return nullptr;
}
std::string host; std::string host;
int port = default_port; int port = default_port;
SplitHostPort(std::string(pszDest), port, host); SplitHostPort(std::string(pszDest), port, host);

View File

@ -452,20 +452,18 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials
return true; return true;
} }
bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int nTimeout) SOCKET CreateSocket(const CService &addrConnect)
{ {
hSocketRet = INVALID_SOCKET;
struct sockaddr_storage sockaddr; struct sockaddr_storage sockaddr;
socklen_t len = sizeof(sockaddr); socklen_t len = sizeof(sockaddr);
if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) { if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString()); LogPrintf("Cannot create socket for %s: unsupported network\n", addrConnect.ToString());
return false; return INVALID_SOCKET;
} }
SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP); SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
if (hSocket == INVALID_SOCKET) if (hSocket == INVALID_SOCKET)
return false; return INVALID_SOCKET;
#ifdef SO_NOSIGPIPE #ifdef SO_NOSIGPIPE
int set = 1; int set = 1;
@ -479,9 +477,24 @@ bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int
// Set to non-blocking // Set to non-blocking
if (!SetSocketNonBlocking(hSocket, true)) { if (!SetSocketNonBlocking(hSocket, true)) {
CloseSocket(hSocket); CloseSocket(hSocket);
return error("ConnectSocketDirectly: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError())); LogPrintf("ConnectSocketDirectly: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
} }
return hSocket;
}
bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocket, int nTimeout)
{
struct sockaddr_storage sockaddr;
socklen_t len = sizeof(sockaddr);
if (hSocket == INVALID_SOCKET) {
LogPrintf("Cannot connect to %s: invalid socket\n", addrConnect.ToString());
return false;
}
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) if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
{ {
int nErr = WSAGetLastError(); int nErr = WSAGetLastError();
@ -534,8 +547,6 @@ bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int
return false; return false;
} }
} }
hSocketRet = hSocket;
return true; return true;
} }
@ -587,9 +598,8 @@ bool IsProxy(const CNetAddr &addr) {
return false; return false;
} }
bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed) bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, SOCKET& hSocket, int nTimeout, bool *outProxyConnectionFailed)
{ {
SOCKET hSocket = INVALID_SOCKET;
// first connect to proxy server // first connect to proxy server
if (!ConnectSocketDirectly(proxy.proxy, hSocket, nTimeout)) { if (!ConnectSocketDirectly(proxy.proxy, hSocket, nTimeout)) {
if (outProxyConnectionFailed) if (outProxyConnectionFailed)
@ -601,14 +611,16 @@ bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int
ProxyCredentials random_auth; ProxyCredentials random_auth;
static std::atomic_int counter(0); static std::atomic_int counter(0);
random_auth.username = random_auth.password = strprintf("%i", counter++); random_auth.username = random_auth.password = strprintf("%i", counter++);
if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket)) if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket)) {
CloseSocket(hSocket);
return false; return false;
}
} else { } else {
if (!Socks5(strDest, (unsigned short)port, 0, hSocket)) if (!Socks5(strDest, (unsigned short)port, 0, hSocket)) {
CloseSocket(hSocket);
return false; return false;
}
} }
hSocketRet = hSocket;
return true; return true;
} }
bool LookupSubNet(const char* pszName, CSubNet& ret) bool LookupSubNet(const char* pszName, CSubNet& ret)

View File

@ -51,6 +51,7 @@ bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLoo
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions); bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions);
CService LookupNumeric(const char *pszName, int portDefault = 0); CService LookupNumeric(const char *pszName, int portDefault = 0);
bool LookupSubNet(const char *pszName, CSubNet& subnet); bool LookupSubNet(const char *pszName, CSubNet& subnet);
SOCKET CreateSocket(const CService &addrConnect);
bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int nTimeout); 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 ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed);
/** Return readable error string for a network error code */ /** Return readable error string for a network error code */