genesis                 1 
genesis                 2 
genesis                 3 
genesis                 4 
genesis                 5 
genesis                 6 #include "headers.h"
genesis                 7 #include "irc.h"
genesis                 8 #include "db.h"
genesis                 9 #include "net.h"
genesis                10 #include "init.h"
genesis                11 #include "strlcpy.h"
genesis                12 
genesis                13 #ifdef WIN32
genesis                14 #include <string.h>
genesis                15 #endif
genesis                16 
genesis                17 #ifdef USE_UPNP
genesis                18 #include <miniupnpc/miniwget.h>
genesis                19 #include <miniupnpc/miniupnpc.h>
genesis                20 #include <miniupnpc/upnpcommands.h>
genesis                21 #include <miniupnpc/upnperrors.h>
genesis                22 #endif
genesis                23 
genesis                24 using namespace std;
genesis                25 using namespace boost;
genesis                26 
genesis                27 static const int MAX_OUTBOUND_CONNECTIONS = 8;
genesis                28 
genesis                29 void ThreadMessageHandler2(void* parg);
genesis                30 void ThreadSocketHandler2(void* parg);
genesis                31 void ThreadOpenConnections2(void* parg);
genesis                32 #ifdef USE_UPNP
genesis                33 void ThreadMapPort2(void* parg);
genesis                34 #endif
genesis                35 void ThreadDNSAddressSeed2(void* parg);
genesis                36 bool OpenNetworkConnection(const CAddress& addrConnect);
genesis                37 
genesis                38 
genesis                39 
genesis                40 
genesis                41 
genesis                42 
genesis                43 
genesis                44 
genesis                45 bool fClient = false;
genesis                46 bool fAllowDNS = false;
genesis                47 uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
genesis                48 CAddress addrLocalHost("0.0.0.0", 0, false, nLocalServices);
genesis                49 static CNode* pnodeLocalHost = NULL;
genesis                50 uint64 nLocalHostNonce = 0;
genesis                51 array<int, 10> vnThreadsRunning;
genesis                52 static SOCKET hListenSocket = INVALID_SOCKET;
genesis                53 
genesis                54 vector<CNode*> vNodes;
genesis                55 CCriticalSection cs_vNodes;
genesis                56 map<vector<unsigned char>, CAddress> mapAddresses;
genesis                57 CCriticalSection cs_mapAddresses;
genesis                58 map<CInv, CDataStream> mapRelay;
genesis                59 deque<pair<int64, CInv> > vRelayExpiration;
genesis                60 CCriticalSection cs_mapRelay;
genesis                61 map<CInv, int64> mapAlreadyAskedFor;
genesis                62 
genesis                63 
genesis                64 int fUseProxy = false;
genesis                65 int nConnectTimeout = 5000;
genesis                66 CAddress addrProxy("127.0.0.1",9050);
genesis                67 
genesis                68 
genesis                69 
genesis                70 
genesis                71 unsigned short GetListenPort()
genesis                72 {
genesis                73     return (unsigned short)(GetArg("-port", GetDefaultPort()));
genesis                74 }
genesis                75 
genesis                76 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
genesis                77 {
genesis                78     
genesis                79     if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
genesis                80         return;
genesis                81     pindexLastGetBlocksBegin = pindexBegin;
genesis                82     hashLastGetBlocksEnd = hashEnd;
genesis                83 
genesis                84     PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
genesis                85 }
genesis                86 
genesis                87 
genesis                88 
genesis                89 
genesis                90 
genesis                91 bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout)
genesis                92 {
genesis                93     hSocketRet = INVALID_SOCKET;
genesis                94 
genesis                95     SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
genesis                96     if (hSocket == INVALID_SOCKET)
genesis                97         return false;
genesis                98 #ifdef SO_NOSIGPIPE
genesis                99     int set = 1;
genesis               100     setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
genesis               101 #endif
genesis               102 
genesis               103     bool fProxy = (fUseProxy && addrConnect.IsRoutable());
genesis               104     struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
genesis               105 
genesis               106 #ifdef WIN32
genesis               107     u_long fNonblock = 1;
genesis               108     if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
genesis               109 #else
genesis               110     int fFlags = fcntl(hSocket, F_GETFL, 0);
genesis               111     if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
genesis               112 #endif
genesis               113     {
genesis               114         closesocket(hSocket);
genesis               115         return false;
genesis               116     }
genesis               117 
genesis               118 
genesis               119     if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
genesis               120     {
genesis               121         
genesis               122         if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
genesis               123         {
genesis               124             struct timeval timeout;
genesis               125             timeout.tv_sec  = nTimeout / 1000;
genesis               126             timeout.tv_usec = (nTimeout % 1000) * 1000;
genesis               127 
genesis               128             fd_set fdset;
genesis               129             FD_ZERO(&fdset);
genesis               130             FD_SET(hSocket, &fdset);
genesis               131             int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
genesis               132             if (nRet == 0)
genesis               133             {
genesis               134                 printf("connection timeout\n");
genesis               135                 closesocket(hSocket);
genesis               136                 return false;
genesis               137             }
genesis               138             if (nRet == SOCKET_ERROR)
genesis               139             {
genesis               140                 printf("select() for connection failed: %i\n",WSAGetLastError());
genesis               141                 closesocket(hSocket);
genesis               142                 return false;
genesis               143             }
genesis               144             socklen_t nRetSize = sizeof(nRet);
genesis               145 #ifdef WIN32
genesis               146             if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
genesis               147 #else
genesis               148             if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
genesis               149 #endif
genesis               150             {
genesis               151                 printf("getsockopt() for connection failed: %i\n",WSAGetLastError());
genesis               152                 closesocket(hSocket);
genesis               153                 return false;
genesis               154             }
genesis               155             if (nRet != 0)
genesis               156             {
genesis               157                 printf("connect() failed after select(): %s\n",strerror(nRet));
genesis               158                 closesocket(hSocket);
genesis               159                 return false;
genesis               160             }
genesis               161         }
genesis               162 #ifdef WIN32
genesis               163         else if (WSAGetLastError() != WSAEISCONN)
genesis               164 #else
genesis               165         else
genesis               166 #endif
genesis               167         {
genesis               168             printf("connect() failed: %i\n",WSAGetLastError());
genesis               169             closesocket(hSocket);
genesis               170             return false;
genesis               171         }
genesis               172     }
genesis               173 
genesis               174     
genesis               175     this isn't even strictly necessary
genesis               176     CNode::ConnectNode immediately turns the socket back to non-blocking
genesis               177     but we'll turn it back to blocking just in case
genesis               178     */
genesis               179 #ifdef WIN32
genesis               180     fNonblock = 0;
genesis               181     if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
genesis               182 #else
genesis               183     fFlags = fcntl(hSocket, F_GETFL, 0);
genesis               184     if (fcntl(hSocket, F_SETFL, fFlags & !O_NONBLOCK) == SOCKET_ERROR)
genesis               185 #endif
genesis               186     {
genesis               187         closesocket(hSocket);
genesis               188         return false;
genesis               189     }
genesis               190 
genesis               191     if (fProxy)
genesis               192     {
genesis               193         printf("proxy connecting %s\n", addrConnect.ToString().c_str());
genesis               194         char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
genesis               195         memcpy(pszSocks4IP + 2, &addrConnect.port, 2);
genesis               196         memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);
genesis               197         char* pszSocks4 = pszSocks4IP;
genesis               198         int nSize = sizeof(pszSocks4IP);
genesis               199 
genesis               200         int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
genesis               201         if (ret != nSize)
genesis               202         {
genesis               203             closesocket(hSocket);
genesis               204             return error("Error sending to proxy");
genesis               205         }
genesis               206         char pchRet[8];
genesis               207         if (recv(hSocket, pchRet, 8, 0) != 8)
genesis               208         {
genesis               209             closesocket(hSocket);
genesis               210             return error("Error reading proxy response");
genesis               211         }
genesis               212         if (pchRet[1] != 0x5a)
genesis               213         {
genesis               214             closesocket(hSocket);
genesis               215             if (pchRet[1] != 0x5b)
genesis               216                 printf("ERROR: Proxy returned error %d\n", pchRet[1]);
genesis               217             return false;
genesis               218         }
genesis               219         printf("proxy connected %s\n", addrConnect.ToString().c_str());
genesis               220     }
genesis               221 
genesis               222     hSocketRet = hSocket;
genesis               223     return true;
genesis               224 }
genesis               225 
genesis               226 
genesis               227 bool Lookup(const char *pszName, vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup, int portDefault, bool fAllowPort)
genesis               228 {
genesis               229     vaddr.clear();
genesis               230     if (pszName[0] == 0)
genesis               231         return false;
genesis               232     int port = portDefault;
genesis               233     char psz[256];
genesis               234     char *pszHost = psz;
genesis               235     strlcpy(psz, pszName, sizeof(psz));
genesis               236     if (fAllowPort)
genesis               237     {
genesis               238         char* pszColon = strrchr(psz+1,':');
genesis               239         char *pszPortEnd = NULL;
genesis               240         int portParsed = pszColon ? strtoul(pszColon+1, &pszPortEnd, 10) : 0;
genesis               241         if (pszColon && pszPortEnd && pszPortEnd[0] == 0)
genesis               242         {
genesis               243             if (psz[0] == '[' && pszColon[-1] == ']')
genesis               244             {
genesis               245                 
genesis               246                 pszHost = psz+1;
genesis               247                 pszColon[-1] = 0;
genesis               248             }
genesis               249             else
genesis               250                 pszColon[0] = 0;
genesis               251             port = portParsed;
genesis               252             if (port < 0 || port > USHRT_MAX)
genesis               253                 port = USHRT_MAX;
genesis               254         }
genesis               255     }
genesis               256 
genesis               257     unsigned int addrIP = inet_addr(pszHost);
genesis               258     if (addrIP != INADDR_NONE)
genesis               259     {
genesis               260         
genesis               261         vaddr.push_back(CAddress(addrIP, port, nServices));
genesis               262         return true;
genesis               263     }
genesis               264 
genesis               265     if (!fAllowLookup)
genesis               266         return false;
genesis               267 
genesis               268     struct hostent* phostent = gethostbyname(pszHost);
genesis               269     if (!phostent)
genesis               270         return false;
genesis               271 
genesis               272     if (phostent->h_addrtype != AF_INET)
genesis               273         return false;
genesis               274 
genesis               275     char** ppAddr = phostent->h_addr_list;
genesis               276     while (*ppAddr != NULL && vaddr.size() != nMaxSolutions)
genesis               277     {
genesis               278         CAddress addr(((struct in_addr*)ppAddr[0])->s_addr, port, nServices);
genesis               279         if (addr.IsValid())
genesis               280             vaddr.push_back(addr);
genesis               281         ppAddr++;
genesis               282     }
genesis               283 
genesis               284     return (vaddr.size() > 0);
genesis               285 }
genesis               286 
genesis               287 
genesis               288 bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup, int portDefault, bool fAllowPort)
genesis               289 {
genesis               290     vector<CAddress> vaddr;
genesis               291     bool fRet = Lookup(pszName, vaddr, nServices, 1, fAllowLookup, portDefault, fAllowPort);
genesis               292     if (fRet)
genesis               293         addr = vaddr[0];
genesis               294     return fRet;
genesis               295 }
genesis               296 
genesis               297 bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const char* pszKeyword, unsigned int& ipRet)
genesis               298 {
genesis               299     SOCKET hSocket;
genesis               300     if (!ConnectSocket(addrConnect, hSocket))
genesis               301         return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
genesis               302 
genesis               303     send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
genesis               304 
genesis               305     string strLine;
genesis               306     while (RecvLine(hSocket, strLine))
genesis               307     {
genesis               308         if (strLine.empty()) 
genesis               309         {
genesis               310             loop
genesis               311             {
genesis               312                 if (!RecvLine(hSocket, strLine))
genesis               313                 {
genesis               314                     closesocket(hSocket);
genesis               315                     return false;
genesis               316                 }
genesis               317                 if (pszKeyword == NULL)
genesis               318                     break;
genesis               319                 if (strLine.find(pszKeyword) != -1)
genesis               320                 {
genesis               321                     strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
genesis               322                     break;
genesis               323                 }
genesis               324             }
genesis               325             closesocket(hSocket);
genesis               326             if (strLine.find("<") != -1)
genesis               327                 strLine = strLine.substr(0, strLine.find("<"));
genesis               328             strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
genesis               329             while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
genesis               330                 strLine.resize(strLine.size()-1);
genesis               331             CAddress addr(strLine,0,true);
genesis               332             printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
genesis               333             if (addr.ip == 0 || addr.ip == INADDR_NONE || !addr.IsRoutable())
genesis               334                 return false;
genesis               335             ipRet = addr.ip;
genesis               336             return true;
genesis               337         }
genesis               338     }
genesis               339     closesocket(hSocket);
genesis               340     return error("GetMyExternalIP() : connection closed");
genesis               341 }
genesis               342 
genesis               343 
genesis               344 bool GetMyExternalIP(unsigned int& ipRet)
genesis               345 {
genesis               346     CAddress addrConnect;
genesis               347     const char* pszGet;
genesis               348     const char* pszKeyword;
genesis               349 
genesis               350     if (fUseProxy)
genesis               351         return false;
genesis               352 
genesis               353     for (int nLookup = 0; nLookup <= 1; nLookup++)
genesis               354     for (int nHost = 1; nHost <= 2; nHost++)
genesis               355     {
genesis               356         
genesis               357         
genesis               358         
genesis               359         
genesis               360         if (nHost == 1)
genesis               361         {
genesis               362             addrConnect = CAddress("91.198.22.70",80); 
genesis               363 
genesis               364             if (nLookup == 1)
genesis               365             {
genesis               366                 CAddress addrIP("checkip.dyndns.org", 80, true);
genesis               367                 if (addrIP.IsValid())
genesis               368                     addrConnect = addrIP;
genesis               369             }
genesis               370 
genesis               371             pszGet = "GET / HTTP/1.1\r\n"
genesis               372                      "Host: checkip.dyndns.org\r\n"
genesis               373                      "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
genesis               374                      "Connection: close\r\n"
genesis               375                      "\r\n";
genesis               376 
genesis               377             pszKeyword = "Address:";
genesis               378         }
genesis               379         else if (nHost == 2)
genesis               380         {
genesis               381             addrConnect = CAddress("74.208.43.192", 80); 
genesis               382 
genesis               383             if (nLookup == 1)
genesis               384             {
genesis               385                 CAddress addrIP("www.showmyip.com", 80, true);
genesis               386                 if (addrIP.IsValid())
genesis               387                     addrConnect = addrIP;
genesis               388             }
genesis               389 
genesis               390             pszGet = "GET /simple/ HTTP/1.1\r\n"
genesis               391                      "Host: www.showmyip.com\r\n"
genesis               392                      "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
genesis               393                      "Connection: close\r\n"
genesis               394                      "\r\n";
genesis               395 
genesis               396             pszKeyword = NULL; 
genesis               397         }
genesis               398 
genesis               399         if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
genesis               400             return true;
genesis               401     }
genesis               402 
genesis               403     return false;
genesis               404 }
genesis               405 
genesis               406 void ThreadGetMyExternalIP(void* parg)
genesis               407 {
genesis               408     
genesis               409     if (!GetBoolArg("-noirc"))
genesis               410     {
genesis               411         for (int i = 0; i < 2 * 60; i++)
genesis               412         {
genesis               413             Sleep(1000);
genesis               414             if (fGotExternalIP || fShutdown)
genesis               415                 return;
genesis               416         }
genesis               417     }
genesis               418 
genesis               419     
genesis               420     if (GetMyExternalIP(addrLocalHost.ip))
genesis               421     {
genesis               422         printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
genesis               423         if (addrLocalHost.IsRoutable())
genesis               424         {
genesis               425             
genesis               426             
genesis               427             CAddress addr(addrLocalHost);
genesis               428             addr.nTime = GetAdjustedTime();
genesis               429             CRITICAL_BLOCK(cs_vNodes)
genesis               430                 BOOST_FOREACH(CNode* pnode, vNodes)
genesis               431                     pnode->PushAddress(addr);
genesis               432         }
genesis               433     }
genesis               434 }
genesis               435 
genesis               436 
genesis               437 
genesis               438 
genesis               439 
genesis               440 bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB)
genesis               441 {
genesis               442     if (!addr.IsRoutable())
genesis               443         return false;
genesis               444     if (addr.ip == addrLocalHost.ip)
genesis               445         return false;
genesis               446     addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty);
genesis               447     bool fUpdated = false;
genesis               448     bool fNew = false;
genesis               449     CAddress addrFound = addr;
genesis               450 
genesis               451     CRITICAL_BLOCK(cs_mapAddresses)
genesis               452     {
genesis               453         map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
genesis               454         if (it == mapAddresses.end())
genesis               455         {
genesis               456             
genesis               457             printf("AddAddress(%s)\n", addr.ToString().c_str());
genesis               458             mapAddresses.insert(make_pair(addr.GetKey(), addr));
genesis               459             fUpdated = true;
genesis               460             fNew = true;
genesis               461         }
genesis               462         else
genesis               463         {
genesis               464             addrFound = (*it).second;
genesis               465             if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
genesis               466             {
genesis               467                 
genesis               468                 addrFound.nServices |= addr.nServices;
genesis               469                 fUpdated = true;
genesis               470             }
genesis               471             bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
genesis               472             int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
genesis               473             if (addrFound.nTime < addr.nTime - nUpdateInterval)
genesis               474             {
genesis               475                 
genesis               476                 addrFound.nTime = addr.nTime;
genesis               477                 fUpdated = true;
genesis               478             }
genesis               479         }
genesis               480     }
genesis               481     
genesis               482     
genesis               483     
genesis               484     
genesis               485     
genesis               486     
genesis               487     if (fUpdated)
genesis               488     {
genesis               489         if (pAddrDB)
genesis               490             pAddrDB->WriteAddress(addrFound);
genesis               491         else
genesis               492             CAddrDB().WriteAddress(addrFound);
genesis               493     }
genesis               494     return fNew;
genesis               495 }
genesis               496 
genesis               497 void AddressCurrentlyConnected(const CAddress& addr)
genesis               498 {
genesis               499     CAddress *paddrFound = NULL;
genesis               500 
genesis               501     CRITICAL_BLOCK(cs_mapAddresses)
genesis               502     {
genesis               503         
genesis               504         map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
genesis               505         if (it != mapAddresses.end())
genesis               506             paddrFound = &(*it).second;
genesis               507     }
genesis               508 
genesis               509     if (paddrFound)
genesis               510     {
genesis               511         int64 nUpdateInterval = 20 * 60;
genesis               512         if (paddrFound->nTime < GetAdjustedTime() - nUpdateInterval)
genesis               513         {
genesis               514             
genesis               515             paddrFound->nTime = GetAdjustedTime();
genesis               516             CAddrDB addrdb;
genesis               517             addrdb.WriteAddress(*paddrFound);
genesis               518         }
genesis               519     }
genesis               520 }
genesis               521 
genesis               522 
genesis               523 
genesis               524 
genesis               525 
genesis               526 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
genesis               527 {
genesis               528     
genesis               529     
genesis               530     CRITICAL_BLOCK(cs_vNodes)
genesis               531     {
genesis               532         BOOST_FOREACH(CNode* pnode, vNodes)
genesis               533         {
genesis               534             CRITICAL_BLOCK(pnode->cs_mapRequests)
genesis               535             {
genesis               536                 for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
genesis               537                 {
genesis               538                     CRequestTracker& tracker = (*mi).second;
genesis               539                     if (tracker.fn == fn && tracker.param1 == param1)
genesis               540                         pnode->mapRequests.erase(mi++);
genesis               541                     else
genesis               542                         mi++;
genesis               543                 }
genesis               544             }
genesis               545         }
genesis               546     }
genesis               547 }
genesis               548 
genesis               549 
genesis               550 
genesis               551 
genesis               552 
genesis               553 
genesis               554 
genesis               555 
genesis               556 
genesis               557 
genesis               558 
genesis               559 
genesis               560 
genesis               561 
genesis               562 
genesis               563 
genesis               564 bool AnySubscribed(unsigned int nChannel)
genesis               565 {
genesis               566     if (pnodeLocalHost->IsSubscribed(nChannel))
genesis               567         return true;
genesis               568     CRITICAL_BLOCK(cs_vNodes)
genesis               569         BOOST_FOREACH(CNode* pnode, vNodes)
genesis               570             if (pnode->IsSubscribed(nChannel))
genesis               571                 return true;
genesis               572     return false;
genesis               573 }
genesis               574 
genesis               575 bool CNode::IsSubscribed(unsigned int nChannel)
genesis               576 {
genesis               577     if (nChannel >= vfSubscribe.size())
genesis               578         return false;
genesis               579     return vfSubscribe[nChannel];
genesis               580 }
genesis               581 
genesis               582 void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
genesis               583 {
genesis               584     if (nChannel >= vfSubscribe.size())
genesis               585         return;
genesis               586 
genesis               587     if (!AnySubscribed(nChannel))
genesis               588     {
genesis               589         
genesis               590         CRITICAL_BLOCK(cs_vNodes)
genesis               591             BOOST_FOREACH(CNode* pnode, vNodes)
genesis               592                 if (pnode != this)
genesis               593                     pnode->PushMessage("subscribe", nChannel, nHops);
genesis               594     }
genesis               595 
genesis               596     vfSubscribe[nChannel] = true;
genesis               597 }
genesis               598 
genesis               599 void CNode::CancelSubscribe(unsigned int nChannel)
genesis               600 {
genesis               601     if (nChannel >= vfSubscribe.size())
genesis               602         return;
genesis               603 
genesis               604     
genesis               605     if (!vfSubscribe[nChannel])
genesis               606         return;
genesis               607     vfSubscribe[nChannel] = false;
genesis               608 
genesis               609     if (!AnySubscribed(nChannel))
genesis               610     {
genesis               611         
genesis               612         CRITICAL_BLOCK(cs_vNodes)
genesis               613             BOOST_FOREACH(CNode* pnode, vNodes)
genesis               614                 if (pnode != this)
genesis               615                     pnode->PushMessage("sub-cancel", nChannel);
genesis               616     }
genesis               617 }
genesis               618 
genesis               619 
genesis               620 
genesis               621 
genesis               622 
genesis               623 
genesis               624 
genesis               625 
genesis               626 
genesis               627 CNode* FindNode(unsigned int ip)
genesis               628 {
genesis               629     CRITICAL_BLOCK(cs_vNodes)
genesis               630     {
genesis               631         BOOST_FOREACH(CNode* pnode, vNodes)
genesis               632             if (pnode->addr.ip == ip)
genesis               633                 return (pnode);
genesis               634     }
genesis               635     return NULL;
genesis               636 }
genesis               637 
genesis               638 CNode* FindNode(CAddress addr)
genesis               639 {
genesis               640     CRITICAL_BLOCK(cs_vNodes)
genesis               641     {
genesis               642         BOOST_FOREACH(CNode* pnode, vNodes)
genesis               643             if (pnode->addr == addr)
genesis               644                 return (pnode);
genesis               645     }
genesis               646     return NULL;
genesis               647 }
genesis               648 
genesis               649 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
genesis               650 {
genesis               651     if (addrConnect.ip == addrLocalHost.ip)
genesis               652         return NULL;
genesis               653 
genesis               654     
genesis               655     CNode* pnode = FindNode(addrConnect.ip);
genesis               656     if (pnode)
genesis               657     {
genesis               658         if (nTimeout != 0)
genesis               659             pnode->AddRef(nTimeout);
genesis               660         else
genesis               661             pnode->AddRef();
genesis               662         return pnode;
genesis               663     }
genesis               664 
genesis               665     
genesis               666     printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",
genesis               667         addrConnect.ToString().c_str(),
genesis               668         (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
genesis               669         (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
genesis               670 
genesis               671     CRITICAL_BLOCK(cs_mapAddresses)
genesis               672         mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
genesis               673 
genesis               674     
genesis               675     SOCKET hSocket;
genesis               676     if (ConnectSocket(addrConnect, hSocket))
genesis               677     {
genesis               678         
genesis               679         printf("connected %s\n", addrConnect.ToString().c_str());
genesis               680 
genesis               681         
genesis               682 #ifdef WIN32
genesis               683         u_long nOne = 1;
genesis               684         if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
genesis               685             printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
genesis               686 #else
genesis               687         if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
genesis               688             printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
genesis               689 #endif
genesis               690 
genesis               691         
genesis               692         CNode* pnode = new CNode(hSocket, addrConnect, false);
genesis               693         if (nTimeout != 0)
genesis               694             pnode->AddRef(nTimeout);
genesis               695         else
genesis               696             pnode->AddRef();
genesis               697         CRITICAL_BLOCK(cs_vNodes)
genesis               698             vNodes.push_back(pnode);
genesis               699 
genesis               700         pnode->nTimeConnected = GetTime();
genesis               701         return pnode;
genesis               702     }
genesis               703     else
genesis               704     {
genesis               705         return NULL;
genesis               706     }
genesis               707 }
genesis               708 
genesis               709 void CNode::CloseSocketDisconnect()
genesis               710 {
genesis               711     fDisconnect = true;
genesis               712     if (hSocket != INVALID_SOCKET)
genesis               713     {
genesis               714         if (fDebug)
genesis               715             printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
genesis               716         printf("disconnecting node %s\n", addr.ToString().c_str());
genesis               717         closesocket(hSocket);
genesis               718         hSocket = INVALID_SOCKET;
genesis               719     }
genesis               720 }
genesis               721 
genesis               722 void CNode::Cleanup()
genesis               723 {
genesis               724     
genesis               725     
genesis               726 
genesis               727     
genesis               728     for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
genesis               729         if (vfSubscribe[nChannel])
genesis               730             CancelSubscribe(nChannel);
genesis               731 }
genesis               732 
genesis               733 
genesis               734 std::map<unsigned int, int64> CNode::setBanned;
genesis               735 CCriticalSection CNode::cs_setBanned;
genesis               736 
genesis               737 void CNode::ClearBanned()
genesis               738 {
genesis               739     setBanned.clear();
genesis               740 }
genesis               741 
genesis               742 bool CNode::IsBanned(unsigned int ip)
genesis               743 {
genesis               744     bool fResult = false;
genesis               745     CRITICAL_BLOCK(cs_setBanned)
genesis               746     {
genesis               747         std::map<unsigned int, int64>::iterator i = setBanned.find(ip);
genesis               748         if (i != setBanned.end())
genesis               749         {
genesis               750             int64 t = (*i).second;
genesis               751             if (GetTime() < t)
genesis               752                 fResult = true;
genesis               753         }
genesis               754     }
genesis               755     return fResult;
genesis               756 }
genesis               757 
genesis               758 bool CNode::Misbehaving(int howmuch)
genesis               759 {
genesis               760     if (addr.IsLocal())
genesis               761     {
genesis               762         printf("Warning: local node %s misbehaving\n", addr.ToString().c_str());
genesis               763         return false;
genesis               764     }
genesis               765 
genesis               766     nMisbehavior += howmuch;
genesis               767     if (nMisbehavior >= GetArg("-banscore", 100))
genesis               768     {
genesis               769         int64 banTime = GetTime()+GetArg("-bantime", 60*60*24);  
genesis               770         CRITICAL_BLOCK(cs_setBanned)
genesis               771             if (setBanned[addr.ip] < banTime)
genesis               772                 setBanned[addr.ip] = banTime;
genesis               773         CloseSocketDisconnect();
genesis               774         printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior);
genesis               775         return true;
genesis               776     }
genesis               777     return false;
genesis               778 }
genesis               779 
genesis               780 
genesis               781 
genesis               782 
genesis               783 
genesis               784 
genesis               785 
genesis               786 
genesis               787 
genesis               788 
genesis               789 
genesis               790 
genesis               791 void ThreadSocketHandler(void* parg)
genesis               792 {
genesis               793     IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
genesis               794     try
genesis               795     {
genesis               796         vnThreadsRunning[0]++;
genesis               797         ThreadSocketHandler2(parg);
genesis               798         vnThreadsRunning[0]--;
genesis               799     }
genesis               800     catch (std::exception& e) {
genesis               801         vnThreadsRunning[0]--;
genesis               802         PrintException(&e, "ThreadSocketHandler()");
genesis               803     } catch (...) {
genesis               804         vnThreadsRunning[0]--;
genesis               805         throw; 
genesis               806     }
genesis               807     printf("ThreadSocketHandler exiting\n");
genesis               808 }
genesis               809 
genesis               810 void ThreadSocketHandler2(void* parg)
genesis               811 {
genesis               812     printf("ThreadSocketHandler started\n");
genesis               813     list<CNode*> vNodesDisconnected;
genesis               814     int nPrevNodeCount = 0;
genesis               815 
genesis               816     loop
genesis               817     {
genesis               818         
genesis               819         
genesis               820         
genesis               821         CRITICAL_BLOCK(cs_vNodes)
genesis               822         {
genesis               823             
genesis               824             vector<CNode*> vNodesCopy = vNodes;
genesis               825             BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis               826             {
genesis               827                 if (pnode->fDisconnect ||
genesis               828                     (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
genesis               829                 {
genesis               830                     
genesis               831                     vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
genesis               832 
genesis               833                     
genesis               834                     pnode->CloseSocketDisconnect();
genesis               835                     pnode->Cleanup();
genesis               836 
genesis               837                     
genesis               838                     pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
genesis               839                     if (pnode->fNetworkNode || pnode->fInbound)
genesis               840                         pnode->Release();
genesis               841                     vNodesDisconnected.push_back(pnode);
genesis               842                 }
genesis               843             }
genesis               844 
genesis               845             
genesis               846             list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
genesis               847             BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
genesis               848             {
genesis               849                 
genesis               850                 if (pnode->GetRefCount() <= 0)
genesis               851                 {
genesis               852                     bool fDelete = false;
genesis               853                     TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis               854                      TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis               855                       TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
genesis               856                        TRY_CRITICAL_BLOCK(pnode->cs_inventory)
genesis               857                         fDelete = true;
genesis               858                     if (fDelete)
genesis               859                     {
genesis               860                         vNodesDisconnected.remove(pnode);
genesis               861                         delete pnode;
genesis               862                     }
genesis               863                 }
genesis               864             }
genesis               865         }
genesis               866         if (vNodes.size() != nPrevNodeCount)
genesis               867         {
genesis               868             nPrevNodeCount = vNodes.size();
genesis               869             MainFrameRepaint();
genesis               870         }
genesis               871 
genesis               872 
genesis               873         
genesis               874         
genesis               875         
genesis               876         struct timeval timeout;
genesis               877         timeout.tv_sec  = 0;
genesis               878         timeout.tv_usec = 50000; 
genesis               879 
genesis               880         fd_set fdsetRecv;
genesis               881         fd_set fdsetSend;
genesis               882         fd_set fdsetError;
genesis               883         FD_ZERO(&fdsetRecv);
genesis               884         FD_ZERO(&fdsetSend);
genesis               885         FD_ZERO(&fdsetError);
genesis               886         SOCKET hSocketMax = 0;
genesis               887 
genesis               888         if(hListenSocket != INVALID_SOCKET)
genesis               889             FD_SET(hListenSocket, &fdsetRecv);
genesis               890         hSocketMax = max(hSocketMax, hListenSocket);
genesis               891         CRITICAL_BLOCK(cs_vNodes)
genesis               892         {
genesis               893             BOOST_FOREACH(CNode* pnode, vNodes)
genesis               894             {
genesis               895                 if (pnode->hSocket == INVALID_SOCKET)
genesis               896                     continue;
genesis               897                 FD_SET(pnode->hSocket, &fdsetRecv);
genesis               898                 FD_SET(pnode->hSocket, &fdsetError);
genesis               899                 hSocketMax = max(hSocketMax, pnode->hSocket);
genesis               900                 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis               901                     if (!pnode->vSend.empty())
genesis               902                         FD_SET(pnode->hSocket, &fdsetSend);
genesis               903             }
genesis               904         }
genesis               905 
genesis               906         vnThreadsRunning[0]--;
genesis               907         int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
genesis               908         vnThreadsRunning[0]++;
genesis               909         if (fShutdown)
genesis               910             return;
genesis               911         if (nSelect == SOCKET_ERROR)
genesis               912         {
genesis               913             int nErr = WSAGetLastError();
genesis               914             if (hSocketMax > -1)
genesis               915             {
genesis               916                 printf("socket select error %d\n", nErr);
genesis               917                 for (int i = 0; i <= hSocketMax; i++)
genesis               918                     FD_SET(i, &fdsetRecv);
genesis               919             }
genesis               920             FD_ZERO(&fdsetSend);
genesis               921             FD_ZERO(&fdsetError);
genesis               922             Sleep(timeout.tv_usec/1000);
genesis               923         }
genesis               924 
genesis               925 
genesis               926         
genesis               927         
genesis               928         
genesis               929         if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
genesis               930         {
genesis               931             struct sockaddr_in sockaddr;
genesis               932             socklen_t len = sizeof(sockaddr);
genesis               933             SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
genesis               934             CAddress addr;
genesis               935             int nInbound = 0;
genesis               936 
genesis               937             if (hSocket != INVALID_SOCKET)
genesis               938                 addr = CAddress(sockaddr);
genesis               939 
genesis               940             CRITICAL_BLOCK(cs_vNodes)
genesis               941                 BOOST_FOREACH(CNode* pnode, vNodes)
genesis               942                 if (pnode->fInbound)
genesis               943                     nInbound++;
genesis               944 
genesis               945             if (hSocket == INVALID_SOCKET)
genesis               946             {
genesis               947                 if (WSAGetLastError() != WSAEWOULDBLOCK)
genesis               948                     printf("socket error accept failed: %d\n", WSAGetLastError());
genesis               949             }
genesis               950             else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
genesis               951             {
genesis               952                 closesocket(hSocket);
genesis               953             }
genesis               954             else if (CNode::IsBanned(addr.ip))
genesis               955             {
genesis               956                 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
genesis               957                 closesocket(hSocket);
genesis               958             }
genesis               959             else
genesis               960             {
genesis               961                 printf("accepted connection %s\n", addr.ToString().c_str());
genesis               962                 CNode* pnode = new CNode(hSocket, addr, true);
genesis               963                 pnode->AddRef();
genesis               964                 CRITICAL_BLOCK(cs_vNodes)
genesis               965                     vNodes.push_back(pnode);
genesis               966             }
genesis               967         }
genesis               968 
genesis               969 
genesis               970         
genesis               971         
genesis               972         
genesis               973         vector<CNode*> vNodesCopy;
genesis               974         CRITICAL_BLOCK(cs_vNodes)
genesis               975         {
genesis               976             vNodesCopy = vNodes;
genesis               977             BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis               978                 pnode->AddRef();
genesis               979         }
genesis               980         BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis               981         {
genesis               982             if (fShutdown)
genesis               983                 return;
genesis               984 
genesis               985             
genesis               986             
genesis               987             
genesis               988             if (pnode->hSocket == INVALID_SOCKET)
genesis               989                 continue;
genesis               990             if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
genesis               991             {
genesis               992                 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis               993                 {
genesis               994                     CDataStream& vRecv = pnode->vRecv;
genesis               995                     unsigned int nPos = vRecv.size();
genesis               996 
genesis               997                     if (nPos > ReceiveBufferSize()) {
genesis               998                         if (!pnode->fDisconnect)
genesis               999                             printf("socket recv flood control disconnect (%d bytes)\n", vRecv.size());
genesis              1000                         pnode->CloseSocketDisconnect();
genesis              1001                     }
genesis              1002                     else {
genesis              1003                         
genesis              1004                         char pchBuf[0x10000];
genesis              1005                         int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
genesis              1006                         if (nBytes > 0)
genesis              1007                         {
genesis              1008                             vRecv.resize(nPos + nBytes);
genesis              1009                             memcpy(&vRecv[nPos], pchBuf, nBytes);
genesis              1010                             pnode->nLastRecv = GetTime();
genesis              1011                         }
genesis              1012                         else if (nBytes == 0)
genesis              1013                         {
genesis              1014                             
genesis              1015                             if (!pnode->fDisconnect)
genesis              1016                                 printf("socket closed\n");
genesis              1017                             pnode->CloseSocketDisconnect();
genesis              1018                         }
genesis              1019                         else if (nBytes < 0)
genesis              1020                         {
genesis              1021                             
genesis              1022                             int nErr = WSAGetLastError();
genesis              1023                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
genesis              1024                             {
genesis              1025                                 if (!pnode->fDisconnect)
genesis              1026                                     printf("socket recv error %d\n", nErr);
genesis              1027                                 pnode->CloseSocketDisconnect();
genesis              1028                             }
genesis              1029                         }
genesis              1030                     }
genesis              1031                 }
genesis              1032             }
genesis              1033 
genesis              1034             
genesis              1035             
genesis              1036             
genesis              1037             if (pnode->hSocket == INVALID_SOCKET)
genesis              1038                 continue;
genesis              1039             if (FD_ISSET(pnode->hSocket, &fdsetSend))
genesis              1040             {
genesis              1041                 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis              1042                 {
genesis              1043                     CDataStream& vSend = pnode->vSend;
genesis              1044                     if (!vSend.empty())
genesis              1045                     {
genesis              1046                         int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
genesis              1047                         if (nBytes > 0)
genesis              1048                         {
genesis              1049                             vSend.erase(vSend.begin(), vSend.begin() + nBytes);
genesis              1050                             pnode->nLastSend = GetTime();
genesis              1051                         }
genesis              1052                         else if (nBytes < 0)
genesis              1053                         {
genesis              1054                             
genesis              1055                             int nErr = WSAGetLastError();
genesis              1056                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
genesis              1057                             {
genesis              1058                                 printf("socket send error %d\n", nErr);
genesis              1059                                 pnode->CloseSocketDisconnect();
genesis              1060                             }
genesis              1061                         }
genesis              1062                         if (vSend.size() > SendBufferSize()) {
genesis              1063                             if (!pnode->fDisconnect)
genesis              1064                                 printf("socket send flood control disconnect (%d bytes)\n", vSend.size());
genesis              1065                             pnode->CloseSocketDisconnect();
genesis              1066                         }
genesis              1067                     }
genesis              1068                 }
genesis              1069             }
genesis              1070 
genesis              1071             
genesis              1072             
genesis              1073             
genesis              1074             if (pnode->vSend.empty())
genesis              1075                 pnode->nLastSendEmpty = GetTime();
genesis              1076             if (GetTime() - pnode->nTimeConnected > 60)
genesis              1077             {
genesis              1078                 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
genesis              1079                 {
genesis              1080                     printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
genesis              1081                     pnode->fDisconnect = true;
genesis              1082                 }
genesis              1083                 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
genesis              1084                 {
genesis              1085                     printf("socket not sending\n");
genesis              1086                     pnode->fDisconnect = true;
genesis              1087                 }
genesis              1088                 else if (GetTime() - pnode->nLastRecv > 90*60)
genesis              1089                 {
genesis              1090                     printf("socket inactivity timeout\n");
genesis              1091                     pnode->fDisconnect = true;
genesis              1092                 }
genesis              1093             }
genesis              1094         }
genesis              1095         CRITICAL_BLOCK(cs_vNodes)
genesis              1096         {
genesis              1097             BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis              1098                 pnode->Release();
genesis              1099         }
genesis              1100 
genesis              1101         Sleep(10);
genesis              1102     }
genesis              1103 }
genesis              1104 
genesis              1105 
genesis              1106 
genesis              1107 
genesis              1108 
genesis              1109 
genesis              1110 
genesis              1111 
genesis              1112 
genesis              1113 #ifdef USE_UPNP
genesis              1114 void ThreadMapPort(void* parg)
genesis              1115 {
genesis              1116     IMPLEMENT_RANDOMIZE_STACK(ThreadMapPort(parg));
genesis              1117     try
genesis              1118     {
genesis              1119         vnThreadsRunning[5]++;
genesis              1120         ThreadMapPort2(parg);
genesis              1121         vnThreadsRunning[5]--;
genesis              1122     }
genesis              1123     catch (std::exception& e) {
genesis              1124         vnThreadsRunning[5]--;
genesis              1125         PrintException(&e, "ThreadMapPort()");
genesis              1126     } catch (...) {
genesis              1127         vnThreadsRunning[5]--;
genesis              1128         PrintException(NULL, "ThreadMapPort()");
genesis              1129     }
genesis              1130     printf("ThreadMapPort exiting\n");
genesis              1131 }
genesis              1132 
genesis              1133 void ThreadMapPort2(void* parg)
genesis              1134 {
genesis              1135     printf("ThreadMapPort started\n");
genesis              1136 
genesis              1137     char port[6];
genesis              1138     sprintf(port, "%d", GetListenPort());
genesis              1139 
genesis              1140     const char * multicastif = 0;
genesis              1141     const char * minissdpdpath = 0;
genesis              1142     struct UPNPDev * devlist = 0;
genesis              1143     char lanaddr[64];
genesis              1144 
genesis              1145 #ifndef UPNPDISCOVER_SUCCESS
genesis              1146     
genesis              1147     devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
genesis              1148 #else
genesis              1149     
genesis              1150     int error = 0;
genesis              1151     devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
genesis              1152 #endif
genesis              1153 
genesis              1154     struct UPNPUrls urls;
genesis              1155     struct IGDdatas data;
genesis              1156     int r;
genesis              1157 
genesis              1158     r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
genesis              1159     if (r == 1)
genesis              1160     {
genesis              1161         if (!addrLocalHost.IsRoutable())
genesis              1162         {
genesis              1163             char externalIPAddress[40];
genesis              1164             r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
genesis              1165             if(r != UPNPCOMMAND_SUCCESS)
genesis              1166                 printf("UPnP: GetExternalIPAddress() returned %d\n", r);
genesis              1167             else
genesis              1168             {
genesis              1169                 if(externalIPAddress[0])
genesis              1170                 {
genesis              1171                     printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
genesis              1172                     CAddress addrExternalFromUPnP(externalIPAddress, 0, false, nLocalServices);
genesis              1173                     if (addrExternalFromUPnP.IsRoutable())
genesis              1174                         addrLocalHost = addrExternalFromUPnP;
genesis              1175                 }
genesis              1176                 else
genesis              1177                     printf("UPnP: GetExternalIPAddress failed.\n");
genesis              1178             }
genesis              1179         }
genesis              1180 
genesis              1181         string strDesc = "Bitcoin " + FormatFullVersion();
genesis              1182 #ifndef UPNPDISCOVER_SUCCESS
genesis              1183         
genesis              1184         r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
genesis              1185                             port, port, lanaddr, strDesc.c_str(), "TCP", 0);
genesis              1186 #else
genesis              1187         
genesis              1188         r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
genesis              1189                             port, port, lanaddr, strDesc.c_str(), "TCP", 0, "0");
genesis              1190 #endif
genesis              1191 
genesis              1192         if(r!=UPNPCOMMAND_SUCCESS)
genesis              1193             printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
genesis              1194                 port, port, lanaddr, r, strupnperror(r));
genesis              1195         else
genesis              1196             printf("UPnP Port Mapping successful.\n");
genesis              1197         int i = 1;
genesis              1198         loop {
genesis              1199             if (fShutdown || !fUseUPnP)
genesis              1200             {
genesis              1201                 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port, "TCP", 0);
genesis              1202                 printf("UPNP_DeletePortMapping() returned : %d\n", r);
genesis              1203                 freeUPNPDevlist(devlist); devlist = 0;
genesis              1204                 FreeUPNPUrls(&urls);
genesis              1205                 return;
genesis              1206             }
genesis              1207             if (i % 600 == 0) 
genesis              1208             {
genesis              1209 #ifndef UPNPDISCOVER_SUCCESS
genesis              1210                 
genesis              1211                 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
genesis              1212                                     port, port, lanaddr, strDesc.c_str(), "TCP", 0);
genesis              1213 #else
genesis              1214                 
genesis              1215                 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
genesis              1216                                     port, port, lanaddr, strDesc.c_str(), "TCP", 0, "0");
genesis              1217 #endif
genesis              1218 
genesis              1219                 if(r!=UPNPCOMMAND_SUCCESS)
genesis              1220                     printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
genesis              1221                         port, port, lanaddr, r, strupnperror(r));
genesis              1222                 else
genesis              1223                     printf("UPnP Port Mapping successful.\n");;
genesis              1224             }
genesis              1225             Sleep(2000);
genesis              1226             i++;
genesis              1227         }
genesis              1228     } else {
genesis              1229         printf("No valid UPnP IGDs found\n");
genesis              1230         freeUPNPDevlist(devlist); devlist = 0;
genesis              1231         if (r != 0)
genesis              1232             FreeUPNPUrls(&urls);
genesis              1233         loop {
genesis              1234             if (fShutdown || !fUseUPnP)
genesis              1235                 return;
genesis              1236             Sleep(2000);
genesis              1237         }
genesis              1238     }
genesis              1239 }
genesis              1240 
genesis              1241 void MapPort(bool fMapPort)
genesis              1242 {
genesis              1243     if (fUseUPnP != fMapPort)
genesis              1244     {
genesis              1245         fUseUPnP = fMapPort;
genesis              1246         WriteSetting("fUseUPnP", fUseUPnP);
genesis              1247     }
genesis              1248     if (fUseUPnP && vnThreadsRunning[5] < 1)
genesis              1249     {
genesis              1250         if (!CreateThread(ThreadMapPort, NULL))
genesis              1251             printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
genesis              1252     }
genesis              1253 }
genesis              1254 #else
genesis              1255 void MapPort(bool )
genesis              1256 {
genesis              1257     
genesis              1258 }
genesis              1259 #endif
genesis              1260 
genesis              1261 
genesis              1262 
genesis              1263 
genesis              1264 
genesis              1265 
genesis              1266 
genesis              1267 
genesis              1268 
genesis              1269 
genesis              1270 static const char *strDNSSeed[] = {
genesis              1271     "bitseed.xf2.org",
genesis              1272     "dnsseed.bluematt.me",
genesis              1273     "seed.bitcoin.sipa.be",
genesis              1274     "dnsseed.bitcoin.dashjr.org",
genesis              1275 };
genesis              1276 
genesis              1277 void ThreadDNSAddressSeed(void* parg)
genesis              1278 {
genesis              1279     IMPLEMENT_RANDOMIZE_STACK(ThreadDNSAddressSeed(parg));
genesis              1280     try
genesis              1281     {
genesis              1282         vnThreadsRunning[6]++;
genesis              1283         ThreadDNSAddressSeed2(parg);
genesis              1284         vnThreadsRunning[6]--;
genesis              1285     }
genesis              1286     catch (std::exception& e) {
genesis              1287         vnThreadsRunning[6]--;
genesis              1288         PrintException(&e, "ThreadDNSAddressSeed()");
genesis              1289     } catch (...) {
genesis              1290         vnThreadsRunning[6]--;
genesis              1291         throw; 
genesis              1292     }
genesis              1293     printf("ThreadDNSAddressSeed exiting\n");
genesis              1294 }
genesis              1295 
genesis              1296 void ThreadDNSAddressSeed2(void* parg)
genesis              1297 {
genesis              1298     printf("ThreadDNSAddressSeed started\n");
genesis              1299     int found = 0;
genesis              1300 
genesis              1301     if (!fTestNet)
genesis              1302     {
genesis              1303         printf("Loading addresses from DNS seeds (could take a while)\n");
genesis              1304 
genesis              1305         for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
genesis              1306             vector<CAddress> vaddr;
genesis              1307             if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, -1, true))
genesis              1308             {
genesis              1309                 CAddrDB addrDB;
genesis              1310                 addrDB.TxnBegin();
genesis              1311                 BOOST_FOREACH (CAddress& addr, vaddr)
genesis              1312                 {
genesis              1313                     if (addr.GetByte(3) != 127)
genesis              1314                     {
genesis              1315                         addr.nTime = 0;
genesis              1316                         AddAddress(addr, 0, &addrDB);
genesis              1317                         found++;
genesis              1318                     }
genesis              1319                 }
genesis              1320                 addrDB.TxnCommit();  
genesis              1321             }
genesis              1322         }
genesis              1323     }
genesis              1324 
genesis              1325     printf("%d addresses found from DNS seeds\n", found);
genesis              1326 }
genesis              1327 
genesis              1328 
genesis              1329 
genesis              1330 
genesis              1331 
genesis              1332 
genesis              1333 
genesis              1334 
genesis              1335 
genesis              1336 
genesis              1337 
genesis              1338 
genesis              1339 unsigned int pnSeed[] =
genesis              1340 {
genesis              1341     0x959bd347, 0xf8de42b2, 0x73bc0518, 0xea6edc50, 0x21b00a4d, 0xc725b43d, 0xd665464d, 0x1a2a770e,
genesis              1342     0x27c93946, 0x65b2fa46, 0xb80ae255, 0x66b3b446, 0xb1877a3e, 0x6ee89e3e, 0xc3175b40, 0x2a01a83c,
genesis              1343     0x95b1363a, 0xa079ad3d, 0xe6ca801f, 0x027f4f4a, 0x34f7f03a, 0xf790f04a, 0x16ca801f, 0x2f4d5e40,
genesis              1344     0x3a4d5e40, 0xc43a322e, 0xc8159753, 0x14d4724c, 0x7919a118, 0xe0bdb34e, 0x68a16b2e, 0xff64b44d,
genesis              1345     0x6099115b, 0x9b57b05b, 0x7bd1b4ad, 0xdf95944f, 0x29d2b73d, 0xafa8db79, 0xe247ba41, 0x24078348,
genesis              1346     0xf722f03c, 0x33567ebc, 0xace64ed4, 0x984d3932, 0xb5f34e55, 0x27b7024d, 0x94579247, 0x8894042e,
genesis              1347     0x9357d34c, 0x1063c24b, 0xcaa228b1, 0xa3c5a8b2, 0x5dc64857, 0xa2c23643, 0xa8369a54, 0x31203077,
genesis              1348     0x00707c5c, 0x09fc0b3a, 0x272e9e2e, 0xf80f043e, 0x9449ca3e, 0x5512c33e, 0xd106b555, 0xe8024157,
genesis              1349     0xe288ec29, 0xc79c5461, 0xafb63932, 0xdb02ab4b, 0x0e512777, 0x8a145a4c, 0xb201ff4f, 0x5e09314b,
genesis              1350     0xcd9bfbcd, 0x1c023765, 0x4394e75c, 0xa728bd4d, 0x65331552, 0xa98420b1, 0x89ecf559, 0x6e80801f,
genesis              1351     0xf404f118, 0xefd62b51, 0x05918346, 0x9b186d5f, 0xacabab46, 0xf912e255, 0xc188ea62, 0xcc55734e,
genesis              1352     0xc668064d, 0xd77a4558, 0x46201c55, 0xf17dfc80, 0xf7142f2e, 0x87bfb718, 0x8aa54fb2, 0xc451d518,
genesis              1353     0xc4ae8831, 0x8dd44d55, 0x5bbd206c, 0x64536b5d, 0x5c667e60, 0x3b064242, 0xfe963a42, 0xa28e6dc8,
genesis              1354     0xe8a9604a, 0xc989464e, 0xd124a659, 0x50065140, 0xa44dfe5e, 0x1079e655, 0x3fb986d5, 0x47895b18,
genesis              1355     0x7d3ce4ad, 0x4561ba50, 0x296eec62, 0x255b41ad, 0xaed35ec9, 0x55556f12, 0xc7d3154d, 0x3297b65d,
genesis              1356     0x8930121f, 0xabf42e4e, 0x4a29e044, 0x1212685d, 0x676c1e40, 0xce009744, 0x383a8948, 0xa2dbd0ad,
genesis              1357     0xecc2564d, 0x07dbc252, 0x887ee24b, 0x5171644c, 0x6bb798c1, 0x847f495d, 0x4cbb7145, 0x3bb81c32,
genesis              1358     0x45eb262e, 0xc8015a4e, 0x250a361b, 0xf694f946, 0xd64a183e, 0xd4f1dd59, 0x8f20ffd4, 0x51d9e55c,
genesis              1359     0x09521763, 0x5e02002e, 0x32c8074d, 0xe685762e, 0x8290b0bc, 0x762a922e, 0xfc5ee754, 0x83a24829,
genesis              1360     0x775b224d, 0x6295bb4d, 0x38ec0555, 0xbffbba50, 0xe5560260, 0x86b16a7c, 0xd372234e, 0x49a3c24b,
genesis              1361     0x2f6a171f, 0x4d75ed60, 0xae94115b, 0xcb543744, 0x63080c59, 0x3f9c724c, 0xc977ce18, 0x532efb18,
genesis              1362     0x69dc3b2e, 0x5f94d929, 0x1732bb4d, 0x9c814b4d, 0xe6b3762e, 0xc024f662, 0x8face35b, 0x6b5b044d,
genesis              1363     0x798c7b57, 0x79a6b44c, 0x067d3057, 0xf9e94e5f, 0x91cbe15b, 0x71405eb2, 0x2662234e, 0xcbcc4a6d,
genesis              1364     0xbf69d54b, 0xa79b4e55, 0xec6d3e51, 0x7c0b3c02, 0x60f83653, 0x24c1e15c, 0x1110b62e, 0x10350f59,
genesis              1365     0xa56f1d55, 0x3509e7a9, 0xeb128354, 0x14268e2e, 0x934e28bc, 0x8e32692e, 0x8331a21f, 0x3e633932,
genesis              1366     0xc812b12e, 0xc684bf2e, 0x80112d2e, 0xe0ddc96c, 0xc630ca4a, 0x5c09b3b2, 0x0b580518, 0xc8e9d54b,
genesis              1367     0xd169aa43, 0x17d0d655, 0x1d029963, 0x7ff87559, 0xcb701f1f, 0x6fa3e85d, 0xe45e9a54, 0xf05d1802,
genesis              1368     0x44d03b2e, 0x837b692e, 0xccd4354e, 0x3d6da13c, 0x3423084d, 0xf707c34a, 0x55f6db3a, 0xad26e442,
genesis              1369     0x6233a21f, 0x09e80e59, 0x8caeb54d, 0xbe870941, 0xb407d20e, 0x20b51018, 0x56fb152e, 0x460d2a4e,
genesis              1370     0xbb9a2946, 0x560eb12e, 0xed83dd29, 0xd6724f53, 0xa50aafb8, 0x451346d9, 0x88348e2e, 0x7312fead,
genesis              1371     0x8ecaf96f, 0x1bda4e5f, 0xf1671e40, 0x3c8c3e3b, 0x4716324d, 0xdde24ede, 0xf98cd17d, 0xa91d4644,
genesis              1372     0x28124eb2, 0x147d5129, 0xd022042e, 0x61733d3b, 0xad0d5e02, 0x8ce2932e, 0xe5c18502, 0x549c1e32,
genesis              1373     0x9685801f, 0x86e217ad, 0xd948214b, 0x4110f462, 0x3a2e894e, 0xbd35492e, 0x87e0d558, 0x64b8ef7d,
genesis              1374     0x7c3eb962, 0x72a84b3e, 0x7cd667c9, 0x28370a2e, 0x4bc60e7b, 0x6fc1ec60, 0x14a6983f, 0x86739a4b,
genesis              1375     0x46954e5f, 0x32e2e15c, 0x2e9326cf, 0xe5801c5e, 0x379607b2, 0x32151145, 0xf0e39744, 0xacb54c55,
genesis              1376     0xa37dfb60, 0x83b55cc9, 0x388f7ca5, 0x15034f5f, 0x3e94965b, 0x68e0ffad, 0x35280f59, 0x8fe190cf,
genesis              1377     0x7c6ba5b2, 0xa5e9db43, 0x4ee1fc60, 0xd9d94e5f, 0x04040677, 0x0ea9b35e, 0x5961f14f, 0x67fda063,
genesis              1378     0xa48a5a31, 0xc6524e55, 0x283d325e, 0x3f37515f, 0x96b94b3e, 0xacce620e, 0x6481cc5b, 0xa4a06d4b,
genesis              1379     0x9e95d2d9, 0xe40c03d5, 0xc2f4514b, 0xb79aad44, 0xf64be843, 0xb2064070, 0xfca00455, 0x429dfa4e,
genesis              1380     0x2323f173, 0xeda4185e, 0xabd5227d, 0x9efd4d58, 0xb1104758, 0x4811e955, 0xbd9ab355, 0xe921f44b,
genesis              1381     0x9f166dce, 0x09e279b2, 0xe0c9ac7b, 0x7901a5ad, 0xa145d4b0, 0x79104671, 0xec31e35a, 0x4fe0b555,
genesis              1382     0xc7d9cbad, 0xad057f55, 0xe94cc759, 0x7fe0b043, 0xe4529f2e, 0x0d4dd4b2, 0x9f11a54d, 0x031e2e4e,
genesis              1383     0xe6014f5f, 0x11d1ca6c, 0x26bd7f61, 0xeb86854f, 0x4d347b57, 0x116bbe2e, 0xdba7234e, 0x7bcbfd2e,
genesis              1384     0x174dd4b2, 0x6686762e, 0xb089ba50, 0xc6258246, 0x087e767b, 0xc4a8cb4a, 0x595dba50, 0x7f0ae502,
genesis              1385     0x7b1dbd5a, 0xa0603492, 0x57d1af4b, 0x9e21ffd4, 0x6393064d, 0x7407376e, 0xe484762e, 0x122a4e53,
genesis              1386     0x4a37aa43, 0x3888a6be, 0xee77864e, 0x039c8dd5, 0x688d89af, 0x0e988f62, 0x08218246, 0xfc2f8246,
genesis              1387     0xd1d97040, 0xd64cd4b2, 0x5ae4a6b8, 0x7d0de9bc, 0x8d304d61, 0x06c5c672, 0xa4c8bd4d, 0xe0fd373b,
genesis              1388     0x575ebe4d, 0x72d26277, 0x55570f55, 0x77b154d9, 0xe214293a, 0xfc740f4b, 0xfe3f6a57, 0xa9c55f02,
genesis              1389     0xae4054db, 0x2394d918, 0xb511b24a, 0xb8741ab2, 0x0758e65e, 0xc7b5795b, 0xb0a30a4c, 0xaf7f170c,
genesis              1390     0xf3b4762e, 0x8179576d, 0x738a1581, 0x4b95b64c, 0x9829b618, 0x1bea932e, 0x7bdeaa4b, 0xcb5e0281,
genesis              1391     0x65618f54, 0x0658474b, 0x27066acf, 0x40556d65, 0x7d204d53, 0xf28bc244, 0xdce23455, 0xadc0ff54,
genesis              1392     0x3863c948, 0xcee34e5f, 0xdeb85e02, 0x2ed17a61, 0x6a7b094d, 0x7f0cfc40, 0x59603f54, 0x3220afbc,
genesis              1393     0xb5dfd962, 0x125d21c0, 0x13f8d243, 0xacfefb4e, 0x86c2c147, 0x3d8bbd59, 0xbd02a21f, 0x2593042e,
genesis              1394     0xc6a17a7c, 0x28925861, 0xb487ed44, 0xb5f4fd6d, 0x90c28a45, 0x5a14f74d, 0x43d71b4c, 0x728ebb5d,
genesis              1395     0x885bf950, 0x08134dd0, 0x38ec046e, 0xc575684b, 0x50082d2e, 0xa2f47757, 0x270f86ae, 0xf3ff6462,
genesis              1396     0x10ed3f4e, 0x4b58d462, 0xe01ce23e, 0x8c5b092e, 0x63e52f4e, 0x22c1e85d, 0xa908f54e, 0x8591624f,
genesis              1397     0x2c0fb94e, 0xa280ba3c, 0xb6f41b4c, 0x24f9aa47, 0x27201647, 0x3a3ea6dc, 0xa14fc3be, 0x3c34bdd5,
genesis              1398     0x5b8d4f5b, 0xaadeaf4b, 0xc71cab50, 0x15697a4c, 0x9a1a734c, 0x2a037d81, 0x2590bd59, 0x48ec2741,
genesis              1399     0x53489c5b, 0x7f00314b, 0x2170d362, 0xf2e92542, 0x42c10b44, 0x98f0f118, 0x883a3456, 0x099a932e,
genesis              1400     0xea38f7bc, 0x644e9247, 0xbb61b62e, 0x30e0863d, 0x5f51be54, 0x207215c7, 0x5f306c45, 0xaa7f3932,
genesis              1401     0x98da7d45, 0x4e339b59, 0x2e411581, 0xa808f618, 0xad2c0c59, 0x54476741, 0x09e99fd1, 0x5db8f752,
genesis              1402     0xc16df8bd, 0x1dd4b44f, 0x106edf2e, 0x9e15c180, 0x2ad6b56f, 0x633a5332, 0xff33787c, 0x077cb545,
genesis              1403     0x6610be6d, 0x75aad2c4, 0x72fb4d5b, 0xe81e0f59, 0x576f6332, 0x47333373, 0x351ed783, 0x2d90fb50,
genesis              1404     0x8d5e0f6c, 0x5b27a552, 0xdb293ebb, 0xe55ef950, 0x4b133ad8, 0x75df975a, 0x7b6a8740, 0xa899464b,
genesis              1405     0xfab15161, 0x10f8b64d, 0xd055ea4d, 0xee8e146b, 0x4b14afb8, 0x4bc1c44a, 0x9b961dcc, 0xd111ff43,
genesis              1406     0xfca0b745, 0xc800e412, 0x0afad9d1, 0xf751c350, 0xf9f0cccf, 0xa290a545, 0x8ef13763, 0x7ec70d59,
genesis              1407     0x2b066acf, 0x65496c45, 0xade02c1b, 0xae6eb077, 0x92c1e65b, 0xc064e6a9, 0xc649e56d, 0x5287a243,
genesis              1408     0x36de4f5b, 0x5b1df6ad, 0x65c39a59, 0xdba805b2, 0x20067aa8, 0x6457e56d, 0x3cee26cf, 0xfd3ff26d,
genesis              1409     0x04f86d4a, 0x06b8e048, 0xa93bcd5c, 0x91135852, 0xbe90a643, 0x8fa0094d, 0x06d8215f, 0x2677094d,
genesis              1410     0xd735685c, 0x164a00c9, 0x5209ac5f, 0xa9564c5c, 0x3b504f5f, 0xcc826bd0, 0x4615042e, 0x5fe13b4a,
genesis              1411     0x8c81b86d, 0x879ab68c, 0x1de564b8, 0x434487d8, 0x2dcb1b63, 0x82ab524a, 0xb0676abb, 0xa13d9c62,
genesis              1412     0xdbb5b86d, 0x5b7f4b59, 0xaddfb44d, 0xad773532, 0x3997054c, 0x72cebd89, 0xb194544c, 0xc5b8046e,
genesis              1413     0x6e1adeb2, 0xaa5abb51, 0xefb54b44, 0x15efc54f, 0xe9f1bc4d, 0x5f401b6c, 0x97f018ad, 0xc82f9252,
genesis              1414     0x2cdc762e, 0x8e52e56d, 0x1827175e, 0x9b7d7d80, 0xb2ad6845, 0x51065140, 0x71180a18, 0x5b27006c,
genesis              1415     0x0621e255, 0x721cbe58, 0x670c0cb8, 0xf8bd715d, 0xe0bdc5d9, 0xed843501, 0x4b84554d, 0x7f1a18bc,
genesis              1416     0x53bcaf47, 0x5729d35f, 0xf0dda246, 0x22382bd0, 0x4d641fb0, 0x316afcde, 0x50a22f1f, 0x73608046,
genesis              1417     0xc461d84a, 0xb2dbe247,
genesis              1418 };
genesis              1419 
genesis              1420 
genesis              1421 
genesis              1422 void ThreadOpenConnections(void* parg)
genesis              1423 {
genesis              1424     IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
genesis              1425     try
genesis              1426     {
genesis              1427         vnThreadsRunning[1]++;
genesis              1428         ThreadOpenConnections2(parg);
genesis              1429         vnThreadsRunning[1]--;
genesis              1430     }
genesis              1431     catch (std::exception& e) {
genesis              1432         vnThreadsRunning[1]--;
genesis              1433         PrintException(&e, "ThreadOpenConnections()");
genesis              1434     } catch (...) {
genesis              1435         vnThreadsRunning[1]--;
genesis              1436         PrintException(NULL, "ThreadOpenConnections()");
genesis              1437     }
genesis              1438     printf("ThreadOpenConnections exiting\n");
genesis              1439 }
genesis              1440 
genesis              1441 void ThreadOpenConnections2(void* parg)
genesis              1442 {
genesis              1443     printf("ThreadOpenConnections started\n");
genesis              1444 
genesis              1445     
genesis              1446     if (mapArgs.count("-connect"))
genesis              1447     {
genesis              1448         for (int64 nLoop = 0;; nLoop++)
genesis              1449         {
genesis              1450             BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
genesis              1451             {
genesis              1452                 CAddress addr(strAddr, fAllowDNS);
genesis              1453                 if (addr.IsValid())
genesis              1454                     OpenNetworkConnection(addr);
genesis              1455                 for (int i = 0; i < 10 && i < nLoop; i++)
genesis              1456                 {
genesis              1457                     Sleep(500);
genesis              1458                     if (fShutdown)
genesis              1459                         return;
genesis              1460                 }
genesis              1461             }
genesis              1462         }
genesis              1463     }
genesis              1464 
genesis              1465     
genesis              1466     if (mapArgs.count("-addnode"))
genesis              1467     {
genesis              1468         BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
genesis              1469         {
genesis              1470             CAddress addr(strAddr, fAllowDNS);
genesis              1471             if (addr.IsValid())
genesis              1472             {
genesis              1473                 OpenNetworkConnection(addr);
genesis              1474                 Sleep(500);
genesis              1475                 if (fShutdown)
genesis              1476                     return;
genesis              1477             }
genesis              1478         }
genesis              1479     }
genesis              1480 
genesis              1481     
genesis              1482     int64 nStart = GetTime();
genesis              1483     loop
genesis              1484     {
genesis              1485         vnThreadsRunning[1]--;
genesis              1486         Sleep(500);
genesis              1487         vnThreadsRunning[1]++;
genesis              1488         if (fShutdown)
genesis              1489             return;
genesis              1490 
genesis              1491         
genesis              1492         loop
genesis              1493         {
genesis              1494             int nOutbound = 0;
genesis              1495             CRITICAL_BLOCK(cs_vNodes)
genesis              1496                 BOOST_FOREACH(CNode* pnode, vNodes)
genesis              1497                     if (!pnode->fInbound)
genesis              1498                         nOutbound++;
genesis              1499             int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
genesis              1500             nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
genesis              1501             if (nOutbound < nMaxOutboundConnections)
genesis              1502                 break;
genesis              1503             vnThreadsRunning[1]--;
genesis              1504             Sleep(2000);
genesis              1505             vnThreadsRunning[1]++;
genesis              1506             if (fShutdown)
genesis              1507                 return;
genesis              1508         }
genesis              1509 
genesis              1510         bool fAddSeeds = false;
genesis              1511 
genesis              1512         CRITICAL_BLOCK(cs_mapAddresses)
genesis              1513         {
genesis              1514             
genesis              1515             bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
genesis              1516             if (mapAddresses.empty() && (GetTime() - nStart > 60 || fUseProxy) && !fTestNet)
genesis              1517                 fAddSeeds = true;
genesis              1518         }
genesis              1519 
genesis              1520         if (fAddSeeds)
genesis              1521         {
genesis              1522             for (int i = 0; i < ARRAYLEN(pnSeed); i++)
genesis              1523             {
genesis              1524                 
genesis              1525                 
genesis              1526                 
genesis              1527                 
genesis              1528                 const int64 nOneWeek = 7*24*60*60;
genesis              1529                 CAddress addr;
genesis              1530                 addr.ip = pnSeed[i];
genesis              1531                 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
genesis              1532                 AddAddress(addr);
genesis              1533             }
genesis              1534         }
genesis              1535 
genesis              1536         
genesis              1537         
genesis              1538         
genesis              1539         CAddress addrConnect;
genesis              1540         int64 nBest = INT64_MIN;
genesis              1541 
genesis              1542         
genesis              1543         
genesis              1544         set<unsigned int> setConnected;
genesis              1545         CRITICAL_BLOCK(cs_vNodes)
genesis              1546             BOOST_FOREACH(CNode* pnode, vNodes)
genesis              1547                 setConnected.insert(pnode->addr.ip & 0x0000ffff);
genesis              1548 
genesis              1549         int64 nANow = GetAdjustedTime();
genesis              1550 
genesis              1551         CRITICAL_BLOCK(cs_mapAddresses)
genesis              1552         {
genesis              1553             BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
genesis              1554             {
genesis              1555                 const CAddress& addr = item.second;
genesis              1556                 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
genesis              1557                     continue;
genesis              1558                 int64 nSinceLastSeen = nANow - addr.nTime;
genesis              1559                 int64 nSinceLastTry = nANow - addr.nLastTry;
genesis              1560 
genesis              1561                 
genesis              1562                 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
genesis              1563                 if (addr.port != htons(GetDefaultPort()))
genesis              1564                     nRandomizer += 2 * 60 * 60;
genesis              1565 
genesis              1566                 
genesis              1567                 
genesis              1568                 
genesis              1569                 
genesis              1570                 
genesis              1571                 
genesis              1572                 
genesis              1573                 
genesis              1574                 
genesis              1575                 
genesis              1576                 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
genesis              1577 
genesis              1578                 
genesis              1579                 if (nSinceLastSeen < 60 * 60)
genesis              1580                     nDelay = 10 * 60;
genesis              1581 
genesis              1582                 
genesis              1583                 if (nSinceLastTry < nDelay)
genesis              1584                     continue;
genesis              1585 
genesis              1586                 
genesis              1587                 
genesis              1588                 if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)
genesis              1589                     continue;
genesis              1590 
genesis              1591                 
genesis              1592                 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
genesis              1593                     continue;
genesis              1594 
genesis              1595                 
genesis              1596                 
genesis              1597                 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
genesis              1598                 if (nScore > nBest)
genesis              1599                 {
genesis              1600                     nBest = nScore;
genesis              1601                     addrConnect = addr;
genesis              1602                 }
genesis              1603             }
genesis              1604         }
genesis              1605 
genesis              1606         if (addrConnect.IsValid())
genesis              1607             OpenNetworkConnection(addrConnect);
genesis              1608     }
genesis              1609 }
genesis              1610 
genesis              1611 bool OpenNetworkConnection(const CAddress& addrConnect)
genesis              1612 {
genesis              1613     
genesis              1614     
genesis              1615     
genesis              1616     if (fShutdown)
genesis              1617         return false;
genesis              1618     if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() ||
genesis              1619         FindNode(addrConnect.ip) || CNode::IsBanned(addrConnect.ip))
genesis              1620         return false;
genesis              1621 
genesis              1622     vnThreadsRunning[1]--;
genesis              1623     CNode* pnode = ConnectNode(addrConnect);
genesis              1624     vnThreadsRunning[1]++;
genesis              1625     if (fShutdown)
genesis              1626         return false;
genesis              1627     if (!pnode)
genesis              1628         return false;
genesis              1629     pnode->fNetworkNode = true;
genesis              1630 
genesis              1631     return true;
genesis              1632 }
genesis              1633 
genesis              1634 
genesis              1635 
genesis              1636 
genesis              1637 
genesis              1638 
genesis              1639 
genesis              1640 
genesis              1641 void ThreadMessageHandler(void* parg)
genesis              1642 {
genesis              1643     IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
genesis              1644     try
genesis              1645     {
genesis              1646         vnThreadsRunning[2]++;
genesis              1647         ThreadMessageHandler2(parg);
genesis              1648         vnThreadsRunning[2]--;
genesis              1649     }
genesis              1650     catch (std::exception& e) {
genesis              1651         vnThreadsRunning[2]--;
genesis              1652         PrintException(&e, "ThreadMessageHandler()");
genesis              1653     } catch (...) {
genesis              1654         vnThreadsRunning[2]--;
genesis              1655         PrintException(NULL, "ThreadMessageHandler()");
genesis              1656     }
genesis              1657     printf("ThreadMessageHandler exiting\n");
genesis              1658 }
genesis              1659 
genesis              1660 void ThreadMessageHandler2(void* parg)
genesis              1661 {
genesis              1662     printf("ThreadMessageHandler started\n");
genesis              1663     SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
genesis              1664     while (!fShutdown)
genesis              1665     {
genesis              1666         vector<CNode*> vNodesCopy;
genesis              1667         CRITICAL_BLOCK(cs_vNodes)
genesis              1668         {
genesis              1669             vNodesCopy = vNodes;
genesis              1670             BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis              1671                 pnode->AddRef();
genesis              1672         }
genesis              1673 
genesis              1674         
genesis              1675         CNode* pnodeTrickle = NULL;
genesis              1676         if (!vNodesCopy.empty())
genesis              1677             pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
genesis              1678         BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis              1679         {
genesis              1680             
genesis              1681             TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis              1682                 ProcessMessages(pnode);
genesis              1683             if (fShutdown)
genesis              1684                 return;
genesis              1685 
genesis              1686             
genesis              1687             TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis              1688                 SendMessages(pnode, pnode == pnodeTrickle);
genesis              1689             if (fShutdown)
genesis              1690                 return;
genesis              1691         }
genesis              1692 
genesis              1693         CRITICAL_BLOCK(cs_vNodes)
genesis              1694         {
genesis              1695             BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis              1696                 pnode->Release();
genesis              1697         }
genesis              1698 
genesis              1699         
genesis              1700         
genesis              1701         
genesis              1702         vnThreadsRunning[2]--;
genesis              1703         Sleep(100);
genesis              1704         if (fRequestShutdown)
genesis              1705             Shutdown(NULL);
genesis              1706         vnThreadsRunning[2]++;
genesis              1707         if (fShutdown)
genesis              1708             return;
genesis              1709     }
genesis              1710 }
genesis              1711 
genesis              1712 
genesis              1713 
genesis              1714 
genesis              1715 
genesis              1716 
genesis              1717 bool BindListenPort(string& strError)
genesis              1718 {
genesis              1719     strError = "";
genesis              1720     int nOne = 1;
genesis              1721     addrLocalHost.port = htons(GetListenPort());
genesis              1722 
genesis              1723 #ifdef WIN32
genesis              1724     
genesis              1725     WSADATA wsadata;
genesis              1726     int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
genesis              1727     if (ret != NO_ERROR)
genesis              1728     {
genesis              1729         strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
genesis              1730         printf("%s\n", strError.c_str());
genesis              1731         return false;
genesis              1732     }
genesis              1733 #endif
genesis              1734 
genesis              1735     
genesis              1736     hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
genesis              1737     if (hListenSocket == INVALID_SOCKET)
genesis              1738     {
genesis              1739         strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
genesis              1740         printf("%s\n", strError.c_str());
genesis              1741         return false;
genesis              1742     }
genesis              1743 
genesis              1744 #ifdef SO_NOSIGPIPE
genesis              1745     
genesis              1746     setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
genesis              1747 #endif
genesis              1748 
genesis              1749 #ifndef WIN32
genesis              1750     
genesis              1751     
genesis              1752     setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
genesis              1753 #endif
genesis              1754 
genesis              1755 #ifdef WIN32
genesis              1756     
genesis              1757     if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
genesis              1758 #else
genesis              1759     if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
genesis              1760 #endif
genesis              1761     {
genesis              1762         strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
genesis              1763         printf("%s\n", strError.c_str());
genesis              1764         return false;
genesis              1765     }
genesis              1766 
genesis              1767     
genesis              1768     
genesis              1769     struct sockaddr_in sockaddr;
genesis              1770     memset(&sockaddr, 0, sizeof(sockaddr));
genesis              1771     sockaddr.sin_family = AF_INET;
genesis              1772     sockaddr.sin_addr.s_addr = INADDR_ANY; 
genesis              1773     sockaddr.sin_port = htons(GetListenPort());
genesis              1774     if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
genesis              1775     {
genesis              1776         int nErr = WSAGetLastError();
genesis              1777         if (nErr == WSAEADDRINUSE)
genesis              1778             strError = strprintf(_("Unable to bind to port %d on this computer.  Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
genesis              1779         else
genesis              1780             strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
genesis              1781         printf("%s\n", strError.c_str());
genesis              1782         return false;
genesis              1783     }
genesis              1784     printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
genesis              1785 
genesis              1786     
genesis              1787     if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
genesis              1788     {
genesis              1789         strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
genesis              1790         printf("%s\n", strError.c_str());
genesis              1791         return false;
genesis              1792     }
genesis              1793 
genesis              1794     return true;
genesis              1795 }
genesis              1796 
genesis              1797 void StartNode(void* parg)
genesis              1798 {
genesis              1799     if (pnodeLocalHost == NULL)
genesis              1800         pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, false, nLocalServices));
genesis              1801 
genesis              1802 #ifdef WIN32
genesis              1803     
genesis              1804     char pszHostName[1000] = "";
genesis              1805     if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
genesis              1806     {
genesis              1807         vector<CAddress> vaddr;
genesis              1808         if (Lookup(pszHostName, vaddr, nLocalServices, -1, true))
genesis              1809             BOOST_FOREACH (const CAddress &addr, vaddr)
genesis              1810                 if (addr.GetByte(3) != 127)
genesis              1811                 {
genesis              1812                     addrLocalHost = addr;
genesis              1813                     break;
genesis              1814                 }
genesis              1815     }
genesis              1816 #else
genesis              1817     
genesis              1818     struct ifaddrs* myaddrs;
genesis              1819     if (getifaddrs(&myaddrs) == 0)
genesis              1820     {
genesis              1821         for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
genesis              1822         {
genesis              1823             if (ifa->ifa_addr == NULL) continue;
genesis              1824             if ((ifa->ifa_flags & IFF_UP) == 0) continue;
genesis              1825             if (strcmp(ifa->ifa_name, "lo") == 0) continue;
genesis              1826             if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
genesis              1827             char pszIP[100];
genesis              1828             if (ifa->ifa_addr->sa_family == AF_INET)
genesis              1829             {
genesis              1830                 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
genesis              1831                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
genesis              1832                     printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
genesis              1833 
genesis              1834                 
genesis              1835                 CAddress addr(*(unsigned int*)&s4->sin_addr, GetListenPort(), nLocalServices);
genesis              1836                 if (addr.IsValid() && addr.GetByte(3) != 127)
genesis              1837                 {
genesis              1838                     addrLocalHost = addr;
genesis              1839                     break;
genesis              1840                 }
genesis              1841             }
genesis              1842             else if (ifa->ifa_addr->sa_family == AF_INET6)
genesis              1843             {
genesis              1844                 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
genesis              1845                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
genesis              1846                     printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
genesis              1847             }
genesis              1848         }
genesis              1849         freeifaddrs(myaddrs);
genesis              1850     }
genesis              1851 #endif
genesis              1852     printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
genesis              1853 
genesis              1854     if (fUseProxy || mapArgs.count("-connect") || fNoListen)
genesis              1855     {
genesis              1856         
genesis              1857         addrLocalHost.ip = CAddress("0.0.0.0").ip;
genesis              1858         printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
genesis              1859     }
genesis              1860     else
genesis              1861     {
genesis              1862         CreateThread(ThreadGetMyExternalIP, NULL);
genesis              1863     }
genesis              1864 
genesis              1865     
genesis              1866     
genesis              1867     
genesis              1868 
genesis              1869     if (GetBoolArg("-nodnsseed"))
genesis              1870         printf("DNS seeding disabled\n");
genesis              1871     else
genesis              1872         if (!CreateThread(ThreadDNSAddressSeed, NULL))
genesis              1873             printf("Error: CreateThread(ThreadDNSAddressSeed) failed\n");
genesis              1874 
genesis              1875     
genesis              1876     if (fHaveUPnP)
genesis              1877         MapPort(fUseUPnP);
genesis              1878 
genesis              1879     
genesis              1880     if (!CreateThread(ThreadIRCSeed, NULL))
genesis              1881         printf("Error: CreateThread(ThreadIRCSeed) failed\n");
genesis              1882 
genesis              1883     
genesis              1884     if (!CreateThread(ThreadSocketHandler, NULL))
genesis              1885         printf("Error: CreateThread(ThreadSocketHandler) failed\n");
genesis              1886 
genesis              1887     
genesis              1888     if (!CreateThread(ThreadOpenConnections, NULL))
genesis              1889         printf("Error: CreateThread(ThreadOpenConnections) failed\n");
genesis              1890 
genesis              1891     
genesis              1892     if (!CreateThread(ThreadMessageHandler, NULL))
genesis              1893         printf("Error: CreateThread(ThreadMessageHandler) failed\n");
genesis              1894 
genesis              1895     
genesis              1896     GenerateBitcoins(fGenerateBitcoins, pwalletMain);
genesis              1897 }
genesis              1898 
genesis              1899 bool StopNode()
genesis              1900 {
genesis              1901     printf("StopNode()\n");
genesis              1902     fShutdown = true;
genesis              1903     nTransactionsUpdated++;
genesis              1904     int64 nStart = GetTime();
genesis              1905     while (vnThreadsRunning[0] > 0 || vnThreadsRunning[1] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0
genesis              1906 #ifdef USE_UPNP
genesis              1907         || vnThreadsRunning[5] > 0
genesis              1908 #endif
genesis              1909     )
genesis              1910     {
genesis              1911         if (GetTime() - nStart > 20)
genesis              1912             break;
genesis              1913         Sleep(20);
genesis              1914     }
genesis              1915     if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
genesis              1916     if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
genesis              1917     if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
genesis              1918     if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
genesis              1919     if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
genesis              1920     if (fHaveUPnP && vnThreadsRunning[5] > 0) printf("ThreadMapPort still running\n");
genesis              1921     if (vnThreadsRunning[6] > 0) printf("ThreadDNSAddressSeed still running\n");
genesis              1922     while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
genesis              1923         Sleep(20);
genesis              1924     Sleep(50);
genesis              1925 
genesis              1926     return true;
genesis              1927 }
genesis              1928 
genesis              1929 class CNetCleanup
genesis              1930 {
genesis              1931 public:
genesis              1932     CNetCleanup()
genesis              1933     {
genesis              1934     }
genesis              1935     ~CNetCleanup()
genesis              1936     {
genesis              1937         
genesis              1938         BOOST_FOREACH(CNode* pnode, vNodes)
genesis              1939             if (pnode->hSocket != INVALID_SOCKET)
genesis              1940                 closesocket(pnode->hSocket);
genesis              1941         if (hListenSocket != INVALID_SOCKET)
genesis              1942             if (closesocket(hListenSocket) == SOCKET_ERROR)
genesis              1943                 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
genesis              1944 
genesis              1945 #ifdef WIN32
genesis              1946         
genesis              1947         WSACleanup();
genesis              1948 #endif
genesis              1949     }
genesis              1950 }
genesis              1951 instance_of_cnetcleanup;