X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fnet.cpp;h=941bcd82f1b09e77fbeea1c215a3fed674f0fff2;hb=6f895c2539c4ddefce658bb2ec7083774bbbd5a3;hp=16439a7461a0c653f409993a2d3d086d2b43b727;hpb=dc51de08660798825d497e79dfad8925c6d442c7;p=novacoin.git diff --git a/src/net.cpp b/src/net.cpp index 16439a7..941bcd8 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -49,24 +49,25 @@ struct LocalServiceInfo { bool fClient = false; bool fDiscover = true; bool fUseUPnP = false; -uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK); +uint64_t nLocalServices = (fClient ? 0 : NODE_NETWORK); static CCriticalSection cs_mapLocalHost; 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; -array vnThreadsRunning; +uint64_t nLocalHostNonce = 0; +boost::array vnThreadsRunning; static std::vector vhListenSocket; CAddrMan addrman; vector vNodes; CCriticalSection cs_vNodes; map mapRelay; -deque > vRelayExpiration; +deque > vRelayExpiration; CCriticalSection cs_mapRelay; -map mapAlreadyAskedFor; +map mapAlreadyAskedFor; static deque vOneShots; CCriticalSection cs_vOneShots; @@ -300,109 +301,20 @@ 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_t rnd = GetRand(~0LL); + const char *srv; + int rc = GetExternalIPbySTUN(rnd, &mapped, &srv); + if(rc >= 0) { + ipRet = CNetAddr(mapped.sin_addr); + printf("GetExternalIPbySTUN(%" PRIu64 ") returned %s in attempt %d; Server=%s\n", rnd, ipRet.ToStringIP().c_str(), rc, srv); + return true; } - return false; } @@ -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,16 +368,14 @@ 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; } -CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64 nTimeout) +CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64_t nTimeout) { if (pszDest == NULL) { if (IsLocal(addrConnect)) @@ -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() @@ -549,7 +468,7 @@ void CNode::Cleanup() void CNode::PushVersion() { /// when NTP implemented, change to just nTime = GetAdjustedTime() - int64 nTime = (fInbound ? GetAdjustedTime() : GetTime()); + int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime()); CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0))); CAddress addrMe = GetLocalAddress(&addr); RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); @@ -562,7 +481,7 @@ void CNode::PushVersion() -std::map CNode::setBanned; +std::map CNode::setBanned; CCriticalSection CNode::cs_setBanned; void CNode::ClearBanned() @@ -575,10 +494,10 @@ bool CNode::IsBanned(CNetAddr ip) bool fResult = false; { LOCK(cs_setBanned); - std::map::iterator i = setBanned.find(ip); + std::map::iterator i = setBanned.find(ip); if (i != setBanned.end()) { - int64 t = (*i).second; + int64_t t = (*i).second; if (GetTime() < t) fResult = true; } @@ -597,7 +516,7 @@ bool CNode::Misbehaving(int howmuch) nMisbehavior += howmuch; if (nMisbehavior >= GetArg("-banscore", 100)) { - int64 banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban + int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior); { LOCK(cs_setBanned); @@ -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 @@ -886,7 +808,7 @@ void ThreadSocketHandler2(void* parg) if (nPos > ReceiveBufferSize()) { if (!pnode->fDisconnect) - printf("socket recv flood control disconnect (%"PRIszu" bytes)\n", vRecv.size()); + printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size()); pnode->CloseSocketDisconnect(); } else { @@ -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) { @@ -1151,8 +1077,10 @@ 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"}, + {"novacoin.ru", "testseed.novacoin.ru"}, {"novaco.in", "dnsseed.novaco.in"}, }; @@ -1222,19 +1150,31 @@ void ThreadDNSAddressSeed2(void* parg) -unsigned int pnSeed[] = +uint32_t 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() { - int64 nStart = GetTimeMillis(); + int64_t nStart = GetTimeMillis(); CAddrDB adb; adb.Write(addrman); - printf("Flushed %d addresses to peers.dat %"PRI64d"ms\n", + printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n", addrman.size(), GetTimeMillis() - nStart); } @@ -1333,7 +1273,7 @@ void ThreadOpenConnections2(void* parg) // Connect to specific addresses if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0) { - for (int64 nLoop = 0;; nLoop++) + for (int64_t nLoop = 0;; nLoop++) { ProcessOneShot(); BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"]) @@ -1352,7 +1292,7 @@ void ThreadOpenConnections2(void* parg) } // Initiate network connections - int64 nStart = GetTime(); + int64_t nStart = GetTime(); while (true) { ProcessOneShot(); @@ -1380,7 +1320,7 @@ void ThreadOpenConnections2(void* parg) // it'll get a pile of addresses with newer timestamps. // Seed nodes are given a random 'last seen time' of between one and two // weeks ago. - const int64 nOneWeek = 7*24*60*60; + const int64_t nOneWeek = 7*24*60*60; struct in_addr ip; memcpy(&ip, &pnSeed[i], sizeof(ip)); CAddress addr(CService(ip, GetDefaultPort())); @@ -1409,7 +1349,7 @@ void ThreadOpenConnections2(void* parg) } } - int64 nANow = GetAdjustedTime(); + int64_t nANow = GetAdjustedTime(); int nTries = 0; while (true) @@ -1572,12 +1512,37 @@ 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) { @@ -1606,14 +1571,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()) @@ -1894,7 +1866,7 @@ bool StopNode() printf("StopNode()\n"); fShutdown = true; nTransactionsUpdated++; - int64 nStart = GetTime(); + int64_t nStart = GetTime(); { LOCK(cs_main); ThreadScriptCheckQuit(); @@ -1985,3 +1957,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; +}