X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fnet.cpp;h=90a1e5e84795df2a213645c835310e7ab0cc5f1d;hb=a5404a5c13b2bb202d37797b7143a709075929c4;hp=d6b31189051e75c3fa46aafc81622361dd91df06;hpb=265dcc7e227581180487d4a34aaca2c9a82d0db0;p=novacoin.git diff --git a/src/net.cpp b/src/net.cpp index d6b3118..90a1e5e 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -55,6 +55,7 @@ static map mapLocalHost; static bool vfReachable[NET_MAX] = {}; static bool vfLimited[NET_MAX] = {}; static CNode* pnodeLocalHost = NULL; +static CNode* pnodeSync = NULL; CAddress addrSeenByPeer(CService("0.0.0.0", 0), nLocalServices); uint64 nLocalHostNonce = 0; boost::array vnThreadsRunning; @@ -300,116 +301,27 @@ bool IsReachable(const CNetAddr& addr) return vfReachable[net] && !vfLimited[net]; } -bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const char* pszKeyword, CNetAddr& ipRet) -{ - SOCKET hSocket; - if (!ConnectSocket(addrConnect, hSocket)) - return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str()); - - send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL); - - string strLine; - while (RecvLine(hSocket, strLine)) - { - if (strLine.empty()) // HTTP response is separated from headers by blank line - { - while (true) - { - if (!RecvLine(hSocket, strLine)) - { - closesocket(hSocket); - return false; - } - if (pszKeyword == NULL) - break; - if (strLine.find(pszKeyword) != string::npos) - { - strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword)); - break; - } - } - closesocket(hSocket); - 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])) - strLine.resize(strLine.size()-1); - CService addr(strLine,0,true); - printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str()); - if (!addr.IsValid() || !addr.IsRoutable()) - return false; - ipRet.SetIP(addr); - return true; - } - } - closesocket(hSocket); - return error("GetMyExternalIP() : connection closed"); -} +extern int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv); // We now get our external IP from the IRC server first and only use this as a backup bool GetMyExternalIP(CNetAddr& ipRet) { - CService addrConnect; - const char* pszGet; - const char* pszKeyword; - - for (int nLookup = 0; nLookup <= 1; nLookup++) - for (int nHost = 1; nHost <= 2; nHost++) - { - // We should be phasing out our use of sites like these. If we need - // replacements, we should ask for volunteers to put this simple - // php file on their web server that prints the client IP: - // - if (nHost == 1) - { - addrConnect = CService("91.198.22.70",80); // checkip.dyndns.org - - if (nLookup == 1) - { - CService addrIP("checkip.dyndns.org", 80, true); - if (addrIP.IsValid()) - addrConnect = addrIP; - } - - pszGet = "GET / HTTP/1.1\r\n" - "Host: checkip.dyndns.org\r\n" - "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n" - "Connection: close\r\n" - "\r\n"; - - pszKeyword = "Address:"; - } - else if (nHost == 2) - { - addrConnect = CService("74.208.43.192", 80); // www.showmyip.com - - if (nLookup == 1) - { - CService addrIP("www.showmyip.com", 80, true); - if (addrIP.IsValid()) - addrConnect = addrIP; - } - - pszGet = "GET /simple/ HTTP/1.1\r\n" - "Host: www.showmyip.com\r\n" - "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n" - "Connection: close\r\n" - "\r\n"; - - pszKeyword = NULL; // Returns just IP address - } - - if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet)) - return true; + struct sockaddr_in mapped; + uint64 rnd = GetRand(~0LL); + const char *srv; + int rc = GetExternalIPbySTUN(rnd, &mapped, &srv); + if(rc >= 0) { + ipRet = CNetAddr(mapped.sin_addr); + printf("GetExternalIPbySTUN(%"PRI64u") returned %s in attempt %d; Server=%s\n", rnd, ipRet.ToStringIP().c_str(), rc, srv); + return true; } - return false; } void ThreadGetMyExternalIP(void* parg) { // Make this thread recognisable as the external IP detection thread - RenameThread("bitcoin-ext-ip"); + RenameThread("novacoin-ext-ip"); CNetAddr addrLocalHost; if (GetMyExternalIP(addrLocalHost)) @@ -431,17 +343,17 @@ void AddressCurrentlyConnected(const CService& addr) - - +uint64_t CNode::nTotalBytesRecv = 0; +uint64_t CNode::nTotalBytesSent = 0; +CCriticalSection CNode::cs_totalBytesRecv; +CCriticalSection CNode::cs_totalBytesSent; CNode* FindNode(const CNetAddr& ip) { - { - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) - if ((CNetAddr)pnode->addr == ip) - return (pnode); - } + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + if ((CNetAddr)pnode->addr == ip) + return (pnode); return NULL; } @@ -456,12 +368,10 @@ CNode* FindNode(std::string addrName) CNode* FindNode(const CService& addr) { - { - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) - if ((CService)pnode->addr == addr) - return (pnode); - } + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + if ((CService)pnode->addr == addr) + return (pnode); return NULL; } @@ -539,6 +449,15 @@ void CNode::CloseSocketDisconnect() hSocket = INVALID_SOCKET; vRecv.clear(); } + + // in case this fails, we'll empty the recv buffer when the CNode is deleted + TRY_LOCK(cs_vRecv, lockRecv); + if (lockRecv) + vRecv.clear(); + + // if this was the sync node, we'll need a new one + if (this == pnodeSync) + pnodeSync = NULL; } void CNode::Cleanup() @@ -626,6 +545,9 @@ void CNode::copyStats(CNodeStats &stats) X(nReleaseTime); X(nStartingHeight); X(nMisbehavior); + X(nSendBytes); + X(nRecvBytes); + stats.fSyncNode = (this == pnodeSync); } #undef X @@ -641,7 +563,7 @@ void CNode::copyStats(CNodeStats &stats) void ThreadSocketHandler(void* parg) { // Make this thread recognisable as the networking thread - RenameThread("bitcoin-net"); + RenameThread("novacoin-net"); try { @@ -898,6 +820,8 @@ void ThreadSocketHandler2(void* parg) vRecv.resize(nPos + nBytes); memcpy(&vRecv[nPos], pchBuf, nBytes); pnode->nLastRecv = GetTime(); + pnode->nRecvBytes += nBytes; + pnode->RecordBytesRecv(nBytes); } else if (nBytes == 0) { @@ -939,6 +863,8 @@ void ThreadSocketHandler2(void* parg) { vSend.erase(vSend.begin(), vSend.begin() + nBytes); pnode->nLastSend = GetTime(); + pnode->nSendBytes += nBytes; + pnode->RecordBytesSent(nBytes); } else if (nBytes < 0) { @@ -1000,7 +926,7 @@ void ThreadSocketHandler2(void* parg) void ThreadMapPort(void* parg) { // Make this thread recognisable as the UPnP thread - RenameThread("bitcoin-UPnP"); + RenameThread("novacoin-UPnP"); try { @@ -1151,14 +1077,16 @@ void MapPort() // 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] = { + {"novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro"}, {"novacoin.su", "dnsseed.novacoin.su"}, + {"novacoin.ru", "dnsseed.novacoin.ru"}, {"novaco.in", "dnsseed.novaco.in"}, }; void ThreadDNSAddressSeed(void* parg) { // Make this thread recognisable as the DNS seeding thread - RenameThread("bitcoin-dnsseed"); + RenameThread("novacoin-dnsseed"); try { @@ -1223,7 +1151,19 @@ void ThreadDNSAddressSeed2(void* parg) unsigned int pnSeed[] = { - 0x90EF78BC, 0x33F1C851, 0x36F1C851, 0xC6F5C851, + 0x5360a653, 0x6c47bb25, 0x52568c5f, 0xc6f5c851, 0x6f17f3a2, 0x1d52a9d5, 0x2c1544c1, 0xb8748368, + 0x055d6ac1, 0x2490bb25, 0x614488d5, 0xa463f8a2, 0xc54c1256, 0xf72d9252, 0x548432c6, 0xade08368, + 0x02bf8f55, 0x79f81c48, 0xeb44a26d, 0x802c0856, 0xe3a8d772, 0xc661c852, 0xde30d4b0, 0x1044d079, + 0xa1e1485d, 0x269d5e02, 0x65ec8b5b, 0x4b78a605, 0xac9a1f5f, 0x307c7db0, 0xb75d4880, 0x31aaef53, + 0xe9433eb0, 0x8ce0861f, 0x1874695f, 0x6baef986, 0x06cfbf2e, 0x6c2e0082, 0x15e024b0, 0x0d0986bc, + 0xe7002d48, 0x064b2d05, 0xba568c5f, 0x3c93fa18, 0xfae6234d, 0xb06f5d02, 0x34e25d02, 0x559425b0, + 0x308eae6e, 0x48e15d02, 0x87fee36d, 0x647f5e02, 0xcbfe61bc, 0x3bf377d4, 0x1543075b, 0x3ee84980, + 0xde26482e, 0x66a65e02, 0x60cf0fb0, 0xf74c8e4f, 0x88d39a5e, 0x1c385e02, 0x62c4f460, 0x5b26df48, + 0x5249515d, 0x2b353f7d, 0xb6e34980, 0x5e7cd23e, 0x5ecc5e02, 0x9349515d, 0x31abbf2e, 0xa8675cb6, + 0xa8ce4762, 0x09e5d4b0, 0x6db26805, 0xb4f45d02, 0xfe07e555, 0xb6ab40bc, 0x8be25d02, 0x92bd345f, + 0x7122306c, 0x9254c248, 0x8dcc5e02, 0x0d1d5d02, 0x35a2805f, 0x404ef986, 0x5dab696d, 0xf153ad2e, + 0xc5c7a988, 0xfafd6d4a, 0xf172a7be, 0x09627bd9, 0x747d695f, 0xaa4a5d02, 0x4d226805, 0x6bb40ab9, + 0x67d61352, }; void DumpAddresses() @@ -1253,7 +1193,7 @@ void ThreadDumpAddress2(void* parg) void ThreadDumpAddress(void* parg) { // Make this thread recognisable as the address dumping thread - RenameThread("bitcoin-adrdump"); + RenameThread("novacoin-adrdump"); try { @@ -1268,7 +1208,7 @@ void ThreadDumpAddress(void* parg) void ThreadOpenConnections(void* parg) { // Make this thread recognisable as the connection opening thread - RenameThread("bitcoin-opencon"); + RenameThread("novacoin-opencon"); try { @@ -1450,7 +1390,7 @@ void ThreadOpenConnections2(void* parg) void ThreadOpenAddedConnections(void* parg) { // Make this thread recognisable as the connection opening thread - RenameThread("bitcoin-opencon"); + RenameThread("novacoin-opencon"); try { @@ -1571,17 +1511,42 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu return true; } +// for now, use a very simple selection metric: the node from which we received +// most recently +double static NodeSyncScore(const CNode *pnode) { + return -pnode->nLastRecv; +} - - - - - +void static StartSync(const vector &vNodes) { + CNode *pnodeNewSync = NULL; + double dBestScore = 0; + + // Iterate over all nodes + BOOST_FOREACH(CNode* pnode, vNodes) { + // check preconditions for allowing a sync + if (!pnode->fClient && !pnode->fOneShot && + !pnode->fDisconnect && pnode->fSuccessfullyConnected && + (pnode->nStartingHeight > (nBestHeight - 144)) && + (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) { + // if ok, compare node's score with the best so far + double dScore = NodeSyncScore(pnode); + if (pnodeNewSync == NULL || dScore > dBestScore) { + pnodeNewSync = pnode; + dBestScore = dScore; + } + } + } + // if a new sync candidate was found, start sync! + if (pnodeNewSync) { + pnodeNewSync->fStartSync = true; + pnodeSync = pnodeNewSync; + } +} void ThreadMessageHandler(void* parg) { // Make this thread recognisable as the message handling thread - RenameThread("bitcoin-msghand"); + RenameThread("novacoin-msghand"); try { @@ -1605,14 +1570,21 @@ void ThreadMessageHandler2(void* parg) SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL); while (!fShutdown) { + bool fHaveSyncNode = false; vector vNodesCopy; { LOCK(cs_vNodes); vNodesCopy = vNodes; - BOOST_FOREACH(CNode* pnode, vNodesCopy) + BOOST_FOREACH(CNode* pnode, vNodesCopy) { pnode->AddRef(); + if (pnode == pnodeSync) + fHaveSyncNode = true; + } } + if (!fHaveSyncNode) + StartSync(vNodesCopy); + // Poll the connected nodes for messages CNode* pnodeTrickle = NULL; if (!vNodesCopy.empty()) @@ -1832,7 +1804,7 @@ void static Discover() void StartNode(void* parg) { // Make this thread recognisable as the startup thread - RenameThread("bitcoin-start"); + RenameThread("novacoin-start"); if (semOutbound == NULL) { // initialize semaphore @@ -1894,6 +1866,10 @@ bool StopNode() fShutdown = true; nTransactionsUpdated++; int64 nStart = GetTime(); + { + LOCK(cs_main); + ThreadScriptCheckQuit(); + } if (semOutbound) for (int i=0; ipost(); @@ -1920,7 +1896,8 @@ bool StopNode() if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n"); if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n"); if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n"); - while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0) + if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n"); + while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) Sleep(20); Sleep(50); DumpAddresses(); @@ -1979,3 +1956,27 @@ void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataSt RelayInventory(inv); } + +void CNode::RecordBytesRecv(uint64_t bytes) +{ + LOCK(cs_totalBytesRecv); + nTotalBytesRecv += bytes; +} + +void CNode::RecordBytesSent(uint64_t bytes) +{ + LOCK(cs_totalBytesSent); + nTotalBytesSent += bytes; +} + +uint64_t CNode::GetTotalBytesRecv() +{ + LOCK(cs_totalBytesRecv); + return nTotalBytesRecv; +} + +uint64_t CNode::GetTotalBytesSent() +{ + LOCK(cs_totalBytesSent); + return nTotalBytesSent; +}