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"
21 static const int MAX_OUTBOUND_CONNECTIONS = 16;
23 void ThreadMessageHandler2(void* parg);
24 void ThreadSocketHandler2(void* parg);
25 void ThreadOpenConnections2(void* parg);
26 void ThreadOpenAddedConnections2(void* parg);
27 void ThreadDNSAddressSeed2(void* parg);
29 // Fix for ancient MinGW versions, that don't have defined these in ws2tcpip.h.
30 // Todo: Can be removed when our pull-tester is upgraded to a modern MinGW version.
32 #ifndef PROTECTION_LEVEL_UNRESTRICTED
33 #define PROTECTION_LEVEL_UNRESTRICTED 10
35 #ifndef IPV6_PROTECTION_LEVEL
36 #define IPV6_PROTECTION_LEVEL 23
40 struct LocalServiceInfo {
46 // Global state variables
49 bool fDiscover = true;
50 uint64_t nLocalServices = (fClient ? 0 : NODE_NETWORK);
51 static CCriticalSection cs_mapLocalHost;
52 static map<CNetAddr, LocalServiceInfo> mapLocalHost;
53 static bool vfReachable[NET_MAX] = {};
54 static bool vfLimited[NET_MAX] = {};
55 static CNode* pnodeLocalHost = NULL;
56 static CNode* pnodeSync = NULL;
57 CAddress addrSeenByPeer(CService("0.0.0.0", nPortZero), nLocalServices);
58 uint64_t nLocalHostNonce = 0;
59 boost::array<int, THREAD_MAX> vnThreadsRunning;
60 static vector<SOCKET> vhListenSocket;
63 vector<CNode*> vNodes;
64 CCriticalSection cs_vNodes;
65 map<CInv, CDataStream> mapRelay;
66 deque<pair<int64_t, CInv> > vRelayExpiration;
67 CCriticalSection cs_mapRelay;
68 map<CInv, int64_t> mapAlreadyAskedFor;
70 static deque<string> vOneShots;
71 CCriticalSection cs_vOneShots;
73 set<CNetAddr> setservAddNodeAddresses;
74 CCriticalSection cs_setservAddNodeAddresses;
76 vector<string> vAddedNodes;
77 CCriticalSection cs_vAddedNodes;
79 static CSemaphore *semOutbound = NULL;
81 void AddOneShot(string strDest)
84 vOneShots.push_back(strDest);
87 uint16_t GetListenPort()
89 return static_cast<uint16_t>(GetArg("-port", GetDefaultPort()));
92 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
94 // Filter out duplicate requests
95 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
97 pindexLastGetBlocksBegin = pindexBegin;
98 hashLastGetBlocksEnd = hashEnd;
100 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
103 // find 'best' local address for a particular peer
104 bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
110 int nBestReachability = -1;
112 LOCK(cs_mapLocalHost);
113 for (auto it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
115 int nScore = (*it).second.nScore;
116 int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
117 if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
119 addr = CService((*it).first, (*it).second.nPort);
120 nBestReachability = nReachability;
125 return nBestScore >= 0;
128 // get best local address for a particular peer as a CAddress
129 CAddress GetLocalAddress(const CNetAddr *paddrPeer)
131 CAddress ret(CService("0.0.0.0", nPortZero), 0);
133 if (GetLocal(addr, paddrPeer))
135 ret = CAddress(addr);
136 ret.nServices = nLocalServices;
137 ret.nTime = GetAdjustedTime();
142 bool RecvLine(SOCKET hSocket, string& strLine)
148 int nBytes = recv(hSocket, &c, 1, 0);
156 if (strLine.size() >= 9000)
159 else if (nBytes <= 0)
165 int nErr = WSAGetLastError();
166 if (nErr == WSAEMSGSIZE)
168 if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
174 if (!strLine.empty())
179 printf("socket closed\n");
185 int nErr = WSAGetLastError();
186 printf("recv failed: %d\n", nErr);
193 // used when scores of local addresses may have changed
194 // pushes better local address to peers
195 void static AdvertizeLocal()
198 for(CNode* pnode : vNodes)
200 if (pnode->fSuccessfullyConnected)
202 auto addrLocal = GetLocalAddress(&pnode->addr);
203 if (addrLocal.IsRoutable() && (CService)addrLocal != pnode->addrLocal)
205 pnode->PushAddress(addrLocal);
206 pnode->addrLocal = addrLocal;
212 void SetReachable(enum Network net, bool fFlag)
214 LOCK(cs_mapLocalHost);
215 vfReachable[net] = fFlag;
216 if (net == NET_IPV6 && fFlag)
217 vfReachable[NET_IPV4] = true;
220 int GetnScore(const CService& addr)
222 LOCK(cs_mapLocalHost);
223 if (mapLocalHost.count(addr) == LOCAL_NONE)
225 return mapLocalHost[addr].nScore;
229 // Is our peer's addrLocal potentially useful as an external IP source?
230 bool IsPeerAddrLocalGood(CNode *pnode)
232 return fDiscover && pnode->addr.IsRoutable() && pnode->addrLocal.IsRoutable() &&
233 !IsLimited(pnode->addrLocal.GetNetwork());
236 // pushes our own address to a peer
237 void AdvertiseLocal(CNode *pnode)
239 if (!fNoListen && pnode->fSuccessfullyConnected)
241 auto addrLocal = GetLocalAddress(&pnode->addr);
242 // If discovery is enabled, sometimes give our peer the address it
243 // tells us that it sees us as in case it has a better idea of our
244 // address than we do.
245 if (IsPeerAddrLocalGood(pnode) && (!addrLocal.IsRoutable() ||
246 GetRand((GetnScore(addrLocal) > LOCAL_MANUAL) ? 8:2) == 0))
248 addrLocal.SetIP(pnode->addrLocal);
250 if (addrLocal.IsRoutable())
252 printf("AdvertiseLocal: advertising address %s\n", addrLocal.ToString().c_str());
253 pnode->PushAddress(addrLocal);
258 // learn a new local address
259 bool AddLocal(const CService& addr, int nScore)
261 if (!addr.IsRoutable())
264 if (!fDiscover && nScore < LOCAL_MANUAL)
270 printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
273 LOCK(cs_mapLocalHost);
274 bool fAlready = mapLocalHost.count(addr) > 0;
275 LocalServiceInfo &info = mapLocalHost[addr];
276 if (!fAlready || nScore >= info.nScore) {
277 info.nScore = nScore + (fAlready ? 1 : 0);
278 info.nPort = addr.GetPort();
280 SetReachable(addr.GetNetwork());
288 bool AddLocal(const CNetAddr &addr, int nScore)
290 return AddLocal(CService(addr, GetListenPort()), nScore);
293 /** Make a particular network entirely off-limits (no automatic connects to it) */
294 void SetLimited(enum Network net, bool fLimited)
296 if (net == NET_UNROUTABLE)
298 LOCK(cs_mapLocalHost);
299 vfLimited[net] = fLimited;
302 bool IsLimited(enum Network net)
304 LOCK(cs_mapLocalHost);
305 return vfLimited[net];
308 bool IsLimited(const CNetAddr &addr)
310 return IsLimited(addr.GetNetwork());
313 /** vote for a local address */
314 bool SeenLocal(const CService& addr)
317 LOCK(cs_mapLocalHost);
318 if (mapLocalHost.count(addr) == 0)
320 mapLocalHost[addr].nScore++;
328 /** check whether a given address is potentially local */
329 bool IsLocal(const CService& addr)
331 LOCK(cs_mapLocalHost);
332 return mapLocalHost.count(addr) > 0;
335 /** check whether a given address is in a network we can probably connect to */
336 bool IsReachable(const CNetAddr& addr)
338 LOCK(cs_mapLocalHost);
339 enum Network net = addr.GetNetwork();
340 return vfReachable[net] && !vfLimited[net];
343 extern int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv);
345 // We now get our external IP from the IRC server first and only use this as a backup
346 bool GetMyExternalIP(CNetAddr& ipRet)
348 struct sockaddr_in mapped;
349 auto rnd = numeric_limits<uint64_t>::max();
351 int rc = GetExternalIPbySTUN(rnd, &mapped, &srv);
353 ipRet = CNetAddr(mapped.sin_addr);
355 printf("GetExternalIPbySTUN(%" PRIu64 ") returned %s in attempt %d; Server=%s\n", rnd, ipRet.ToStringIP().c_str(), rc, srv);
362 void ThreadGetMyExternalIP(void* parg)
364 // Make this thread recognisable as the external IP detection thread
365 RenameThread("novacoin-ext-ip");
367 CNetAddr addrLocalHost;
368 if (GetMyExternalIP(addrLocalHost))
370 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
371 AddLocal(addrLocalHost, LOCAL_HTTP);
375 void AddressCurrentlyConnected(const CService& addr)
377 addrman.Connected(addr);
383 uint64_t CNode::nTotalBytesRecv = 0;
384 uint64_t CNode::nTotalBytesSent = 0;
385 CCriticalSection CNode::cs_totalBytesRecv;
386 CCriticalSection CNode::cs_totalBytesSent;
388 CNode* FindNode(const CNetAddr& ip)
391 for(CNode* pnode : vNodes)
392 if ((CNetAddr)pnode->addr == ip)
397 CNode* FindNode(string addrName)
400 for(CNode* pnode : vNodes)
401 if (pnode->addrName == addrName)
406 CNode* FindNode(const CService& addr)
409 for(CNode* pnode : vNodes)
410 if ((CService)pnode->addr == addr)
415 CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64_t nTimeout)
417 if (pszDest == NULL) {
418 if (IsLocal(addrConnect))
421 // Look for an existing connection
422 CNode* pnode = FindNode((CService)addrConnect);
426 pnode->AddRef(nTimeout);
435 printf("trying connection %s lastseen=%.1fhrs\n",
436 pszDest ? pszDest : addrConnect.ToString().c_str(),
437 pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
441 if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
443 addrman.Attempt(addrConnect);
446 printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
448 // Set to non-blocking
451 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
452 printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
454 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
455 printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
459 CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
461 pnode->AddRef(nTimeout);
467 vNodes.push_back(pnode);
470 pnode->nTimeConnected = GetTime();
479 void CNode::CloseSocketDisconnect()
482 if (hSocket != INVALID_SOCKET)
484 printf("disconnecting node %s\n", addrName.c_str());
485 CloseSocket(hSocket);
489 // in case this fails, we'll empty the recv buffer when the CNode is deleted
490 TRY_LOCK(cs_vRecv, lockRecv);
494 // if this was the sync node, we'll need a new one
495 if (this == pnodeSync)
499 void CNode::Cleanup()
504 void CNode::PushVersion()
506 auto nTime = GetAdjustedTime();
507 CAddress addrYou, addrMe;
509 bool fHidden = false;
511 if (mapArgs.count("-torname")) {
512 // Our hidden service address
513 CService addrTorName(mapArgs["-torname"], GetListenPort());
515 if (addrTorName.IsValid()) {
517 addrMe = CAddress(addrTorName);
524 addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", nPortZero)));
525 addrMe = GetLocalAddress(&addr);
528 RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
529 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());
530 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
531 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, vector<string>()), nBestHeight);
538 map<CNetAddr, int64_t> CNode::setBanned;
539 CCriticalSection CNode::cs_setBanned;
541 void CNode::ClearBanned()
546 bool CNode::IsBanned(CNetAddr ip)
548 bool fResult = false;
551 auto i = setBanned.find(ip);
552 if (i != setBanned.end())
554 auto t = (*i).second;
562 bool CNode::Misbehaving(int howmuch)
566 printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
570 nMisbehavior += howmuch;
571 if (nMisbehavior >= GetArgInt("-banscore", 100))
573 auto banTime = GetTime()+GetArg("-bantime", nOneDay); // Default 24-hour ban
574 printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
577 if (setBanned[addr] < banTime)
578 setBanned[addr] = banTime;
580 CloseSocketDisconnect();
583 printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
588 #define X(name) stats.name = name
589 void CNode::copyStats(CNodeStats &stats)
604 stats.fSyncNode = (this == pnodeSync);
608 void Release(CNode* node) {
616 void ThreadSocketHandler(void* parg)
618 // Make this thread recognisable as the networking thread
619 RenameThread("novacoin-net");
623 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
624 ThreadSocketHandler2(parg);
625 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
627 catch (exception& e) {
628 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
629 PrintException(&e, "ThreadSocketHandler()");
631 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
632 throw; // support pthread_cancel()
634 printf("ThreadSocketHandler exited\n");
637 static list<CNode*> vNodesDisconnected;
639 void ThreadSocketHandler2(void* parg)
641 printf("ThreadSocketHandler started\n");
642 size_t nPrevNodeCount = 0;
650 // Disconnect unused nodes
651 vector<CNode*> vNodesCopy = vNodes;
652 for(CNode* pnode : vNodesCopy)
654 if (pnode->fDisconnect ||
655 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
657 // remove from vNodes
658 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
660 // release outbound grant (if any)
661 pnode->grantOutbound.Release();
663 // close socket and cleanup
664 pnode->CloseSocketDisconnect();
667 // hold in disconnected pool until all refs are released
668 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
669 if (pnode->fNetworkNode || pnode->fInbound)
671 vNodesDisconnected.push_back(pnode);
675 // Delete disconnected nodes
676 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
677 for(CNode* pnode : vNodesDisconnectedCopy)
679 // wait until threads are done using it
680 if (pnode->GetRefCount() <= 0)
682 bool fDelete = false;
684 TRY_LOCK(pnode->cs_vSend, lockSend);
687 TRY_LOCK(pnode->cs_vRecv, lockRecv);
690 TRY_LOCK(pnode->cs_mapRequests, lockReq);
693 TRY_LOCK(pnode->cs_inventory, lockInv);
702 vNodesDisconnected.remove(pnode);
708 if (vNodes.size() != nPrevNodeCount)
710 nPrevNodeCount = vNodes.size();
711 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
716 // Find which sockets have data to receive
718 struct timeval timeout;
720 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
727 FD_ZERO(&fdsetError);
728 SOCKET hSocketMax = 0;
729 bool have_fds = false;
731 for(SOCKET hListenSocket : vhListenSocket) {
732 FD_SET(hListenSocket, &fdsetRecv);
733 hSocketMax = max(hSocketMax, hListenSocket);
738 for(CNode* pnode : vNodes)
740 if (pnode->hSocket == INVALID_SOCKET)
742 FD_SET(pnode->hSocket, &fdsetRecv);
743 FD_SET(pnode->hSocket, &fdsetError);
744 hSocketMax = max(hSocketMax, pnode->hSocket);
747 TRY_LOCK(pnode->cs_vSend, lockSend);
748 if (lockSend && !pnode->vSend.empty())
749 FD_SET(pnode->hSocket, &fdsetSend);
754 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
755 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
756 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
757 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
760 if (nSelect == SOCKET_ERROR)
764 int nErr = WSAGetLastError();
765 printf("socket select error %d\n", nErr);
766 for (unsigned int i = 0; i <= hSocketMax; i++)
767 FD_SET(i, &fdsetRecv);
770 FD_ZERO(&fdsetError);
771 Sleep(timeout.tv_usec/1000);
776 // Accept new connections
778 for(SOCKET hListenSocket : vhListenSocket)
779 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
782 struct sockaddr_storage sockaddr;
784 struct sockaddr sockaddr;
786 socklen_t len = sizeof(sockaddr);
787 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
791 if (hSocket != INVALID_SOCKET)
792 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
793 printf("Warning: Unknown socket family\n");
797 for(CNode* pnode : vNodes)
802 if (hSocket == INVALID_SOCKET)
804 int nErr = WSAGetLastError();
805 if (nErr != WSAEWOULDBLOCK)
806 printf("socket error accept failed: %d\n", nErr);
808 else if (nInbound >= GetArgInt("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
811 LOCK(cs_setservAddNodeAddresses);
812 if (!setservAddNodeAddresses.count(addr))
813 CloseSocket(hSocket);
816 else if (CNode::IsBanned(addr))
818 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
819 CloseSocket(hSocket);
823 printf("accepted connection %s\n", addr.ToString().c_str());
824 CNode* pnode = new CNode(hSocket, addr, "", true);
828 vNodes.push_back(pnode);
835 // Service each socket
837 vector<CNode*> vNodesCopy;
841 for(CNode* pnode : vNodesCopy)
844 for(CNode* pnode : vNodesCopy)
852 if (pnode->hSocket == INVALID_SOCKET)
854 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
856 TRY_LOCK(pnode->cs_vRecv, lockRecv);
859 CDataStream& vRecv = pnode->vRecv;
860 uint64_t nPos = vRecv.size();
862 if (nPos > ReceiveBufferSize()) {
863 if (!pnode->fDisconnect)
864 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
865 pnode->CloseSocketDisconnect();
868 // typical socket buffer is 8K-64K
869 char pchBuf[0x10000];
870 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
873 vRecv.resize(nPos + nBytes);
874 memcpy(&vRecv[nPos], pchBuf, nBytes);
875 pnode->nLastRecv = GetTime();
876 pnode->nRecvBytes += nBytes;
877 pnode->RecordBytesRecv(nBytes);
879 else if (nBytes == 0)
881 // socket closed gracefully
882 if (!pnode->fDisconnect)
883 printf("socket closed\n");
884 pnode->CloseSocketDisconnect();
889 int nErr = WSAGetLastError();
890 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
892 if (!pnode->fDisconnect)
893 printf("socket recv error %d\n", nErr);
894 pnode->CloseSocketDisconnect();
904 if (pnode->hSocket == INVALID_SOCKET)
906 if (FD_ISSET(pnode->hSocket, &fdsetSend))
908 TRY_LOCK(pnode->cs_vSend, lockSend);
911 CDataStream& vSend = pnode->vSend;
914 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
917 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
918 pnode->nLastSend = GetTime();
919 pnode->nSendBytes += nBytes;
920 pnode->RecordBytesSent(nBytes);
925 int nErr = WSAGetLastError();
926 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
928 printf("socket send error %d\n", nErr);
929 pnode->CloseSocketDisconnect();
937 // Inactivity checking
939 if (pnode->vSend.empty())
940 pnode->nLastSendEmpty = GetTime();
941 if (GetTime() - pnode->nTimeConnected > 60)
943 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
945 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
946 pnode->fDisconnect = true;
948 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
950 printf("socket not sending\n");
951 pnode->fDisconnect = true;
953 else if (GetTime() - pnode->nLastRecv > 90*60)
955 printf("socket inactivity timeout\n");
956 pnode->fDisconnect = true;
962 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
969 void ThreadDNSAddressSeed(void* parg)
971 // Make this thread recognisable as the DNS seeding thread
972 RenameThread("novacoin-dnsseed");
976 vnThreadsRunning[THREAD_DNSSEED]++;
977 ThreadDNSAddressSeed2(parg);
978 vnThreadsRunning[THREAD_DNSSEED]--;
980 catch (exception& e) {
981 vnThreadsRunning[THREAD_DNSSEED]--;
982 PrintException(&e, "ThreadDNSAddressSeed()");
984 vnThreadsRunning[THREAD_DNSSEED]--;
985 throw; // support pthread_cancel()
987 printf("ThreadDNSAddressSeed exited\n");
990 void ThreadDNSAddressSeed2(void* parg)
992 printf("ThreadDNSAddressSeed started\n");
998 // Each pair gives a source name and a seed name.
999 // The first name is used as information source for addrman.
1000 // The second name should resolve to a list of seed addresses.
1001 static const vector<pair <string, string> > vstrDNSSeed = {
1002 { "node.novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro" },
1003 { "novacoin.ru", "dnsseed.novacoin.ru" },
1004 { "novacoin.ru", "testseed.novacoin.ru" },
1005 { "novaco.in", "dnsseed.novaco.in" },
1007 printf("Loading addresses from DNS seeds (could take a while)\n");
1009 for (unsigned int seed_idx = 0; seed_idx < vstrDNSSeed.size(); seed_idx++) {
1010 if (HaveNameProxy()) {
1011 AddOneShot(vstrDNSSeed[seed_idx].second);
1013 vector<CNetAddr> vaddr;
1014 vector<CAddress> vAdd;
1015 if (LookupHost(vstrDNSSeed[seed_idx].second, vaddr))
1017 for(CNetAddr& ip : vaddr)
1019 auto addr = CAddress(CService(ip, GetDefaultPort()));
1020 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1021 vAdd.push_back(addr);
1025 addrman.Add(vAdd, CNetAddr(vstrDNSSeed[seed_idx].first, true));
1030 printf("%d addresses found from DNS seeds\n", found);
1033 void DumpAddresses()
1035 auto nStart = GetTimeMillis();
1040 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1041 addrman.size(), GetTimeMillis() - nStart);
1044 void ThreadDumpAddress2(void* parg)
1046 printf("ThreadDumpAddress started\n");
1048 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1052 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1054 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1056 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1059 void ThreadDumpAddress(void* parg)
1061 // Make this thread recognisable as the address dumping thread
1062 RenameThread("novacoin-adrdump");
1066 ThreadDumpAddress2(parg);
1068 catch (exception& e) {
1069 PrintException(&e, "ThreadDumpAddress()");
1071 printf("ThreadDumpAddress exited\n");
1074 void ThreadOpenConnections(void* parg)
1076 // Make this thread recognisable as the connection opening thread
1077 RenameThread("novacoin-opencon");
1081 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1082 ThreadOpenConnections2(parg);
1083 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1085 catch (exception& e) {
1086 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1087 PrintException(&e, "ThreadOpenConnections()");
1089 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1090 PrintException(NULL, "ThreadOpenConnections()");
1092 printf("ThreadOpenConnections exited\n");
1095 void static ProcessOneShot()
1100 if (vOneShots.empty())
1102 strDest = vOneShots.front();
1103 vOneShots.pop_front();
1106 CSemaphoreGrant grant(*semOutbound, true);
1108 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1109 AddOneShot(strDest);
1113 void ThreadOpenConnections2(void* parg)
1115 printf("ThreadOpenConnections started\n");
1117 // Connect to specific addresses
1118 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1120 for (int64_t nLoop = 0;; nLoop++)
1123 for(string strAddr : mapMultiArgs["-connect"])
1126 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1127 for (int i = 0; i < 10 && i < nLoop; i++)
1138 // Initiate network connections
1139 auto nStart = GetTime();
1144 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1146 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1151 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1152 CSemaphoreGrant grant(*semOutbound);
1153 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1157 // Add seed nodes if IRC isn't working
1158 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1160 vector<uint32_t> vnSeed =
1162 0x1c542868, 0x3859dd6f, 0x203c2e68, 0xf145a6bc, 0x638a545f, 0x325da346, 0x385da346, 0xfb2b8d5f,
1163 0x52568c5f, 0xa979e65b, 0x8de6485d, 0x9f79e65b, 0x048a861f, 0x3388b55f, 0x6ff0b45e, 0x17e81f5f,
1164 0x6c47bb25, 0x1ecdc852, 0x28263db9, 0x47824e5d, 0x36f1c851, 0x2bf913b2, 0x95923cb3, 0x84e63eb2,
1165 0xefdeedbf, 0x65200092, 0xf36f6805, 0x42692d05, 0x772c1955, 0xb6bf1b4e, 0x7abb5f5d, 0xdb2fa6bc,
1166 0x90e911bf, 0x82de565f, 0x694416b2, 0x0ab600bc, 0xfcecbe6d, 0x24ed9fb2, 0x1bb618c2, 0xc64765bb,
1167 0x4e3d62c3, 0xdba24baa, 0x4b7109b0, 0x12a12cc2, 0xfc01864f, 0x0b69e85b, 0x33922c1f, 0xac611bc6,
1168 0x2a257155, 0x991d5fc0, 0xbfdabcb1, 0x9b73ee55, 0x5bc2b95d, 0xdef0762e, 0x6ab7c936, 0x9c4416b2,
1169 0xd60d864f, 0x03671f1f, 0x3b5da346, 0xc6f5c851, 0x5411b2d4, 0xe7c25702, 0x63474fb0, 0x7e11c854,
1170 0x52381d5f, 0x72fdfe59, 0x51599a05, 0xfb12b2d4, 0xaee4f15e, 0xd0e3f15e, 0x2aa2805f, 0xa1caf15e,
1171 0x34fe425e, 0x46e1f15e, 0xd7c71955, 0xaeeff15e, 0x47c2af55, 0x563d89b2, 0x67980fd9, 0xc9def15e,
1172 0x9cc51eb9, 0xdaa7aa6b, 0x78e6871f, 0x0d5d2cb2, 0x7aedf15e, 0x9bcaf15e, 0xe5f7f15e, 0x501c1759,
1173 0xdfbc4980, 0xa7397f2e, 0x31ea1a02, 0x3a27655e, 0xaa86f05c, 0xdcddf15e, 0x64689cb2, 0xd4bf62d4,
1174 0xf093eab2, 0x98def15e, 0xb6c5f15e, 0x81e8f15e, 0xe5d2fe59, 0xa312786d, 0x4cf9fe59, 0x8a922c1f,
1175 0x00c7fe59, 0x1ade565f, 0x9e4116b2, 0x2c36983e, 0x68f8f15e, 0x51b7eab2, 0x76c51eb9, 0x9edd4980,
1176 0x90ef565f, 0x0dd80857, 0xd513fb94, 0xf5bdeab2, 0xa95277b0, 0x2cf2f15e, 0x1897eab2, 0x924416b2,
1177 0x985c9b59, 0x30aa43d8, 0xf9c6745f, 0xaf862e5f, 0xe0ceeab2, 0xb9b3eab2, 0x6da4eab2, 0xa4fdeab2,
1178 0x0fa6c125, 0xe38bbd05, 0x5d922c1f, 0x9bd0eab2, 0x73025e02, 0xc4fd794d, 0x8435b35f, 0x2d01bc2e,
1179 0xaa2a14d4, 0xa22b07cb, 0xebda6f4f, 0xddc6514e, 0xf23feab2, 0xea1e5256, 0x6147b45e, 0x47d21e4f,
1180 0x67c41c1f, 0x53ec1a02, 0x352e786d, 0x6bec1a02, 0x78fb4abe, 0xd3014c5d, 0x9fbbeab2, 0x1fc51eb9,
1181 0x720eeab2, 0x2db5eab2, 0xe8baf65c, 0x521b459e, 0x65c4955f, 0x0e7b915f, 0xa8f37e6d, 0x6d0b465f,
1182 0xfab8ff5c, 0xf7c27e6d, 0x7345a846, 0x4fd1a7d5, 0xdfc97e6d, 0x26c27e6d, 0xa9de36b2, 0xc615344d,
1183 0x28ceb95d, 0xa52d895e, 0x18c17e6d, 0x13ec1a02, 0x0ba37125, 0x6c3d344d, 0xb3922c1f, 0x506bbeb0,
1184 0x4d04994e, 0xa1bbe56d, 0xf62c344d, 0x0847d048, 0x4bdc6451, 0xc95b9a05, 0xbcd3a7d5, 0x29b57125,
1185 0x0c4d2cb2, 0xf2b8eab2, 0xc2d5b95d, 0x0185ef59, 0x30adeab2, 0xcaf0e92e, 0x756c344d, 0xfd9e252e,
1186 0xbe5ef3bc, 0x4689344d, 0xb223895e, 0xfcebeaad, 0xb7c0e92e, 0x993c1760, 0xe1e171b0, 0xb857e75b,
1187 0xbf10002e, 0xb55b2cb2, 0xa90e2cb2, 0x13d6f15e, 0xf8be9225, 0x14ddf15e, 0x06e90305, 0x82472cb2,
1189 vector<CAddress> vAdd;
1190 for (unsigned int i = 0; i < vnSeed.size(); i++)
1192 // It'll only connect to one or two seed nodes because once it connects,
1193 // it'll get a pile of addresses with newer timestamps.
1194 // Seed nodes are given a random 'last seen time' of between one and two
1197 memcpy(&ip, &vnSeed[i], sizeof(ip));
1198 CAddress addr(CService(ip, GetDefaultPort()));
1199 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1200 vAdd.push_back(addr);
1202 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1205 // Add Tor nodes if we have connection with onion router
1206 if (mapArgs.count("-tor"))
1208 const vector<string> vstrTorSeed =
1210 "seedp4knqnoei57u.onion",
1211 "seedr3hhlepyi7fd.onion",
1212 "seed3uuomkclbiz4.onion",
1213 "seedeh7qck3ouff5.onion",
1214 "5rg3vq4jagckeckf.onion",
1215 "seedt3sraf53ajiy.onion",
1216 "seedg4qyccsg42oq.onion",
1217 "novaqrtoywpg7jly.onion",
1218 "seed3d5wolqbgrcb.onion",
1219 "seed24u5dwph3qw4.onion",
1220 "mj26ulzbs2oskgym.onion",
1221 "eqon4usunavt76m7.onion",
1222 "seedd3aldwpslzl3.onion"
1224 vector<CAddress> vAdd;
1225 for (unsigned int i = 0; i < vstrTorSeed.size(); i++)
1227 CAddress addr(CService(vstrTorSeed[i], GetDefaultPort()));
1228 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1229 vAdd.push_back(addr);
1231 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1235 // Choose an address to connect to based on most recently seen
1237 CAddress addrConnect;
1239 // Only connect out to one peer per network group (/16 for IPv4).
1240 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1242 set<vector<unsigned char> > setConnected;
1245 for(CNode* pnode : vNodes) {
1246 if (!pnode->fInbound) {
1247 setConnected.insert(pnode->addr.GetGroup());
1253 auto nANow = GetAdjustedTime();
1258 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1259 auto addr = addrman.Select(10 + min(nOutbound,8)*10);
1261 // if we selected an invalid address, restart
1262 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1265 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1266 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1267 // already-connected network ranges, ...) before trying new addrman addresses.
1272 if (IsLimited(addr))
1275 // only consider very recently tried nodes after 30 failed attempts
1276 if (nANow - addr.nLastTry < 600 && nTries < 30)
1279 // do not allow non-default ports, unless after 50 invalid addresses selected already
1280 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1287 if (addrConnect.IsValid())
1288 OpenNetworkConnection(addrConnect, &grant);
1292 void ThreadOpenAddedConnections(void* parg)
1294 // Make this thread recognisable as the connection opening thread
1295 RenameThread("novacoin-opencon");
1299 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1300 ThreadOpenAddedConnections2(parg);
1301 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1303 catch (exception& e) {
1304 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1305 PrintException(&e, "ThreadOpenAddedConnections()");
1307 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1308 PrintException(NULL, "ThreadOpenAddedConnections()");
1310 printf("ThreadOpenAddedConnections exited\n");
1313 void ThreadOpenAddedConnections2(void* parg)
1315 printf("ThreadOpenAddedConnections started\n");
1318 LOCK(cs_vAddedNodes);
1319 vAddedNodes = mapMultiArgs["-addnode"];
1322 if (HaveNameProxy()) {
1324 list<string> lAddresses(0);
1326 LOCK(cs_vAddedNodes);
1327 for(string& strAddNode : vAddedNodes)
1328 lAddresses.push_back(strAddNode);
1330 for(string& strAddNode : lAddresses) {
1332 CSemaphoreGrant grant(*semOutbound);
1333 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1336 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1337 Sleep(120000); // Retry every 2 minutes
1338 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1343 for (uint32_t i = 0; true; i++)
1345 list<string> lAddresses(0);
1347 LOCK(cs_vAddedNodes);
1348 for(string& strAddNode : vAddedNodes)
1349 lAddresses.push_back(strAddNode);
1352 list<vector<CService> > lservAddressesToAdd(0);
1353 for(string& strAddNode : lAddresses)
1355 vector<CService> vservNode(0);
1356 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1358 lservAddressesToAdd.push_back(vservNode);
1360 LOCK(cs_setservAddNodeAddresses);
1361 for(CService& serv : vservNode)
1362 setservAddNodeAddresses.insert(serv);
1366 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1367 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1370 for(CNode* pnode : vNodes)
1371 for (auto it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1373 for(CService& addrNode : *(it))
1374 if (pnode->addr == addrNode)
1376 it = lservAddressesToAdd.erase(it);
1377 if(it != lservAddressesToAdd.begin())
1381 if (it == lservAddressesToAdd.end())
1385 for(vector<CService>& vserv : lservAddressesToAdd)
1387 if (vserv.size() == 0)
1389 CSemaphoreGrant grant(*semOutbound);
1390 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1397 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1398 Sleep(120000); // Retry every 2 minutes
1399 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1405 // if successful, this moves the passed grant to the constructed node
1406 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1409 // Initiate outbound network connection
1414 if (IsLocal(addrConnect) ||
1415 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1416 FindNode(addrConnect.ToStringIPPort().c_str()))
1418 if (strDest && FindNode(strDest))
1421 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1422 CNode* pnode = ConnectNode(addrConnect, strDest);
1423 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1429 grantOutbound->MoveTo(pnode->grantOutbound);
1430 pnode->fNetworkNode = true;
1432 pnode->fOneShot = true;
1437 // for now, use a very simple selection metric: the node from which we received
1439 static int64_t NodeSyncScore(const CNode *pnode) {
1440 return pnode->nLastRecv;
1443 void static StartSync(const vector<CNode*> &vNodes) {
1444 CNode *pnodeNewSync = NULL;
1445 int64_t nBestScore = 0;
1447 // Iterate over all nodes
1448 for(CNode* pnode : vNodes) {
1449 // check preconditions for allowing a sync
1450 if (!pnode->fClient && !pnode->fOneShot &&
1451 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1452 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1453 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1454 // if ok, compare node's score with the best so far
1455 int64_t nScore = NodeSyncScore(pnode);
1456 if (pnodeNewSync == NULL || nScore > nBestScore) {
1457 pnodeNewSync = pnode;
1458 nBestScore = nScore;
1462 // if a new sync candidate was found, start sync!
1464 pnodeNewSync->fStartSync = true;
1465 pnodeSync = pnodeNewSync;
1469 void ThreadMessageHandler(void* parg)
1471 // Make this thread recognisable as the message handling thread
1472 RenameThread("novacoin-msghand");
1476 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1477 ThreadMessageHandler2(parg);
1478 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1480 catch (exception& e) {
1481 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1482 PrintException(&e, "ThreadMessageHandler()");
1484 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1485 PrintException(NULL, "ThreadMessageHandler()");
1487 printf("ThreadMessageHandler exited\n");
1490 void ThreadMessageHandler2(void* parg)
1492 printf("ThreadMessageHandler started\n");
1493 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1496 bool fHaveSyncNode = false;
1497 vector<CNode*> vNodesCopy;
1500 vNodesCopy = vNodes;
1501 for(CNode* pnode : vNodesCopy) {
1503 if (pnode == pnodeSync)
1504 fHaveSyncNode = true;
1509 StartSync(vNodesCopy);
1511 // Poll the connected nodes for messages
1512 for(CNode* pnode : vNodesCopy)
1516 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1518 ProcessMessages(pnode);
1525 TRY_LOCK(pnode->cs_vSend, lockSend);
1527 SendMessages(pnode);
1535 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
1538 // Wait and allow messages to bunch up.
1539 // Reduce vnThreadsRunning so StopNode has permission to exit while
1540 // we're sleeping, but we must always check fShutdown after doing this.
1541 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1543 if (fRequestShutdown)
1545 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1556 bool BindListenPort(const CService &addrBind, string& strError)
1561 // Create socket for listening for incoming connections
1563 struct sockaddr_storage sockaddr;
1565 struct sockaddr sockaddr;
1567 socklen_t len = sizeof(sockaddr);
1568 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1570 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1571 printf("%s\n", strError.c_str());
1575 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1576 if (hListenSocket == INVALID_SOCKET)
1578 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1579 printf("%s\n", strError.c_str());
1585 // Different way of disabling SIGPIPE on BSD
1586 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1588 // Allow binding if the port is still in TIME_WAIT state after
1589 // the program was closed and restarted. Not an issue on windows!
1590 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1594 // Set to non-blocking, incoming connections will also inherit this
1595 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1597 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1600 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1601 printf("%s\n", strError.c_str());
1606 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1607 // and enable it by default or not. Try to enable it, if possible.
1608 if (addrBind.IsIPv6()) {
1611 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1613 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1617 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1618 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
1623 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1625 int nErr = WSAGetLastError();
1626 if (nErr == WSAEADDRINUSE)
1627 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1629 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1630 printf("%s\n", strError.c_str());
1631 CloseSocket(hListenSocket);
1634 printf("Bound to %s\n", addrBind.ToString().c_str());
1636 // Listen for incoming connections
1637 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1639 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1640 printf("%s\n", strError.c_str());
1641 CloseSocket(hListenSocket);
1645 vhListenSocket.push_back(hListenSocket);
1647 if (addrBind.IsRoutable() && fDiscover)
1648 AddLocal(addrBind, LOCAL_BIND);
1653 void static Discover()
1659 // Get local host IP
1660 char pszHostName[1000] = "";
1661 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1663 vector<CNetAddr> vaddr;
1664 if (LookupHost(pszHostName, vaddr))
1666 for(const auto &addr : vaddr)
1668 AddLocal(addr, LOCAL_IF);
1673 // Get local host ip
1674 struct ifaddrs* myaddrs;
1675 if (getifaddrs(&myaddrs) == 0)
1677 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1679 if (ifa->ifa_addr == NULL) continue;
1680 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1681 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1682 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1683 if (ifa->ifa_addr->sa_family == AF_INET)
1685 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1686 CNetAddr addr(s4->sin_addr);
1687 if (AddLocal(addr, LOCAL_IF))
1688 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1691 else if (ifa->ifa_addr->sa_family == AF_INET6)
1693 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1694 CNetAddr addr(s6->sin6_addr);
1695 if (AddLocal(addr, LOCAL_IF))
1696 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1700 freeifaddrs(myaddrs);
1704 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1705 if (!IsLimited(NET_IPV4))
1706 NewThread(ThreadGetMyExternalIP, NULL);
1709 void StartNode(void* parg)
1711 // Make this thread recognisable as the startup thread
1712 RenameThread("novacoin-start");
1714 if (semOutbound == NULL) {
1715 // initialize semaphore
1716 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1717 semOutbound = new CSemaphore(nMaxOutbound);
1720 if (pnodeLocalHost == NULL)
1721 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1729 if (!GetBoolArg("-dnsseed", true))
1730 printf("DNS seeding disabled\n");
1732 if (!NewThread(ThreadDNSAddressSeed, NULL))
1733 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1735 // Get addresses from IRC and advertise ours
1736 if (!GetBoolArg("-irc", true))
1737 printf("IRC seeding disabled\n");
1739 if (!NewThread(ThreadIRCSeed, NULL))
1740 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1742 // Send and receive from sockets, accept connections
1743 if (!NewThread(ThreadSocketHandler, NULL))
1744 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1746 // Initiate outbound connections from -addnode
1747 if (!NewThread(ThreadOpenAddedConnections, NULL))
1748 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1750 // Initiate outbound connections
1751 if (!NewThread(ThreadOpenConnections, NULL))
1752 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1755 if (!NewThread(ThreadMessageHandler, NULL))
1756 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1758 // Dump network addresses
1759 if (!NewThread(ThreadDumpAddress, NULL))
1760 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1762 // Mine proof-of-stake blocks in the background
1763 if (!NewThread(ThreadStakeMiner, pwalletMain))
1764 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1766 // Trusted NTP server, it's localhost by default.
1767 strTrustedUpstream = GetArg("-ntp", "localhost");
1769 // Start periodical NTP sampling thread
1770 NewThread(ThreadNtpSamples, NULL);
1776 printf("StopNode()\n");
1778 nTransactionsUpdated++;
1779 auto nStart = GetTime();
1782 ThreadScriptCheckQuit();
1785 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1786 semOutbound->post();
1789 int nThreadsRunning = 0;
1790 for (int n = 0; n < THREAD_MAX; n++)
1791 nThreadsRunning += vnThreadsRunning[n];
1792 if (nThreadsRunning == 0)
1794 if (GetTime() - nStart > 20)
1798 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1799 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1800 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1801 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1802 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1803 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1804 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1805 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1806 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1807 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1808 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1825 for(CNode* pnode : vNodes)
1826 if (pnode->hSocket != INVALID_SOCKET)
1827 CloseSocket(pnode->hSocket);
1828 for(SOCKET hListenSocket : vhListenSocket)
1829 if (hListenSocket != INVALID_SOCKET)
1830 if (!CloseSocket(hListenSocket))
1831 printf("CloseSocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1833 // clean up some globals (to help leak detection)
1834 for(CNode *pnode : vNodes)
1836 for(CNode *pnode : vNodesDisconnected)
1839 vNodesDisconnected.clear();
1842 delete pnodeLocalHost;
1843 pnodeLocalHost = NULL;
1846 // Shutdown Windows Sockets
1851 instance_of_cnetcleanup;
1853 void RelayTransaction(const CTransaction& tx, const uint256& hash)
1855 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1858 RelayTransaction(tx, hash, ss);
1861 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
1863 CInv inv(MSG_TX, hash);
1866 // Expire old relay messages
1867 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1869 mapRelay.erase(vRelayExpiration.front().second);
1870 vRelayExpiration.pop_front();
1873 // Save original serialized message so newer versions are preserved
1874 mapRelay.insert({inv, ss});
1875 vRelayExpiration.push_back({GetTime() + 15 * 60, inv});
1878 RelayInventory(inv);
1881 void CNode::RecordBytesRecv(uint64_t bytes)
1883 LOCK(cs_totalBytesRecv);
1884 nTotalBytesRecv += bytes;
1887 void CNode::RecordBytesSent(uint64_t bytes)
1889 LOCK(cs_totalBytesSent);
1890 nTotalBytesSent += bytes;
1893 uint64_t CNode::GetTotalBytesRecv()
1895 LOCK(cs_totalBytesRecv);
1896 return nTotalBytesRecv;
1899 uint64_t CNode::GetTotalBytesSent()
1901 LOCK(cs_totalBytesSent);
1902 return nTotalBytesSent;
1904 int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) {
1905 return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);