diff --git a/src/init.cpp b/src/init.cpp index e01516eb..890a7d03 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -192,7 +192,7 @@ bool AppInit2(int argc, char* argv[]) " -dns \t " + _("Allow DNS lookups for addnode and connect") + "\n" + " -port= \t\t " + _("Listen for connections on (default: 8333 or testnet: 18333)") + "\n" + " -maxconnections=\t " + _("Maintain at most connections to peers (default: 125)") + "\n" + - " -addnode= \t " + _("Add a node to connect to") + "\n" + + " -addnode= \t " + _("Add a node to connect to and attempt to keep the connection open") + "\n" + " -connect= \t\t " + _("Connect only to the specified node") + "\n" + " -noirc \t " + _("Don't find peers using internet relay chat") + "\n" + " -nolisten \t " + _("Don't accept connections from outside") + "\n" + diff --git a/src/net.cpp b/src/net.cpp index 817203b0..cdd72fdd 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -29,6 +29,7 @@ static const int MAX_OUTBOUND_CONNECTIONS = 8; void ThreadMessageHandler2(void* parg); void ThreadSocketHandler2(void* parg); void ThreadOpenConnections2(void* parg); +void ThreadOpenAddedConnections2(void* parg); #ifdef USE_UPNP void ThreadMapPort2(void* parg); #endif @@ -61,6 +62,9 @@ CCriticalSection cs_mapRelay; map mapAlreadyAskedFor; +set setservAddNodeAddresses; +CCriticalSection cs_setservAddNodeAddresses; + @@ -750,7 +754,9 @@ void ThreadSocketHandler2(void* parg) } else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS) { - closesocket(hSocket); + CRITICAL_BLOCK(cs_setservAddNodeAddresses) + if (!setservAddNodeAddresses.count(addr)) + closesocket(hSocket); } else if (CNode::IsBanned(addr)) { @@ -1211,22 +1217,6 @@ void ThreadOpenConnections2(void* parg) } } - // Connect to manually added nodes first - if (mapArgs.count("-addnode")) - { - BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"]) - { - CAddress addr(strAddr, fAllowDNS); - if (addr.IsValid()) - { - OpenNetworkConnection(addr); - Sleep(500); - if (fShutdown) - return; - } - } - } - // Initiate network connections int64 nStart = GetTime(); loop @@ -1355,6 +1345,76 @@ void ThreadOpenConnections2(void* parg) } } +void ThreadOpenAddedConnections(void* parg) +{ + IMPLEMENT_RANDOMIZE_STACK(ThreadOpenAddedConnections(parg)); + try + { + vnThreadsRunning[7]++; + ThreadOpenAddedConnections2(parg); + vnThreadsRunning[7]--; + } + catch (std::exception& e) { + vnThreadsRunning[7]--; + PrintException(&e, "ThreadOpenAddedConnections()"); + } catch (...) { + vnThreadsRunning[7]--; + PrintException(NULL, "ThreadOpenAddedConnections()"); + } + printf("ThreadOpenAddedConnections exiting\n"); +} + +void ThreadOpenAddedConnections2(void* parg) +{ + printf("ThreadOpenAddedConnections started\n"); + + if (mapArgs.count("-addnode") == 0) + return; + + vector > vservAddressesToAdd(0); + BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"]) + { + vector vservNode(0); + if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fAllowDNS, 0)) + { + vservAddressesToAdd.push_back(vservNode); + CRITICAL_BLOCK(cs_setservAddNodeAddresses) + BOOST_FOREACH(CService& serv, vservNode) + setservAddNodeAddresses.insert(serv); + } + } + loop + { + vector > vservConnectAddresses = vservAddressesToAdd; + // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry + // (keeping in mind that addnode entries can have many IPs if fAllowDNS) + CRITICAL_BLOCK(cs_vNodes) + BOOST_FOREACH(CNode* pnode, vNodes) + for (vector >::iterator it = vservConnectAddresses.begin(); it != vservConnectAddresses.end(); it++) + BOOST_FOREACH(CService& addrNode, *(it)) + if (pnode->addr == addrNode) + { + it = vservConnectAddresses.erase(it); + it--; + break; + } + BOOST_FOREACH(vector& vserv, vservConnectAddresses) + { + OpenNetworkConnection(CAddress(*(vserv.begin()))); + Sleep(500); + if (fShutdown) + return; + } + if (fShutdown) + return; + vnThreadsRunning[7]--; + Sleep(120000); // Retry every 2 minutes + vnThreadsRunning[7]++; + if (fShutdown) + return; + } +} + bool OpenNetworkConnection(const CAddress& addrConnect) { // @@ -1631,6 +1691,10 @@ void StartNode(void* parg) if (!CreateThread(ThreadSocketHandler, NULL)) printf("Error: CreateThread(ThreadSocketHandler) failed\n"); + // Initiate outbound connections from -addnode + if (!CreateThread(ThreadOpenAddedConnections, NULL)) + printf("Error: CreateThread(ThreadOpenAddedConnections) failed\n"); + // Initiate outbound connections if (!CreateThread(ThreadOpenConnections, NULL)) printf("Error: CreateThread(ThreadOpenConnections) failed\n"); @@ -1650,9 +1714,7 @@ bool StopNode() nTransactionsUpdated++; int64 nStart = GetTime(); while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0 -#ifdef USE_UPNP - || vnThreadsRunning[5] > 0 -#endif + || (fHaveUPnP && vnThreadsRunning[5] > 0) || vnThreadsRunning[6] > 0 || vnThreadsRunning[7] > 0 ) { if (GetTime() - nStart > 20) @@ -1666,6 +1728,7 @@ bool StopNode() if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n"); if (fHaveUPnP && vnThreadsRunning[5] > 0) printf("ThreadMapPort still running\n"); if (vnThreadsRunning[6] > 0) printf("ThreadDNSAddressSeed still running\n"); + if (vnThreadsRunning[7] > 0) printf("ThreadOpenAddedConnections still running\n"); while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0) Sleep(20); Sleep(50); diff --git a/src/netbase.cpp b/src/netbase.cpp index ca27c2a8..48db3625 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -98,7 +98,7 @@ bool LookupHostNumeric(const char *pszName, std::vector& vIP, int nMax return LookupHost(pszName, vIP, nMaxSolutions, false); } -bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup) +bool Lookup(const char *pszName, std::vector& vAddr, int portDefault, bool fAllowLookup, int nMaxSolutions) { if (pszName[0] == 0) return false; @@ -132,10 +132,22 @@ bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLoo } std::vector vIP; - bool fRet = LookupIntern(pszHost, vIP, 1, fAllowLookup); + bool fRet = LookupIntern(pszHost, vIP, nMaxSolutions, fAllowLookup); + if (!fRet) + return false; + vAddr.resize(vIP.size()); + for (int i = 0; i < vIP.size(); i++) + vAddr[i] = CService(vIP[i], port); + return true; +} + +bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup) +{ + std::vector vService; + bool fRet = Lookup(pszName, vService, portDefault, fAllowLookup, 1); if (!fRet) return false; - addr = CService(vIP[0], port); + addr = vService[0]; return true; } diff --git a/src/netbase.h b/src/netbase.h index 6f06f8fe..b12fb004 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -128,6 +128,7 @@ class CService : public CNetAddr bool LookupHost(const char *pszName, std::vector& vIP, int nMaxSolutions = 0, bool fAllowLookup = true); bool LookupHostNumeric(const char *pszName, std::vector& vIP, int nMaxSolutions = 0); bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true); +bool Lookup(const char *pszName, std::vector& vAddr, int portDefault = 0, bool fAllowLookup = true, int nMaxSolutions = 0); bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0); bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout);