diff --git a/src/net.cpp b/src/net.cpp --- a/src/net.cpp +++ b/src/net.cpp @@ -373,38 +373,72 @@ ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime) / 3600.0); - // Connect - SOCKET hSocket; - bool proxyConnectionFailed = false; - if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, - config->GetChainParams().GetDefaultPort(), - nConnectTimeout, &proxyConnectionFailed) - : ConnectSocket(addrConnect, hSocket, nConnectTimeout, - &proxyConnectionFailed)) { - if (!IsSelectableSocket(hSocket)) { - LogPrintf("Cannot create connection: non-selectable socket created " - "(fd >= FD_SETSIZE ?)\n"); - CloseSocket(hSocket); - return nullptr; - } - - if (pszDest && addrConnect.IsValid()) { + // Resolve + const int default_port = Params().GetDefaultPort(); + if (pszDest) { + std::vector resolved; + if (Lookup(pszDest, resolved, default_port, + fNameLookup && !HaveNameProxy(), 256) && + !resolved.empty()) { + addrConnect = + CAddress(resolved[GetRand(resolved.size())], NODE_NONE); + if (!addrConnect.IsValid()) { + LogPrint(BCLog::NET, + "Resolver returned invalid address %s for %s\n", + addrConnect.ToString(), pszDest); + return nullptr; + } // It is possible that we already have a connection to the IP/port // pszDest resolved to. In that case, drop the connection that was // just created, and return the existing CNode instead. Also store // the name we used to connect in that CNode, so that future // FindNode() calls to that name catch this early. LOCK(cs_vNodes); - CNode *pnode = FindNode((CService)addrConnect); + CNode *pnode = FindNode(static_cast(addrConnect)); if (pnode) { pnode->MaybeSetAddrName(std::string(pszDest)); - CloseSocket(hSocket); LogPrintf("Failed to open new connection, already connected\n"); return nullptr; } } + } - addrman.Attempt(addrConnect, fCountFailure); + // Connect + bool connected = false; + SOCKET hSocket = INVALID_SOCKET; + proxyType proxy; + if (addrConnect.IsValid()) { + bool proxyConnectionFailed = false; + + if (GetProxy(addrConnect.GetNetwork(), proxy)) { + connected = ConnectThroughProxy( + proxy, addrConnect.ToStringIP(), addrConnect.GetPort(), hSocket, + nConnectTimeout, &proxyConnectionFailed); + } else { + // no proxy needed (none set for target network) + connected = + ConnectSocketDirectly(addrConnect, hSocket, nConnectTimeout); + } + if (!proxyConnectionFailed) { + // 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. + addrman.Attempt(addrConnect, fCountFailure); + } + } else if (pszDest && GetNameProxy(proxy)) { + std::string host; + int port = default_port; + SplitHostPort(std::string(pszDest), port, host); + connected = ConnectThroughProxy(proxy, host, port, hSocket, + nConnectTimeout, nullptr); + } + if (connected) { + if (!IsSelectableSocket(hSocket)) { + LogPrintf("Cannot create connection: non-selectable socket created " + "(fd >= FD_SETSIZE ?)\n"); + CloseSocket(hSocket); + return nullptr; + } // Add node NodeId id = GetNewNodeId(); @@ -420,10 +454,6 @@ pnode->AddRef(); return pnode; - } else if (!proxyConnectionFailed) { - // If connecting to the node failed, and failure is not caused by a - // problem connecting to the proxy, mark this as an attempt. - addrman.Attempt(addrConnect, fCountFailure); } return nullptr; @@ -2061,16 +2091,11 @@ // addednodeinfo state might change. break; } - // If strAddedNode is an IP/port, decode it immediately, so - // OpenNetworkConnection can detect existing connections to that - // IP/port. tried = true; - CService service( - LookupNumeric(info.strAddedNode.c_str(), - config->GetChainParams().GetDefaultPort())); - OpenNetworkConnection(CAddress(service, NODE_NONE), false, - &grant, info.strAddedNode.c_str(), false, - false, true); + CAddress addr(CService(), NODE_NONE); + OpenNetworkConnection(addr, false, &grant, + info.strAddedNode.c_str(), false, false, + true); if (!interruptNet.sleep_for(std::chrono::milliseconds(500))) { return; } diff --git a/src/netbase.h b/src/netbase.h --- a/src/netbase.h +++ b/src/netbase.h @@ -44,6 +44,7 @@ bool IsProxy(const CNetAddr &addr); bool SetNameProxy(const proxyType &addrProxy); bool HaveNameProxy(); +bool GetNameProxy(proxyType &nameProxyOut); bool LookupHost(const char *pszName, std::vector &vIP, unsigned int nMaxSolutions, bool fAllowLookup); bool LookupHost(const char *pszName, CNetAddr &addr, bool fAllowLookup); @@ -53,11 +54,11 @@ bool fAllowLookup, unsigned int nMaxSolutions); CService LookupNumeric(const char *pszName, int portDefault = 0); bool LookupSubNet(const char *pszName, CSubNet &subnet); -bool ConnectSocket(const CService &addr, SOCKET &hSocketRet, int nTimeout, - bool *outProxyConnectionFailed = 0); -bool ConnectSocketByName(CService &addr, SOCKET &hSocketRet, - const char *pszDest, int portDefault, int nTimeout, - bool *outProxyConnectionFailed = 0); +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); /** Return readable error string for a network error code */ std::string NetworkErrorString(int err); /** Close socket and set hSocket to INVALID_SOCKET */ diff --git a/src/netbase.cpp b/src/netbase.cpp --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -413,8 +413,8 @@ return true; } -static bool ConnectSocketDirectly(const CService &addrConnect, - SOCKET &hSocketRet, int nTimeout) { +bool ConnectSocketDirectly(const CService &addrConnect, SOCKET &hSocketRet, + int nTimeout) { hSocketRet = INVALID_SOCKET; struct sockaddr_storage sockaddr; @@ -554,10 +554,9 @@ return false; } -static 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) { SOCKET hSocket = INVALID_SOCKET; // first connect to proxy server if (!ConnectSocketDirectly(proxy.proxy, hSocket, nTimeout)) { @@ -570,60 +569,16 @@ static std::atomic_int 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)) { return false; - } else { - if (!Socks5(strDest, (unsigned short)port, 0, hSocket)) return false; + } + } else if (!Socks5(strDest, (unsigned short)port, 0, hSocket)) { + return false; } hSocketRet = hSocket; return true; } - -bool ConnectSocket(const CService &addrDest, SOCKET &hSocketRet, int nTimeout, - bool *outProxyConnectionFailed) { - proxyType proxy; - if (outProxyConnectionFailed) *outProxyConnectionFailed = false; - - if (GetProxy(addrDest.GetNetwork(), proxy)) { - return ConnectThroughProxy(proxy, addrDest.ToStringIP(), - addrDest.GetPort(), hSocketRet, nTimeout, - outProxyConnectionFailed); - } else { - // no proxy needed (none set for target network) - return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout); - } -} - -bool ConnectSocketByName(CService &addr, SOCKET &hSocketRet, - const char *pszDest, int portDefault, int nTimeout, - bool *outProxyConnectionFailed) { - std::string strDest; - int port = portDefault; - - if (outProxyConnectionFailed) *outProxyConnectionFailed = false; - - SplitHostPort(std::string(pszDest), port, strDest); - - proxyType proxy; - GetNameProxy(proxy); - - std::vector addrResolved; - if (Lookup(strDest.c_str(), addrResolved, port, - fNameLookup && !HaveNameProxy(), 256)) { - if (addrResolved.size() > 0) { - addr = addrResolved[GetRand(addrResolved.size())]; - return ConnectSocket(addr, hSocketRet, nTimeout); - } - } - - addr = CService(); - - if (!HaveNameProxy()) return false; - return ConnectThroughProxy(proxy, strDest, port, hSocketRet, nTimeout, - outProxyConnectionFailed); -} - bool LookupSubNet(const char *pszName, CSubNet &ret) { std::string strSubnet(pszName); size_t slash = strSubnet.find_last_of('/'); diff --git a/src/seeder/bitcoin.cpp b/src/seeder/bitcoin.cpp --- a/src/seeder/bitcoin.cpp +++ b/src/seeder/bitcoin.cpp @@ -252,9 +252,25 @@ } bool Run() { - bool proxyConnectionFailed = false; - if (!ConnectSocket(you, sock, nConnectTimeout, - &proxyConnectionFailed)) { + // FIXME: This logic is duplicated with CConnman::ConnectNode for no + // good reason. + bool connected = false; + proxyType proxy; + + if (you.IsValid()) { + bool proxyConnectionFailed = false; + + if (GetProxy(you.GetNetwork(), proxy)) { + connected = ConnectThroughProxy( + proxy, you.ToStringIP(), you.GetPort(), sock, + nConnectTimeout, &proxyConnectionFailed); + } else { + // no proxy needed (none set for target network) + connected = ConnectSocketDirectly(you, sock, nConnectTimeout); + } + } + + if (!connected) { return false; }