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 uint16_t GetListenPort()
90 return static_cast<uint16_t>(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);
972 void ThreadDNSAddressSeed(void* parg)
974 // Make this thread recognisable as the DNS seeding thread
975 RenameThread("novacoin-dnsseed");
979 vnThreadsRunning[THREAD_DNSSEED]++;
980 ThreadDNSAddressSeed2(parg);
981 vnThreadsRunning[THREAD_DNSSEED]--;
983 catch (std::exception& e) {
984 vnThreadsRunning[THREAD_DNSSEED]--;
985 PrintException(&e, "ThreadDNSAddressSeed()");
987 vnThreadsRunning[THREAD_DNSSEED]--;
988 throw; // support pthread_cancel()
990 printf("ThreadDNSAddressSeed exited\n");
993 void ThreadDNSAddressSeed2(void* parg)
995 printf("ThreadDNSAddressSeed started\n");
1001 // Each pair gives a source name and a seed name.
1002 // The first name is used as information source for addrman.
1003 // The second name should resolve to a list of seed addresses.
1004 static const vector<pair <string, string> > vstrDNSSeed = {
1005 { "novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro" },
1006 { "novacoin.ru", "dnsseed.novacoin.ru" },
1007 { "novacoin.ru", "testseed.novacoin.ru" },
1008 { "novaco.in", "dnsseed.novaco.in" },
1010 printf("Loading addresses from DNS seeds (could take a while)\n");
1012 for (unsigned int seed_idx = 0; seed_idx < vstrDNSSeed.size(); seed_idx++) {
1013 if (HaveNameProxy()) {
1014 AddOneShot(vstrDNSSeed[seed_idx].second);
1016 vector<CNetAddr> vaddr;
1017 vector<CAddress> vAdd;
1018 if (LookupHost(vstrDNSSeed[seed_idx].second, vaddr))
1020 for(CNetAddr& ip : vaddr)
1022 auto addr = CAddress(CService(ip, GetDefaultPort()));
1023 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1024 vAdd.push_back(addr);
1028 addrman.Add(vAdd, CNetAddr(vstrDNSSeed[seed_idx].first, true));
1033 printf("%d addresses found from DNS seeds\n", found);
1036 void DumpAddresses()
1038 auto nStart = GetTimeMillis();
1043 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1044 addrman.size(), GetTimeMillis() - nStart);
1047 void ThreadDumpAddress2(void* parg)
1049 printf("ThreadDumpAddress started\n");
1051 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1055 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1057 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1059 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1062 void ThreadDumpAddress(void* parg)
1064 // Make this thread recognisable as the address dumping thread
1065 RenameThread("novacoin-adrdump");
1069 ThreadDumpAddress2(parg);
1071 catch (std::exception& e) {
1072 PrintException(&e, "ThreadDumpAddress()");
1074 printf("ThreadDumpAddress exited\n");
1077 void ThreadOpenConnections(void* parg)
1079 // Make this thread recognisable as the connection opening thread
1080 RenameThread("novacoin-opencon");
1084 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1085 ThreadOpenConnections2(parg);
1086 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1088 catch (std::exception& e) {
1089 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1090 PrintException(&e, "ThreadOpenConnections()");
1092 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1093 PrintException(NULL, "ThreadOpenConnections()");
1095 printf("ThreadOpenConnections exited\n");
1098 void static ProcessOneShot()
1103 if (vOneShots.empty())
1105 strDest = vOneShots.front();
1106 vOneShots.pop_front();
1109 CSemaphoreGrant grant(*semOutbound, true);
1111 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1112 AddOneShot(strDest);
1116 void ThreadOpenConnections2(void* parg)
1118 printf("ThreadOpenConnections started\n");
1120 // Connect to specific addresses
1121 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1123 for (int64_t nLoop = 0;; nLoop++)
1126 for(string strAddr : mapMultiArgs["-connect"])
1129 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1130 for (int i = 0; i < 10 && i < nLoop; i++)
1141 // Initiate network connections
1142 auto nStart = GetTime();
1147 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1149 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1154 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1155 CSemaphoreGrant grant(*semOutbound);
1156 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1160 // Add seed nodes if IRC isn't working
1161 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1163 std::vector<uint32_t> vnSeed =
1165 0xa52bf0da, 0x30aa43d8, 0x614488d5, 0x517b6fd5, 0xd4bf62d4, 0xb7d638d4, 0xbc12bcd1, 0xa2501bc6,
1166 0xfde617c6, 0x3337b1c6, 0x1dcd71c3, 0x2c1544c1, 0xe05f6ac1, 0x852f63c0, 0x3e2363c0, 0x15f563c0,
1167 0x430d63c0, 0x50d6a9c0, 0xf0a679c0, 0xefdeedbf, 0x7aaee8bc, 0x3a3dbbbc, 0xef218abc, 0x0bef78bc,
1168 0x8baa3eb2, 0x2bf913b2, 0x24ed9fb2, 0xb42289b2, 0x718a09b0, 0xe9433eb0, 0x559425b0, 0xc97e1fb0,
1169 0x18e1d4b0, 0x8f6cc1b0, 0xac3838ae, 0x86c0ffad, 0x6b0272a7, 0xa463f8a2, 0x6f17f3a2, 0xb3d6f3a2,
1170 0x9cd8f997, 0xd513fb94, 0x39e64880, 0x3859dd6f, 0x0b08fe6d, 0xe601fe6d, 0xeb44a26d, 0xfe53186c,
1171 0x203c2e68, 0x1c542868, 0x0caa8368, 0xb8748368, 0xccca4762, 0xc637555f, 0x638a545f, 0x59b2205f,
1172 0x52568c5f, 0xba568c5f, 0x8a568c5f, 0x31b0f45e, 0x54a0f45e, 0x37d6f15e, 0xc520175e, 0x7620175e,
1173 0xc310175e, 0x8e33b45e, 0x7abb5f5d, 0xd3014c5d, 0xa1e1485d, 0x9947645d, 0xfab8ff5c, 0xa979e65b,
1174 0xa879e65b, 0x9f79e65b, 0x9fa3d25b, 0x112a925b, 0x7b92905b, 0x60647a5b, 0x1e389d5a, 0x851afa59,
1175 0x0185ef59, 0x26549b59, 0x1c9efe57, 0xc54c1256, 0x1ad51955, 0x19d21955, 0x73c41955, 0x3f74ee55,
1176 0x633eea55, 0x6883d655, 0xfb72c655, 0x5360a653, 0x17c1ea52, 0xc661c852, 0x1ecdc852, 0x006a9752,
1177 0xf72d9252, 0x82650551, 0x36f1c851, 0x33f1c851, 0xd5c1864f, 0xb6bf1b4e, 0x96da184e, 0x40d0234d,
1178 0x9a96ab4c, 0x8fc2a84c, 0xb5dbd048, 0xf4644447, 0x2d51af47, 0xa9625445, 0x83f05243, 0x89672941,
1179 0x3a8bad3e, 0xf0a05436, 0x6ab7c936, 0x49971d32, 0xadd4482e, 0xcffd212e, 0x6730bc2e, 0x839aa12e,
1180 0x68d9692e, 0xc7183b25, 0x6c47bb25, 0x2490bb25, 0xad651c1f, 0x048a861f, 0x6937811f, 0x064b2d05,
1183 std::vector<CAddress> vAdd;
1184 for (unsigned int i = 0; i < vnSeed.size(); i++)
1186 // It'll only connect to one or two seed nodes because once it connects,
1187 // it'll get a pile of addresses with newer timestamps.
1188 // Seed nodes are given a random 'last seen time' of between one and two
1191 memcpy(&ip, &vnSeed[i], sizeof(ip));
1192 CAddress addr(CService(ip, GetDefaultPort()));
1193 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1194 vAdd.push_back(addr);
1196 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1199 // Add Tor nodes if we have connection with onion router
1200 if (mapArgs.count("-tor"))
1202 const std::vector<std::string> vstrTorSeed =
1204 "seedp4knqnoei57u.onion",
1205 "seedr3hhlepyi7fd.onion",
1206 "seed3uuomkclbiz4.onion",
1207 "seedeh7qck3ouff5.onion",
1208 "5rg3vq4jagckeckf.onion",
1209 "seedt3sraf53ajiy.onion",
1210 "seedg4qyccsg42oq.onion",
1211 "novaqrtoywpg7jly.onion",
1212 "seed3d5wolqbgrcb.onion",
1213 "seed24u5dwph3qw4.onion",
1214 "mj26ulzbs2oskgym.onion",
1215 "eqon4usunavt76m7.onion",
1216 "seedd3aldwpslzl3.onion"
1218 std::vector<CAddress> vAdd;
1219 for (unsigned int i = 0; i < vstrTorSeed.size(); i++)
1221 CAddress addr(CService(vstrTorSeed[i], GetDefaultPort()));
1222 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1223 vAdd.push_back(addr);
1225 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1229 // Choose an address to connect to based on most recently seen
1231 CAddress addrConnect;
1233 // Only connect out to one peer per network group (/16 for IPv4).
1234 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1236 set<vector<unsigned char> > setConnected;
1239 for(CNode* pnode : vNodes) {
1240 if (!pnode->fInbound) {
1241 setConnected.insert(pnode->addr.GetGroup());
1247 auto nANow = GetAdjustedTime();
1252 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1253 auto addr = addrman.Select(10 + min(nOutbound,8)*10);
1255 // if we selected an invalid address, restart
1256 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1259 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1260 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1261 // already-connected network ranges, ...) before trying new addrman addresses.
1266 if (IsLimited(addr))
1269 // only consider very recently tried nodes after 30 failed attempts
1270 if (nANow - addr.nLastTry < 600 && nTries < 30)
1273 // do not allow non-default ports, unless after 50 invalid addresses selected already
1274 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1281 if (addrConnect.IsValid())
1282 OpenNetworkConnection(addrConnect, &grant);
1286 void ThreadOpenAddedConnections(void* parg)
1288 // Make this thread recognisable as the connection opening thread
1289 RenameThread("novacoin-opencon");
1293 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1294 ThreadOpenAddedConnections2(parg);
1295 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1297 catch (std::exception& e) {
1298 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1299 PrintException(&e, "ThreadOpenAddedConnections()");
1301 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1302 PrintException(NULL, "ThreadOpenAddedConnections()");
1304 printf("ThreadOpenAddedConnections exited\n");
1307 void ThreadOpenAddedConnections2(void* parg)
1309 printf("ThreadOpenAddedConnections started\n");
1312 LOCK(cs_vAddedNodes);
1313 vAddedNodes = mapMultiArgs["-addnode"];
1316 if (HaveNameProxy()) {
1318 list<string> lAddresses(0);
1320 LOCK(cs_vAddedNodes);
1321 for(string& strAddNode : vAddedNodes)
1322 lAddresses.push_back(strAddNode);
1324 for(string& strAddNode : lAddresses) {
1326 CSemaphoreGrant grant(*semOutbound);
1327 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1330 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1331 Sleep(120000); // Retry every 2 minutes
1332 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1337 for (uint32_t i = 0; true; i++)
1339 list<string> lAddresses(0);
1341 LOCK(cs_vAddedNodes);
1342 for(string& strAddNode : vAddedNodes)
1343 lAddresses.push_back(strAddNode);
1346 list<vector<CService> > lservAddressesToAdd(0);
1347 for(string& strAddNode : lAddresses)
1349 vector<CService> vservNode(0);
1350 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1352 lservAddressesToAdd.push_back(vservNode);
1354 LOCK(cs_setservAddNodeAddresses);
1355 for(CService& serv : vservNode)
1356 setservAddNodeAddresses.insert(serv);
1360 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1361 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1364 for(CNode* pnode : vNodes)
1365 for (auto it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1367 for(CService& addrNode : *(it))
1368 if (pnode->addr == addrNode)
1370 it = lservAddressesToAdd.erase(it);
1371 if(it != lservAddressesToAdd.begin())
1375 if (it == lservAddressesToAdd.end())
1379 for(vector<CService>& vserv : lservAddressesToAdd)
1381 if (vserv.size() == 0)
1383 CSemaphoreGrant grant(*semOutbound);
1384 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1391 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1392 Sleep(120000); // Retry every 2 minutes
1393 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1399 // if successful, this moves the passed grant to the constructed node
1400 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1403 // Initiate outbound network connection
1408 if (IsLocal(addrConnect) ||
1409 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1410 FindNode(addrConnect.ToStringIPPort().c_str()))
1412 if (strDest && FindNode(strDest))
1415 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1416 CNode* pnode = ConnectNode(addrConnect, strDest);
1417 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1423 grantOutbound->MoveTo(pnode->grantOutbound);
1424 pnode->fNetworkNode = true;
1426 pnode->fOneShot = true;
1431 // for now, use a very simple selection metric: the node from which we received
1433 static int64_t NodeSyncScore(const CNode *pnode) {
1434 return pnode->nLastRecv;
1437 void static StartSync(const vector<CNode*> &vNodes) {
1438 CNode *pnodeNewSync = NULL;
1439 int64_t nBestScore = 0;
1441 // Iterate over all nodes
1442 for(CNode* pnode : vNodes) {
1443 // check preconditions for allowing a sync
1444 if (!pnode->fClient && !pnode->fOneShot &&
1445 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1446 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1447 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1448 // if ok, compare node's score with the best so far
1449 int64_t nScore = NodeSyncScore(pnode);
1450 if (pnodeNewSync == NULL || nScore > nBestScore) {
1451 pnodeNewSync = pnode;
1452 nBestScore = nScore;
1456 // if a new sync candidate was found, start sync!
1458 pnodeNewSync->fStartSync = true;
1459 pnodeSync = pnodeNewSync;
1463 void ThreadMessageHandler(void* parg)
1465 // Make this thread recognisable as the message handling thread
1466 RenameThread("novacoin-msghand");
1470 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1471 ThreadMessageHandler2(parg);
1472 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1474 catch (std::exception& e) {
1475 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1476 PrintException(&e, "ThreadMessageHandler()");
1478 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1479 PrintException(NULL, "ThreadMessageHandler()");
1481 printf("ThreadMessageHandler exited\n");
1484 void ThreadMessageHandler2(void* parg)
1486 printf("ThreadMessageHandler started\n");
1487 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1490 bool fHaveSyncNode = false;
1491 vector<CNode*> vNodesCopy;
1494 vNodesCopy = vNodes;
1495 for(CNode* pnode : vNodesCopy) {
1497 if (pnode == pnodeSync)
1498 fHaveSyncNode = true;
1503 StartSync(vNodesCopy);
1505 // Poll the connected nodes for messages
1506 for(CNode* pnode : vNodesCopy)
1510 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1512 ProcessMessages(pnode);
1519 TRY_LOCK(pnode->cs_vSend, lockSend);
1521 SendMessages(pnode);
1529 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
1532 // Wait and allow messages to bunch up.
1533 // Reduce vnThreadsRunning so StopNode has permission to exit while
1534 // we're sleeping, but we must always check fShutdown after doing this.
1535 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1537 if (fRequestShutdown)
1539 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1550 bool BindListenPort(const CService &addrBind, string& strError)
1555 // Create socket for listening for incoming connections
1557 struct sockaddr_storage sockaddr;
1559 struct sockaddr sockaddr;
1561 socklen_t len = sizeof(sockaddr);
1562 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1564 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1565 printf("%s\n", strError.c_str());
1569 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1570 if (hListenSocket == INVALID_SOCKET)
1572 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1573 printf("%s\n", strError.c_str());
1579 // Different way of disabling SIGPIPE on BSD
1580 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1582 // Allow binding if the port is still in TIME_WAIT state after
1583 // the program was closed and restarted. Not an issue on windows!
1584 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1588 // Set to non-blocking, incoming connections will also inherit this
1589 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1591 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1594 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1595 printf("%s\n", strError.c_str());
1600 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1601 // and enable it by default or not. Try to enable it, if possible.
1602 if (addrBind.IsIPv6()) {
1605 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1607 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1611 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1612 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
1617 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1619 int nErr = WSAGetLastError();
1620 if (nErr == WSAEADDRINUSE)
1621 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1623 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1624 printf("%s\n", strError.c_str());
1625 CloseSocket(hListenSocket);
1628 printf("Bound to %s\n", addrBind.ToString().c_str());
1630 // Listen for incoming connections
1631 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1633 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1634 printf("%s\n", strError.c_str());
1635 CloseSocket(hListenSocket);
1639 vhListenSocket.push_back(hListenSocket);
1641 if (addrBind.IsRoutable() && fDiscover)
1642 AddLocal(addrBind, LOCAL_BIND);
1647 void static Discover()
1653 // Get local host IP
1654 char pszHostName[1000] = "";
1655 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1657 vector<CNetAddr> vaddr;
1658 if (LookupHost(pszHostName, vaddr))
1660 for(const auto &addr : vaddr)
1662 AddLocal(addr, LOCAL_IF);
1667 // Get local host ip
1668 struct ifaddrs* myaddrs;
1669 if (getifaddrs(&myaddrs) == 0)
1671 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1673 if (ifa->ifa_addr == NULL) continue;
1674 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1675 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1676 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1677 if (ifa->ifa_addr->sa_family == AF_INET)
1679 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1680 CNetAddr addr(s4->sin_addr);
1681 if (AddLocal(addr, LOCAL_IF))
1682 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1685 else if (ifa->ifa_addr->sa_family == AF_INET6)
1687 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1688 CNetAddr addr(s6->sin6_addr);
1689 if (AddLocal(addr, LOCAL_IF))
1690 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1694 freeifaddrs(myaddrs);
1698 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1699 if (!IsLimited(NET_IPV4))
1700 NewThread(ThreadGetMyExternalIP, NULL);
1703 void StartNode(void* parg)
1705 // Make this thread recognisable as the startup thread
1706 RenameThread("novacoin-start");
1708 if (semOutbound == NULL) {
1709 // initialize semaphore
1710 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1711 semOutbound = new CSemaphore(nMaxOutbound);
1714 if (pnodeLocalHost == NULL)
1715 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1723 if (!GetBoolArg("-dnsseed", true))
1724 printf("DNS seeding disabled\n");
1726 if (!NewThread(ThreadDNSAddressSeed, NULL))
1727 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1729 // Get addresses from IRC and advertise ours
1730 if (!GetBoolArg("-irc", true))
1731 printf("IRC seeding disabled\n");
1733 if (!NewThread(ThreadIRCSeed, NULL))
1734 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1736 // Send and receive from sockets, accept connections
1737 if (!NewThread(ThreadSocketHandler, NULL))
1738 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1740 // Initiate outbound connections from -addnode
1741 if (!NewThread(ThreadOpenAddedConnections, NULL))
1742 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1744 // Initiate outbound connections
1745 if (!NewThread(ThreadOpenConnections, NULL))
1746 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1749 if (!NewThread(ThreadMessageHandler, NULL))
1750 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1752 // Dump network addresses
1753 if (!NewThread(ThreadDumpAddress, NULL))
1754 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1756 // Mine proof-of-stake blocks in the background
1757 if (!NewThread(ThreadStakeMiner, pwalletMain))
1758 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1760 // Trusted NTP server, it's localhost by default.
1761 strTrustedUpstream = GetArg("-ntp", "localhost");
1763 // Start periodical NTP sampling thread
1764 NewThread(ThreadNtpSamples, NULL);
1770 printf("StopNode()\n");
1772 nTransactionsUpdated++;
1773 auto nStart = GetTime();
1776 ThreadScriptCheckQuit();
1779 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1780 semOutbound->post();
1783 int nThreadsRunning = 0;
1784 for (int n = 0; n < THREAD_MAX; n++)
1785 nThreadsRunning += vnThreadsRunning[n];
1786 if (nThreadsRunning == 0)
1788 if (GetTime() - nStart > 20)
1792 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1793 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1794 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1795 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1796 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1797 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1798 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1799 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1800 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1801 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1802 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1819 for(CNode* pnode : vNodes)
1820 if (pnode->hSocket != INVALID_SOCKET)
1821 CloseSocket(pnode->hSocket);
1822 for(SOCKET hListenSocket : vhListenSocket)
1823 if (hListenSocket != INVALID_SOCKET)
1824 if (!CloseSocket(hListenSocket))
1825 printf("CloseSocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1827 // clean up some globals (to help leak detection)
1828 for(CNode *pnode : vNodes)
1830 for(CNode *pnode : vNodesDisconnected)
1833 vNodesDisconnected.clear();
1836 delete pnodeLocalHost;
1837 pnodeLocalHost = NULL;
1840 // Shutdown Windows Sockets
1845 instance_of_cnetcleanup;
1847 void RelayTransaction(const CTransaction& tx, const uint256& hash)
1849 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1852 RelayTransaction(tx, hash, ss);
1855 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
1857 CInv inv(MSG_TX, hash);
1860 // Expire old relay messages
1861 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1863 mapRelay.erase(vRelayExpiration.front().second);
1864 vRelayExpiration.pop_front();
1867 // Save original serialized message so newer versions are preserved
1868 mapRelay.insert(std::make_pair(inv, ss));
1869 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
1872 RelayInventory(inv);
1875 void CNode::RecordBytesRecv(uint64_t bytes)
1877 LOCK(cs_totalBytesRecv);
1878 nTotalBytesRecv += bytes;
1881 void CNode::RecordBytesSent(uint64_t bytes)
1883 LOCK(cs_totalBytesSent);
1884 nTotalBytesSent += bytes;
1887 uint64_t CNode::GetTotalBytesRecv()
1889 LOCK(cs_totalBytesRecv);
1890 return nTotalBytesRecv;
1893 uint64_t CNode::GetTotalBytesSent()
1895 LOCK(cs_totalBytesSent);
1896 return nTotalBytesSent;
1898 int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) {
1899 return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);