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 "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 std::array<int, THREAD_MAX> vnThreadsRunning;
60 static std::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<std::string> vAddedNodes;
77 CCriticalSection cs_vAddedNodes;
79 static CSemaphore *semOutbound = NULL;
81 void AddOneShot(string strDest)
84 vOneShots.push_back(strDest);
87 unsigned short GetListenPort()
89 return (unsigned short)(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 (map<CNetAddr, LocalServiceInfo>::iterator 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 CAddress 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 CAddress 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 uint64_t rnd = std::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(std::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 int64_t 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, std::vector<string>()), nBestHeight);
540 std::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 std::map<CNetAddr, int64_t>::iterator i = setBanned.find(ip);
554 if (i != setBanned.end())
556 int64_t 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 int64_t 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 (std::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);
972 // Each pair gives a source name and a seed name.
973 // The first name is used as information source for addrman.
974 // The second name should resolve to a list of seed addresses.
975 static const char *strDNSSeed[][2] = {
976 {"node.novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro"},
977 {"novacoin.ru", "dnsseed.novacoin.ru"},
978 {"novacoin.ru", "testseed.novacoin.ru"},
979 {"novaco.in", "dnsseed.novaco.in"},
982 void ThreadDNSAddressSeed(void* parg)
984 // Make this thread recognisable as the DNS seeding thread
985 RenameThread("novacoin-dnsseed");
989 vnThreadsRunning[THREAD_DNSSEED]++;
990 ThreadDNSAddressSeed2(parg);
991 vnThreadsRunning[THREAD_DNSSEED]--;
993 catch (std::exception& e) {
994 vnThreadsRunning[THREAD_DNSSEED]--;
995 PrintException(&e, "ThreadDNSAddressSeed()");
997 vnThreadsRunning[THREAD_DNSSEED]--;
998 throw; // support pthread_cancel()
1000 printf("ThreadDNSAddressSeed exited\n");
1003 void ThreadDNSAddressSeed2(void* parg)
1005 printf("ThreadDNSAddressSeed started\n");
1010 printf("Loading addresses from DNS seeds (could take a while)\n");
1012 for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1013 if (HaveNameProxy()) {
1014 AddOneShot(strDNSSeed[seed_idx][1]);
1016 vector<CNetAddr> vaddr;
1017 vector<CAddress> vAdd;
1018 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
1020 for (CNetAddr& ip : vaddr)
1022 CAddress 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(strDNSSeed[seed_idx][0], true));
1033 printf("%d addresses found from DNS seeds\n", found);
1049 0x1c542868, 0x3859dd6f, 0x203c2e68, 0xf145a6bc, 0x638a545f, 0x325da346, 0x385da346, 0xfb2b8d5f,
1050 0x52568c5f, 0xa979e65b, 0x8de6485d, 0x9f79e65b, 0x048a861f, 0x3388b55f, 0x6ff0b45e, 0x17e81f5f,
1051 0x6c47bb25, 0x1ecdc852, 0x28263db9, 0x47824e5d, 0x36f1c851, 0x2bf913b2, 0x95923cb3, 0x84e63eb2,
1052 0xefdeedbf, 0x65200092, 0xf36f6805, 0x42692d05, 0x772c1955, 0xb6bf1b4e, 0x7abb5f5d, 0xdb2fa6bc,
1053 0x90e911bf, 0x82de565f, 0x694416b2, 0x0ab600bc, 0xfcecbe6d, 0x24ed9fb2, 0x1bb618c2, 0xc64765bb,
1054 0x4e3d62c3, 0xdba24baa, 0x4b7109b0, 0x12a12cc2, 0xfc01864f, 0x0b69e85b, 0x33922c1f, 0xac611bc6,
1055 0x2a257155, 0x991d5fc0, 0xbfdabcb1, 0x9b73ee55, 0x5bc2b95d, 0xdef0762e, 0x6ab7c936, 0x9c4416b2,
1056 0xd60d864f, 0x03671f1f, 0x3b5da346, 0xc6f5c851, 0x5411b2d4, 0xe7c25702, 0x63474fb0, 0x7e11c854,
1057 0x52381d5f, 0x72fdfe59, 0x51599a05, 0xfb12b2d4, 0xaee4f15e, 0xd0e3f15e, 0x2aa2805f, 0xa1caf15e,
1058 0x34fe425e, 0x46e1f15e, 0xd7c71955, 0xaeeff15e, 0x47c2af55, 0x563d89b2, 0x67980fd9, 0xc9def15e,
1059 0x9cc51eb9, 0xdaa7aa6b, 0x78e6871f, 0x0d5d2cb2, 0x7aedf15e, 0x9bcaf15e, 0xe5f7f15e, 0x501c1759,
1060 0xdfbc4980, 0xa7397f2e, 0x31ea1a02, 0x3a27655e, 0xaa86f05c, 0xdcddf15e, 0x64689cb2, 0xd4bf62d4,
1061 0xf093eab2, 0x98def15e, 0xb6c5f15e, 0x81e8f15e, 0xe5d2fe59, 0xa312786d, 0x4cf9fe59, 0x8a922c1f,
1062 0x00c7fe59, 0x1ade565f, 0x9e4116b2, 0x2c36983e, 0x68f8f15e, 0x51b7eab2, 0x76c51eb9, 0x9edd4980,
1063 0x90ef565f, 0x0dd80857, 0xd513fb94, 0xf5bdeab2, 0xa95277b0, 0x2cf2f15e, 0x1897eab2, 0x924416b2,
1064 0x985c9b59, 0x30aa43d8, 0xf9c6745f, 0xaf862e5f, 0xe0ceeab2, 0xb9b3eab2, 0x6da4eab2, 0xa4fdeab2,
1065 0x0fa6c125, 0xe38bbd05, 0x5d922c1f, 0x9bd0eab2, 0x73025e02, 0xc4fd794d, 0x8435b35f, 0x2d01bc2e,
1066 0xaa2a14d4, 0xa22b07cb, 0xebda6f4f, 0xddc6514e, 0xf23feab2, 0xea1e5256, 0x6147b45e, 0x47d21e4f,
1067 0x67c41c1f, 0x53ec1a02, 0x352e786d, 0x6bec1a02, 0x78fb4abe, 0xd3014c5d, 0x9fbbeab2, 0x1fc51eb9,
1068 0x720eeab2, 0x2db5eab2, 0xe8baf65c, 0x521b459e, 0x65c4955f, 0x0e7b915f, 0xa8f37e6d, 0x6d0b465f,
1069 0xfab8ff5c, 0xf7c27e6d, 0x7345a846, 0x4fd1a7d5, 0xdfc97e6d, 0x26c27e6d, 0xa9de36b2, 0xc615344d,
1070 0x28ceb95d, 0xa52d895e, 0x18c17e6d, 0x13ec1a02, 0x0ba37125, 0x6c3d344d, 0xb3922c1f, 0x506bbeb0,
1071 0x4d04994e, 0xa1bbe56d, 0xf62c344d, 0x0847d048, 0x4bdc6451, 0xc95b9a05, 0xbcd3a7d5, 0x29b57125,
1072 0x0c4d2cb2, 0xf2b8eab2, 0xc2d5b95d, 0x0185ef59, 0x30adeab2, 0xcaf0e92e, 0x756c344d, 0xfd9e252e,
1073 0xbe5ef3bc, 0x4689344d, 0xb223895e, 0xfcebeaad, 0xb7c0e92e, 0x993c1760, 0xe1e171b0, 0xb857e75b,
1074 0xbf10002e, 0xb55b2cb2, 0xa90e2cb2, 0x13d6f15e, 0xf8be9225, 0x14ddf15e, 0x06e90305, 0x82472cb2,
1077 const char* pchTorSeed[] =
1079 "seedp4knqnoei57u.onion",
1080 "seedr3hhlepyi7fd.onion",
1081 "seed3uuomkclbiz4.onion",
1082 "seedeh7qck3ouff5.onion",
1083 "5rg3vq4jagckeckf.onion",
1084 "seedt3sraf53ajiy.onion",
1085 "seedg4qyccsg42oq.onion",
1086 "novaqrtoywpg7jly.onion",
1087 "seed3d5wolqbgrcb.onion",
1088 "seed24u5dwph3qw4.onion",
1089 "mj26ulzbs2oskgym.onion",
1090 "eqon4usunavt76m7.onion",
1091 "seedd3aldwpslzl3.onion"
1094 void DumpAddresses()
1096 int64_t nStart = GetTimeMillis();
1101 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1102 addrman.size(), GetTimeMillis() - nStart);
1105 void ThreadDumpAddress2(void* parg)
1107 printf("ThreadDumpAddress started\n");
1109 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1113 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1115 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1117 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1120 void ThreadDumpAddress(void* parg)
1122 // Make this thread recognisable as the address dumping thread
1123 RenameThread("novacoin-adrdump");
1127 ThreadDumpAddress2(parg);
1129 catch (std::exception& e) {
1130 PrintException(&e, "ThreadDumpAddress()");
1132 printf("ThreadDumpAddress exited\n");
1135 void ThreadOpenConnections(void* parg)
1137 // Make this thread recognisable as the connection opening thread
1138 RenameThread("novacoin-opencon");
1142 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1143 ThreadOpenConnections2(parg);
1144 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1146 catch (std::exception& e) {
1147 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1148 PrintException(&e, "ThreadOpenConnections()");
1150 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1151 PrintException(NULL, "ThreadOpenConnections()");
1153 printf("ThreadOpenConnections exited\n");
1156 void static ProcessOneShot()
1161 if (vOneShots.empty())
1163 strDest = vOneShots.front();
1164 vOneShots.pop_front();
1167 CSemaphoreGrant grant(*semOutbound, true);
1169 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1170 AddOneShot(strDest);
1174 void ThreadOpenConnections2(void* parg)
1176 printf("ThreadOpenConnections started\n");
1178 // Connect to specific addresses
1179 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1181 for (int64_t nLoop = 0;; nLoop++)
1184 for (string strAddr : mapMultiArgs["-connect"])
1187 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1188 for (int i = 0; i < 10 && i < nLoop; i++)
1199 // Initiate network connections
1200 int64_t nStart = GetTime();
1205 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1207 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1212 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1213 CSemaphoreGrant grant(*semOutbound);
1214 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1218 // Add seed nodes if IRC isn't working
1219 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1221 std::vector<CAddress> vAdd;
1222 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1224 // It'll only connect to one or two seed nodes because once it connects,
1225 // it'll get a pile of addresses with newer timestamps.
1226 // Seed nodes are given a random 'last seen time' of between one and two
1229 memcpy(&ip, &pnSeed[i], sizeof(ip));
1230 CAddress addr(CService(ip, GetDefaultPort()));
1231 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1232 vAdd.push_back(addr);
1234 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1237 // Add Tor nodes if we have connection with onion router
1238 if (mapArgs.count("-tor"))
1240 std::vector<CAddress> vAdd;
1241 for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1243 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1244 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1245 vAdd.push_back(addr);
1247 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1251 // Choose an address to connect to based on most recently seen
1253 CAddress addrConnect;
1255 // Only connect out to one peer per network group (/16 for IPv4).
1256 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1258 set<vector<unsigned char> > setConnected;
1261 for (CNode* pnode : vNodes) {
1262 if (!pnode->fInbound) {
1263 setConnected.insert(pnode->addr.GetGroup());
1269 int64_t nANow = GetAdjustedTime();
1274 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1275 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1277 // if we selected an invalid address, restart
1278 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1281 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1282 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1283 // already-connected network ranges, ...) before trying new addrman addresses.
1288 if (IsLimited(addr))
1291 // only consider very recently tried nodes after 30 failed attempts
1292 if (nANow - addr.nLastTry < 600 && nTries < 30)
1295 // do not allow non-default ports, unless after 50 invalid addresses selected already
1296 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1303 if (addrConnect.IsValid())
1304 OpenNetworkConnection(addrConnect, &grant);
1308 void ThreadOpenAddedConnections(void* parg)
1310 // Make this thread recognisable as the connection opening thread
1311 RenameThread("novacoin-opencon");
1315 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1316 ThreadOpenAddedConnections2(parg);
1317 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1319 catch (std::exception& e) {
1320 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1321 PrintException(&e, "ThreadOpenAddedConnections()");
1323 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1324 PrintException(NULL, "ThreadOpenAddedConnections()");
1326 printf("ThreadOpenAddedConnections exited\n");
1329 void ThreadOpenAddedConnections2(void* parg)
1331 printf("ThreadOpenAddedConnections started\n");
1334 LOCK(cs_vAddedNodes);
1335 vAddedNodes = mapMultiArgs["-addnode"];
1338 if (HaveNameProxy()) {
1340 list<string> lAddresses(0);
1342 LOCK(cs_vAddedNodes);
1343 for (string& strAddNode : vAddedNodes)
1344 lAddresses.push_back(strAddNode);
1346 for (string& strAddNode : lAddresses) {
1348 CSemaphoreGrant grant(*semOutbound);
1349 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1352 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1353 Sleep(120000); // Retry every 2 minutes
1354 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1359 for (uint32_t i = 0; true; i++)
1361 list<string> lAddresses(0);
1363 LOCK(cs_vAddedNodes);
1364 for (string& strAddNode : vAddedNodes)
1365 lAddresses.push_back(strAddNode);
1368 list<vector<CService> > lservAddressesToAdd(0);
1369 for (string& strAddNode : lAddresses)
1371 vector<CService> vservNode(0);
1372 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1374 lservAddressesToAdd.push_back(vservNode);
1376 LOCK(cs_setservAddNodeAddresses);
1377 for (CService& serv : vservNode)
1378 setservAddNodeAddresses.insert(serv);
1382 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1383 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1386 for (CNode* pnode : vNodes)
1387 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1389 for (CService& addrNode : *(it))
1390 if (pnode->addr == addrNode)
1392 it = lservAddressesToAdd.erase(it);
1393 if(it != lservAddressesToAdd.begin())
1397 if (it == lservAddressesToAdd.end())
1401 for (vector<CService>& vserv : lservAddressesToAdd)
1403 if (vserv.size() == 0)
1405 CSemaphoreGrant grant(*semOutbound);
1406 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1413 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1414 Sleep(120000); // Retry every 2 minutes
1415 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1421 // if successful, this moves the passed grant to the constructed node
1422 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1425 // Initiate outbound network connection
1430 if (IsLocal(addrConnect) ||
1431 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1432 FindNode(addrConnect.ToStringIPPort().c_str()))
1434 if (strDest && FindNode(strDest))
1437 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1438 CNode* pnode = ConnectNode(addrConnect, strDest);
1439 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1445 grantOutbound->MoveTo(pnode->grantOutbound);
1446 pnode->fNetworkNode = true;
1448 pnode->fOneShot = true;
1453 // for now, use a very simple selection metric: the node from which we received
1455 static int64_t NodeSyncScore(const CNode *pnode) {
1456 return pnode->nLastRecv;
1459 void static StartSync(const vector<CNode*> &vNodes) {
1460 CNode *pnodeNewSync = NULL;
1461 int64_t nBestScore = 0;
1463 // Iterate over all nodes
1464 for (CNode* pnode : vNodes) {
1465 // check preconditions for allowing a sync
1466 if (!pnode->fClient && !pnode->fOneShot &&
1467 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1468 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1469 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1470 // if ok, compare node's score with the best so far
1471 int64_t nScore = NodeSyncScore(pnode);
1472 if (pnodeNewSync == NULL || nScore > nBestScore) {
1473 pnodeNewSync = pnode;
1474 nBestScore = nScore;
1478 // if a new sync candidate was found, start sync!
1480 pnodeNewSync->fStartSync = true;
1481 pnodeSync = pnodeNewSync;
1485 void ThreadMessageHandler(void* parg)
1487 // Make this thread recognisable as the message handling thread
1488 RenameThread("novacoin-msghand");
1492 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1493 ThreadMessageHandler2(parg);
1494 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1496 catch (std::exception& e) {
1497 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1498 PrintException(&e, "ThreadMessageHandler()");
1500 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1501 PrintException(NULL, "ThreadMessageHandler()");
1503 printf("ThreadMessageHandler exited\n");
1506 void ThreadMessageHandler2(void* parg)
1508 printf("ThreadMessageHandler started\n");
1509 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1512 bool fHaveSyncNode = false;
1513 vector<CNode*> vNodesCopy;
1516 vNodesCopy = vNodes;
1517 for (CNode* pnode : vNodesCopy) {
1519 if (pnode == pnodeSync)
1520 fHaveSyncNode = true;
1525 StartSync(vNodesCopy);
1527 // Poll the connected nodes for messages
1528 for (CNode* pnode : vNodesCopy)
1532 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1534 if (!ProcessMessages(pnode)) {
1535 pnode->CloseSocketDisconnect();
1536 if (pnode == pnodeSync)
1537 fHaveSyncNode = false;
1546 TRY_LOCK(pnode->cs_vSend, lockSend);
1548 SendMessages(pnode);
1556 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
1559 // Wait and allow messages to bunch up.
1560 // Reduce vnThreadsRunning so StopNode has permission to exit while
1561 // we're sleeping, but we must always check fShutdown after doing this.
1562 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1564 if (fRequestShutdown)
1566 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1577 bool BindListenPort(const CService &addrBind, string& strError)
1582 // Create socket for listening for incoming connections
1584 struct sockaddr_storage sockaddr;
1586 struct sockaddr sockaddr;
1588 socklen_t len = sizeof(sockaddr);
1589 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1591 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1592 printf("%s\n", strError.c_str());
1596 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1597 if (hListenSocket == INVALID_SOCKET)
1599 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1600 printf("%s\n", strError.c_str());
1606 // Different way of disabling SIGPIPE on BSD
1607 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1609 // Allow binding if the port is still in TIME_WAIT state after
1610 // the program was closed and restarted. Not an issue on windows!
1611 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1615 // Set to non-blocking, incoming connections will also inherit this
1616 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1618 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1621 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1622 printf("%s\n", strError.c_str());
1627 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1628 // and enable it by default or not. Try to enable it, if possible.
1629 if (addrBind.IsIPv6()) {
1632 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1634 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1638 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1639 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
1644 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1646 int nErr = WSAGetLastError();
1647 if (nErr == WSAEADDRINUSE)
1648 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1650 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1651 printf("%s\n", strError.c_str());
1652 CloseSocket(hListenSocket);
1655 printf("Bound to %s\n", addrBind.ToString().c_str());
1657 // Listen for incoming connections
1658 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1660 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1661 printf("%s\n", strError.c_str());
1662 CloseSocket(hListenSocket);
1666 vhListenSocket.push_back(hListenSocket);
1668 if (addrBind.IsRoutable() && fDiscover)
1669 AddLocal(addrBind, LOCAL_BIND);
1674 void static Discover()
1680 // Get local host IP
1681 char pszHostName[1000] = "";
1682 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1684 vector<CNetAddr> vaddr;
1685 if (LookupHost(pszHostName, vaddr))
1687 for (const CNetAddr &addr : vaddr)
1689 AddLocal(addr, LOCAL_IF);
1694 // Get local host ip
1695 struct ifaddrs* myaddrs;
1696 if (getifaddrs(&myaddrs) == 0)
1698 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1700 if (ifa->ifa_addr == NULL) continue;
1701 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1702 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1703 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1704 if (ifa->ifa_addr->sa_family == AF_INET)
1706 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1707 CNetAddr addr(s4->sin_addr);
1708 if (AddLocal(addr, LOCAL_IF))
1709 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1712 else if (ifa->ifa_addr->sa_family == AF_INET6)
1714 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1715 CNetAddr addr(s6->sin6_addr);
1716 if (AddLocal(addr, LOCAL_IF))
1717 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1721 freeifaddrs(myaddrs);
1725 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1726 if (!IsLimited(NET_IPV4))
1727 NewThread(ThreadGetMyExternalIP, NULL);
1730 void StartNode(void* parg)
1732 // Make this thread recognisable as the startup thread
1733 RenameThread("novacoin-start");
1735 if (semOutbound == NULL) {
1736 // initialize semaphore
1737 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1738 semOutbound = new CSemaphore(nMaxOutbound);
1741 if (pnodeLocalHost == NULL)
1742 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1750 if (!GetBoolArg("-dnsseed", true))
1751 printf("DNS seeding disabled\n");
1753 if (!NewThread(ThreadDNSAddressSeed, NULL))
1754 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1756 // Get addresses from IRC and advertise ours
1757 if (!GetBoolArg("-irc", true))
1758 printf("IRC seeding disabled\n");
1760 if (!NewThread(ThreadIRCSeed, NULL))
1761 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1763 // Send and receive from sockets, accept connections
1764 if (!NewThread(ThreadSocketHandler, NULL))
1765 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1767 // Initiate outbound connections from -addnode
1768 if (!NewThread(ThreadOpenAddedConnections, NULL))
1769 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1771 // Initiate outbound connections
1772 if (!NewThread(ThreadOpenConnections, NULL))
1773 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1776 if (!NewThread(ThreadMessageHandler, NULL))
1777 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1779 // Dump network addresses
1780 if (!NewThread(ThreadDumpAddress, NULL))
1781 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1783 // Mine proof-of-stake blocks in the background
1784 if (!NewThread(ThreadStakeMiner, pwalletMain))
1785 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1787 // Trusted NTP server, it's localhost by default.
1788 strTrustedUpstream = GetArg("-ntp", "localhost");
1790 // Start periodical NTP sampling thread
1791 NewThread(ThreadNtpSamples, NULL);
1797 printf("StopNode()\n");
1799 nTransactionsUpdated++;
1800 int64_t nStart = GetTime();
1803 ThreadScriptCheckQuit();
1806 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1807 semOutbound->post();
1810 int nThreadsRunning = 0;
1811 for (int n = 0; n < THREAD_MAX; n++)
1812 nThreadsRunning += vnThreadsRunning[n];
1813 if (nThreadsRunning == 0)
1815 if (GetTime() - nStart > 20)
1819 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1820 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1821 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1822 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1823 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1824 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1825 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1826 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1827 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1828 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1829 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1846 for (CNode* pnode : vNodes)
1847 if (pnode->hSocket != INVALID_SOCKET)
1848 CloseSocket(pnode->hSocket);
1849 for (SOCKET hListenSocket : vhListenSocket)
1850 if (hListenSocket != INVALID_SOCKET)
1851 if (!CloseSocket(hListenSocket))
1852 printf("CloseSocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1854 // clean up some globals (to help leak detection)
1855 for (CNode *pnode : vNodes)
1857 for (CNode *pnode : vNodesDisconnected)
1860 vNodesDisconnected.clear();
1863 delete pnodeLocalHost;
1864 pnodeLocalHost = NULL;
1867 // Shutdown Windows Sockets
1872 instance_of_cnetcleanup;
1874 void RelayTransaction(const CTransaction& tx, const uint256& hash)
1876 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1879 RelayTransaction(tx, hash, ss);
1882 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
1884 CInv inv(MSG_TX, hash);
1887 // Expire old relay messages
1888 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1890 mapRelay.erase(vRelayExpiration.front().second);
1891 vRelayExpiration.pop_front();
1894 // Save original serialized message so newer versions are preserved
1895 mapRelay.insert(std::make_pair(inv, ss));
1896 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
1899 RelayInventory(inv);
1902 void CNode::RecordBytesRecv(uint64_t bytes)
1904 LOCK(cs_totalBytesRecv);
1905 nTotalBytesRecv += bytes;
1908 void CNode::RecordBytesSent(uint64_t bytes)
1910 LOCK(cs_totalBytesSent);
1911 nTotalBytesSent += bytes;
1914 uint64_t CNode::GetTotalBytesRecv()
1916 LOCK(cs_totalBytesRecv);
1917 return nTotalBytesRecv;
1920 uint64_t CNode::GetTotalBytesSent()
1922 LOCK(cs_totalBytesSent);
1923 return nTotalBytesSent;
1925 int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) {
1926 return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);