Back to home page

Bitcoin sources

 
 

    


0001 // Copyright (c) 2009-2010 Satoshi Nakamoto
0002 // Copyright (c) 2009-2012 The Bitcoin developers
0003 // Distributed under the MIT/X11 software license, see the accompanying
0004 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
0005 
0006 #include "headers.h"
0007 #include "irc.h"
0008 #include "db.h"
0009 #include "net.h"
0010 #include "init.h"
0011 #include "strlcpy.h"
0012 
0013 
0014 using namespace std;
0015 using namespace boost;
0016 
0017 static const int MAX_OUTBOUND_CONNECTIONS = 8;
0018 
0019 void ThreadMessageHandler2(void* parg);
0020 void ThreadSocketHandler2(void* parg);
0021 void ThreadOpenConnections2(void* parg);
0022 void ThreadDNSAddressSeed2(void* parg);
0023 bool OpenNetworkConnection(const CAddress& addrConnect);
0024 
0025 
0026 
0027 
0028 
0029 //
0030 // Global state variables
0031 //
0032 bool fClient = false;
0033 bool fAllowDNS = false;
0034 uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
0035 CAddress addrLocalHost("0.0.0.0", 0, false, nLocalServices);
0036 static CNode* pnodeLocalHost = NULL;
0037 uint64 nLocalHostNonce = 0;
0038 array<int, 10> vnThreadsRunning;
0039 static SOCKET hListenSocket = INVALID_SOCKET;
0040 
0041 vector<CNode*> vNodes;
0042 CCriticalSection cs_vNodes;
0043 map<vector<unsigned char>, CAddress> mapAddresses;
0044 CCriticalSection cs_mapAddresses;
0045 map<CInv, CDataStream> mapRelay;
0046 deque<pair<int64, CInv> > vRelayExpiration;
0047 CCriticalSection cs_mapRelay;
0048 map<CInv, int64> mapAlreadyAskedFor;
0049 
0050 // Settings
0051 int fUseProxy = false;
0052 int nConnectTimeout = 5000;
0053 CAddress addrProxy("127.0.0.1",9050);
0054 
0055 
0056 
0057 
0058 unsigned short GetListenPort()
0059 {
0060     return (unsigned short)(GetArg("-port", GetDefaultPort()));
0061 }
0062 
0063 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
0064 {
0065     // Filter out duplicate requests
0066     if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
0067         return;
0068     pindexLastGetBlocksBegin = pindexBegin;
0069     hashLastGetBlocksEnd = hashEnd;
0070 
0071     PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
0072 }
0073 
0074 
0075 
0076 
0077 
0078 bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout)
0079 {
0080     hSocketRet = INVALID_SOCKET;
0081 
0082     SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
0083     if (hSocket == INVALID_SOCKET)
0084         return false;
0085 #ifdef SO_NOSIGPIPE
0086     int set = 1;
0087     setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
0088 #endif
0089 
0090     bool fProxy = (fUseProxy && addrConnect.IsRoutable());
0091     struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
0092 
0093     int fFlags = fcntl(hSocket, F_GETFL, 0);
0094     if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
0095 
0096     {
0097         closesocket(hSocket);
0098         return false;
0099     }
0100 
0101 
0102     if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
0103     {
0104         // WSAEINVAL is here because some legacy version of winsock uses it
0105         if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
0106         {
0107             struct timeval timeout;
0108             timeout.tv_sec  = nTimeout / 1000;
0109             timeout.tv_usec = (nTimeout % 1000) * 1000;
0110 
0111             fd_set fdset;
0112             FD_ZERO(&fdset);
0113             FD_SET(hSocket, &fdset);
0114             int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
0115             if (nRet == 0)
0116             {
0117                 printf("connection timeout\n");
0118                 closesocket(hSocket);
0119                 return false;
0120             }
0121             if (nRet == SOCKET_ERROR)
0122             {
0123                 printf("select() for connection failed: %i\n",WSAGetLastError());
0124                 closesocket(hSocket);
0125                 return false;
0126             }
0127             socklen_t nRetSize = sizeof(nRet);
0128             if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
0129             {
0130                 printf("getsockopt() for connection failed: %i\n",WSAGetLastError());
0131                 closesocket(hSocket);
0132                 return false;
0133             }
0134             if (nRet != 0)
0135             {
0136                 printf("connect() failed after select(): %s\n",strerror(nRet));
0137                 closesocket(hSocket);
0138                 return false;
0139             }
0140         }
0141         else
0142         {
0143             printf("connect() failed: %i\n",WSAGetLastError());
0144             closesocket(hSocket);
0145             return false;
0146         }
0147     }
0148 
0149     /*
0150     this isn't even strictly necessary
0151     CNode::ConnectNode immediately turns the socket back to non-blocking
0152     but we'll turn it back to blocking just in case
0153     */
0154     fFlags = fcntl(hSocket, F_GETFL, 0);
0155     if (fcntl(hSocket, F_SETFL, fFlags & !O_NONBLOCK) == SOCKET_ERROR)
0156     {
0157         closesocket(hSocket);
0158         return false;
0159     }
0160 
0161     if (fProxy)
0162     {
0163         printf("proxy connecting %s\n", addrConnect.ToString().c_str());
0164         char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
0165         memcpy(pszSocks4IP + 2, &addrConnect.port, 2);
0166         memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);
0167         char* pszSocks4 = pszSocks4IP;
0168         int nSize = sizeof(pszSocks4IP);
0169 
0170         int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
0171         if (ret != nSize)
0172         {
0173             closesocket(hSocket);
0174             return error("Error sending to proxy");
0175         }
0176         char pchRet[8];
0177         if (recv(hSocket, pchRet, 8, 0) != 8)
0178         {
0179             closesocket(hSocket);
0180             return error("Error reading proxy response");
0181         }
0182         if (pchRet[1] != 0x5a)
0183         {
0184             closesocket(hSocket);
0185             if (pchRet[1] != 0x5b)
0186                 printf("ERROR: Proxy returned error %d\n", pchRet[1]);
0187             return false;
0188         }
0189         printf("proxy connected %s\n", addrConnect.ToString().c_str());
0190     }
0191 
0192     hSocketRet = hSocket;
0193     return true;
0194 }
0195 
0196 // portDefault is in host order
0197 bool Lookup(const char *pszName, vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup, int portDefault, bool fAllowPort)
0198 {
0199     vaddr.clear();
0200     if (pszName[0] == 0)
0201         return false;
0202     int port = portDefault;
0203     char psz[256];
0204     char *pszHost = psz;
0205     strlcpy(psz, pszName, sizeof(psz));
0206     if (fAllowPort)
0207     {
0208         char* pszColon = strrchr(psz+1,':');
0209         char *pszPortEnd = NULL;
0210         int portParsed = pszColon ? strtoul(pszColon+1, &pszPortEnd, 10) : 0;
0211         if (pszColon && pszPortEnd && pszPortEnd[0] == 0)
0212         {
0213             if (psz[0] == '[' && pszColon[-1] == ']')
0214             {
0215                 // Future: enable IPv6 colon-notation inside []
0216                 pszHost = psz+1;
0217                 pszColon[-1] = 0;
0218             }
0219             else
0220                 pszColon[0] = 0;
0221             port = portParsed;
0222             if (port < 0 || port > USHRT_MAX)
0223                 port = USHRT_MAX;
0224         }
0225     }
0226 
0227     unsigned int addrIP = inet_addr(pszHost);
0228     if (addrIP != INADDR_NONE)
0229     {
0230         // valid IP address passed
0231         vaddr.push_back(CAddress(addrIP, port, nServices));
0232         return true;
0233     }
0234 
0235     if (!fAllowLookup)
0236         return false;
0237 
0238     struct hostent* phostent = gethostbyname(pszHost);
0239     if (!phostent)
0240         return false;
0241 
0242     if (phostent->h_addrtype != AF_INET)
0243         return false;
0244 
0245     char** ppAddr = phostent->h_addr_list;
0246     while (*ppAddr != NULL && vaddr.size() != nMaxSolutions)
0247     {
0248         CAddress addr(((struct in_addr*)ppAddr[0])->s_addr, port, nServices);
0249         if (addr.IsValid())
0250             vaddr.push_back(addr);
0251         ppAddr++;
0252     }
0253 
0254     return (vaddr.size() > 0);
0255 }
0256 
0257 // portDefault is in host order
0258 bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup, int portDefault, bool fAllowPort)
0259 {
0260     vector<CAddress> vaddr;
0261     bool fRet = Lookup(pszName, vaddr, nServices, 1, fAllowLookup, portDefault, fAllowPort);
0262     if (fRet)
0263         addr = vaddr[0];
0264     return fRet;
0265 }
0266 
0267 bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const char* pszKeyword, unsigned int& ipRet)
0268 {
0269     SOCKET hSocket;
0270     if (!ConnectSocket(addrConnect, hSocket))
0271         return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
0272 
0273     send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
0274 
0275     string strLine;
0276     while (RecvLine(hSocket, strLine))
0277     {
0278         if (strLine.empty()) // HTTP response is separated from headers by blank line
0279         {
0280             loop
0281             {
0282                 if (!RecvLine(hSocket, strLine))
0283                 {
0284                     closesocket(hSocket);
0285                     return false;
0286                 }
0287                 if (pszKeyword == NULL)
0288                     break;
0289                 if (strLine.find(pszKeyword) != -1)
0290                 {
0291                     strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
0292                     break;
0293                 }
0294             }
0295             closesocket(hSocket);
0296             if (strLine.find("<") != -1)
0297                 strLine = strLine.substr(0, strLine.find("<"));
0298             strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
0299             while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
0300                 strLine.resize(strLine.size()-1);
0301             CAddress addr(strLine,0,true);
0302             printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
0303             if (addr.ip == 0 || addr.ip == INADDR_NONE || !addr.IsRoutable())
0304                 return false;
0305             ipRet = addr.ip;
0306             return true;
0307         }
0308     }
0309     closesocket(hSocket);
0310     return error("GetMyExternalIP() : connection closed");
0311 }
0312 
0313 // We now get our external IP from the IRC server first and only use this as a backup
0314 bool GetMyExternalIP(unsigned int& ipRet)
0315 {
0316     CAddress addrConnect;
0317     const char* pszGet;
0318     const char* pszKeyword;
0319 
0320     if (fUseProxy)
0321         return false;
0322 
0323     for (int nLookup = 0; nLookup <= 1; nLookup++)
0324     for (int nHost = 1; nHost <= 2; nHost++)
0325     {
0326         // We should be phasing out our use of sites like these.  If we need
0327         // replacements, we should ask for volunteers to put this simple
0328         // php file on their webserver that prints the client IP:
0329         //  <?php echo $_SERVER["REMOTE_ADDR"]; ?>
0330         if (nHost == 1)
0331         {
0332             addrConnect = CAddress("91.198.22.70",80); // checkip.dyndns.org
0333 
0334             if (nLookup == 1)
0335             {
0336                 CAddress addrIP("checkip.dyndns.org", 80, true);
0337                 if (addrIP.IsValid())
0338                     addrConnect = addrIP;
0339             }
0340 
0341             pszGet = "GET / HTTP/1.1\r\n"
0342                      "Host: checkip.dyndns.org\r\n"
0343                      "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
0344                      "Connection: close\r\n"
0345                      "\r\n";
0346 
0347             pszKeyword = "Address:";
0348         }
0349         else if (nHost == 2)
0350         {
0351             addrConnect = CAddress("74.208.43.192", 80); // www.showmyip.com
0352 
0353             if (nLookup == 1)
0354             {
0355                 CAddress addrIP("www.showmyip.com", 80, true);
0356                 if (addrIP.IsValid())
0357                     addrConnect = addrIP;
0358             }
0359 
0360             pszGet = "GET /simple/ HTTP/1.1\r\n"
0361                      "Host: www.showmyip.com\r\n"
0362                      "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
0363                      "Connection: close\r\n"
0364                      "\r\n";
0365 
0366             pszKeyword = NULL; // Returns just IP address
0367         }
0368 
0369         if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
0370             return true;
0371     }
0372 
0373     return false;
0374 }
0375 
0376 void ThreadGetMyExternalIP(void* parg)
0377 {
0378     // Wait for IRC to get it first
0379     if (!GetBoolArg("-noirc"))
0380     {
0381         for (int i = 0; i < 2 * 60; i++)
0382         {
0383             Sleep(1000);
0384             if (fGotExternalIP || fShutdown)
0385                 return;
0386         }
0387     }
0388 
0389     // Fallback in case IRC fails to get it
0390     if (GetMyExternalIP(addrLocalHost.ip))
0391     {
0392         printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
0393         if (addrLocalHost.IsRoutable())
0394         {
0395             // If we already connected to a few before we had our IP, go back and addr them.
0396             // setAddrKnown automatically filters any duplicate sends.
0397             CAddress addr(addrLocalHost);
0398             addr.nTime = GetAdjustedTime();
0399             CRITICAL_BLOCK(cs_vNodes)
0400                 BOOST_FOREACH(CNode* pnode, vNodes)
0401                     pnode->PushAddress(addr);
0402         }
0403     }
0404 }
0405 
0406 
0407 
0408 
0409 
0410 bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB)
0411 {
0412     if (!addr.IsRoutable())
0413         return false;
0414     if (addr.ip == addrLocalHost.ip)
0415         return false;
0416     addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty);
0417     bool fUpdated = false;
0418     bool fNew = false;
0419     CAddress addrFound = addr;
0420 
0421     CRITICAL_BLOCK(cs_mapAddresses)
0422     {
0423         map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
0424         if (it == mapAddresses.end())
0425         {
0426             // New address
0427             printf("AddAddress(%s)\n", addr.ToString().c_str());
0428             mapAddresses.insert(make_pair(addr.GetKey(), addr));
0429             fUpdated = true;
0430             fNew = true;
0431         }
0432         else
0433         {
0434             addrFound = (*it).second;
0435             if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
0436             {
0437                 // Services have been added
0438                 addrFound.nServices |= addr.nServices;
0439                 fUpdated = true;
0440             }
0441             bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
0442             int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
0443             if (addrFound.nTime < addr.nTime - nUpdateInterval)
0444             {
0445                 // Periodically update most recently seen time
0446                 addrFound.nTime = addr.nTime;
0447                 fUpdated = true;
0448             }
0449         }
0450     }
0451     // There is a nasty deadlock bug if this is done inside the cs_mapAddresses
0452     // CRITICAL_BLOCK:
0453     // Thread 1:  begin db transaction (locks inside-db-mutex)
0454     //            then AddAddress (locks cs_mapAddresses)
0455     // Thread 2:  AddAddress (locks cs_mapAddresses)
0456     //             ... then db operation hangs waiting for inside-db-mutex
0457     if (fUpdated)
0458     {
0459         if (pAddrDB)
0460             pAddrDB->WriteAddress(addrFound);
0461         else
0462             CAddrDB().WriteAddress(addrFound);
0463     }
0464     return fNew;
0465 }
0466 
0467 void AddressCurrentlyConnected(const CAddress& addr)
0468 {
0469     CAddress *paddrFound = NULL;
0470 
0471     CRITICAL_BLOCK(cs_mapAddresses)
0472     {
0473         // Only if it's been published already
0474         map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
0475         if (it != mapAddresses.end())
0476             paddrFound = &(*it).second;
0477     }
0478 
0479     if (paddrFound)
0480     {
0481         int64 nUpdateInterval = 20 * 60;
0482         if (paddrFound->nTime < GetAdjustedTime() - nUpdateInterval)
0483         {
0484             // Periodically update most recently seen time
0485             paddrFound->nTime = GetAdjustedTime();
0486             CAddrDB addrdb;
0487             addrdb.WriteAddress(*paddrFound);
0488         }
0489     }
0490 }
0491 
0492 
0493 
0494 
0495 
0496 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
0497 {
0498     // If the dialog might get closed before the reply comes back,
0499     // call this in the destructor so it doesn't get called after it's deleted.
0500     CRITICAL_BLOCK(cs_vNodes)
0501     {
0502         BOOST_FOREACH(CNode* pnode, vNodes)
0503         {
0504             CRITICAL_BLOCK(pnode->cs_mapRequests)
0505             {
0506                 for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
0507                 {
0508                     CRequestTracker& tracker = (*mi).second;
0509                     if (tracker.fn == fn && tracker.param1 == param1)
0510                         pnode->mapRequests.erase(mi++);
0511                     else
0512                         mi++;
0513                 }
0514             }
0515         }
0516     }
0517 }
0518 
0519 
0520 
0521 
0522 
0523 
0524 
0525 //
0526 // Subscription methods for the broadcast and subscription system.
0527 // Channel numbers are message numbers, i.e. MSG_TABLE and MSG_PRODUCT.
0528 //
0529 // The subscription system uses a meet-in-the-middle strategy.
0530 // With 100,000 nodes, if senders broadcast to 1000 random nodes and receivers
0531 // subscribe to 1000 random nodes, 99.995% (1 - 0.99^1000) of messages will get through.
0532 //
0533 
0534 bool AnySubscribed(unsigned int nChannel)
0535 {
0536     if (pnodeLocalHost->IsSubscribed(nChannel))
0537         return true;
0538     CRITICAL_BLOCK(cs_vNodes)
0539         BOOST_FOREACH(CNode* pnode, vNodes)
0540             if (pnode->IsSubscribed(nChannel))
0541                 return true;
0542     return false;
0543 }
0544 
0545 bool CNode::IsSubscribed(unsigned int nChannel)
0546 {
0547     if (nChannel >= vfSubscribe.size())
0548         return false;
0549     return vfSubscribe[nChannel];
0550 }
0551 
0552 void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
0553 {
0554     if (nChannel >= vfSubscribe.size())
0555         return;
0556 
0557     if (!AnySubscribed(nChannel))
0558     {
0559         // Relay subscribe
0560         CRITICAL_BLOCK(cs_vNodes)
0561             BOOST_FOREACH(CNode* pnode, vNodes)
0562                 if (pnode != this)
0563                     pnode->PushMessage("subscribe", nChannel, nHops);
0564     }
0565 
0566     vfSubscribe[nChannel] = true;
0567 }
0568 
0569 void CNode::CancelSubscribe(unsigned int nChannel)
0570 {
0571     if (nChannel >= vfSubscribe.size())
0572         return;
0573 
0574     // Prevent from relaying cancel if wasn't subscribed
0575     if (!vfSubscribe[nChannel])
0576         return;
0577     vfSubscribe[nChannel] = false;
0578 
0579     if (!AnySubscribed(nChannel))
0580     {
0581         // Relay subscription cancel
0582         CRITICAL_BLOCK(cs_vNodes)
0583             BOOST_FOREACH(CNode* pnode, vNodes)
0584                 if (pnode != this)
0585                     pnode->PushMessage("sub-cancel", nChannel);
0586     }
0587 }
0588 
0589 
0590 
0591 
0592 
0593 
0594 
0595 
0596 
0597 CNode* FindNode(unsigned int ip)
0598 {
0599     CRITICAL_BLOCK(cs_vNodes)
0600     {
0601         BOOST_FOREACH(CNode* pnode, vNodes)
0602             if (pnode->addr.ip == ip)
0603                 return (pnode);
0604     }
0605     return NULL;
0606 }
0607 
0608 CNode* FindNode(CAddress addr)
0609 {
0610     CRITICAL_BLOCK(cs_vNodes)
0611     {
0612         BOOST_FOREACH(CNode* pnode, vNodes)
0613             if (pnode->addr == addr)
0614                 return (pnode);
0615     }
0616     return NULL;
0617 }
0618 
0619 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
0620 {
0621     if (addrConnect.ip == addrLocalHost.ip)
0622         return NULL;
0623 
0624     // Look for an existing connection
0625     CNode* pnode = FindNode(addrConnect.ip);
0626     if (pnode)
0627     {
0628         if (nTimeout != 0)
0629             pnode->AddRef(nTimeout);
0630         else
0631             pnode->AddRef();
0632         return pnode;
0633     }
0634 
0635     /// debug print
0636     printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",
0637         addrConnect.ToString().c_str(),
0638         (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
0639         (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
0640 
0641     CRITICAL_BLOCK(cs_mapAddresses)
0642         mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
0643 
0644     // Connect
0645     SOCKET hSocket;
0646     if (ConnectSocket(addrConnect, hSocket))
0647     {
0648         /// debug print
0649         printf("connected %s\n", addrConnect.ToString().c_str());
0650 
0651         // Set to nonblocking
0652         if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
0653             printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
0654 
0655         // Add node
0656         CNode* pnode = new CNode(hSocket, addrConnect, false);
0657         if (nTimeout != 0)
0658             pnode->AddRef(nTimeout);
0659         else
0660             pnode->AddRef();
0661         CRITICAL_BLOCK(cs_vNodes)
0662             vNodes.push_back(pnode);
0663 
0664         pnode->nTimeConnected = GetTime();
0665         return pnode;
0666     }
0667     else
0668     {
0669         return NULL;
0670     }
0671 }
0672 
0673 void CNode::CloseSocketDisconnect()
0674 {
0675     fDisconnect = true;
0676     if (hSocket != INVALID_SOCKET)
0677     {
0678         if (fDebug)
0679             printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
0680         printf("disconnecting node %s\n", addr.ToString().c_str());
0681         closesocket(hSocket);
0682         hSocket = INVALID_SOCKET;
0683     }
0684 }
0685 
0686 void CNode::Cleanup()
0687 {
0688     // All of a nodes broadcasts and subscriptions are automatically torn down
0689     // when it goes down, so a node has to stay up to keep its broadcast going.
0690 
0691     // Cancel subscriptions
0692     for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
0693         if (vfSubscribe[nChannel])
0694             CancelSubscribe(nChannel);
0695 }
0696 
0697 
0698 std::map<unsigned int, int64> CNode::setBanned;
0699 CCriticalSection CNode::cs_setBanned;
0700 
0701 void CNode::ClearBanned()
0702 {
0703     setBanned.clear();
0704 }
0705 
0706 bool CNode::IsBanned(unsigned int ip)
0707 {
0708     bool fResult = false;
0709     CRITICAL_BLOCK(cs_setBanned)
0710     {
0711         std::map<unsigned int, int64>::iterator i = setBanned.find(ip);
0712         if (i != setBanned.end())
0713         {
0714             int64 t = (*i).second;
0715             if (GetTime() < t)
0716                 fResult = true;
0717         }
0718     }
0719     return fResult;
0720 }
0721 
0722 bool CNode::Misbehaving(int howmuch)
0723 {
0724     if (addr.IsLocal())
0725     {
0726         printf("Warning: local node %s misbehaving\n", addr.ToString().c_str());
0727         return false;
0728     }
0729 
0730     nMisbehavior += howmuch;
0731     if (nMisbehavior >= GetArg("-banscore", 100))
0732     {
0733         int64 banTime = GetTime()+GetArg("-bantime", 60*60*24);  // Default 24-hour ban
0734         CRITICAL_BLOCK(cs_setBanned)
0735             if (setBanned[addr.ip] < banTime)
0736                 setBanned[addr.ip] = banTime;
0737         CloseSocketDisconnect();
0738         printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior);
0739         return true;
0740     }
0741     return false;
0742 }
0743 
0744 
0745 
0746 
0747 
0748 
0749 
0750 
0751 
0752 
0753 
0754 
0755 void ThreadSocketHandler(void* parg)
0756 {
0757     IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
0758     try
0759     {
0760         vnThreadsRunning[0]++;
0761         ThreadSocketHandler2(parg);
0762         vnThreadsRunning[0]--;
0763     }
0764     catch (std::exception& e) {
0765         vnThreadsRunning[0]--;
0766         PrintException(&e, "ThreadSocketHandler()");
0767     } catch (...) {
0768         vnThreadsRunning[0]--;
0769         throw; // support pthread_cancel()
0770     }
0771     printf("ThreadSocketHandler exiting\n");
0772 }
0773 
0774 void ThreadSocketHandler2(void* parg)
0775 {
0776     printf("ThreadSocketHandler started\n");
0777     list<CNode*> vNodesDisconnected;
0778     int nPrevNodeCount = 0;
0779 
0780     loop
0781     {
0782         //
0783         // Disconnect nodes
0784         //
0785         CRITICAL_BLOCK(cs_vNodes)
0786         {
0787             // Disconnect unused nodes
0788             vector<CNode*> vNodesCopy = vNodes;
0789             BOOST_FOREACH(CNode* pnode, vNodesCopy)
0790             {
0791                 if (pnode->fDisconnect ||
0792                     (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
0793                 {
0794                     // remove from vNodes
0795                     vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
0796 
0797                     // close socket and cleanup
0798                     pnode->CloseSocketDisconnect();
0799                     pnode->Cleanup();
0800 
0801                     // hold in disconnected pool until all refs are released
0802                     pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
0803                     if (pnode->fNetworkNode || pnode->fInbound)
0804                         pnode->Release();
0805                     vNodesDisconnected.push_back(pnode);
0806                 }
0807             }
0808 
0809             // Delete disconnected nodes
0810             list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
0811             BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
0812             {
0813                 // wait until threads are done using it
0814                 if (pnode->GetRefCount() <= 0)
0815                 {
0816                     bool fDelete = false;
0817                     TRY_CRITICAL_BLOCK(pnode->cs_vSend)
0818                      TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
0819                       TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
0820                        TRY_CRITICAL_BLOCK(pnode->cs_inventory)
0821                         fDelete = true;
0822                     if (fDelete)
0823                     {
0824                         vNodesDisconnected.remove(pnode);
0825                         delete pnode;
0826                     }
0827                 }
0828             }
0829         }
0830         if (vNodes.size() != nPrevNodeCount)
0831         {
0832             nPrevNodeCount = vNodes.size();
0833             MainFrameRepaint();
0834         }
0835 
0836 
0837         //
0838         // Find which sockets have data to receive
0839         //
0840         struct timeval timeout;
0841         timeout.tv_sec  = 0;
0842         timeout.tv_usec = 50000; // frequency to poll pnode->vSend
0843 
0844         fd_set fdsetRecv;
0845         fd_set fdsetSend;
0846         fd_set fdsetError;
0847         FD_ZERO(&fdsetRecv);
0848         FD_ZERO(&fdsetSend);
0849         FD_ZERO(&fdsetError);
0850         SOCKET hSocketMax = 0;
0851 
0852         if(hListenSocket != INVALID_SOCKET)
0853             FD_SET(hListenSocket, &fdsetRecv);
0854         hSocketMax = max(hSocketMax, hListenSocket);
0855         CRITICAL_BLOCK(cs_vNodes)
0856         {
0857             BOOST_FOREACH(CNode* pnode, vNodes)
0858             {
0859                 if (pnode->hSocket == INVALID_SOCKET)
0860                     continue;
0861                 FD_SET(pnode->hSocket, &fdsetRecv);
0862                 FD_SET(pnode->hSocket, &fdsetError);
0863                 hSocketMax = max(hSocketMax, pnode->hSocket);
0864                 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
0865                     if (!pnode->vSend.empty())
0866                         FD_SET(pnode->hSocket, &fdsetSend);
0867             }
0868         }
0869 
0870         vnThreadsRunning[0]--;
0871         int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
0872         vnThreadsRunning[0]++;
0873         if (fShutdown)
0874             return;
0875         if (nSelect == SOCKET_ERROR)
0876         {
0877             int nErr = WSAGetLastError();
0878             if (hSocketMax > -1)
0879             {
0880                 printf("socket select error %d\n", nErr);
0881                 for (int i = 0; i <= hSocketMax; i++)
0882                     FD_SET(i, &fdsetRecv);
0883             }
0884             FD_ZERO(&fdsetSend);
0885             FD_ZERO(&fdsetError);
0886             Sleep(timeout.tv_usec/1000);
0887         }
0888 
0889 
0890         //
0891         // Accept new connections
0892         //
0893         if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
0894         {
0895             struct sockaddr_in sockaddr;
0896             socklen_t len = sizeof(sockaddr);
0897             SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
0898             CAddress addr;
0899             int nInbound = 0;
0900 
0901             if (hSocket != INVALID_SOCKET)
0902                 addr = CAddress(sockaddr);
0903 
0904             CRITICAL_BLOCK(cs_vNodes)
0905                 BOOST_FOREACH(CNode* pnode, vNodes)
0906                 if (pnode->fInbound)
0907                     nInbound++;
0908 
0909             if (hSocket == INVALID_SOCKET)
0910             {
0911                 if (WSAGetLastError() != WSAEWOULDBLOCK)
0912                     printf("socket error accept failed: %d\n", WSAGetLastError());
0913             }
0914             else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
0915             {
0916                 closesocket(hSocket);
0917             }
0918             else if (CNode::IsBanned(addr.ip))
0919             {
0920                 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
0921                 closesocket(hSocket);
0922             }
0923             else
0924             {
0925                 printf("accepted connection %s\n", addr.ToString().c_str());
0926                 CNode* pnode = new CNode(hSocket, addr, true);
0927                 pnode->AddRef();
0928                 CRITICAL_BLOCK(cs_vNodes)
0929                     vNodes.push_back(pnode);
0930             }
0931         }
0932 
0933 
0934         //
0935         // Service each socket
0936         //
0937         vector<CNode*> vNodesCopy;
0938         CRITICAL_BLOCK(cs_vNodes)
0939         {
0940             vNodesCopy = vNodes;
0941             BOOST_FOREACH(CNode* pnode, vNodesCopy)
0942                 pnode->AddRef();
0943         }
0944         BOOST_FOREACH(CNode* pnode, vNodesCopy)
0945         {
0946             if (fShutdown)
0947                 return;
0948 
0949             //
0950             // Receive
0951             //
0952             if (pnode->hSocket == INVALID_SOCKET)
0953                 continue;
0954             if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
0955             {
0956                 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
0957                 {
0958                     CDataStream& vRecv = pnode->vRecv;
0959                     unsigned int nPos = vRecv.size();
0960 
0961                     if (nPos > ReceiveBufferSize()) {
0962                         if (!pnode->fDisconnect)
0963                             printf("socket recv flood control disconnect (%d bytes)\n", vRecv.size());
0964                         pnode->CloseSocketDisconnect();
0965                     }
0966                     else {
0967                         // typical socket buffer is 8K-64K
0968                         char pchBuf[0x10000];
0969                         int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
0970                         if (nBytes > 0)
0971                         {
0972                             vRecv.resize(nPos + nBytes);
0973                             memcpy(&vRecv[nPos], pchBuf, nBytes);
0974                             pnode->nLastRecv = GetTime();
0975                         }
0976                         else if (nBytes == 0)
0977                         {
0978                             // socket closed gracefully
0979                             if (!pnode->fDisconnect)
0980                                 printf("socket closed\n");
0981                             pnode->CloseSocketDisconnect();
0982                         }
0983                         else if (nBytes < 0)
0984                         {
0985                             // error
0986                             int nErr = WSAGetLastError();
0987                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
0988                             {
0989                                 if (!pnode->fDisconnect)
0990                                     printf("socket recv error %d\n", nErr);
0991                                 pnode->CloseSocketDisconnect();
0992                             }
0993                         }
0994                     }
0995                 }
0996             }
0997 
0998             //
0999             // Send
1000             //
1001             if (pnode->hSocket == INVALID_SOCKET)
1002                 continue;
1003             if (FD_ISSET(pnode->hSocket, &fdsetSend))
1004             {
1005                 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
1006                 {
1007                     CDataStream& vSend = pnode->vSend;
1008                     if (!vSend.empty())
1009                     {
1010                         int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
1011                         if (nBytes > 0)
1012                         {
1013                             vSend.erase(vSend.begin(), vSend.begin() + nBytes);
1014                             pnode->nLastSend = GetTime();
1015                         }
1016                         else if (nBytes < 0)
1017                         {
1018                             // error
1019                             int nErr = WSAGetLastError();
1020                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
1021                             {
1022                                 printf("socket send error %d\n", nErr);
1023                                 pnode->CloseSocketDisconnect();
1024                             }
1025                         }
1026                         if (vSend.size() > SendBufferSize()) {
1027                             if (!pnode->fDisconnect)
1028                                 printf("socket send flood control disconnect (%d bytes)\n", vSend.size());
1029                             pnode->CloseSocketDisconnect();
1030                         }
1031                     }
1032                 }
1033             }
1034 
1035             //
1036             // Inactivity checking
1037             //
1038             if (pnode->vSend.empty())
1039                 pnode->nLastSendEmpty = GetTime();
1040             if (GetTime() - pnode->nTimeConnected > 60)
1041             {
1042                 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
1043                 {
1044                     printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
1045                     pnode->fDisconnect = true;
1046                 }
1047                 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
1048                 {
1049                     printf("socket not sending\n");
1050                     pnode->fDisconnect = true;
1051                 }
1052                 else if (GetTime() - pnode->nLastRecv > 90*60)
1053                 {
1054                     printf("socket inactivity timeout\n");
1055                     pnode->fDisconnect = true;
1056                 }
1057             }
1058         }
1059         CRITICAL_BLOCK(cs_vNodes)
1060         {
1061             BOOST_FOREACH(CNode* pnode, vNodesCopy)
1062                 pnode->Release();
1063         }
1064 
1065         Sleep(10);
1066     }
1067 }
1068 
1069 
1070 
1071 
1072 
1073 
1074 
1075 
1076 
1077 
1078 
1079 
1080 
1081 
1082 
1083 
1084 
1085 
1086 
1087 static const char *strDNSSeed[] = {
1088     "bitseed.xf2.org",
1089     "dnsseed.bluematt.me",
1090     "seed.bitcoin.sipa.be",
1091     "dnsseed.bitcoin.dashjr.org",
1092 };
1093 
1094 void ThreadDNSAddressSeed(void* parg)
1095 {
1096     IMPLEMENT_RANDOMIZE_STACK(ThreadDNSAddressSeed(parg));
1097     try
1098     {
1099         vnThreadsRunning[6]++;
1100         ThreadDNSAddressSeed2(parg);
1101         vnThreadsRunning[6]--;
1102     }
1103     catch (std::exception& e) {
1104         vnThreadsRunning[6]--;
1105         PrintException(&e, "ThreadDNSAddressSeed()");
1106     } catch (...) {
1107         vnThreadsRunning[6]--;
1108         throw; // support pthread_cancel()
1109     }
1110     printf("ThreadDNSAddressSeed exiting\n");
1111 }
1112 
1113 void ThreadDNSAddressSeed2(void* parg)
1114 {
1115     printf("ThreadDNSAddressSeed started\n");
1116     int found = 0;
1117 
1118     if (!fTestNet)
1119     {
1120         printf("Loading addresses from DNS seeds (could take a while)\n");
1121 
1122         for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1123             vector<CAddress> vaddr;
1124             if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, -1, true))
1125             {
1126                 CAddrDB addrDB;
1127                 addrDB.TxnBegin();
1128                 BOOST_FOREACH (CAddress& addr, vaddr)
1129                 {
1130                     if (addr.GetByte(3) != 127)
1131                     {
1132                         addr.nTime = 0;
1133                         AddAddress(addr, 0, &addrDB);
1134                         found++;
1135                     }
1136                 }
1137                 addrDB.TxnCommit();  // Save addresses (it's ok if this fails)
1138             }
1139         }
1140     }
1141 
1142     printf("%d addresses found from DNS seeds\n", found);
1143 }
1144 
1145 
1146 
1147 
1148 
1149 
1150 
1151 
1152 
1153 
1154 
1155 
1156 unsigned int pnSeed[] =
1157 {
1158     0x959bd347, 0xf8de42b2, 0x73bc0518, 0xea6edc50, 0x21b00a4d, 0xc725b43d, 0xd665464d, 0x1a2a770e,
1159     0x27c93946, 0x65b2fa46, 0xb80ae255, 0x66b3b446, 0xb1877a3e, 0x6ee89e3e, 0xc3175b40, 0x2a01a83c,
1160     0x95b1363a, 0xa079ad3d, 0xe6ca801f, 0x027f4f4a, 0x34f7f03a, 0xf790f04a, 0x16ca801f, 0x2f4d5e40,
1161     0x3a4d5e40, 0xc43a322e, 0xc8159753, 0x14d4724c, 0x7919a118, 0xe0bdb34e, 0x68a16b2e, 0xff64b44d,
1162     0x6099115b, 0x9b57b05b, 0x7bd1b4ad, 0xdf95944f, 0x29d2b73d, 0xafa8db79, 0xe247ba41, 0x24078348,
1163     0xf722f03c, 0x33567ebc, 0xace64ed4, 0x984d3932, 0xb5f34e55, 0x27b7024d, 0x94579247, 0x8894042e,
1164     0x9357d34c, 0x1063c24b, 0xcaa228b1, 0xa3c5a8b2, 0x5dc64857, 0xa2c23643, 0xa8369a54, 0x31203077,
1165     0x00707c5c, 0x09fc0b3a, 0x272e9e2e, 0xf80f043e, 0x9449ca3e, 0x5512c33e, 0xd106b555, 0xe8024157,
1166     0xe288ec29, 0xc79c5461, 0xafb63932, 0xdb02ab4b, 0x0e512777, 0x8a145a4c, 0xb201ff4f, 0x5e09314b,
1167     0xcd9bfbcd, 0x1c023765, 0x4394e75c, 0xa728bd4d, 0x65331552, 0xa98420b1, 0x89ecf559, 0x6e80801f,
1168     0xf404f118, 0xefd62b51, 0x05918346, 0x9b186d5f, 0xacabab46, 0xf912e255, 0xc188ea62, 0xcc55734e,
1169     0xc668064d, 0xd77a4558, 0x46201c55, 0xf17dfc80, 0xf7142f2e, 0x87bfb718, 0x8aa54fb2, 0xc451d518,
1170     0xc4ae8831, 0x8dd44d55, 0x5bbd206c, 0x64536b5d, 0x5c667e60, 0x3b064242, 0xfe963a42, 0xa28e6dc8,
1171     0xe8a9604a, 0xc989464e, 0xd124a659, 0x50065140, 0xa44dfe5e, 0x1079e655, 0x3fb986d5, 0x47895b18,
1172     0x7d3ce4ad, 0x4561ba50, 0x296eec62, 0x255b41ad, 0xaed35ec9, 0x55556f12, 0xc7d3154d, 0x3297b65d,
1173     0x8930121f, 0xabf42e4e, 0x4a29e044, 0x1212685d, 0x676c1e40, 0xce009744, 0x383a8948, 0xa2dbd0ad,
1174     0xecc2564d, 0x07dbc252, 0x887ee24b, 0x5171644c, 0x6bb798c1, 0x847f495d, 0x4cbb7145, 0x3bb81c32,
1175     0x45eb262e, 0xc8015a4e, 0x250a361b, 0xf694f946, 0xd64a183e, 0xd4f1dd59, 0x8f20ffd4, 0x51d9e55c,
1176     0x09521763, 0x5e02002e, 0x32c8074d, 0xe685762e, 0x8290b0bc, 0x762a922e, 0xfc5ee754, 0x83a24829,
1177     0x775b224d, 0x6295bb4d, 0x38ec0555, 0xbffbba50, 0xe5560260, 0x86b16a7c, 0xd372234e, 0x49a3c24b,
1178     0x2f6a171f, 0x4d75ed60, 0xae94115b, 0xcb543744, 0x63080c59, 0x3f9c724c, 0xc977ce18, 0x532efb18,
1179     0x69dc3b2e, 0x5f94d929, 0x1732bb4d, 0x9c814b4d, 0xe6b3762e, 0xc024f662, 0x8face35b, 0x6b5b044d,
1180     0x798c7b57, 0x79a6b44c, 0x067d3057, 0xf9e94e5f, 0x91cbe15b, 0x71405eb2, 0x2662234e, 0xcbcc4a6d,
1181     0xbf69d54b, 0xa79b4e55, 0xec6d3e51, 0x7c0b3c02, 0x60f83653, 0x24c1e15c, 0x1110b62e, 0x10350f59,
1182     0xa56f1d55, 0x3509e7a9, 0xeb128354, 0x14268e2e, 0x934e28bc, 0x8e32692e, 0x8331a21f, 0x3e633932,
1183     0xc812b12e, 0xc684bf2e, 0x80112d2e, 0xe0ddc96c, 0xc630ca4a, 0x5c09b3b2, 0x0b580518, 0xc8e9d54b,
1184     0xd169aa43, 0x17d0d655, 0x1d029963, 0x7ff87559, 0xcb701f1f, 0x6fa3e85d, 0xe45e9a54, 0xf05d1802,
1185     0x44d03b2e, 0x837b692e, 0xccd4354e, 0x3d6da13c, 0x3423084d, 0xf707c34a, 0x55f6db3a, 0xad26e442,
1186     0x6233a21f, 0x09e80e59, 0x8caeb54d, 0xbe870941, 0xb407d20e, 0x20b51018, 0x56fb152e, 0x460d2a4e,
1187     0xbb9a2946, 0x560eb12e, 0xed83dd29, 0xd6724f53, 0xa50aafb8, 0x451346d9, 0x88348e2e, 0x7312fead,
1188     0x8ecaf96f, 0x1bda4e5f, 0xf1671e40, 0x3c8c3e3b, 0x4716324d, 0xdde24ede, 0xf98cd17d, 0xa91d4644,
1189     0x28124eb2, 0x147d5129, 0xd022042e, 0x61733d3b, 0xad0d5e02, 0x8ce2932e, 0xe5c18502, 0x549c1e32,
1190     0x9685801f, 0x86e217ad, 0xd948214b, 0x4110f462, 0x3a2e894e, 0xbd35492e, 0x87e0d558, 0x64b8ef7d,
1191     0x7c3eb962, 0x72a84b3e, 0x7cd667c9, 0x28370a2e, 0x4bc60e7b, 0x6fc1ec60, 0x14a6983f, 0x86739a4b,
1192     0x46954e5f, 0x32e2e15c, 0x2e9326cf, 0xe5801c5e, 0x379607b2, 0x32151145, 0xf0e39744, 0xacb54c55,
1193     0xa37dfb60, 0x83b55cc9, 0x388f7ca5, 0x15034f5f, 0x3e94965b, 0x68e0ffad, 0x35280f59, 0x8fe190cf,
1194     0x7c6ba5b2, 0xa5e9db43, 0x4ee1fc60, 0xd9d94e5f, 0x04040677, 0x0ea9b35e, 0x5961f14f, 0x67fda063,
1195     0xa48a5a31, 0xc6524e55, 0x283d325e, 0x3f37515f, 0x96b94b3e, 0xacce620e, 0x6481cc5b, 0xa4a06d4b,
1196     0x9e95d2d9, 0xe40c03d5, 0xc2f4514b, 0xb79aad44, 0xf64be843, 0xb2064070, 0xfca00455, 0x429dfa4e,
1197     0x2323f173, 0xeda4185e, 0xabd5227d, 0x9efd4d58, 0xb1104758, 0x4811e955, 0xbd9ab355, 0xe921f44b,
1198     0x9f166dce, 0x09e279b2, 0xe0c9ac7b, 0x7901a5ad, 0xa145d4b0, 0x79104671, 0xec31e35a, 0x4fe0b555,
1199     0xc7d9cbad, 0xad057f55, 0xe94cc759, 0x7fe0b043, 0xe4529f2e, 0x0d4dd4b2, 0x9f11a54d, 0x031e2e4e,
1200     0xe6014f5f, 0x11d1ca6c, 0x26bd7f61, 0xeb86854f, 0x4d347b57, 0x116bbe2e, 0xdba7234e, 0x7bcbfd2e,
1201     0x174dd4b2, 0x6686762e, 0xb089ba50, 0xc6258246, 0x087e767b, 0xc4a8cb4a, 0x595dba50, 0x7f0ae502,
1202     0x7b1dbd5a, 0xa0603492, 0x57d1af4b, 0x9e21ffd4, 0x6393064d, 0x7407376e, 0xe484762e, 0x122a4e53,
1203     0x4a37aa43, 0x3888a6be, 0xee77864e, 0x039c8dd5, 0x688d89af, 0x0e988f62, 0x08218246, 0xfc2f8246,
1204     0xd1d97040, 0xd64cd4b2, 0x5ae4a6b8, 0x7d0de9bc, 0x8d304d61, 0x06c5c672, 0xa4c8bd4d, 0xe0fd373b,
1205     0x575ebe4d, 0x72d26277, 0x55570f55, 0x77b154d9, 0xe214293a, 0xfc740f4b, 0xfe3f6a57, 0xa9c55f02,
1206     0xae4054db, 0x2394d918, 0xb511b24a, 0xb8741ab2, 0x0758e65e, 0xc7b5795b, 0xb0a30a4c, 0xaf7f170c,
1207     0xf3b4762e, 0x8179576d, 0x738a1581, 0x4b95b64c, 0x9829b618, 0x1bea932e, 0x7bdeaa4b, 0xcb5e0281,
1208     0x65618f54, 0x0658474b, 0x27066acf, 0x40556d65, 0x7d204d53, 0xf28bc244, 0xdce23455, 0xadc0ff54,
1209     0x3863c948, 0xcee34e5f, 0xdeb85e02, 0x2ed17a61, 0x6a7b094d, 0x7f0cfc40, 0x59603f54, 0x3220afbc,
1210     0xb5dfd962, 0x125d21c0, 0x13f8d243, 0xacfefb4e, 0x86c2c147, 0x3d8bbd59, 0xbd02a21f, 0x2593042e,
1211     0xc6a17a7c, 0x28925861, 0xb487ed44, 0xb5f4fd6d, 0x90c28a45, 0x5a14f74d, 0x43d71b4c, 0x728ebb5d,
1212     0x885bf950, 0x08134dd0, 0x38ec046e, 0xc575684b, 0x50082d2e, 0xa2f47757, 0x270f86ae, 0xf3ff6462,
1213     0x10ed3f4e, 0x4b58d462, 0xe01ce23e, 0x8c5b092e, 0x63e52f4e, 0x22c1e85d, 0xa908f54e, 0x8591624f,
1214     0x2c0fb94e, 0xa280ba3c, 0xb6f41b4c, 0x24f9aa47, 0x27201647, 0x3a3ea6dc, 0xa14fc3be, 0x3c34bdd5,
1215     0x5b8d4f5b, 0xaadeaf4b, 0xc71cab50, 0x15697a4c, 0x9a1a734c, 0x2a037d81, 0x2590bd59, 0x48ec2741,
1216     0x53489c5b, 0x7f00314b, 0x2170d362, 0xf2e92542, 0x42c10b44, 0x98f0f118, 0x883a3456, 0x099a932e,
1217     0xea38f7bc, 0x644e9247, 0xbb61b62e, 0x30e0863d, 0x5f51be54, 0x207215c7, 0x5f306c45, 0xaa7f3932,
1218     0x98da7d45, 0x4e339b59, 0x2e411581, 0xa808f618, 0xad2c0c59, 0x54476741, 0x09e99fd1, 0x5db8f752,
1219     0xc16df8bd, 0x1dd4b44f, 0x106edf2e, 0x9e15c180, 0x2ad6b56f, 0x633a5332, 0xff33787c, 0x077cb545,
1220     0x6610be6d, 0x75aad2c4, 0x72fb4d5b, 0xe81e0f59, 0x576f6332, 0x47333373, 0x351ed783, 0x2d90fb50,
1221     0x8d5e0f6c, 0x5b27a552, 0xdb293ebb, 0xe55ef950, 0x4b133ad8, 0x75df975a, 0x7b6a8740, 0xa899464b,
1222     0xfab15161, 0x10f8b64d, 0xd055ea4d, 0xee8e146b, 0x4b14afb8, 0x4bc1c44a, 0x9b961dcc, 0xd111ff43,
1223     0xfca0b745, 0xc800e412, 0x0afad9d1, 0xf751c350, 0xf9f0cccf, 0xa290a545, 0x8ef13763, 0x7ec70d59,
1224     0x2b066acf, 0x65496c45, 0xade02c1b, 0xae6eb077, 0x92c1e65b, 0xc064e6a9, 0xc649e56d, 0x5287a243,
1225     0x36de4f5b, 0x5b1df6ad, 0x65c39a59, 0xdba805b2, 0x20067aa8, 0x6457e56d, 0x3cee26cf, 0xfd3ff26d,
1226     0x04f86d4a, 0x06b8e048, 0xa93bcd5c, 0x91135852, 0xbe90a643, 0x8fa0094d, 0x06d8215f, 0x2677094d,
1227     0xd735685c, 0x164a00c9, 0x5209ac5f, 0xa9564c5c, 0x3b504f5f, 0xcc826bd0, 0x4615042e, 0x5fe13b4a,
1228     0x8c81b86d, 0x879ab68c, 0x1de564b8, 0x434487d8, 0x2dcb1b63, 0x82ab524a, 0xb0676abb, 0xa13d9c62,
1229     0xdbb5b86d, 0x5b7f4b59, 0xaddfb44d, 0xad773532, 0x3997054c, 0x72cebd89, 0xb194544c, 0xc5b8046e,
1230     0x6e1adeb2, 0xaa5abb51, 0xefb54b44, 0x15efc54f, 0xe9f1bc4d, 0x5f401b6c, 0x97f018ad, 0xc82f9252,
1231     0x2cdc762e, 0x8e52e56d, 0x1827175e, 0x9b7d7d80, 0xb2ad6845, 0x51065140, 0x71180a18, 0x5b27006c,
1232     0x0621e255, 0x721cbe58, 0x670c0cb8, 0xf8bd715d, 0xe0bdc5d9, 0xed843501, 0x4b84554d, 0x7f1a18bc,
1233     0x53bcaf47, 0x5729d35f, 0xf0dda246, 0x22382bd0, 0x4d641fb0, 0x316afcde, 0x50a22f1f, 0x73608046,
1234     0xc461d84a, 0xb2dbe247,
1235 };
1236 
1237 
1238 
1239 void ThreadOpenConnections(void* parg)
1240 {
1241     IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
1242     try
1243     {
1244         vnThreadsRunning[1]++;
1245         ThreadOpenConnections2(parg);
1246         vnThreadsRunning[1]--;
1247     }
1248     catch (std::exception& e) {
1249         vnThreadsRunning[1]--;
1250         PrintException(&e, "ThreadOpenConnections()");
1251     } catch (...) {
1252         vnThreadsRunning[1]--;
1253         PrintException(NULL, "ThreadOpenConnections()");
1254     }
1255     printf("ThreadOpenConnections exiting\n");
1256 }
1257 
1258 void ThreadOpenConnections2(void* parg)
1259 {
1260     printf("ThreadOpenConnections started\n");
1261 
1262     // Connect to specific addresses
1263     if (mapArgs.count("-connect"))
1264     {
1265         for (int64 nLoop = 0;; nLoop++)
1266         {
1267             BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1268             {
1269                 CAddress addr(strAddr, fAllowDNS);
1270                 if (addr.IsValid())
1271                     OpenNetworkConnection(addr);
1272                 for (int i = 0; i < 10 && i < nLoop; i++)
1273                 {
1274                     Sleep(500);
1275                     if (fShutdown)
1276                         return;
1277                 }
1278             }
1279         }
1280     }
1281 
1282     // Connect to manually added nodes first
1283     if (mapArgs.count("-addnode"))
1284     {
1285         BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
1286         {
1287             CAddress addr(strAddr, fAllowDNS);
1288             if (addr.IsValid())
1289             {
1290                 OpenNetworkConnection(addr);
1291                 Sleep(500);
1292                 if (fShutdown)
1293                     return;
1294             }
1295         }
1296     }
1297 
1298     // Initiate network connections
1299     int64 nStart = GetTime();
1300     loop
1301     {
1302         vnThreadsRunning[1]--;
1303         Sleep(500);
1304         vnThreadsRunning[1]++;
1305         if (fShutdown)
1306             return;
1307 
1308         // Limit outbound connections
1309         loop
1310         {
1311             int nOutbound = 0;
1312             CRITICAL_BLOCK(cs_vNodes)
1313                 BOOST_FOREACH(CNode* pnode, vNodes)
1314                     if (!pnode->fInbound)
1315                         nOutbound++;
1316             int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
1317             nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
1318             if (nOutbound < nMaxOutboundConnections)
1319                 break;
1320             vnThreadsRunning[1]--;
1321             Sleep(2000);
1322             vnThreadsRunning[1]++;
1323             if (fShutdown)
1324                 return;
1325         }
1326 
1327         bool fAddSeeds = false;
1328 
1329         CRITICAL_BLOCK(cs_mapAddresses)
1330         {
1331             // Add seed nodes if IRC isn't working
1332             bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
1333             if (mapAddresses.empty() && (GetTime() - nStart > 60 || fUseProxy) && !fTestNet)
1334                 fAddSeeds = true;
1335         }
1336 
1337         if (fAddSeeds)
1338         {
1339             for (int i = 0; i < ARRAYLEN(pnSeed); i++)
1340             {
1341                 // It'll only connect to one or two seed nodes because once it connects,
1342                 // it'll get a pile of addresses with newer timestamps.
1343                 // Seed nodes are given a random 'last seen time' of between one and two
1344                 // weeks ago.
1345                 const int64 nOneWeek = 7*24*60*60;
1346                 CAddress addr;
1347                 addr.ip = pnSeed[i];
1348                 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1349                 AddAddress(addr);
1350             }
1351         }
1352 
1353         //
1354         // Choose an address to connect to based on most recently seen
1355         //
1356         CAddress addrConnect;
1357         int64 nBest = INT64_MIN;
1358 
1359         // Only connect to one address per a.b.?.? range.
1360         // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1361         set<unsigned int> setConnected;
1362         CRITICAL_BLOCK(cs_vNodes)
1363             BOOST_FOREACH(CNode* pnode, vNodes)
1364                 setConnected.insert(pnode->addr.ip & 0x0000ffff);
1365 
1366         int64 nANow = GetAdjustedTime();
1367 
1368         CRITICAL_BLOCK(cs_mapAddresses)
1369         {
1370             BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
1371             {
1372                 const CAddress& addr = item.second;
1373                 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
1374                     continue;
1375                 int64 nSinceLastSeen = nANow - addr.nTime;
1376                 int64 nSinceLastTry = nANow - addr.nLastTry;
1377 
1378                 // Randomize the order in a deterministic way, putting the standard port first
1379                 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
1380                 if (addr.port != htons(GetDefaultPort()))
1381                     nRandomizer += 2 * 60 * 60;
1382 
1383                 // Last seen  Base retry frequency
1384                 //   <1 hour   10 min
1385                 //    1 hour    1 hour
1386                 //    4 hours   2 hours
1387                 //   24 hours   5 hours
1388                 //   48 hours   7 hours
1389                 //    7 days   13 hours
1390                 //   30 days   27 hours
1391                 //   90 days   46 hours
1392                 //  365 days   93 hours
1393                 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
1394 
1395                 // Fast reconnect for one hour after last seen
1396                 if (nSinceLastSeen < 60 * 60)
1397                     nDelay = 10 * 60;
1398 
1399                 // Limit retry frequency
1400                 if (nSinceLastTry < nDelay)
1401                     continue;
1402 
1403                 // If we have IRC, we'll be notified when they first come online,
1404                 // and again every 24 hours by the refresh broadcast.
1405                 if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)
1406                     continue;
1407 
1408                 // Only try the old stuff if we don't have enough connections
1409                 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
1410                     continue;
1411 
1412                 // If multiple addresses are ready, prioritize by time since
1413                 // last seen and time since last tried.
1414                 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
1415                 if (nScore > nBest)
1416                 {
1417                     nBest = nScore;
1418                     addrConnect = addr;
1419                 }
1420             }
1421         }
1422 
1423         if (addrConnect.IsValid())
1424             OpenNetworkConnection(addrConnect);
1425     }
1426 }
1427 
1428 bool OpenNetworkConnection(const CAddress& addrConnect)
1429 {
1430     //
1431     // Initiate outbound network connection
1432     //
1433     if (fShutdown)
1434         return false;
1435     if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() ||
1436         FindNode(addrConnect.ip) || CNode::IsBanned(addrConnect.ip))
1437         return false;
1438 
1439     vnThreadsRunning[1]--;
1440     CNode* pnode = ConnectNode(addrConnect);
1441     vnThreadsRunning[1]++;
1442     if (fShutdown)
1443         return false;
1444     if (!pnode)
1445         return false;
1446     pnode->fNetworkNode = true;
1447 
1448     return true;
1449 }
1450 
1451 
1452 
1453 
1454 
1455 
1456 
1457 
1458 void ThreadMessageHandler(void* parg)
1459 {
1460     IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
1461     try
1462     {
1463         vnThreadsRunning[2]++;
1464         ThreadMessageHandler2(parg);
1465         vnThreadsRunning[2]--;
1466     }
1467     catch (std::exception& e) {
1468         vnThreadsRunning[2]--;
1469         PrintException(&e, "ThreadMessageHandler()");
1470     } catch (...) {
1471         vnThreadsRunning[2]--;
1472         PrintException(NULL, "ThreadMessageHandler()");
1473     }
1474     printf("ThreadMessageHandler exiting\n");
1475 }
1476 
1477 void ThreadMessageHandler2(void* parg)
1478 {
1479     printf("ThreadMessageHandler started\n");
1480     SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1481     while (!fShutdown)
1482     {
1483         vector<CNode*> vNodesCopy;
1484         CRITICAL_BLOCK(cs_vNodes)
1485         {
1486             vNodesCopy = vNodes;
1487             BOOST_FOREACH(CNode* pnode, vNodesCopy)
1488                 pnode->AddRef();
1489         }
1490 
1491         // Poll the connected nodes for messages
1492         CNode* pnodeTrickle = NULL;
1493         if (!vNodesCopy.empty())
1494             pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1495         BOOST_FOREACH(CNode* pnode, vNodesCopy)
1496         {
1497             // Receive messages
1498             TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
1499                 ProcessMessages(pnode);
1500             if (fShutdown)
1501                 return;
1502 
1503             // Send messages
1504             TRY_CRITICAL_BLOCK(pnode->cs_vSend)
1505                 SendMessages(pnode, pnode == pnodeTrickle);
1506             if (fShutdown)
1507                 return;
1508         }
1509 
1510         CRITICAL_BLOCK(cs_vNodes)
1511         {
1512             BOOST_FOREACH(CNode* pnode, vNodesCopy)
1513                 pnode->Release();
1514         }
1515 
1516         // Wait and allow messages to bunch up.
1517         // Reduce vnThreadsRunning so StopNode has permission to exit while
1518         // we're sleeping, but we must always check fShutdown after doing this.
1519         vnThreadsRunning[2]--;
1520         Sleep(100);
1521         if (fRequestShutdown)
1522             Shutdown(NULL);
1523         vnThreadsRunning[2]++;
1524         if (fShutdown)
1525             return;
1526     }
1527 }
1528 
1529 
1530 
1531 
1532 
1533 
1534 bool BindListenPort(string& strError)
1535 {
1536     strError = "";
1537     int nOne = 1;
1538     addrLocalHost.port = htons(GetListenPort());
1539 
1540     // Create socket for listening for incoming connections
1541     hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1542     if (hListenSocket == INVALID_SOCKET)
1543     {
1544         strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1545         printf("%s\n", strError.c_str());
1546         return false;
1547     }
1548 
1549 #ifdef SO_NOSIGPIPE
1550     // Different way of disabling SIGPIPE on BSD
1551     setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1552 #endif
1553 
1554     // Allow binding if the port is still in TIME_WAIT state after
1555     // the program was closed and restarted.  Not an issue on windows.
1556     setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1557 
1558     if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1559     {
1560         strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1561         printf("%s\n", strError.c_str());
1562         return false;
1563     }
1564 
1565     // The sockaddr_in structure specifies the address family,
1566     // IP address, and port for the socket that is being bound
1567     struct sockaddr_in sockaddr;
1568     memset(&sockaddr, 0, sizeof(sockaddr));
1569     sockaddr.sin_family = AF_INET;
1570     sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
1571     sockaddr.sin_port = htons(GetListenPort());
1572     if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
1573     {
1574         int nErr = WSAGetLastError();
1575         if (nErr == WSAEADDRINUSE)
1576             strError = strprintf(_("Unable to bind to port %d on this computer.  Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
1577         else
1578             strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
1579         printf("%s\n", strError.c_str());
1580         return false;
1581     }
1582     printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
1583 
1584     // Listen for incoming connections
1585     if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1586     {
1587         strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1588         printf("%s\n", strError.c_str());
1589         return false;
1590     }
1591 
1592     return true;
1593 }
1594 
1595 void StartNode(void* parg)
1596 {
1597     if (pnodeLocalHost == NULL)
1598         pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, false, nLocalServices));
1599 
1600     // Get local host ip
1601     struct ifaddrs* myaddrs;
1602     if (getifaddrs(&myaddrs) == 0)
1603     {
1604         for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1605         {
1606             if (ifa->ifa_addr == NULL) continue;
1607             if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1608             if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1609             if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1610             char pszIP[100];
1611             if (ifa->ifa_addr->sa_family == AF_INET)
1612             {
1613                 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1614                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
1615                     printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
1616 
1617                 // Take the first IP that isn't loopback 127.x.x.x
1618                 CAddress addr(*(unsigned int*)&s4->sin_addr, GetListenPort(), nLocalServices);
1619                 if (addr.IsValid() && addr.GetByte(3) != 127)
1620                 {
1621                     addrLocalHost = addr;
1622                     break;
1623                 }
1624             }
1625             else if (ifa->ifa_addr->sa_family == AF_INET6)
1626             {
1627                 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1628                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
1629                     printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
1630             }
1631         }
1632         freeifaddrs(myaddrs);
1633     }
1634 
1635     printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1636 
1637     if (fUseProxy || mapArgs.count("-connect") || fNoListen)
1638     {
1639         // Proxies can't take incoming connections
1640         addrLocalHost.ip = CAddress("0.0.0.0").ip;
1641         printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1642     }
1643     else
1644     {
1645         CreateThread(ThreadGetMyExternalIP, NULL);
1646     }
1647 
1648     //
1649     // Start threads
1650     //
1651 
1652     if (GetBoolArg("-nodnsseed"))
1653         printf("DNS seeding disabled\n");
1654     else
1655         if (!CreateThread(ThreadDNSAddressSeed, NULL))
1656             printf("Error: CreateThread(ThreadDNSAddressSeed) failed\n");
1657 
1658     // Get addresses from IRC and advertise ours
1659     if (!CreateThread(ThreadIRCSeed, NULL))
1660         printf("Error: CreateThread(ThreadIRCSeed) failed\n");
1661 
1662     // Send and receive from sockets, accept connections
1663     if (!CreateThread(ThreadSocketHandler, NULL))
1664         printf("Error: CreateThread(ThreadSocketHandler) failed\n");
1665 
1666     // Initiate outbound connections
1667     if (!CreateThread(ThreadOpenConnections, NULL))
1668         printf("Error: CreateThread(ThreadOpenConnections) failed\n");
1669 
1670     // Process messages
1671     if (!CreateThread(ThreadMessageHandler, NULL))
1672         printf("Error: CreateThread(ThreadMessageHandler) failed\n");
1673 
1674     // Generate coins in the background
1675     GenerateBitcoins(fGenerateBitcoins, pwalletMain);
1676 }
1677 
1678 bool StopNode()
1679 {
1680     printf("StopNode()\n");
1681     fShutdown = true;
1682     nTransactionsUpdated++;
1683     int64 nStart = GetTime();
1684     while (vnThreadsRunning[0] > 0 || vnThreadsRunning[1] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0
1685     )
1686     {
1687         if (GetTime() - nStart > 20)
1688             break;
1689         Sleep(20);
1690     }
1691     if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
1692     if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
1693     if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
1694     if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
1695     if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
1696     if (vnThreadsRunning[6] > 0) printf("ThreadDNSAddressSeed still running\n");
1697     while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
1698         Sleep(20);
1699     Sleep(50);
1700 
1701     return true;
1702 }
1703 
1704 class CNetCleanup
1705 {
1706 public:
1707     CNetCleanup()
1708     {
1709     }
1710     ~CNetCleanup()
1711     {
1712         // Close sockets
1713         BOOST_FOREACH(CNode* pnode, vNodes)
1714             if (pnode->hSocket != INVALID_SOCKET)
1715                 closesocket(pnode->hSocket);
1716         if (hListenSocket != INVALID_SOCKET)
1717             if (closesocket(hListenSocket) == SOCKET_ERROR)
1718                 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1719 
1720     }
1721 }
1722 instance_of_cnetcleanup;