X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fnet.cpp;h=e5cb6d4b24955ce1f0ed8f0a40a9991f8cc8ccf2;hb=ea22a380de824500644db6fd6f33d0465b34f7a1;hp=66c9218cd01227a954dd00a460ffd4dc355bd935;hpb=177dbcaace432f46b191add5c26226dbaac2c81c;p=novacoin.git diff --git a/src/net.cpp b/src/net.cpp index 66c9218..e5cb6d4 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2011 The Bitcoin developers +// Copyright (c) 2009-2012 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file license.txt or http://www.opensource.org/licenses/mit-license.php. @@ -9,9 +9,12 @@ #include "net.h" #include "init.h" #include "strlcpy.h" +#include "addrman.h" #ifdef WIN32 #include +#else +#include #endif #ifdef USE_UPNP @@ -38,24 +41,22 @@ bool OpenNetworkConnection(const CAddress& addrConnect); - - // // Global state variables // bool fClient = false; bool fAllowDNS = false; +static bool fUseUPnP = false; uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK); CAddress addrLocalHost(CService("0.0.0.0", 0), nLocalServices); static CNode* pnodeLocalHost = NULL; uint64 nLocalHostNonce = 0; -array vnThreadsRunning; +array vnThreadsRunning; static SOCKET hListenSocket = INVALID_SOCKET; +CAddrMan addrman; vector vNodes; CCriticalSection cs_vNodes; -map, CAddress> mapAddresses; -CCriticalSection cs_mapAddresses; map mapRelay; deque > vRelayExpiration; CCriticalSection cs_mapRelay; @@ -67,7 +68,6 @@ CCriticalSection cs_setservAddNodeAddresses; - unsigned short GetListenPort() { return (unsigned short)(GetArg("-port", GetDefaultPort())); @@ -86,6 +86,57 @@ void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd) +bool RecvLine(SOCKET hSocket, string& strLine) +{ + strLine = ""; + loop + { + char c; + int nBytes = recv(hSocket, &c, 1, 0); + if (nBytes > 0) + { + if (c == '\n') + continue; + if (c == '\r') + return true; + strLine += c; + if (strLine.size() >= 9000) + return true; + } + else if (nBytes <= 0) + { + if (fShutdown) + return false; + if (nBytes < 0) + { + int nErr = WSAGetLastError(); + if (nErr == WSAEMSGSIZE) + continue; + if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS) + { + Sleep(10); + continue; + } + } + if (!strLine.empty()) + return true; + if (nBytes == 0) + { + // socket closed + printf("socket closed\n"); + return false; + } + else + { + // socket error + int nErr = WSAGetLastError(); + printf("recv failed: %d\n", nErr); + return false; + } + } + } +} + bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const char* pszKeyword, CNetAddr& ipRet) @@ -110,14 +161,14 @@ bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const cha } if (pszKeyword == NULL) break; - if (strLine.find(pszKeyword) != -1) + if (strLine.find(pszKeyword) != string::npos) { strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword)); break; } } closesocket(hSocket); - if (strLine.find("<") != -1) + if (strLine.find("<") != string::npos) strLine = strLine.substr(0, strLine.find("<")); strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r")); while (strLine.size() > 0 && isspace(strLine[strLine.size()-1])) @@ -141,7 +192,7 @@ bool GetMyExternalIP(CNetAddr& ipRet) const char* pszGet; const char* pszKeyword; - if (fUseProxy) + if (fNoListen||fUseProxy) return false; for (int nLookup = 0; nLookup <= 1; nLookup++) @@ -200,7 +251,7 @@ bool GetMyExternalIP(CNetAddr& ipRet) void ThreadGetMyExternalIP(void* parg) { // Wait for IRC to get it first - if (!GetBoolArg("-noirc")) + if (GetBoolArg("-irc", false)) { for (int i = 0; i < 2 * 60; i++) { @@ -231,86 +282,9 @@ void ThreadGetMyExternalIP(void* parg) -bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB) -{ - if (!addr.IsRoutable()) - return false; - if ((CService)addr == (CService)addrLocalHost) - return false; - addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty); - bool fUpdated = false; - bool fNew = false; - CAddress addrFound = addr; - - CRITICAL_BLOCK(cs_mapAddresses) - { - map, CAddress>::iterator it = mapAddresses.find(addr.GetKey()); - if (it == mapAddresses.end()) - { - // New address - printf("AddAddress(%s)\n", addr.ToString().c_str()); - mapAddresses.insert(make_pair(addr.GetKey(), addr)); - fUpdated = true; - fNew = true; - } - else - { - addrFound = (*it).second; - if ((addrFound.nServices | addr.nServices) != addrFound.nServices) - { - // Services have been added - addrFound.nServices |= addr.nServices; - fUpdated = true; - } - bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60); - int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60); - if (addrFound.nTime < addr.nTime - nUpdateInterval) - { - // Periodically update most recently seen time - addrFound.nTime = addr.nTime; - fUpdated = true; - } - } - } - // There is a nasty deadlock bug if this is done inside the cs_mapAddresses - // CRITICAL_BLOCK: - // Thread 1: begin db transaction (locks inside-db-mutex) - // then AddAddress (locks cs_mapAddresses) - // Thread 2: AddAddress (locks cs_mapAddresses) - // ... then db operation hangs waiting for inside-db-mutex - if (fUpdated) - { - if (pAddrDB) - pAddrDB->WriteAddress(addrFound); - else - CAddrDB().WriteAddress(addrFound); - } - return fNew; -} - void AddressCurrentlyConnected(const CService& addr) { - CAddress *paddrFound = NULL; - - CRITICAL_BLOCK(cs_mapAddresses) - { - // Only if it's been published already - map, CAddress>::iterator it = mapAddresses.find(addr.GetKey()); - if (it != mapAddresses.end()) - paddrFound = &(*it).second; - } - - if (paddrFound) - { - int64 nUpdateInterval = 20 * 60; - if (paddrFound->nTime < GetAdjustedTime() - nUpdateInterval) - { - // Periodically update most recently seen time - paddrFound->nTime = GetAdjustedTime(); - CAddrDB addrdb; - addrdb.WriteAddress(*paddrFound); - } - } + addrman.Connected(addr); } @@ -457,13 +431,11 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout) } /// debug print - printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n", + printf("trying connection %s lastseen=%.1fhrs\n", addrConnect.ToString().c_str(), - (double)(addrConnect.nTime - GetAdjustedTime())/3600.0, - (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0); + (double)(addrConnect.nTime - GetAdjustedTime())/3600.0); - CRITICAL_BLOCK(cs_mapAddresses) - mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime(); + addrman.Attempt(addrConnect); // Connect SOCKET hSocket; @@ -510,6 +482,7 @@ void CNode::CloseSocketDisconnect() printf("disconnecting node %s\n", addr.ToString().c_str()); closesocket(hSocket); hSocket = INVALID_SOCKET; + vRecv.clear(); } } @@ -530,7 +503,7 @@ void CNode::PushVersion() /// when NTP implemented, change to just nTime = GetAdjustedTime() int64 nTime = (fInbound ? GetAdjustedTime() : GetTime()); CAddress addrYou = (fUseProxy ? CAddress(CService("0.0.0.0",0)) : addr); - CAddress addrMe = (fUseProxy ? CAddress(CService("0.0.0.0",0)) : addrLocalHost); + CAddress addrMe = (fUseProxy || !addrLocalHost.IsRoutable() ? CAddress(CService("0.0.0.0",0)) : addrLocalHost); RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe, nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector()), nBestHeight); @@ -602,15 +575,15 @@ void ThreadSocketHandler(void* parg) IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg)); try { - vnThreadsRunning[0]++; + vnThreadsRunning[THREAD_SOCKETHANDLER]++; ThreadSocketHandler2(parg); - vnThreadsRunning[0]--; + vnThreadsRunning[THREAD_SOCKETHANDLER]--; } catch (std::exception& e) { - vnThreadsRunning[0]--; + vnThreadsRunning[THREAD_SOCKETHANDLER]--; PrintException(&e, "ThreadSocketHandler()"); } catch (...) { - vnThreadsRunning[0]--; + vnThreadsRunning[THREAD_SOCKETHANDLER]--; throw; // support pthread_cancel() } printf("ThreadSocketHandler exiting\n"); @@ -712,9 +685,9 @@ void ThreadSocketHandler2(void* parg) } } - vnThreadsRunning[0]--; + vnThreadsRunning[THREAD_SOCKETHANDLER]--; int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout); - vnThreadsRunning[0]++; + vnThreadsRunning[THREAD_SOCKETHANDLER]++; if (fShutdown) return; if (nSelect == SOCKET_ERROR) @@ -723,7 +696,7 @@ void ThreadSocketHandler2(void* parg) if (hSocketMax > -1) { printf("socket select error %d\n", nErr); - for (int i = 0; i <= hSocketMax; i++) + for (unsigned int i = 0; i <= hSocketMax; i++) FD_SET(i, &fdsetRecv); } FD_ZERO(&fdsetSend); @@ -740,13 +713,17 @@ void ThreadSocketHandler2(void* parg) struct sockaddr_in sockaddr; socklen_t len = sizeof(sockaddr); SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len); - CAddress addr(sockaddr); + CAddress addr; int nInbound = 0; + if (hSocket != INVALID_SOCKET) + addr = CAddress(sockaddr); + CRITICAL_BLOCK(cs_vNodes) BOOST_FOREACH(CNode* pnode, vNodes) if (pnode->fInbound) nInbound++; + if (hSocket == INVALID_SOCKET) { if (WSAGetLastError() != WSAEWOULDBLOCK) @@ -760,7 +737,7 @@ void ThreadSocketHandler2(void* parg) } else if (CNode::IsBanned(addr)) { - printf("connetion from %s dropped (banned)\n", addr.ToString().c_str()); + printf("connection from %s dropped (banned)\n", addr.ToString().c_str()); closesocket(hSocket); } else @@ -923,15 +900,15 @@ void ThreadMapPort(void* parg) IMPLEMENT_RANDOMIZE_STACK(ThreadMapPort(parg)); try { - vnThreadsRunning[5]++; + vnThreadsRunning[THREAD_UPNP]++; ThreadMapPort2(parg); - vnThreadsRunning[5]--; + vnThreadsRunning[THREAD_UPNP]--; } catch (std::exception& e) { - vnThreadsRunning[5]--; + vnThreadsRunning[THREAD_UPNP]--; PrintException(&e, "ThreadMapPort()"); } catch (...) { - vnThreadsRunning[5]--; + vnThreadsRunning[THREAD_UPNP]--; PrintException(NULL, "ThreadMapPort()"); } printf("ThreadMapPort exiting\n"); @@ -965,6 +942,26 @@ void ThreadMapPort2(void* parg) r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); if (r == 1) { + if (!addrLocalHost.IsRoutable()) + { + char externalIPAddress[40]; + r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress); + if(r != UPNPCOMMAND_SUCCESS) + printf("UPnP: GetExternalIPAddress() returned %d\n", r); + else + { + if(externalIPAddress[0]) + { + printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress); + CAddress addrExternalFromUPnP(CService(externalIPAddress, 0), nLocalServices); + if (addrExternalFromUPnP.IsRoutable()) + addrLocalHost = addrExternalFromUPnP; + } + else + printf("UPnP: GetExternalIPAddress failed.\n"); + } + } + string strDesc = "Bitcoin " + FormatFullVersion(); #ifndef UPNPDISCOVER_SUCCESS /* miniupnpc 1.5 */ @@ -1030,9 +1027,8 @@ void MapPort(bool fMapPort) if (fUseUPnP != fMapPort) { fUseUPnP = fMapPort; - WriteSetting("fUseUPnP", fUseUPnP); } - if (fUseUPnP && vnThreadsRunning[5] < 1) + if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1) { if (!CreateThread(ThreadMapPort, NULL)) printf("Error: ThreadMapPort(ThreadMapPort) failed\n"); @@ -1053,12 +1049,15 @@ void MapPort(bool /* unused fMapPort */) - -static const char *strDNSSeed[] = { - "bitseed.xf2.org", - "dnsseed.bluematt.me", - "seed.bitcoin.sipa.be", - "dnsseed.bitcoin.dashjr.org", +// DNS seeds +// Each pair gives a source name and a seed name. +// The first name is used as information source for addrman. +// The second name should resolve to a list of seed addresses. +static const char *strDNSSeed[][2] = { + {"xf2.org", "bitseed.xf2.org"}, + {"bluematt.me", "dnsseed.bluematt.me"}, + {"bitcoin.sipa.be", "seed.bitcoin.sipa.be"}, + {"dashjr.org", "dnsseed.bitcoin.dashjr.org"}, }; void ThreadDNSAddressSeed(void* parg) @@ -1066,15 +1065,15 @@ void ThreadDNSAddressSeed(void* parg) IMPLEMENT_RANDOMIZE_STACK(ThreadDNSAddressSeed(parg)); try { - vnThreadsRunning[6]++; + vnThreadsRunning[THREAD_DNSSEED]++; ThreadDNSAddressSeed2(parg); - vnThreadsRunning[6]--; + vnThreadsRunning[THREAD_DNSSEED]--; } catch (std::exception& e) { - vnThreadsRunning[6]--; + vnThreadsRunning[THREAD_DNSSEED]--; PrintException(&e, "ThreadDNSAddressSeed()"); } catch (...) { - vnThreadsRunning[6]--; + vnThreadsRunning[THREAD_DNSSEED]--; throw; // support pthread_cancel() } printf("ThreadDNSAddressSeed exiting\n"); @@ -1089,24 +1088,21 @@ void ThreadDNSAddressSeed2(void* parg) { printf("Loading addresses from DNS seeds (could take a while)\n"); - for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) { + for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) { vector vaddr; - if (LookupHost(strDNSSeed[seed_idx], vaddr)) + vector vAdd; + if (LookupHost(strDNSSeed[seed_idx][1], vaddr)) { - CAddrDB addrDB; - addrDB.TxnBegin(); - BOOST_FOREACH (CNetAddr& ip, vaddr) + BOOST_FOREACH(CNetAddr& ip, vaddr) { - if (ip.IsRoutable()) - { - CAddress addr(CService(ip, GetDefaultPort()), NODE_NETWORK); - addr.nTime = 0; - AddAddress(addr, 0, &addrDB); - found++; - } + int nOneDay = 24*3600; + CAddress addr = CAddress(CService(ip, GetDefaultPort())); + addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old + vAdd.push_back(addr); + found++; } - addrDB.TxnCommit(); // Save addresses (it's ok if this fails) } + addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true)); } } @@ -1205,22 +1201,52 @@ unsigned int pnSeed[] = 0xc461d84a, 0xb2dbe247, }; +void DumpAddresses() +{ + CAddrDB adb; + adb.WriteAddrman(addrman); +} + +void ThreadDumpAddress2(void* parg) +{ + vnThreadsRunning[THREAD_DUMPADDRESS]++; + while (!fShutdown) + { + DumpAddresses(); + vnThreadsRunning[THREAD_DUMPADDRESS]--; + Sleep(100000); + vnThreadsRunning[THREAD_DUMPADDRESS]++; + } + vnThreadsRunning[THREAD_DUMPADDRESS]--; +} +void ThreadDumpAddress(void* parg) +{ + IMPLEMENT_RANDOMIZE_STACK(ThreadDumpAddress(parg)); + try + { + ThreadDumpAddress2(parg); + } + catch (std::exception& e) { + PrintException(&e, "ThreadDumpAddress()"); + } + printf("ThreadDumpAddress exiting\n"); +} void ThreadOpenConnections(void* parg) { IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg)); try { - vnThreadsRunning[1]++; + vnThreadsRunning[THREAD_OPENCONNECTIONS]++; ThreadOpenConnections2(parg); - vnThreadsRunning[1]--; + vnThreadsRunning[THREAD_OPENCONNECTIONS]--; } catch (std::exception& e) { - vnThreadsRunning[1]--; + vnThreadsRunning[THREAD_OPENCONNECTIONS]--; PrintException(&e, "ThreadOpenConnections()"); } catch (...) { - vnThreadsRunning[1]--; + vnThreadsRunning[THREAD_OPENCONNECTIONS]--; PrintException(NULL, "ThreadOpenConnections()"); } printf("ThreadOpenConnections exiting\n"); @@ -1254,12 +1280,18 @@ void ThreadOpenConnections2(void* parg) int64 nStart = GetTime(); loop { - // Limit outbound connections - vnThreadsRunning[1]--; + int nOutbound = 0; + + vnThreadsRunning[THREAD_OPENCONNECTIONS]--; Sleep(500); + vnThreadsRunning[THREAD_OPENCONNECTIONS]++; + if (fShutdown) + return; + + // Limit outbound connections loop { - int nOutbound = 0; + nOutbound = 0; CRITICAL_BLOCK(cs_vNodes) BOOST_FOREACH(CNode* pnode, vNodes) if (!pnode->fInbound) @@ -1268,27 +1300,19 @@ void ThreadOpenConnections2(void* parg) nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125)); if (nOutbound < nMaxOutboundConnections) break; + vnThreadsRunning[THREAD_OPENCONNECTIONS]--; Sleep(2000); + vnThreadsRunning[THREAD_OPENCONNECTIONS]++; if (fShutdown) return; } - vnThreadsRunning[1]++; - if (fShutdown) - return; - - bool fAddSeeds = false; - - CRITICAL_BLOCK(cs_mapAddresses) - { - // Add seed nodes if IRC isn't working - bool fTOR = (fUseProxy && addrProxy.GetPort() == 9050); - if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR) && !fTestNet) - fAddSeeds = true; - } - if (fAddSeeds) + // Add seed nodes if IRC isn't working + bool fTOR = (fUseProxy && addrProxy.GetPort() == 9050); + if (addrman.size()==0 && (GetTime() - nStart > 60 || fTOR) && !fTestNet) { - for (int i = 0; i < ARRAYLEN(pnSeed); i++) + std::vector vAdd; + for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++) { // It'll only connect to one or two seed nodes because once it connects, // it'll get a pile of addresses with newer timestamps. @@ -1299,15 +1323,15 @@ void ThreadOpenConnections2(void* parg) memcpy(&ip, &pnSeed[i], sizeof(ip)); CAddress addr(CService(ip, GetDefaultPort())); addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek; - AddAddress(addr); + vAdd.push_back(addr); } + addrman.Add(vAdd, CNetAddr("127.0.0.1")); } // // Choose an address to connect to based on most recently seen // CAddress addrConnect; - int64 nBest = std::numeric_limits::min(); // Only connect to one address per a.b.?.? range. // Do this here so we don't have to critsect vNodes inside mapAddresses critsect. @@ -1318,59 +1342,28 @@ void ThreadOpenConnections2(void* parg) int64 nANow = GetAdjustedTime(); - CRITICAL_BLOCK(cs_mapAddresses) + int nTries = 0; + loop { - BOOST_FOREACH(const PAIRTYPE(vector, CAddress)& item, mapAddresses) - { - const CAddress& addr = item.second; - if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.GetGroup())) - continue; - int64 nSinceLastSeen = nANow - addr.nTime; - int64 nSinceLastTry = nANow - addr.nLastTry; - - // Randomize the order in a deterministic way, putting the standard port first - int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.GetHash()) % (2 * 60 * 60); - if (addr.GetPort() != GetDefaultPort()) - nRandomizer += 2 * 60 * 60; - - // Last seen Base retry frequency - // <1 hour 10 min - // 1 hour 1 hour - // 4 hours 2 hours - // 24 hours 5 hours - // 48 hours 7 hours - // 7 days 13 hours - // 30 days 27 hours - // 90 days 46 hours - // 365 days 93 hours - int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer); - - // Fast reconnect for one hour after last seen - if (nSinceLastSeen < 60 * 60) - nDelay = 10 * 60; - - // Limit retry frequency - if (nSinceLastTry < nDelay) - continue; + // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections) + CAddress addr = addrman.Select(10 + min(nOutbound,8)*10); - // If we have IRC, we'll be notified when they first come online, - // and again every 24 hours by the refresh broadcast. - if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60) - continue; + // if we selected an invalid address, restart + if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.GetGroup()) || addr == addrLocalHost) + break; - // Only try the old stuff if we don't have enough connections - if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60) - continue; + nTries++; - // If multiple addresses are ready, prioritize by time since - // last seen and time since last tried. - int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer; - if (nScore > nBest) - { - nBest = nScore; - addrConnect = addr; - } - } + // only consider very recently tried nodes after 30 failed attempts + if (nANow - addr.nLastTry < 600 && nTries < 30) + continue; + + // do not allow non-default ports, unless after 50 invalid addresses selected already + if (addr.GetPort() != GetDefaultPort() && nTries < 50) + continue; + + addrConnect = addr; + break; } if (addrConnect.IsValid()) @@ -1383,15 +1376,15 @@ void ThreadOpenAddedConnections(void* parg) IMPLEMENT_RANDOMIZE_STACK(ThreadOpenAddedConnections(parg)); try { - vnThreadsRunning[7]++; + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++; ThreadOpenAddedConnections2(parg); - vnThreadsRunning[7]--; + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; } catch (std::exception& e) { - vnThreadsRunning[7]--; + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; PrintException(&e, "ThreadOpenAddedConnections()"); } catch (...) { - vnThreadsRunning[7]--; + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; PrintException(NULL, "ThreadOpenAddedConnections()"); } printf("ThreadOpenAddedConnections exiting\n"); @@ -1440,9 +1433,9 @@ void ThreadOpenAddedConnections2(void* parg) } if (fShutdown) return; - vnThreadsRunning[7]--; + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; Sleep(120000); // Retry every 2 minutes - vnThreadsRunning[7]++; + vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++; if (fShutdown) return; } @@ -1459,9 +1452,9 @@ bool OpenNetworkConnection(const CAddress& addrConnect) FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect)) return false; - vnThreadsRunning[1]--; + vnThreadsRunning[THREAD_OPENCONNECTIONS]--; CNode* pnode = ConnectNode(addrConnect); - vnThreadsRunning[1]++; + vnThreadsRunning[THREAD_OPENCONNECTIONS]++; if (fShutdown) return false; if (!pnode) @@ -1483,15 +1476,15 @@ void ThreadMessageHandler(void* parg) IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg)); try { - vnThreadsRunning[2]++; + vnThreadsRunning[THREAD_MESSAGEHANDLER]++; ThreadMessageHandler2(parg); - vnThreadsRunning[2]--; + vnThreadsRunning[THREAD_MESSAGEHANDLER]--; } catch (std::exception& e) { - vnThreadsRunning[2]--; + vnThreadsRunning[THREAD_MESSAGEHANDLER]--; PrintException(&e, "ThreadMessageHandler()"); } catch (...) { - vnThreadsRunning[2]--; + vnThreadsRunning[THREAD_MESSAGEHANDLER]--; PrintException(NULL, "ThreadMessageHandler()"); } printf("ThreadMessageHandler exiting\n"); @@ -1539,11 +1532,11 @@ void ThreadMessageHandler2(void* parg) // Wait and allow messages to bunch up. // Reduce vnThreadsRunning so StopNode has permission to exit while // we're sleeping, but we must always check fShutdown after doing this. - vnThreadsRunning[2]--; + vnThreadsRunning[THREAD_MESSAGEHANDLER]--; Sleep(100); if (fRequestShutdown) Shutdown(NULL); - vnThreadsRunning[2]++; + vnThreadsRunning[THREAD_MESSAGEHANDLER]++; if (fShutdown) return; } @@ -1636,6 +1629,14 @@ bool BindListenPort(string& strError) void StartNode(void* parg) { +#ifdef USE_UPNP +#if USE_UPNP + fUseUPnP = GetBoolArg("-upnp", true); +#else + fUseUPnP = GetBoolArg("-upnp", false); +#endif +#endif + if (pnodeLocalHost == NULL) pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices)); @@ -1706,7 +1707,7 @@ void StartNode(void* parg) // Start threads // - if (GetBoolArg("-nodnsseed")) + if (!GetBoolArg("-dnsseed", true)) printf("DNS seeding disabled\n"); else if (!CreateThread(ThreadDNSAddressSeed, NULL)) @@ -1736,8 +1737,12 @@ void StartNode(void* parg) if (!CreateThread(ThreadMessageHandler, NULL)) printf("Error: CreateThread(ThreadMessageHandler) failed\n"); + // Dump network addresses + if (!CreateThread(ThreadDumpAddress, NULL)) + printf("Error; CreateThread(ThreadDumpAddress) failed\n"); + // Generate coins in the background - GenerateBitcoins(fGenerateBitcoins, pwalletMain); + GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain); } bool StopNode() @@ -1746,26 +1751,30 @@ bool StopNode() fShutdown = true; nTransactionsUpdated++; int64 nStart = GetTime(); - while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0 - || (fHaveUPnP && vnThreadsRunning[5] > 0) || vnThreadsRunning[6] > 0 || vnThreadsRunning[7] > 0 - ) + do { + int nThreadsRunning = 0; + for (int n = 0; n < THREAD_MAX; n++) + nThreadsRunning += vnThreadsRunning[n]; + if (nThreadsRunning == 0) + break; if (GetTime() - nStart > 20) break; Sleep(20); - } - if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n"); - if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n"); - if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n"); - if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n"); - if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n"); - if (fHaveUPnP && vnThreadsRunning[5] > 0) printf("ThreadMapPort still running\n"); - if (vnThreadsRunning[6] > 0) printf("ThreadDNSAddressSeed still running\n"); - if (vnThreadsRunning[7] > 0) printf("ThreadOpenAddedConnections still running\n"); - while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0) + } while(true); + if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n"); + if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n"); + if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n"); + if (vnThreadsRunning[THREAD_MINER] > 0) printf("ThreadBitcoinMiner still running\n"); + if (vnThreadsRunning[THREAD_RPCSERVER] > 0) printf("ThreadRPCServer still running\n"); + if (fHaveUPnP && vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n"); + if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n"); + if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n"); + if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n"); + while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCSERVER] > 0) Sleep(20); Sleep(50); - + DumpAddresses(); return true; }