Merge branch 'keepnode' of https://github.com/TheBlueMatt/bitcoin
authorGavin Andresen <gavinandresen@gmail.com>
Mon, 16 Jan 2012 21:45:43 +0000 (16:45 -0500)
committerGavin Andresen <gavinandresen@gmail.com>
Mon, 16 Jan 2012 21:45:43 +0000 (16:45 -0500)
1  2 
src/net.cpp
src/netbase.cpp

diff --combined src/net.cpp
@@@ -29,6 -29,7 +29,7 @@@ static const int MAX_OUTBOUND_CONNECTIO
  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 +62,9 @@@ CCriticalSection cs_mapRelay
  map<CInv, int64> mapAlreadyAskedFor;
  
  
+ set<CNetAddr> setservAddNodeAddresses;
+ CCriticalSection cs_setservAddNodeAddresses;
  
  
  
@@@ -750,7 -754,9 +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))
              {
@@@ -938,6 -944,7 +944,6 @@@ void ThreadMapPort2(void* parg
      char port[6];
      sprintf(port, "%d", GetListenPort());
  
 -    const char * rootdescurl = 0;
      const char * multicastif = 0;
      const char * minissdpdpath = 0;
      struct UPNPDev * devlist = 0;
      r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
      if (r == 1)
      {
 -        char intClient[16];
 -        char intPort[6];
          string strDesc = "Bitcoin " + FormatFullVersion();
  #ifndef UPNPDISCOVER_SUCCESS
      /* miniupnpc 1.5 */
@@@ -1211,22 -1220,6 +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
      }
  }
  
+ 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<vector<CService> > vservAddressesToAdd(0);
+     BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"])
+     {
+         vector<CService> 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<vector<CService> > 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<vector<CService> >::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<CService>& 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 -1694,10 +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 -1717,7 +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)
      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 --combined src/netbase.cpp
@@@ -25,9 -25,7 +25,9 @@@ static const unsigned char pchIPv4[12] 
  bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions, bool fAllowLookup)
  {
      vIP.clear();
 -    struct addrinfo aiHint = {};
 +    struct addrinfo aiHint;
 +    memset(&aiHint, 0, sizeof(struct addrinfo));
 +
      aiHint.ai_socktype = SOCK_STREAM;
      aiHint.ai_protocol = IPPROTO_TCP;
  #ifdef WIN32
@@@ -98,7 -96,7 +98,7 @@@ bool LookupHostNumeric(const char *pszN
      return LookupHost(pszName, vIP, nMaxSolutions, false);
  }
  
- bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup)
+ bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, int nMaxSolutions)
  {
      if (pszName[0] == 0)
          return false;
      }
  
      std::vector<CNetAddr> 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<CService> vService;
+     bool fRet = Lookup(pszName, vService, portDefault, fAllowLookup, 1);
      if (!fRet)
          return false;
-     addr = CService(vIP[0], port);
+     addr = vService[0];
      return true;
  }