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);
354 printf("GetExternalIPbySTUN(%" PRIu64 ") returned %s in attempt %d; Server=%s\n", rnd, ipRet.ToStringIP().c_str(), rc, srv);
360 void ThreadGetMyExternalIP(void* parg)
362 // Make this thread recognisable as the external IP detection thread
363 RenameThread("novacoin-ext-ip");
365 CNetAddr addrLocalHost;
366 if (GetMyExternalIP(addrLocalHost))
368 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
369 AddLocal(addrLocalHost, LOCAL_HTTP);
377 void AddressCurrentlyConnected(const CService& addr)
379 addrman.Connected(addr);
385 uint64_t CNode::nTotalBytesRecv = 0;
386 uint64_t CNode::nTotalBytesSent = 0;
387 CCriticalSection CNode::cs_totalBytesRecv;
388 CCriticalSection CNode::cs_totalBytesSent;
390 CNode* FindNode(const CNetAddr& ip)
393 for(CNode* pnode : vNodes)
394 if ((CNetAddr)pnode->addr == ip)
399 CNode* FindNode(string addrName)
402 for(CNode* pnode : vNodes)
403 if (pnode->addrName == addrName)
408 CNode* FindNode(const CService& addr)
411 for(CNode* pnode : vNodes)
412 if ((CService)pnode->addr == addr)
417 CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64_t nTimeout)
419 if (pszDest == NULL) {
420 if (IsLocal(addrConnect))
423 // Look for an existing connection
424 CNode* pnode = FindNode((CService)addrConnect);
428 pnode->AddRef(nTimeout);
437 printf("trying connection %s lastseen=%.1fhrs\n",
438 pszDest ? pszDest : addrConnect.ToString().c_str(),
439 pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
443 if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
445 addrman.Attempt(addrConnect);
448 printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
450 // Set to non-blocking
453 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
454 printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
456 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
457 printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
461 CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
463 pnode->AddRef(nTimeout);
469 vNodes.push_back(pnode);
472 pnode->nTimeConnected = GetTime();
481 void CNode::CloseSocketDisconnect()
484 if (hSocket != INVALID_SOCKET)
486 printf("disconnecting node %s\n", addrName.c_str());
487 CloseSocket(hSocket);
491 // in case this fails, we'll empty the recv buffer when the CNode is deleted
492 TRY_LOCK(cs_vRecv, lockRecv);
496 // if this was the sync node, we'll need a new one
497 if (this == pnodeSync)
501 void CNode::Cleanup()
506 void CNode::PushVersion()
508 auto nTime = GetAdjustedTime();
509 CAddress addrYou, addrMe;
511 bool fHidden = false;
513 if (mapArgs.count("-torname")) {
514 // Our hidden service address
515 CService addrTorName(mapArgs["-torname"], GetListenPort());
517 if (addrTorName.IsValid()) {
519 addrMe = CAddress(addrTorName);
526 addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", nPortZero)));
527 addrMe = GetLocalAddress(&addr);
530 RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
531 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());
532 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
533 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, vector<string>()), nBestHeight);
540 map<CNetAddr, int64_t> CNode::setBanned;
541 CCriticalSection CNode::cs_setBanned;
543 void CNode::ClearBanned()
548 bool CNode::IsBanned(CNetAddr ip)
550 bool fResult = false;
553 auto i = setBanned.find(ip);
554 if (i != setBanned.end())
556 auto t = (*i).second;
564 bool CNode::Misbehaving(int howmuch)
568 printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
572 nMisbehavior += howmuch;
573 if (nMisbehavior >= GetArgInt("-banscore", 100))
575 auto banTime = GetTime()+GetArg("-bantime", nOneDay); // Default 24-hour ban
576 printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
579 if (setBanned[addr] < banTime)
580 setBanned[addr] = banTime;
582 CloseSocketDisconnect();
585 printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
590 #define X(name) stats.name = name
591 void CNode::copyStats(CNodeStats &stats)
606 stats.fSyncNode = (this == pnodeSync);
610 void Release(CNode* node) {
618 void ThreadSocketHandler(void* parg)
620 // Make this thread recognisable as the networking thread
621 RenameThread("novacoin-net");
625 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
626 ThreadSocketHandler2(parg);
627 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
629 catch (exception& e) {
630 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
631 PrintException(&e, "ThreadSocketHandler()");
633 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
634 throw; // support pthread_cancel()
636 printf("ThreadSocketHandler exited\n");
639 static list<CNode*> vNodesDisconnected;
641 void ThreadSocketHandler2(void* parg)
643 printf("ThreadSocketHandler started\n");
644 size_t nPrevNodeCount = 0;
652 // Disconnect unused nodes
653 vector<CNode*> vNodesCopy = vNodes;
654 for(CNode* pnode : vNodesCopy)
656 if (pnode->fDisconnect ||
657 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
659 // remove from vNodes
660 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
662 // release outbound grant (if any)
663 pnode->grantOutbound.Release();
665 // close socket and cleanup
666 pnode->CloseSocketDisconnect();
669 // hold in disconnected pool until all refs are released
670 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
671 if (pnode->fNetworkNode || pnode->fInbound)
673 vNodesDisconnected.push_back(pnode);
677 // Delete disconnected nodes
678 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
679 for(CNode* pnode : vNodesDisconnectedCopy)
681 // wait until threads are done using it
682 if (pnode->GetRefCount() <= 0)
684 bool fDelete = false;
686 TRY_LOCK(pnode->cs_vSend, lockSend);
689 TRY_LOCK(pnode->cs_vRecv, lockRecv);
692 TRY_LOCK(pnode->cs_mapRequests, lockReq);
695 TRY_LOCK(pnode->cs_inventory, lockInv);
704 vNodesDisconnected.remove(pnode);
710 if (vNodes.size() != nPrevNodeCount)
712 nPrevNodeCount = vNodes.size();
713 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
718 // Find which sockets have data to receive
720 struct timeval timeout;
722 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
729 FD_ZERO(&fdsetError);
730 SOCKET hSocketMax = 0;
731 bool have_fds = false;
733 for(SOCKET hListenSocket : vhListenSocket) {
734 FD_SET(hListenSocket, &fdsetRecv);
735 hSocketMax = max(hSocketMax, hListenSocket);
740 for(CNode* pnode : vNodes)
742 if (pnode->hSocket == INVALID_SOCKET)
744 FD_SET(pnode->hSocket, &fdsetRecv);
745 FD_SET(pnode->hSocket, &fdsetError);
746 hSocketMax = max(hSocketMax, pnode->hSocket);
749 TRY_LOCK(pnode->cs_vSend, lockSend);
750 if (lockSend && !pnode->vSend.empty())
751 FD_SET(pnode->hSocket, &fdsetSend);
756 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
757 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
758 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
759 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
762 if (nSelect == SOCKET_ERROR)
766 int nErr = WSAGetLastError();
767 printf("socket select error %d\n", nErr);
768 for (unsigned int i = 0; i <= hSocketMax; i++)
769 FD_SET(i, &fdsetRecv);
772 FD_ZERO(&fdsetError);
773 Sleep(timeout.tv_usec/1000);
778 // Accept new connections
780 for(SOCKET hListenSocket : vhListenSocket)
781 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
784 struct sockaddr_storage sockaddr;
786 struct sockaddr sockaddr;
788 socklen_t len = sizeof(sockaddr);
789 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
793 if (hSocket != INVALID_SOCKET)
794 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
795 printf("Warning: Unknown socket family\n");
799 for(CNode* pnode : vNodes)
804 if (hSocket == INVALID_SOCKET)
806 int nErr = WSAGetLastError();
807 if (nErr != WSAEWOULDBLOCK)
808 printf("socket error accept failed: %d\n", nErr);
810 else if (nInbound >= GetArgInt("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
813 LOCK(cs_setservAddNodeAddresses);
814 if (!setservAddNodeAddresses.count(addr))
815 CloseSocket(hSocket);
818 else if (CNode::IsBanned(addr))
820 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
821 CloseSocket(hSocket);
825 printf("accepted connection %s\n", addr.ToString().c_str());
826 CNode* pnode = new CNode(hSocket, addr, "", true);
830 vNodes.push_back(pnode);
837 // Service each socket
839 vector<CNode*> vNodesCopy;
843 for(CNode* pnode : vNodesCopy)
846 for(CNode* pnode : vNodesCopy)
854 if (pnode->hSocket == INVALID_SOCKET)
856 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
858 TRY_LOCK(pnode->cs_vRecv, lockRecv);
861 CDataStream& vRecv = pnode->vRecv;
862 uint64_t nPos = vRecv.size();
864 if (nPos > ReceiveBufferSize()) {
865 if (!pnode->fDisconnect)
866 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
867 pnode->CloseSocketDisconnect();
870 // typical socket buffer is 8K-64K
871 char pchBuf[0x10000];
872 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
875 vRecv.resize(nPos + nBytes);
876 memcpy(&vRecv[nPos], pchBuf, nBytes);
877 pnode->nLastRecv = GetTime();
878 pnode->nRecvBytes += nBytes;
879 pnode->RecordBytesRecv(nBytes);
881 else if (nBytes == 0)
883 // socket closed gracefully
884 if (!pnode->fDisconnect)
885 printf("socket closed\n");
886 pnode->CloseSocketDisconnect();
891 int nErr = WSAGetLastError();
892 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
894 if (!pnode->fDisconnect)
895 printf("socket recv error %d\n", nErr);
896 pnode->CloseSocketDisconnect();
906 if (pnode->hSocket == INVALID_SOCKET)
908 if (FD_ISSET(pnode->hSocket, &fdsetSend))
910 TRY_LOCK(pnode->cs_vSend, lockSend);
913 CDataStream& vSend = pnode->vSend;
916 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
919 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
920 pnode->nLastSend = GetTime();
921 pnode->nSendBytes += nBytes;
922 pnode->RecordBytesSent(nBytes);
927 int nErr = WSAGetLastError();
928 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
930 printf("socket send error %d\n", nErr);
931 pnode->CloseSocketDisconnect();
939 // Inactivity checking
941 if (pnode->vSend.empty())
942 pnode->nLastSendEmpty = GetTime();
943 if (GetTime() - pnode->nTimeConnected > 60)
945 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
947 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
948 pnode->fDisconnect = true;
950 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
952 printf("socket not sending\n");
953 pnode->fDisconnect = true;
955 else if (GetTime() - pnode->nLastRecv > 90*60)
957 printf("socket inactivity timeout\n");
958 pnode->fDisconnect = true;
964 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
971 void ThreadDNSAddressSeed(void* parg)
973 // Make this thread recognisable as the DNS seeding thread
974 RenameThread("novacoin-dnsseed");
978 vnThreadsRunning[THREAD_DNSSEED]++;
979 ThreadDNSAddressSeed2(parg);
980 vnThreadsRunning[THREAD_DNSSEED]--;
982 catch (exception& e) {
983 vnThreadsRunning[THREAD_DNSSEED]--;
984 PrintException(&e, "ThreadDNSAddressSeed()");
986 vnThreadsRunning[THREAD_DNSSEED]--;
987 throw; // support pthread_cancel()
989 printf("ThreadDNSAddressSeed exited\n");
992 void ThreadDNSAddressSeed2(void* parg)
994 printf("ThreadDNSAddressSeed started\n");
1000 // Each pair gives a source name and a seed name.
1001 // The first name is used as information source for addrman.
1002 // The second name should resolve to a list of seed addresses.
1003 static const vector<pair <string, string> > vstrDNSSeed = {
1004 { "novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro" },
1005 { "novacoin.ru", "dnsseed.novacoin.ru" },
1006 { "novacoin.ru", "testseed.novacoin.ru" },
1007 { "novaco.in", "dnsseed.novaco.in" },
1009 printf("Loading addresses from DNS seeds (could take a while)\n");
1011 for (unsigned int seed_idx = 0; seed_idx < vstrDNSSeed.size(); seed_idx++) {
1012 if (HaveNameProxy()) {
1013 AddOneShot(vstrDNSSeed[seed_idx].second);
1015 vector<CNetAddr> vaddr;
1016 vector<CAddress> vAdd;
1017 if (LookupHost(vstrDNSSeed[seed_idx].second, vaddr))
1019 for(CNetAddr& ip : vaddr)
1021 auto addr = CAddress(CService(ip, GetDefaultPort()));
1022 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1023 vAdd.push_back(addr);
1027 addrman.Add(vAdd, CNetAddr(vstrDNSSeed[seed_idx].first, true));
1032 printf("%d addresses found from DNS seeds\n", found);
1035 void DumpAddresses()
1037 auto nStart = GetTimeMillis();
1042 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1043 addrman.size(), GetTimeMillis() - nStart);
1046 void ThreadDumpAddress2(void* parg)
1048 printf("ThreadDumpAddress started\n");
1050 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1054 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1056 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1058 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1061 void ThreadDumpAddress(void* parg)
1063 // Make this thread recognisable as the address dumping thread
1064 RenameThread("novacoin-adrdump");
1068 ThreadDumpAddress2(parg);
1070 catch (exception& e) {
1071 PrintException(&e, "ThreadDumpAddress()");
1073 printf("ThreadDumpAddress exited\n");
1076 void ThreadOpenConnections(void* parg)
1078 // Make this thread recognisable as the connection opening thread
1079 RenameThread("novacoin-opencon");
1083 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1084 ThreadOpenConnections2(parg);
1085 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1087 catch (exception& e) {
1088 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1089 PrintException(&e, "ThreadOpenConnections()");
1091 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1092 PrintException(NULL, "ThreadOpenConnections()");
1094 printf("ThreadOpenConnections exited\n");
1097 void static ProcessOneShot()
1102 if (vOneShots.empty())
1104 strDest = vOneShots.front();
1105 vOneShots.pop_front();
1108 CSemaphoreGrant grant(*semOutbound, true);
1110 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1111 AddOneShot(strDest);
1115 void ThreadOpenConnections2(void* parg)
1117 printf("ThreadOpenConnections started\n");
1119 // Connect to specific addresses
1120 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1122 for (int64_t nLoop = 0;; nLoop++)
1125 for(string strAddr : mapMultiArgs["-connect"])
1128 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1129 for (int i = 0; i < 10 && i < nLoop; i++)
1140 // Initiate network connections
1141 auto nStart = GetTime();
1146 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1148 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1153 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1154 CSemaphoreGrant grant(*semOutbound);
1155 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1159 // Add seed nodes if IRC isn't working
1160 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1162 vector<uint32_t> vnSeed =
1164 0x1c542868, 0x3859dd6f, 0x203c2e68, 0xf145a6bc, 0x638a545f, 0x325da346, 0x385da346, 0xfb2b8d5f,
1165 0x52568c5f, 0xa979e65b, 0x8de6485d, 0x9f79e65b, 0x048a861f, 0x3388b55f, 0x6ff0b45e, 0x17e81f5f,
1166 0x6c47bb25, 0x1ecdc852, 0x28263db9, 0x47824e5d, 0x36f1c851, 0x2bf913b2, 0x95923cb3, 0x84e63eb2,
1167 0xefdeedbf, 0x65200092, 0xf36f6805, 0x42692d05, 0x772c1955, 0xb6bf1b4e, 0x7abb5f5d, 0xdb2fa6bc,
1168 0x90e911bf, 0x82de565f, 0x694416b2, 0x0ab600bc, 0xfcecbe6d, 0x24ed9fb2, 0x1bb618c2, 0xc64765bb,
1169 0x4e3d62c3, 0xdba24baa, 0x4b7109b0, 0x12a12cc2, 0xfc01864f, 0x0b69e85b, 0x33922c1f, 0xac611bc6,
1170 0x2a257155, 0x991d5fc0, 0xbfdabcb1, 0x9b73ee55, 0x5bc2b95d, 0xdef0762e, 0x6ab7c936, 0x9c4416b2,
1171 0xd60d864f, 0x03671f1f, 0x3b5da346, 0xc6f5c851, 0x5411b2d4, 0xe7c25702, 0x63474fb0, 0x7e11c854,
1172 0x52381d5f, 0x72fdfe59, 0x51599a05, 0xfb12b2d4, 0xaee4f15e, 0xd0e3f15e, 0x2aa2805f, 0xa1caf15e,
1173 0x34fe425e, 0x46e1f15e, 0xd7c71955, 0xaeeff15e, 0x47c2af55, 0x563d89b2, 0x67980fd9, 0xc9def15e,
1174 0x9cc51eb9, 0xdaa7aa6b, 0x78e6871f, 0x0d5d2cb2, 0x7aedf15e, 0x9bcaf15e, 0xe5f7f15e, 0x501c1759,
1175 0xdfbc4980, 0xa7397f2e, 0x31ea1a02, 0x3a27655e, 0xaa86f05c, 0xdcddf15e, 0x64689cb2, 0xd4bf62d4,
1176 0xf093eab2, 0x98def15e, 0xb6c5f15e, 0x81e8f15e, 0xe5d2fe59, 0xa312786d, 0x4cf9fe59, 0x8a922c1f,
1177 0x00c7fe59, 0x1ade565f, 0x9e4116b2, 0x2c36983e, 0x68f8f15e, 0x51b7eab2, 0x76c51eb9, 0x9edd4980,
1178 0x90ef565f, 0x0dd80857, 0xd513fb94, 0xf5bdeab2, 0xa95277b0, 0x2cf2f15e, 0x1897eab2, 0x924416b2,
1179 0x985c9b59, 0x30aa43d8, 0xf9c6745f, 0xaf862e5f, 0xe0ceeab2, 0xb9b3eab2, 0x6da4eab2, 0xa4fdeab2,
1180 0x0fa6c125, 0xe38bbd05, 0x5d922c1f, 0x9bd0eab2, 0x73025e02, 0xc4fd794d, 0x8435b35f, 0x2d01bc2e,
1181 0xaa2a14d4, 0xa22b07cb, 0xebda6f4f, 0xddc6514e, 0xf23feab2, 0xea1e5256, 0x6147b45e, 0x47d21e4f,
1182 0x67c41c1f, 0x53ec1a02, 0x352e786d, 0x6bec1a02, 0x78fb4abe, 0xd3014c5d, 0x9fbbeab2, 0x1fc51eb9,
1183 0x720eeab2, 0x2db5eab2, 0xe8baf65c, 0x521b459e, 0x65c4955f, 0x0e7b915f, 0xa8f37e6d, 0x6d0b465f,
1184 0xfab8ff5c, 0xf7c27e6d, 0x7345a846, 0x4fd1a7d5, 0xdfc97e6d, 0x26c27e6d, 0xa9de36b2, 0xc615344d,
1185 0x28ceb95d, 0xa52d895e, 0x18c17e6d, 0x13ec1a02, 0x0ba37125, 0x6c3d344d, 0xb3922c1f, 0x506bbeb0,
1186 0x4d04994e, 0xa1bbe56d, 0xf62c344d, 0x0847d048, 0x4bdc6451, 0xc95b9a05, 0xbcd3a7d5, 0x29b57125,
1187 0x0c4d2cb2, 0xf2b8eab2, 0xc2d5b95d, 0x0185ef59, 0x30adeab2, 0xcaf0e92e, 0x756c344d, 0xfd9e252e,
1188 0xbe5ef3bc, 0x4689344d, 0xb223895e, 0xfcebeaad, 0xb7c0e92e, 0x993c1760, 0xe1e171b0, 0xb857e75b,
1189 0xbf10002e, 0xb55b2cb2, 0xa90e2cb2, 0x13d6f15e, 0xf8be9225, 0x14ddf15e, 0x06e90305, 0x82472cb2,
1191 vector<CAddress> vAdd;
1192 for (unsigned int i = 0; i < vnSeed.size(); i++)
1194 // It'll only connect to one or two seed nodes because once it connects,
1195 // it'll get a pile of addresses with newer timestamps.
1196 // Seed nodes are given a random 'last seen time' of between one and two
1199 memcpy(&ip, &vnSeed[i], sizeof(ip));
1200 CAddress addr(CService(ip, GetDefaultPort()));
1201 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1202 vAdd.push_back(addr);
1204 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1207 // Add Tor nodes if we have connection with onion router
1208 if (mapArgs.count("-tor"))
1210 const vector<string> vstrTorSeed =
1212 "seedp4knqnoei57u.onion",
1213 "seedr3hhlepyi7fd.onion",
1214 "seed3uuomkclbiz4.onion",
1215 "seedeh7qck3ouff5.onion",
1216 "5rg3vq4jagckeckf.onion",
1217 "seedt3sraf53ajiy.onion",
1218 "seedg4qyccsg42oq.onion",
1219 "novaqrtoywpg7jly.onion",
1220 "seed3d5wolqbgrcb.onion",
1221 "seed24u5dwph3qw4.onion",
1222 "mj26ulzbs2oskgym.onion",
1223 "eqon4usunavt76m7.onion",
1224 "seedd3aldwpslzl3.onion"
1226 vector<CAddress> vAdd;
1227 for (unsigned int i = 0; i < vstrTorSeed.size(); i++)
1229 CAddress addr(CService(vstrTorSeed[i], GetDefaultPort()));
1230 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1231 vAdd.push_back(addr);
1233 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1237 // Choose an address to connect to based on most recently seen
1239 CAddress addrConnect;
1241 // Only connect out to one peer per network group (/16 for IPv4).
1242 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1244 set<vector<unsigned char> > setConnected;
1247 for(CNode* pnode : vNodes) {
1248 if (!pnode->fInbound) {
1249 setConnected.insert(pnode->addr.GetGroup());
1255 auto nANow = GetAdjustedTime();
1260 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1261 auto addr = addrman.Select(10 + min(nOutbound,8)*10);
1263 // if we selected an invalid address, restart
1264 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1267 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1268 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1269 // already-connected network ranges, ...) before trying new addrman addresses.
1274 if (IsLimited(addr))
1277 // only consider very recently tried nodes after 30 failed attempts
1278 if (nANow - addr.nLastTry < 600 && nTries < 30)
1281 // do not allow non-default ports, unless after 50 invalid addresses selected already
1282 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1289 if (addrConnect.IsValid())
1290 OpenNetworkConnection(addrConnect, &grant);
1294 void ThreadOpenAddedConnections(void* parg)
1296 // Make this thread recognisable as the connection opening thread
1297 RenameThread("novacoin-opencon");
1301 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1302 ThreadOpenAddedConnections2(parg);
1303 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1305 catch (exception& e) {
1306 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1307 PrintException(&e, "ThreadOpenAddedConnections()");
1309 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1310 PrintException(NULL, "ThreadOpenAddedConnections()");
1312 printf("ThreadOpenAddedConnections exited\n");
1315 void ThreadOpenAddedConnections2(void* parg)
1317 printf("ThreadOpenAddedConnections started\n");
1320 LOCK(cs_vAddedNodes);
1321 vAddedNodes = mapMultiArgs["-addnode"];
1324 if (HaveNameProxy()) {
1326 list<string> lAddresses(0);
1328 LOCK(cs_vAddedNodes);
1329 for(string& strAddNode : vAddedNodes)
1330 lAddresses.push_back(strAddNode);
1332 for(string& strAddNode : lAddresses) {
1334 CSemaphoreGrant grant(*semOutbound);
1335 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1338 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1339 Sleep(120000); // Retry every 2 minutes
1340 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1345 for (uint32_t i = 0; true; i++)
1347 list<string> lAddresses(0);
1349 LOCK(cs_vAddedNodes);
1350 for(string& strAddNode : vAddedNodes)
1351 lAddresses.push_back(strAddNode);
1354 list<vector<CService> > lservAddressesToAdd(0);
1355 for(string& strAddNode : lAddresses)
1357 vector<CService> vservNode(0);
1358 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1360 lservAddressesToAdd.push_back(vservNode);
1362 LOCK(cs_setservAddNodeAddresses);
1363 for(CService& serv : vservNode)
1364 setservAddNodeAddresses.insert(serv);
1368 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1369 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1372 for(CNode* pnode : vNodes)
1373 for (auto it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1375 for(CService& addrNode : *(it))
1376 if (pnode->addr == addrNode)
1378 it = lservAddressesToAdd.erase(it);
1379 if(it != lservAddressesToAdd.begin())
1383 if (it == lservAddressesToAdd.end())
1387 for(vector<CService>& vserv : lservAddressesToAdd)
1389 if (vserv.size() == 0)
1391 CSemaphoreGrant grant(*semOutbound);
1392 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1399 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1400 Sleep(120000); // Retry every 2 minutes
1401 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1407 // if successful, this moves the passed grant to the constructed node
1408 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1411 // Initiate outbound network connection
1416 if (IsLocal(addrConnect) ||
1417 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1418 FindNode(addrConnect.ToStringIPPort().c_str()))
1420 if (strDest && FindNode(strDest))
1423 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1424 CNode* pnode = ConnectNode(addrConnect, strDest);
1425 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1431 grantOutbound->MoveTo(pnode->grantOutbound);
1432 pnode->fNetworkNode = true;
1434 pnode->fOneShot = true;
1439 // for now, use a very simple selection metric: the node from which we received
1441 static int64_t NodeSyncScore(const CNode *pnode) {
1442 return pnode->nLastRecv;
1445 void static StartSync(const vector<CNode*> &vNodes) {
1446 CNode *pnodeNewSync = NULL;
1447 int64_t nBestScore = 0;
1449 // Iterate over all nodes
1450 for(CNode* pnode : vNodes) {
1451 // check preconditions for allowing a sync
1452 if (!pnode->fClient && !pnode->fOneShot &&
1453 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1454 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1455 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1456 // if ok, compare node's score with the best so far
1457 int64_t nScore = NodeSyncScore(pnode);
1458 if (pnodeNewSync == NULL || nScore > nBestScore) {
1459 pnodeNewSync = pnode;
1460 nBestScore = nScore;
1464 // if a new sync candidate was found, start sync!
1466 pnodeNewSync->fStartSync = true;
1467 pnodeSync = pnodeNewSync;
1471 void ThreadMessageHandler(void* parg)
1473 // Make this thread recognisable as the message handling thread
1474 RenameThread("novacoin-msghand");
1478 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1479 ThreadMessageHandler2(parg);
1480 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1482 catch (exception& e) {
1483 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1484 PrintException(&e, "ThreadMessageHandler()");
1486 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1487 PrintException(NULL, "ThreadMessageHandler()");
1489 printf("ThreadMessageHandler exited\n");
1492 void ThreadMessageHandler2(void* parg)
1494 printf("ThreadMessageHandler started\n");
1495 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1498 bool fHaveSyncNode = false;
1499 vector<CNode*> vNodesCopy;
1502 vNodesCopy = vNodes;
1503 for(CNode* pnode : vNodesCopy) {
1505 if (pnode == pnodeSync)
1506 fHaveSyncNode = true;
1511 StartSync(vNodesCopy);
1513 // Poll the connected nodes for messages
1514 for(CNode* pnode : vNodesCopy)
1518 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1520 ProcessMessages(pnode);
1527 TRY_LOCK(pnode->cs_vSend, lockSend);
1529 SendMessages(pnode);
1537 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
1540 // Wait and allow messages to bunch up.
1541 // Reduce vnThreadsRunning so StopNode has permission to exit while
1542 // we're sleeping, but we must always check fShutdown after doing this.
1543 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1545 if (fRequestShutdown)
1547 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1558 bool BindListenPort(const CService &addrBind, string& strError)
1563 // Create socket for listening for incoming connections
1565 struct sockaddr_storage sockaddr;
1567 struct sockaddr sockaddr;
1569 socklen_t len = sizeof(sockaddr);
1570 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1572 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1573 printf("%s\n", strError.c_str());
1577 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1578 if (hListenSocket == INVALID_SOCKET)
1580 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1581 printf("%s\n", strError.c_str());
1587 // Different way of disabling SIGPIPE on BSD
1588 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1590 // Allow binding if the port is still in TIME_WAIT state after
1591 // the program was closed and restarted. Not an issue on windows!
1592 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1596 // Set to non-blocking, incoming connections will also inherit this
1597 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1599 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1602 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1603 printf("%s\n", strError.c_str());
1608 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1609 // and enable it by default or not. Try to enable it, if possible.
1610 if (addrBind.IsIPv6()) {
1613 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1615 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1619 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1620 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
1625 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1627 int nErr = WSAGetLastError();
1628 if (nErr == WSAEADDRINUSE)
1629 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1631 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1632 printf("%s\n", strError.c_str());
1633 CloseSocket(hListenSocket);
1636 printf("Bound to %s\n", addrBind.ToString().c_str());
1638 // Listen for incoming connections
1639 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1641 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1642 printf("%s\n", strError.c_str());
1643 CloseSocket(hListenSocket);
1647 vhListenSocket.push_back(hListenSocket);
1649 if (addrBind.IsRoutable() && fDiscover)
1650 AddLocal(addrBind, LOCAL_BIND);
1655 void static Discover()
1661 // Get local host IP
1662 char pszHostName[1000] = "";
1663 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1665 vector<CNetAddr> vaddr;
1666 if (LookupHost(pszHostName, vaddr))
1668 for(const auto &addr : vaddr)
1670 AddLocal(addr, LOCAL_IF);
1675 // Get local host ip
1676 struct ifaddrs* myaddrs;
1677 if (getifaddrs(&myaddrs) == 0)
1679 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1681 if (ifa->ifa_addr == NULL) continue;
1682 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1683 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1684 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1685 if (ifa->ifa_addr->sa_family == AF_INET)
1687 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1688 CNetAddr addr(s4->sin_addr);
1689 if (AddLocal(addr, LOCAL_IF))
1690 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1693 else if (ifa->ifa_addr->sa_family == AF_INET6)
1695 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1696 CNetAddr addr(s6->sin6_addr);
1697 if (AddLocal(addr, LOCAL_IF))
1698 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1702 freeifaddrs(myaddrs);
1706 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1707 if (!IsLimited(NET_IPV4))
1708 NewThread(ThreadGetMyExternalIP, NULL);
1711 void StartNode(void* parg)
1713 // Make this thread recognisable as the startup thread
1714 RenameThread("novacoin-start");
1716 if (semOutbound == NULL) {
1717 // initialize semaphore
1718 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1719 semOutbound = new CSemaphore(nMaxOutbound);
1722 if (pnodeLocalHost == NULL)
1723 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1731 if (!GetBoolArg("-dnsseed", true))
1732 printf("DNS seeding disabled\n");
1734 if (!NewThread(ThreadDNSAddressSeed, NULL))
1735 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1737 // Get addresses from IRC and advertise ours
1738 if (!GetBoolArg("-irc", true))
1739 printf("IRC seeding disabled\n");
1741 if (!NewThread(ThreadIRCSeed, NULL))
1742 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1744 // Send and receive from sockets, accept connections
1745 if (!NewThread(ThreadSocketHandler, NULL))
1746 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1748 // Initiate outbound connections from -addnode
1749 if (!NewThread(ThreadOpenAddedConnections, NULL))
1750 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1752 // Initiate outbound connections
1753 if (!NewThread(ThreadOpenConnections, NULL))
1754 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1757 if (!NewThread(ThreadMessageHandler, NULL))
1758 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1760 // Dump network addresses
1761 if (!NewThread(ThreadDumpAddress, NULL))
1762 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1764 // Mine proof-of-stake blocks in the background
1765 if (!NewThread(ThreadStakeMiner, pwalletMain))
1766 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1768 // Trusted NTP server, it's localhost by default.
1769 strTrustedUpstream = GetArg("-ntp", "localhost");
1771 // Start periodical NTP sampling thread
1772 NewThread(ThreadNtpSamples, NULL);
1778 printf("StopNode()\n");
1780 nTransactionsUpdated++;
1781 auto nStart = GetTime();
1784 ThreadScriptCheckQuit();
1787 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1788 semOutbound->post();
1791 int nThreadsRunning = 0;
1792 for (int n = 0; n < THREAD_MAX; n++)
1793 nThreadsRunning += vnThreadsRunning[n];
1794 if (nThreadsRunning == 0)
1796 if (GetTime() - nStart > 20)
1800 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1801 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1802 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1803 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1804 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1805 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1806 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1807 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1808 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1809 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1810 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1827 for(CNode* pnode : vNodes)
1828 if (pnode->hSocket != INVALID_SOCKET)
1829 CloseSocket(pnode->hSocket);
1830 for(SOCKET hListenSocket : vhListenSocket)
1831 if (hListenSocket != INVALID_SOCKET)
1832 if (!CloseSocket(hListenSocket))
1833 printf("CloseSocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1835 // clean up some globals (to help leak detection)
1836 for(CNode *pnode : vNodes)
1838 for(CNode *pnode : vNodesDisconnected)
1841 vNodesDisconnected.clear();
1844 delete pnodeLocalHost;
1845 pnodeLocalHost = NULL;
1848 // Shutdown Windows Sockets
1853 instance_of_cnetcleanup;
1855 void RelayTransaction(const CTransaction& tx, const uint256& hash)
1857 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1860 RelayTransaction(tx, hash, ss);
1863 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
1865 CInv inv(MSG_TX, hash);
1868 // Expire old relay messages
1869 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1871 mapRelay.erase(vRelayExpiration.front().second);
1872 vRelayExpiration.pop_front();
1875 // Save original serialized message so newer versions are preserved
1876 mapRelay.insert({inv, ss});
1877 vRelayExpiration.push_back({GetTime() + 15 * 60, inv});
1880 RelayInventory(inv);
1883 void CNode::RecordBytesRecv(uint64_t bytes)
1885 LOCK(cs_totalBytesRecv);
1886 nTotalBytesRecv += bytes;
1889 void CNode::RecordBytesSent(uint64_t bytes)
1891 LOCK(cs_totalBytesSent);
1892 nTotalBytesSent += bytes;
1895 uint64_t CNode::GetTotalBytesRecv()
1897 LOCK(cs_totalBytesRecv);
1898 return nTotalBytesRecv;
1901 uint64_t CNode::GetTotalBytesSent()
1903 LOCK(cs_totalBytesSent);
1904 return nTotalBytesSent;
1906 int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) {
1907 return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);