1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
11 #include "ui_interface.h"
20 using namespace boost;
22 static const int MAX_OUTBOUND_CONNECTIONS = 16;
24 void ThreadMessageHandler2(void* parg);
25 void ThreadSocketHandler2(void* parg);
26 void ThreadOpenConnections2(void* parg);
27 void ThreadOpenAddedConnections2(void* parg);
28 void ThreadDNSAddressSeed2(void* parg);
30 // Fix for ancient MinGW versions, that don't have defined these in ws2tcpip.h.
31 // Todo: Can be removed when our pull-tester is upgraded to a modern MinGW version.
33 #ifndef PROTECTION_LEVEL_UNRESTRICTED
34 #define PROTECTION_LEVEL_UNRESTRICTED 10
36 #ifndef IPV6_PROTECTION_LEVEL
37 #define IPV6_PROTECTION_LEVEL 23
41 struct LocalServiceInfo {
47 // Global state variables
50 bool fDiscover = true;
51 uint64_t nLocalServices = (fClient ? 0 : NODE_NETWORK);
52 static CCriticalSection cs_mapLocalHost;
53 static map<CNetAddr, LocalServiceInfo> mapLocalHost;
54 static bool vfReachable[NET_MAX] = {};
55 static bool vfLimited[NET_MAX] = {};
56 static CNode* pnodeLocalHost = NULL;
57 static CNode* pnodeSync = NULL;
58 CAddress addrSeenByPeer(CService("0.0.0.0", nPortZero), nLocalServices);
59 uint64_t nLocalHostNonce = 0;
60 boost::array<int, THREAD_MAX> vnThreadsRunning;
61 static std::vector<SOCKET> vhListenSocket;
64 vector<CNode*> vNodes;
65 CCriticalSection cs_vNodes;
66 map<CInv, CDataStream> mapRelay;
67 deque<pair<int64_t, CInv> > vRelayExpiration;
68 CCriticalSection cs_mapRelay;
69 map<CInv, int64_t> mapAlreadyAskedFor;
71 static deque<string> vOneShots;
72 CCriticalSection cs_vOneShots;
74 set<CNetAddr> setservAddNodeAddresses;
75 CCriticalSection cs_setservAddNodeAddresses;
77 vector<std::string> vAddedNodes;
78 CCriticalSection cs_vAddedNodes;
80 static CSemaphore *semOutbound = NULL;
82 void AddOneShot(string strDest)
85 vOneShots.push_back(strDest);
88 unsigned short GetListenPort()
90 return (unsigned short)(GetArg("-port", GetDefaultPort()));
93 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
95 // Filter out duplicate requests
96 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
98 pindexLastGetBlocksBegin = pindexBegin;
99 hashLastGetBlocksEnd = hashEnd;
101 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
104 // find 'best' local address for a particular peer
105 bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
111 int nBestReachability = -1;
113 LOCK(cs_mapLocalHost);
114 for (auto it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
116 int nScore = (*it).second.nScore;
117 int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
118 if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
120 addr = CService((*it).first, (*it).second.nPort);
121 nBestReachability = nReachability;
126 return nBestScore >= 0;
129 // get best local address for a particular peer as a CAddress
130 CAddress GetLocalAddress(const CNetAddr *paddrPeer)
132 CAddress ret(CService("0.0.0.0", nPortZero), 0);
134 if (GetLocal(addr, paddrPeer))
136 ret = CAddress(addr);
137 ret.nServices = nLocalServices;
138 ret.nTime = GetAdjustedTime();
143 bool RecvLine(SOCKET hSocket, string& strLine)
149 int nBytes = recv(hSocket, &c, 1, 0);
157 if (strLine.size() >= 9000)
160 else if (nBytes <= 0)
166 int nErr = WSAGetLastError();
167 if (nErr == WSAEMSGSIZE)
169 if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
175 if (!strLine.empty())
180 printf("socket closed\n");
186 int nErr = WSAGetLastError();
187 printf("recv failed: %d\n", nErr);
194 // used when scores of local addresses may have changed
195 // pushes better local address to peers
196 void static AdvertizeLocal()
199 for(CNode* pnode : vNodes)
201 if (pnode->fSuccessfullyConnected)
203 auto addrLocal = GetLocalAddress(&pnode->addr);
204 if (addrLocal.IsRoutable() && (CService)addrLocal != pnode->addrLocal)
206 pnode->PushAddress(addrLocal);
207 pnode->addrLocal = addrLocal;
213 void SetReachable(enum Network net, bool fFlag)
215 LOCK(cs_mapLocalHost);
216 vfReachable[net] = fFlag;
217 if (net == NET_IPV6 && fFlag)
218 vfReachable[NET_IPV4] = true;
221 int GetnScore(const CService& addr)
223 LOCK(cs_mapLocalHost);
224 if (mapLocalHost.count(addr) == LOCAL_NONE)
226 return mapLocalHost[addr].nScore;
230 // Is our peer's addrLocal potentially useful as an external IP source?
231 bool IsPeerAddrLocalGood(CNode *pnode)
233 return fDiscover && pnode->addr.IsRoutable() && pnode->addrLocal.IsRoutable() &&
234 !IsLimited(pnode->addrLocal.GetNetwork());
237 // pushes our own address to a peer
238 void AdvertiseLocal(CNode *pnode)
240 if (!fNoListen && pnode->fSuccessfullyConnected)
242 auto addrLocal = GetLocalAddress(&pnode->addr);
243 // If discovery is enabled, sometimes give our peer the address it
244 // tells us that it sees us as in case it has a better idea of our
245 // address than we do.
246 if (IsPeerAddrLocalGood(pnode) && (!addrLocal.IsRoutable() ||
247 GetRand((GetnScore(addrLocal) > LOCAL_MANUAL) ? 8:2) == 0))
249 addrLocal.SetIP(pnode->addrLocal);
251 if (addrLocal.IsRoutable())
253 printf("AdvertiseLocal: advertising address %s\n", addrLocal.ToString().c_str());
254 pnode->PushAddress(addrLocal);
259 // learn a new local address
260 bool AddLocal(const CService& addr, int nScore)
262 if (!addr.IsRoutable())
265 if (!fDiscover && nScore < LOCAL_MANUAL)
271 printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
274 LOCK(cs_mapLocalHost);
275 bool fAlready = mapLocalHost.count(addr) > 0;
276 LocalServiceInfo &info = mapLocalHost[addr];
277 if (!fAlready || nScore >= info.nScore) {
278 info.nScore = nScore + (fAlready ? 1 : 0);
279 info.nPort = addr.GetPort();
281 SetReachable(addr.GetNetwork());
289 bool AddLocal(const CNetAddr &addr, int nScore)
291 return AddLocal(CService(addr, GetListenPort()), nScore);
294 /** Make a particular network entirely off-limits (no automatic connects to it) */
295 void SetLimited(enum Network net, bool fLimited)
297 if (net == NET_UNROUTABLE)
299 LOCK(cs_mapLocalHost);
300 vfLimited[net] = fLimited;
303 bool IsLimited(enum Network net)
305 LOCK(cs_mapLocalHost);
306 return vfLimited[net];
309 bool IsLimited(const CNetAddr &addr)
311 return IsLimited(addr.GetNetwork());
314 /** vote for a local address */
315 bool SeenLocal(const CService& addr)
318 LOCK(cs_mapLocalHost);
319 if (mapLocalHost.count(addr) == 0)
321 mapLocalHost[addr].nScore++;
329 /** check whether a given address is potentially local */
330 bool IsLocal(const CService& addr)
332 LOCK(cs_mapLocalHost);
333 return mapLocalHost.count(addr) > 0;
336 /** check whether a given address is in a network we can probably connect to */
337 bool IsReachable(const CNetAddr& addr)
339 LOCK(cs_mapLocalHost);
340 enum Network net = addr.GetNetwork();
341 return vfReachable[net] && !vfLimited[net];
344 extern int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv);
346 // We now get our external IP from the IRC server first and only use this as a backup
347 bool GetMyExternalIP(CNetAddr& ipRet)
349 struct sockaddr_in mapped;
350 auto rnd = std::numeric_limits<uint64_t>::max();
352 int rc = GetExternalIPbySTUN(rnd, &mapped, &srv);
354 ipRet = CNetAddr(mapped.sin_addr);
355 printf("GetExternalIPbySTUN(%" PRIu64 ") returned %s in attempt %d; Server=%s\n", rnd, ipRet.ToStringIP().c_str(), rc, srv);
361 void ThreadGetMyExternalIP(void* parg)
363 // Make this thread recognisable as the external IP detection thread
364 RenameThread("novacoin-ext-ip");
366 CNetAddr addrLocalHost;
367 if (GetMyExternalIP(addrLocalHost))
369 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
370 AddLocal(addrLocalHost, LOCAL_HTTP);
378 void AddressCurrentlyConnected(const CService& addr)
380 addrman.Connected(addr);
386 uint64_t CNode::nTotalBytesRecv = 0;
387 uint64_t CNode::nTotalBytesSent = 0;
388 CCriticalSection CNode::cs_totalBytesRecv;
389 CCriticalSection CNode::cs_totalBytesSent;
391 CNode* FindNode(const CNetAddr& ip)
394 for(CNode* pnode : vNodes)
395 if ((CNetAddr)pnode->addr == ip)
400 CNode* FindNode(std::string addrName)
403 for(CNode* pnode : vNodes)
404 if (pnode->addrName == addrName)
409 CNode* FindNode(const CService& addr)
412 for(CNode* pnode : vNodes)
413 if ((CService)pnode->addr == addr)
418 CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64_t nTimeout)
420 if (pszDest == NULL) {
421 if (IsLocal(addrConnect))
424 // Look for an existing connection
425 CNode* pnode = FindNode((CService)addrConnect);
429 pnode->AddRef(nTimeout);
438 printf("trying connection %s lastseen=%.1fhrs\n",
439 pszDest ? pszDest : addrConnect.ToString().c_str(),
440 pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
444 if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
446 addrman.Attempt(addrConnect);
449 printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
451 // Set to non-blocking
454 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
455 printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
457 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
458 printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
462 CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
464 pnode->AddRef(nTimeout);
470 vNodes.push_back(pnode);
473 pnode->nTimeConnected = GetTime();
482 void CNode::CloseSocketDisconnect()
485 if (hSocket != INVALID_SOCKET)
487 printf("disconnecting node %s\n", addrName.c_str());
488 CloseSocket(hSocket);
492 // in case this fails, we'll empty the recv buffer when the CNode is deleted
493 TRY_LOCK(cs_vRecv, lockRecv);
497 // if this was the sync node, we'll need a new one
498 if (this == pnodeSync)
502 void CNode::Cleanup()
507 void CNode::PushVersion()
509 auto nTime = GetAdjustedTime();
510 CAddress addrYou, addrMe;
512 bool fHidden = false;
514 if (mapArgs.count("-torname")) {
515 // Our hidden service address
516 CService addrTorName(mapArgs["-torname"], GetListenPort());
518 if (addrTorName.IsValid()) {
520 addrMe = CAddress(addrTorName);
527 addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", nPortZero)));
528 addrMe = GetLocalAddress(&addr);
531 RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
532 printf("send version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString().c_str(), addrYou.ToString().c_str(), addr.ToString().c_str());
533 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
534 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
541 std::map<CNetAddr, int64_t> CNode::setBanned;
542 CCriticalSection CNode::cs_setBanned;
544 void CNode::ClearBanned()
549 bool CNode::IsBanned(CNetAddr ip)
551 bool fResult = false;
554 auto i = setBanned.find(ip);
555 if (i != setBanned.end())
557 auto t = (*i).second;
565 bool CNode::Misbehaving(int howmuch)
569 printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
573 nMisbehavior += howmuch;
574 if (nMisbehavior >= GetArgInt("-banscore", 100))
576 auto banTime = GetTime()+GetArg("-bantime", nOneDay); // Default 24-hour ban
577 printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
580 if (setBanned[addr] < banTime)
581 setBanned[addr] = banTime;
583 CloseSocketDisconnect();
586 printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
591 #define X(name) stats.name = name
592 void CNode::copyStats(CNodeStats &stats)
607 stats.fSyncNode = (this == pnodeSync);
611 void Release(CNode* node) {
619 void ThreadSocketHandler(void* parg)
621 // Make this thread recognisable as the networking thread
622 RenameThread("novacoin-net");
626 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
627 ThreadSocketHandler2(parg);
628 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
630 catch (std::exception& e) {
631 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
632 PrintException(&e, "ThreadSocketHandler()");
634 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
635 throw; // support pthread_cancel()
637 printf("ThreadSocketHandler exited\n");
640 static list<CNode*> vNodesDisconnected;
642 void ThreadSocketHandler2(void* parg)
644 printf("ThreadSocketHandler started\n");
645 size_t nPrevNodeCount = 0;
653 // Disconnect unused nodes
654 vector<CNode*> vNodesCopy = vNodes;
655 for(CNode* pnode : vNodesCopy)
657 if (pnode->fDisconnect ||
658 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
660 // remove from vNodes
661 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
663 // release outbound grant (if any)
664 pnode->grantOutbound.Release();
666 // close socket and cleanup
667 pnode->CloseSocketDisconnect();
670 // hold in disconnected pool until all refs are released
671 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
672 if (pnode->fNetworkNode || pnode->fInbound)
674 vNodesDisconnected.push_back(pnode);
678 // Delete disconnected nodes
679 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
680 for(CNode* pnode : vNodesDisconnectedCopy)
682 // wait until threads are done using it
683 if (pnode->GetRefCount() <= 0)
685 bool fDelete = false;
687 TRY_LOCK(pnode->cs_vSend, lockSend);
690 TRY_LOCK(pnode->cs_vRecv, lockRecv);
693 TRY_LOCK(pnode->cs_mapRequests, lockReq);
696 TRY_LOCK(pnode->cs_inventory, lockInv);
705 vNodesDisconnected.remove(pnode);
711 if (vNodes.size() != nPrevNodeCount)
713 nPrevNodeCount = vNodes.size();
714 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
719 // Find which sockets have data to receive
721 struct timeval timeout;
723 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
730 FD_ZERO(&fdsetError);
731 SOCKET hSocketMax = 0;
732 bool have_fds = false;
734 for(SOCKET hListenSocket : vhListenSocket) {
735 FD_SET(hListenSocket, &fdsetRecv);
736 hSocketMax = max(hSocketMax, hListenSocket);
741 for(CNode* pnode : vNodes)
743 if (pnode->hSocket == INVALID_SOCKET)
745 FD_SET(pnode->hSocket, &fdsetRecv);
746 FD_SET(pnode->hSocket, &fdsetError);
747 hSocketMax = max(hSocketMax, pnode->hSocket);
750 TRY_LOCK(pnode->cs_vSend, lockSend);
751 if (lockSend && !pnode->vSend.empty())
752 FD_SET(pnode->hSocket, &fdsetSend);
757 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
758 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
759 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
760 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
763 if (nSelect == SOCKET_ERROR)
767 int nErr = WSAGetLastError();
768 printf("socket select error %d\n", nErr);
769 for (unsigned int i = 0; i <= hSocketMax; i++)
770 FD_SET(i, &fdsetRecv);
773 FD_ZERO(&fdsetError);
774 Sleep(timeout.tv_usec/1000);
779 // Accept new connections
781 for(SOCKET hListenSocket : vhListenSocket)
782 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
785 struct sockaddr_storage sockaddr;
787 struct sockaddr sockaddr;
789 socklen_t len = sizeof(sockaddr);
790 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
794 if (hSocket != INVALID_SOCKET)
795 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
796 printf("Warning: Unknown socket family\n");
800 for(CNode* pnode : vNodes)
805 if (hSocket == INVALID_SOCKET)
807 int nErr = WSAGetLastError();
808 if (nErr != WSAEWOULDBLOCK)
809 printf("socket error accept failed: %d\n", nErr);
811 else if (nInbound >= GetArgInt("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
814 LOCK(cs_setservAddNodeAddresses);
815 if (!setservAddNodeAddresses.count(addr))
816 CloseSocket(hSocket);
819 else if (CNode::IsBanned(addr))
821 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
822 CloseSocket(hSocket);
826 printf("accepted connection %s\n", addr.ToString().c_str());
827 CNode* pnode = new CNode(hSocket, addr, "", true);
831 vNodes.push_back(pnode);
838 // Service each socket
840 vector<CNode*> vNodesCopy;
844 for(CNode* pnode : vNodesCopy)
847 for(CNode* pnode : vNodesCopy)
855 if (pnode->hSocket == INVALID_SOCKET)
857 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
859 TRY_LOCK(pnode->cs_vRecv, lockRecv);
862 CDataStream& vRecv = pnode->vRecv;
863 uint64_t nPos = vRecv.size();
865 if (nPos > ReceiveBufferSize()) {
866 if (!pnode->fDisconnect)
867 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
868 pnode->CloseSocketDisconnect();
871 // typical socket buffer is 8K-64K
872 char pchBuf[0x10000];
873 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
876 vRecv.resize(nPos + nBytes);
877 memcpy(&vRecv[nPos], pchBuf, nBytes);
878 pnode->nLastRecv = GetTime();
879 pnode->nRecvBytes += nBytes;
880 pnode->RecordBytesRecv(nBytes);
882 else if (nBytes == 0)
884 // socket closed gracefully
885 if (!pnode->fDisconnect)
886 printf("socket closed\n");
887 pnode->CloseSocketDisconnect();
892 int nErr = WSAGetLastError();
893 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
895 if (!pnode->fDisconnect)
896 printf("socket recv error %d\n", nErr);
897 pnode->CloseSocketDisconnect();
907 if (pnode->hSocket == INVALID_SOCKET)
909 if (FD_ISSET(pnode->hSocket, &fdsetSend))
911 TRY_LOCK(pnode->cs_vSend, lockSend);
914 CDataStream& vSend = pnode->vSend;
917 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
920 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
921 pnode->nLastSend = GetTime();
922 pnode->nSendBytes += nBytes;
923 pnode->RecordBytesSent(nBytes);
928 int nErr = WSAGetLastError();
929 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
931 printf("socket send error %d\n", nErr);
932 pnode->CloseSocketDisconnect();
940 // Inactivity checking
942 if (pnode->vSend.empty())
943 pnode->nLastSendEmpty = GetTime();
944 if (GetTime() - pnode->nTimeConnected > 60)
946 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
948 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
949 pnode->fDisconnect = true;
951 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
953 printf("socket not sending\n");
954 pnode->fDisconnect = true;
956 else if (GetTime() - pnode->nLastRecv > 90*60)
958 printf("socket inactivity timeout\n");
959 pnode->fDisconnect = true;
965 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
973 // Each pair gives a source name and a seed name.
974 // The first name is used as information source for addrman.
975 // The second name should resolve to a list of seed addresses.
976 static const char *strDNSSeed[][2] = {
977 {"novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro"},
978 {"novacoin.ru", "dnsseed.novacoin.ru"},
979 {"novacoin.ru", "testseed.novacoin.ru"},
980 {"novaco.in", "dnsseed.novaco.in"},
983 void ThreadDNSAddressSeed(void* parg)
985 // Make this thread recognisable as the DNS seeding thread
986 RenameThread("novacoin-dnsseed");
990 vnThreadsRunning[THREAD_DNSSEED]++;
991 ThreadDNSAddressSeed2(parg);
992 vnThreadsRunning[THREAD_DNSSEED]--;
994 catch (std::exception& e) {
995 vnThreadsRunning[THREAD_DNSSEED]--;
996 PrintException(&e, "ThreadDNSAddressSeed()");
998 vnThreadsRunning[THREAD_DNSSEED]--;
999 throw; // support pthread_cancel()
1001 printf("ThreadDNSAddressSeed exited\n");
1004 void ThreadDNSAddressSeed2(void* parg)
1006 printf("ThreadDNSAddressSeed started\n");
1011 printf("Loading addresses from DNS seeds (could take a while)\n");
1013 for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1014 if (HaveNameProxy()) {
1015 AddOneShot(strDNSSeed[seed_idx][1]);
1017 vector<CNetAddr> vaddr;
1018 vector<CAddress> vAdd;
1019 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
1021 for(CNetAddr& ip : vaddr)
1023 auto addr = CAddress(CService(ip, GetDefaultPort()));
1024 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1025 vAdd.push_back(addr);
1029 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
1034 printf("%d addresses found from DNS seeds\n", found);
1050 0xa52bf0da, 0x30aa43d8, 0x614488d5, 0x517b6fd5, 0xd4bf62d4, 0xb7d638d4, 0xbc12bcd1, 0xa2501bc6,
1051 0xfde617c6, 0x3337b1c6, 0x1dcd71c3, 0x2c1544c1, 0xe05f6ac1, 0x852f63c0, 0x3e2363c0, 0x15f563c0,
1052 0x430d63c0, 0x50d6a9c0, 0xf0a679c0, 0xefdeedbf, 0x7aaee8bc, 0x3a3dbbbc, 0xef218abc, 0x0bef78bc,
1053 0x8baa3eb2, 0x2bf913b2, 0x24ed9fb2, 0xb42289b2, 0x718a09b0, 0xe9433eb0, 0x559425b0, 0xc97e1fb0,
1054 0x18e1d4b0, 0x8f6cc1b0, 0xac3838ae, 0x86c0ffad, 0x6b0272a7, 0xa463f8a2, 0x6f17f3a2, 0xb3d6f3a2,
1055 0x9cd8f997, 0xd513fb94, 0x39e64880, 0x3859dd6f, 0x0b08fe6d, 0xe601fe6d, 0xeb44a26d, 0xfe53186c,
1056 0x203c2e68, 0x1c542868, 0x0caa8368, 0xb8748368, 0xccca4762, 0xc637555f, 0x638a545f, 0x59b2205f,
1057 0x52568c5f, 0xba568c5f, 0x8a568c5f, 0x31b0f45e, 0x54a0f45e, 0x37d6f15e, 0xc520175e, 0x7620175e,
1058 0xc310175e, 0x8e33b45e, 0x7abb5f5d, 0xd3014c5d, 0xa1e1485d, 0x9947645d, 0xfab8ff5c, 0xa979e65b,
1059 0xa879e65b, 0x9f79e65b, 0x9fa3d25b, 0x112a925b, 0x7b92905b, 0x60647a5b, 0x1e389d5a, 0x851afa59,
1060 0x0185ef59, 0x26549b59, 0x1c9efe57, 0xc54c1256, 0x1ad51955, 0x19d21955, 0x73c41955, 0x3f74ee55,
1061 0x633eea55, 0x6883d655, 0xfb72c655, 0x5360a653, 0x17c1ea52, 0xc661c852, 0x1ecdc852, 0x006a9752,
1062 0xf72d9252, 0x82650551, 0x36f1c851, 0x33f1c851, 0xd5c1864f, 0xb6bf1b4e, 0x96da184e, 0x40d0234d,
1063 0x9a96ab4c, 0x8fc2a84c, 0xb5dbd048, 0xf4644447, 0x2d51af47, 0xa9625445, 0x83f05243, 0x89672941,
1064 0x3a8bad3e, 0xf0a05436, 0x6ab7c936, 0x49971d32, 0xadd4482e, 0xcffd212e, 0x6730bc2e, 0x839aa12e,
1065 0x68d9692e, 0xc7183b25, 0x6c47bb25, 0x2490bb25, 0xad651c1f, 0x048a861f, 0x6937811f, 0x064b2d05,
1069 void DumpAddresses()
1071 auto nStart = GetTimeMillis();
1076 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1077 addrman.size(), GetTimeMillis() - nStart);
1080 void ThreadDumpAddress2(void* parg)
1082 printf("ThreadDumpAddress started\n");
1084 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1088 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1090 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1092 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1095 void ThreadDumpAddress(void* parg)
1097 // Make this thread recognisable as the address dumping thread
1098 RenameThread("novacoin-adrdump");
1102 ThreadDumpAddress2(parg);
1104 catch (std::exception& e) {
1105 PrintException(&e, "ThreadDumpAddress()");
1107 printf("ThreadDumpAddress exited\n");
1110 void ThreadOpenConnections(void* parg)
1112 // Make this thread recognisable as the connection opening thread
1113 RenameThread("novacoin-opencon");
1117 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1118 ThreadOpenConnections2(parg);
1119 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1121 catch (std::exception& e) {
1122 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1123 PrintException(&e, "ThreadOpenConnections()");
1125 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1126 PrintException(NULL, "ThreadOpenConnections()");
1128 printf("ThreadOpenConnections exited\n");
1131 void static ProcessOneShot()
1136 if (vOneShots.empty())
1138 strDest = vOneShots.front();
1139 vOneShots.pop_front();
1142 CSemaphoreGrant grant(*semOutbound, true);
1144 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1145 AddOneShot(strDest);
1149 void ThreadOpenConnections2(void* parg)
1151 printf("ThreadOpenConnections started\n");
1153 // Connect to specific addresses
1154 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1156 for (int64_t nLoop = 0;; nLoop++)
1159 for(string strAddr : mapMultiArgs["-connect"])
1162 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1163 for (int i = 0; i < 10 && i < nLoop; i++)
1174 // Initiate network connections
1175 auto nStart = GetTime();
1180 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1182 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1187 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1188 CSemaphoreGrant grant(*semOutbound);
1189 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1193 // Add seed nodes if IRC isn't working
1194 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1196 std::vector<CAddress> vAdd;
1197 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1199 // It'll only connect to one or two seed nodes because once it connects,
1200 // it'll get a pile of addresses with newer timestamps.
1201 // Seed nodes are given a random 'last seen time' of between one and two
1204 memcpy(&ip, &pnSeed[i], sizeof(ip));
1205 CAddress addr(CService(ip, GetDefaultPort()));
1206 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1207 vAdd.push_back(addr);
1209 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1212 // Add Tor nodes if we have connection with onion router
1213 if (mapArgs.count("-tor"))
1215 const std::vector<std::string> vstrTorSeed =
1217 "seedp4knqnoei57u.onion",
1218 "seedr3hhlepyi7fd.onion",
1219 "seed3uuomkclbiz4.onion",
1220 "seedeh7qck3ouff5.onion",
1221 "5rg3vq4jagckeckf.onion",
1222 "seedt3sraf53ajiy.onion",
1223 "seedg4qyccsg42oq.onion",
1224 "novaqrtoywpg7jly.onion",
1225 "seed3d5wolqbgrcb.onion",
1226 "seed24u5dwph3qw4.onion",
1227 "mj26ulzbs2oskgym.onion",
1228 "eqon4usunavt76m7.onion",
1229 "seedd3aldwpslzl3.onion"
1231 std::vector<CAddress> vAdd;
1232 for (unsigned int i = 0; i < vstrTorSeed.size(); i++)
1234 CAddress addr(CService(vstrTorSeed[i], GetDefaultPort()));
1235 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1236 vAdd.push_back(addr);
1238 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1242 // Choose an address to connect to based on most recently seen
1244 CAddress addrConnect;
1246 // Only connect out to one peer per network group (/16 for IPv4).
1247 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1249 set<vector<unsigned char> > setConnected;
1252 for(CNode* pnode : vNodes) {
1253 if (!pnode->fInbound) {
1254 setConnected.insert(pnode->addr.GetGroup());
1260 auto nANow = GetAdjustedTime();
1265 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1266 auto addr = addrman.Select(10 + min(nOutbound,8)*10);
1268 // if we selected an invalid address, restart
1269 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1272 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1273 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1274 // already-connected network ranges, ...) before trying new addrman addresses.
1279 if (IsLimited(addr))
1282 // only consider very recently tried nodes after 30 failed attempts
1283 if (nANow - addr.nLastTry < 600 && nTries < 30)
1286 // do not allow non-default ports, unless after 50 invalid addresses selected already
1287 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1294 if (addrConnect.IsValid())
1295 OpenNetworkConnection(addrConnect, &grant);
1299 void ThreadOpenAddedConnections(void* parg)
1301 // Make this thread recognisable as the connection opening thread
1302 RenameThread("novacoin-opencon");
1306 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1307 ThreadOpenAddedConnections2(parg);
1308 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1310 catch (std::exception& e) {
1311 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1312 PrintException(&e, "ThreadOpenAddedConnections()");
1314 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1315 PrintException(NULL, "ThreadOpenAddedConnections()");
1317 printf("ThreadOpenAddedConnections exited\n");
1320 void ThreadOpenAddedConnections2(void* parg)
1322 printf("ThreadOpenAddedConnections started\n");
1325 LOCK(cs_vAddedNodes);
1326 vAddedNodes = mapMultiArgs["-addnode"];
1329 if (HaveNameProxy()) {
1331 list<string> lAddresses(0);
1333 LOCK(cs_vAddedNodes);
1334 for(string& strAddNode : vAddedNodes)
1335 lAddresses.push_back(strAddNode);
1337 for(string& strAddNode : lAddresses) {
1339 CSemaphoreGrant grant(*semOutbound);
1340 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1343 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1344 Sleep(120000); // Retry every 2 minutes
1345 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1350 for (uint32_t i = 0; true; i++)
1352 list<string> lAddresses(0);
1354 LOCK(cs_vAddedNodes);
1355 for(string& strAddNode : vAddedNodes)
1356 lAddresses.push_back(strAddNode);
1359 list<vector<CService> > lservAddressesToAdd(0);
1360 for(string& strAddNode : lAddresses)
1362 vector<CService> vservNode(0);
1363 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1365 lservAddressesToAdd.push_back(vservNode);
1367 LOCK(cs_setservAddNodeAddresses);
1368 for(CService& serv : vservNode)
1369 setservAddNodeAddresses.insert(serv);
1373 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1374 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1377 for(CNode* pnode : vNodes)
1378 for (auto it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1380 for(CService& addrNode : *(it))
1381 if (pnode->addr == addrNode)
1383 it = lservAddressesToAdd.erase(it);
1384 if(it != lservAddressesToAdd.begin())
1388 if (it == lservAddressesToAdd.end())
1392 for(vector<CService>& vserv : lservAddressesToAdd)
1394 if (vserv.size() == 0)
1396 CSemaphoreGrant grant(*semOutbound);
1397 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1404 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1405 Sleep(120000); // Retry every 2 minutes
1406 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1412 // if successful, this moves the passed grant to the constructed node
1413 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1416 // Initiate outbound network connection
1421 if (IsLocal(addrConnect) ||
1422 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1423 FindNode(addrConnect.ToStringIPPort().c_str()))
1425 if (strDest && FindNode(strDest))
1428 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1429 CNode* pnode = ConnectNode(addrConnect, strDest);
1430 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1436 grantOutbound->MoveTo(pnode->grantOutbound);
1437 pnode->fNetworkNode = true;
1439 pnode->fOneShot = true;
1444 // for now, use a very simple selection metric: the node from which we received
1446 static int64_t NodeSyncScore(const CNode *pnode) {
1447 return pnode->nLastRecv;
1450 void static StartSync(const vector<CNode*> &vNodes) {
1451 CNode *pnodeNewSync = NULL;
1452 int64_t nBestScore = 0;
1454 // Iterate over all nodes
1455 for(CNode* pnode : vNodes) {
1456 // check preconditions for allowing a sync
1457 if (!pnode->fClient && !pnode->fOneShot &&
1458 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1459 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1460 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1461 // if ok, compare node's score with the best so far
1462 int64_t nScore = NodeSyncScore(pnode);
1463 if (pnodeNewSync == NULL || nScore > nBestScore) {
1464 pnodeNewSync = pnode;
1465 nBestScore = nScore;
1469 // if a new sync candidate was found, start sync!
1471 pnodeNewSync->fStartSync = true;
1472 pnodeSync = pnodeNewSync;
1476 void ThreadMessageHandler(void* parg)
1478 // Make this thread recognisable as the message handling thread
1479 RenameThread("novacoin-msghand");
1483 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1484 ThreadMessageHandler2(parg);
1485 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1487 catch (std::exception& e) {
1488 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1489 PrintException(&e, "ThreadMessageHandler()");
1491 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1492 PrintException(NULL, "ThreadMessageHandler()");
1494 printf("ThreadMessageHandler exited\n");
1497 void ThreadMessageHandler2(void* parg)
1499 printf("ThreadMessageHandler started\n");
1500 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1503 bool fHaveSyncNode = false;
1504 vector<CNode*> vNodesCopy;
1507 vNodesCopy = vNodes;
1508 for(CNode* pnode : vNodesCopy) {
1510 if (pnode == pnodeSync)
1511 fHaveSyncNode = true;
1516 StartSync(vNodesCopy);
1518 // Poll the connected nodes for messages
1519 for(CNode* pnode : vNodesCopy)
1523 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1525 ProcessMessages(pnode);
1532 TRY_LOCK(pnode->cs_vSend, lockSend);
1534 SendMessages(pnode);
1542 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
1545 // Wait and allow messages to bunch up.
1546 // Reduce vnThreadsRunning so StopNode has permission to exit while
1547 // we're sleeping, but we must always check fShutdown after doing this.
1548 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1550 if (fRequestShutdown)
1552 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1563 bool BindListenPort(const CService &addrBind, string& strError)
1568 // Create socket for listening for incoming connections
1570 struct sockaddr_storage sockaddr;
1572 struct sockaddr sockaddr;
1574 socklen_t len = sizeof(sockaddr);
1575 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1577 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1578 printf("%s\n", strError.c_str());
1582 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1583 if (hListenSocket == INVALID_SOCKET)
1585 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1586 printf("%s\n", strError.c_str());
1592 // Different way of disabling SIGPIPE on BSD
1593 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1595 // Allow binding if the port is still in TIME_WAIT state after
1596 // the program was closed and restarted. Not an issue on windows!
1597 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1601 // Set to non-blocking, incoming connections will also inherit this
1602 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1604 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1607 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1608 printf("%s\n", strError.c_str());
1613 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1614 // and enable it by default or not. Try to enable it, if possible.
1615 if (addrBind.IsIPv6()) {
1618 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1620 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1624 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1625 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
1630 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1632 int nErr = WSAGetLastError();
1633 if (nErr == WSAEADDRINUSE)
1634 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1636 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1637 printf("%s\n", strError.c_str());
1638 CloseSocket(hListenSocket);
1641 printf("Bound to %s\n", addrBind.ToString().c_str());
1643 // Listen for incoming connections
1644 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1646 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1647 printf("%s\n", strError.c_str());
1648 CloseSocket(hListenSocket);
1652 vhListenSocket.push_back(hListenSocket);
1654 if (addrBind.IsRoutable() && fDiscover)
1655 AddLocal(addrBind, LOCAL_BIND);
1660 void static Discover()
1666 // Get local host IP
1667 char pszHostName[1000] = "";
1668 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1670 vector<CNetAddr> vaddr;
1671 if (LookupHost(pszHostName, vaddr))
1673 for(const auto &addr : vaddr)
1675 AddLocal(addr, LOCAL_IF);
1680 // Get local host ip
1681 struct ifaddrs* myaddrs;
1682 if (getifaddrs(&myaddrs) == 0)
1684 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1686 if (ifa->ifa_addr == NULL) continue;
1687 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1688 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1689 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1690 if (ifa->ifa_addr->sa_family == AF_INET)
1692 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1693 CNetAddr addr(s4->sin_addr);
1694 if (AddLocal(addr, LOCAL_IF))
1695 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1698 else if (ifa->ifa_addr->sa_family == AF_INET6)
1700 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1701 CNetAddr addr(s6->sin6_addr);
1702 if (AddLocal(addr, LOCAL_IF))
1703 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1707 freeifaddrs(myaddrs);
1711 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1712 if (!IsLimited(NET_IPV4))
1713 NewThread(ThreadGetMyExternalIP, NULL);
1716 void StartNode(void* parg)
1718 // Make this thread recognisable as the startup thread
1719 RenameThread("novacoin-start");
1721 if (semOutbound == NULL) {
1722 // initialize semaphore
1723 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1724 semOutbound = new CSemaphore(nMaxOutbound);
1727 if (pnodeLocalHost == NULL)
1728 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1736 if (!GetBoolArg("-dnsseed", true))
1737 printf("DNS seeding disabled\n");
1739 if (!NewThread(ThreadDNSAddressSeed, NULL))
1740 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1742 // Get addresses from IRC and advertise ours
1743 if (!GetBoolArg("-irc", true))
1744 printf("IRC seeding disabled\n");
1746 if (!NewThread(ThreadIRCSeed, NULL))
1747 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1749 // Send and receive from sockets, accept connections
1750 if (!NewThread(ThreadSocketHandler, NULL))
1751 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1753 // Initiate outbound connections from -addnode
1754 if (!NewThread(ThreadOpenAddedConnections, NULL))
1755 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1757 // Initiate outbound connections
1758 if (!NewThread(ThreadOpenConnections, NULL))
1759 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1762 if (!NewThread(ThreadMessageHandler, NULL))
1763 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1765 // Dump network addresses
1766 if (!NewThread(ThreadDumpAddress, NULL))
1767 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1769 // Mine proof-of-stake blocks in the background
1770 if (!NewThread(ThreadStakeMiner, pwalletMain))
1771 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1773 // Trusted NTP server, it's localhost by default.
1774 strTrustedUpstream = GetArg("-ntp", "localhost");
1776 // Start periodical NTP sampling thread
1777 NewThread(ThreadNtpSamples, NULL);
1783 printf("StopNode()\n");
1785 nTransactionsUpdated++;
1786 auto nStart = GetTime();
1789 ThreadScriptCheckQuit();
1792 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1793 semOutbound->post();
1796 int nThreadsRunning = 0;
1797 for (int n = 0; n < THREAD_MAX; n++)
1798 nThreadsRunning += vnThreadsRunning[n];
1799 if (nThreadsRunning == 0)
1801 if (GetTime() - nStart > 20)
1805 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1806 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1807 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1808 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1809 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1810 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1811 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1812 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1813 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1814 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1815 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1832 for(CNode* pnode : vNodes)
1833 if (pnode->hSocket != INVALID_SOCKET)
1834 CloseSocket(pnode->hSocket);
1835 for(SOCKET hListenSocket : vhListenSocket)
1836 if (hListenSocket != INVALID_SOCKET)
1837 if (!CloseSocket(hListenSocket))
1838 printf("CloseSocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1840 // clean up some globals (to help leak detection)
1841 for(CNode *pnode : vNodes)
1843 for(CNode *pnode : vNodesDisconnected)
1846 vNodesDisconnected.clear();
1849 delete pnodeLocalHost;
1850 pnodeLocalHost = NULL;
1853 // Shutdown Windows Sockets
1858 instance_of_cnetcleanup;
1860 void RelayTransaction(const CTransaction& tx, const uint256& hash)
1862 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1865 RelayTransaction(tx, hash, ss);
1868 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
1870 CInv inv(MSG_TX, hash);
1873 // Expire old relay messages
1874 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1876 mapRelay.erase(vRelayExpiration.front().second);
1877 vRelayExpiration.pop_front();
1880 // Save original serialized message so newer versions are preserved
1881 mapRelay.insert(std::make_pair(inv, ss));
1882 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
1885 RelayInventory(inv);
1888 void CNode::RecordBytesRecv(uint64_t bytes)
1890 LOCK(cs_totalBytesRecv);
1891 nTotalBytesRecv += bytes;
1894 void CNode::RecordBytesSent(uint64_t bytes)
1896 LOCK(cs_totalBytesSent);
1897 nTotalBytesSent += bytes;
1900 uint64_t CNode::GetTotalBytesRecv()
1902 LOCK(cs_totalBytesRecv);
1903 return nTotalBytesRecv;
1906 uint64_t CNode::GetTotalBytesSent()
1908 LOCK(cs_totalBytesSent);
1909 return nTotalBytesSent;
1911 int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) {
1912 return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);