X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fnet.cpp;h=9ce8ec37842f3f740a11ebe9e26e3fd219298b89;hb=6e9bdffe9ddcda32a6c0431cacdd27d5daf33ce3;hp=13633789e7b32277201f6640e2cf1c2547d6f7f2;hpb=6145f2d5e9f380a11bce933fe343d48fd8936a33;p=novacoin.git diff --git a/src/net.cpp b/src/net.cpp index 1363378..9ce8ec3 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -55,9 +55,10 @@ 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; +boost::array vnThreadsRunning; static std::vector vhListenSocket; CAddrMan addrman; @@ -140,7 +141,7 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer) bool RecvLine(SOCKET hSocket, string& strLine) { strLine = ""; - loop + while (true) { char c; int nBytes = recv(hSocket, &c, 1, 0); @@ -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 - { - loop - { - 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 { @@ -665,7 +587,7 @@ void ThreadSocketHandler2(void* parg) list vNodesDisconnected; unsigned int nPrevNodeCount = 0; - loop + while (true) { // // Disconnect nodes @@ -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 { @@ -1078,7 +1004,8 @@ void ThreadMapPort2(void* parg) else printf("UPnP Port Mapping successful.\n"); int i = 1; - loop { + while (true) + { if (fShutdown || !fUseUPnP) { r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0); @@ -1113,7 +1040,8 @@ void ThreadMapPort2(void* parg) freeUPNPDevlist(devlist); devlist = 0; if (r != 0) FreeUPNPUrls(&urls); - loop { + while (true) + { if (fShutdown || !fUseUPnP) return; Sleep(2000); @@ -1149,13 +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.su", "seed.novacoin.su"}, + {"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 { @@ -1241,7 +1172,7 @@ void ThreadDumpAddress2(void* parg) { DumpAddresses(); vnThreadsRunning[THREAD_DUMPADDRESS]--; - Sleep(100000); + Sleep(600000); vnThreadsRunning[THREAD_DUMPADDRESS]++; } vnThreadsRunning[THREAD_DUMPADDRESS]--; @@ -1250,7 +1181,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 { @@ -1265,7 +1196,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 { @@ -1309,7 +1240,7 @@ void static ThreadStakeMinter(void* parg) try { vnThreadsRunning[THREAD_MINTER]++; - BitcoinMiner(pwallet, true); + StakeMiner(pwallet); vnThreadsRunning[THREAD_MINTER]--; } catch (std::exception& e) { @@ -1349,7 +1280,7 @@ void ThreadOpenConnections2(void* parg) // Initiate network connections int64 nStart = GetTime(); - loop + while (true) { ProcessOneShot(); @@ -1408,7 +1339,7 @@ void ThreadOpenConnections2(void* parg) int64 nANow = GetAdjustedTime(); int nTries = 0; - loop + while (true) { // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections) CAddress addr = addrman.Select(10 + min(nOutbound,8)*10); @@ -1447,7 +1378,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 { @@ -1501,7 +1432,7 @@ void ThreadOpenAddedConnections2(void* parg) } } } - loop + while (true) { vector > vservConnectAddresses = vservAddressesToAdd; // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry @@ -1568,17 +1499,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 { @@ -1602,14 +1558,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()) @@ -1727,8 +1690,12 @@ bool BindListenPort(const CService &addrBind, string& strError) // and enable it by default or not. Try to enable it, if possible. if (addrBind.IsIPv6()) { #ifdef IPV6_V6ONLY +#ifdef WIN32 + setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int)); +#else setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int)); #endif +#endif #ifdef WIN32 int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */; int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */; @@ -1825,7 +1792,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 @@ -1842,18 +1809,11 @@ void StartNode(void* parg) // Start threads // -/* if (!GetBoolArg("-dnsseed", true)) printf("DNS seeding disabled\n"); else if (!NewThread(ThreadDNSAddressSeed, NULL)) printf("Error: NewThread(ThreadDNSAddressSeed) failed\n"); -*/ - - if (!GetBoolArg("-dnsseed", false)) - printf("DNS seeding disabled\n"); - if (GetBoolArg("-dnsseed", false)) - printf("DNS seeding NYI\n"); // Map ports with UPnP if (fUseUPnP) @@ -1886,9 +1846,6 @@ void StartNode(void* parg) // ppcoin: mint proof-of-stake blocks in the background if (!NewThread(ThreadStakeMinter, pwalletMain)) printf("Error: NewThread(ThreadStakeMinter) failed\n"); - - // Generate coins in the background - GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain); } bool StopNode() @@ -1897,6 +1854,10 @@ bool StopNode() fShutdown = true; nTransactionsUpdated++; int64 nStart = GetTime(); + { + LOCK(cs_main); + ThreadScriptCheckQuit(); + } if (semOutbound) for (int i=0; ipost(); @@ -1914,7 +1875,6 @@ bool StopNode() 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_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n"); if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n"); #ifdef USE_UPNP @@ -1924,7 +1884,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(); @@ -1955,3 +1916,55 @@ public: } } instance_of_cnetcleanup; + +void RelayTransaction(const CTransaction& tx, const uint256& hash) +{ + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss.reserve(10000); + ss << tx; + RelayTransaction(tx, hash, ss); +} + +void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss) +{ + CInv inv(MSG_TX, hash); + { + LOCK(cs_mapRelay); + // Expire old relay messages + while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime()) + { + mapRelay.erase(vRelayExpiration.front().second); + vRelayExpiration.pop_front(); + } + + // Save original serialized message so newer versions are preserved + mapRelay.insert(std::make_pair(inv, ss)); + vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv)); + } + + 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; +}