1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
11 #include "ui_interface.h"
20 using namespace boost;
22 static const int MAX_OUTBOUND_CONNECTIONS = 16;
24 void ThreadMessageHandler2(void* parg);
25 void ThreadSocketHandler2(void* parg);
26 void ThreadOpenConnections2(void* parg);
27 void ThreadOpenAddedConnections2(void* parg);
28 void ThreadDNSAddressSeed2(void* parg);
30 // Fix for ancient MinGW versions, that don't have defined these in ws2tcpip.h.
31 // Todo: Can be removed when our pull-tester is upgraded to a modern MinGW version.
33 #ifndef PROTECTION_LEVEL_UNRESTRICTED
34 #define PROTECTION_LEVEL_UNRESTRICTED 10
36 #ifndef IPV6_PROTECTION_LEVEL
37 #define IPV6_PROTECTION_LEVEL 23
41 struct LocalServiceInfo {
47 // Global state variables
50 bool fDiscover = true;
51 uint64_t nLocalServices = (fClient ? 0 : NODE_NETWORK);
52 static CCriticalSection cs_mapLocalHost;
53 static map<CNetAddr, LocalServiceInfo> mapLocalHost;
54 static bool vfReachable[NET_MAX] = {};
55 static bool vfLimited[NET_MAX] = {};
56 static CNode* pnodeLocalHost = NULL;
57 static CNode* pnodeSync = NULL;
58 CAddress addrSeenByPeer(CService("0.0.0.0", nPortZero), nLocalServices);
59 uint64_t nLocalHostNonce = 0;
60 boost::array<int, THREAD_MAX> vnThreadsRunning;
61 static std::vector<SOCKET> vhListenSocket;
64 vector<CNode*> vNodes;
65 CCriticalSection cs_vNodes;
66 map<CInv, CDataStream> mapRelay;
67 deque<pair<int64_t, CInv> > vRelayExpiration;
68 CCriticalSection cs_mapRelay;
69 map<CInv, int64_t> mapAlreadyAskedFor;
71 static deque<string> vOneShots;
72 CCriticalSection cs_vOneShots;
74 set<CNetAddr> setservAddNodeAddresses;
75 CCriticalSection cs_setservAddNodeAddresses;
77 vector<std::string> vAddedNodes;
78 CCriticalSection cs_vAddedNodes;
80 static CSemaphore *semOutbound = NULL;
82 void AddOneShot(string strDest)
85 vOneShots.push_back(strDest);
88 unsigned short GetListenPort()
90 return (unsigned short)(GetArg("-port", GetDefaultPort()));
93 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
95 // Filter out duplicate requests
96 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
98 pindexLastGetBlocksBegin = pindexBegin;
99 hashLastGetBlocksEnd = hashEnd;
101 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
104 // find 'best' local address for a particular peer
105 bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
111 int nBestReachability = -1;
113 LOCK(cs_mapLocalHost);
114 for (map<CNetAddr, LocalServiceInfo>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
116 int nScore = (*it).second.nScore;
117 int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
118 if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
120 addr = CService((*it).first, (*it).second.nPort);
121 nBestReachability = nReachability;
126 return nBestScore >= 0;
129 // get best local address for a particular peer as a CAddress
130 CAddress GetLocalAddress(const CNetAddr *paddrPeer)
132 CAddress ret(CService("0.0.0.0", nPortZero), 0);
134 if (GetLocal(addr, paddrPeer))
136 ret = CAddress(addr);
137 ret.nServices = nLocalServices;
138 ret.nTime = GetAdjustedTime();
143 bool RecvLine(SOCKET hSocket, string& strLine)
149 int nBytes = recv(hSocket, &c, 1, 0);
157 if (strLine.size() >= 9000)
160 else if (nBytes <= 0)
166 int nErr = WSAGetLastError();
167 if (nErr == WSAEMSGSIZE)
169 if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
175 if (!strLine.empty())
180 printf("socket closed\n");
186 int nErr = WSAGetLastError();
187 printf("recv failed: %d\n", nErr);
194 // used when scores of local addresses may have changed
195 // pushes better local address to peers
196 void static AdvertizeLocal()
199 BOOST_FOREACH(CNode* pnode, vNodes)
201 if (pnode->fSuccessfullyConnected)
203 CAddress addrLocal = GetLocalAddress(&pnode->addr);
204 if (addrLocal.IsRoutable() && (CService)addrLocal != (CService)pnode->addrLocal)
206 pnode->PushAddress(addrLocal);
207 pnode->addrLocal = addrLocal;
213 void SetReachable(enum Network net, bool fFlag)
215 LOCK(cs_mapLocalHost);
216 vfReachable[net] = fFlag;
217 if (net == NET_IPV6 && fFlag)
218 vfReachable[NET_IPV4] = true;
221 // learn a new local address
222 bool AddLocal(const CService& addr, int nScore)
224 if (!addr.IsRoutable())
227 if (!fDiscover && nScore < LOCAL_MANUAL)
233 printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
236 LOCK(cs_mapLocalHost);
237 bool fAlready = mapLocalHost.count(addr) > 0;
238 LocalServiceInfo &info = mapLocalHost[addr];
239 if (!fAlready || nScore >= info.nScore) {
240 info.nScore = nScore + (fAlready ? 1 : 0);
241 info.nPort = addr.GetPort();
243 SetReachable(addr.GetNetwork());
251 bool AddLocal(const CNetAddr &addr, int nScore)
253 return AddLocal(CService(addr, GetListenPort()), nScore);
256 /** Make a particular network entirely off-limits (no automatic connects to it) */
257 void SetLimited(enum Network net, bool fLimited)
259 if (net == NET_UNROUTABLE)
261 LOCK(cs_mapLocalHost);
262 vfLimited[net] = fLimited;
265 bool IsLimited(enum Network net)
267 LOCK(cs_mapLocalHost);
268 return vfLimited[net];
271 bool IsLimited(const CNetAddr &addr)
273 return IsLimited(addr.GetNetwork());
276 /** vote for a local address */
277 bool SeenLocal(const CService& addr)
280 LOCK(cs_mapLocalHost);
281 if (mapLocalHost.count(addr) == 0)
283 mapLocalHost[addr].nScore++;
291 /** check whether a given address is potentially local */
292 bool IsLocal(const CService& addr)
294 LOCK(cs_mapLocalHost);
295 return mapLocalHost.count(addr) > 0;
298 /** check whether a given address is in a network we can probably connect to */
299 bool IsReachable(const CNetAddr& addr)
301 LOCK(cs_mapLocalHost);
302 enum Network net = addr.GetNetwork();
303 return vfReachable[net] && !vfLimited[net];
306 extern int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv);
308 // We now get our external IP from the IRC server first and only use this as a backup
309 bool GetMyExternalIP(CNetAddr& ipRet)
311 struct sockaddr_in mapped;
312 uint64_t rnd = std::numeric_limits<uint64_t>::max();
314 int rc = GetExternalIPbySTUN(rnd, &mapped, &srv);
316 ipRet = CNetAddr(mapped.sin_addr);
317 printf("GetExternalIPbySTUN(%" PRIu64 ") returned %s in attempt %d; Server=%s\n", rnd, ipRet.ToStringIP().c_str(), rc, srv);
323 void ThreadGetMyExternalIP(void* parg)
325 // Make this thread recognisable as the external IP detection thread
326 RenameThread("novacoin-ext-ip");
328 CNetAddr addrLocalHost;
329 if (GetMyExternalIP(addrLocalHost))
331 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
332 AddLocal(addrLocalHost, LOCAL_HTTP);
340 void AddressCurrentlyConnected(const CService& addr)
342 addrman.Connected(addr);
348 uint64_t CNode::nTotalBytesRecv = 0;
349 uint64_t CNode::nTotalBytesSent = 0;
350 CCriticalSection CNode::cs_totalBytesRecv;
351 CCriticalSection CNode::cs_totalBytesSent;
353 CNode* FindNode(const CNetAddr& ip)
356 BOOST_FOREACH(CNode* pnode, vNodes)
357 if ((CNetAddr)pnode->addr == ip)
362 CNode* FindNode(std::string addrName)
365 BOOST_FOREACH(CNode* pnode, vNodes)
366 if (pnode->addrName == addrName)
371 CNode* FindNode(const CService& addr)
374 BOOST_FOREACH(CNode* pnode, vNodes)
375 if ((CService)pnode->addr == addr)
380 CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64_t nTimeout)
382 if (pszDest == NULL) {
383 if (IsLocal(addrConnect))
386 // Look for an existing connection
387 CNode* pnode = FindNode((CService)addrConnect);
391 pnode->AddRef(nTimeout);
400 printf("trying connection %s lastseen=%.1fhrs\n",
401 pszDest ? pszDest : addrConnect.ToString().c_str(),
402 pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
406 if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
408 addrman.Attempt(addrConnect);
411 printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
413 // Set to non-blocking
416 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
417 printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
419 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
420 printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
424 CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
426 pnode->AddRef(nTimeout);
432 vNodes.push_back(pnode);
435 pnode->nTimeConnected = GetTime();
444 void CNode::CloseSocketDisconnect()
447 if (hSocket != INVALID_SOCKET)
449 printf("disconnecting node %s\n", addrName.c_str());
450 closesocket(hSocket);
451 hSocket = INVALID_SOCKET;
455 // in case this fails, we'll empty the recv buffer when the CNode is deleted
456 TRY_LOCK(cs_vRecv, lockRecv);
460 // if this was the sync node, we'll need a new one
461 if (this == pnodeSync)
465 void CNode::Cleanup()
470 void CNode::PushVersion()
472 int64_t nTime = GetAdjustedTime();
473 CAddress addrYou, addrMe;
475 bool fHidden = false;
477 if (mapArgs.count("-torname")) {
478 // Our hidden service address
479 CService addrTorName(mapArgs["-torname"], GetListenPort());
481 if (addrTorName.IsValid()) {
483 addrMe = CAddress(addrTorName);
490 addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", nPortZero)));
491 addrMe = GetLocalAddress(&addr);
494 RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
495 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());
496 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
497 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
504 std::map<CNetAddr, int64_t> CNode::setBanned;
505 CCriticalSection CNode::cs_setBanned;
507 void CNode::ClearBanned()
512 bool CNode::IsBanned(CNetAddr ip)
514 bool fResult = false;
517 std::map<CNetAddr, int64_t>::iterator i = setBanned.find(ip);
518 if (i != setBanned.end())
520 int64_t t = (*i).second;
528 bool CNode::Misbehaving(int howmuch)
532 printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
536 nMisbehavior += howmuch;
537 if (nMisbehavior >= GetArgInt("-banscore", 100))
539 int64_t banTime = GetTime()+GetArg("-bantime", nOneDay); // Default 24-hour ban
540 printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
543 if (setBanned[addr] < banTime)
544 setBanned[addr] = banTime;
546 CloseSocketDisconnect();
549 printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
554 #define X(name) stats.name = name
555 void CNode::copyStats(CNodeStats &stats)
570 stats.fSyncNode = (this == pnodeSync);
583 void ThreadSocketHandler(void* parg)
585 // Make this thread recognisable as the networking thread
586 RenameThread("novacoin-net");
590 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
591 ThreadSocketHandler2(parg);
592 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
594 catch (std::exception& e) {
595 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
596 PrintException(&e, "ThreadSocketHandler()");
598 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
599 throw; // support pthread_cancel()
601 printf("ThreadSocketHandler exited\n");
604 static list<CNode*> vNodesDisconnected;
606 void ThreadSocketHandler2(void* parg)
608 printf("ThreadSocketHandler started\n");
609 size_t nPrevNodeCount = 0;
617 // Disconnect unused nodes
618 vector<CNode*> vNodesCopy = vNodes;
619 BOOST_FOREACH(CNode* pnode, vNodesCopy)
621 if (pnode->fDisconnect ||
622 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
624 // remove from vNodes
625 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
627 // release outbound grant (if any)
628 pnode->grantOutbound.Release();
630 // close socket and cleanup
631 pnode->CloseSocketDisconnect();
634 // hold in disconnected pool until all refs are released
635 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
636 if (pnode->fNetworkNode || pnode->fInbound)
638 vNodesDisconnected.push_back(pnode);
642 // Delete disconnected nodes
643 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
644 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
646 // wait until threads are done using it
647 if (pnode->GetRefCount() <= 0)
649 bool fDelete = false;
651 TRY_LOCK(pnode->cs_vSend, lockSend);
654 TRY_LOCK(pnode->cs_vRecv, lockRecv);
657 TRY_LOCK(pnode->cs_mapRequests, lockReq);
660 TRY_LOCK(pnode->cs_inventory, lockInv);
669 vNodesDisconnected.remove(pnode);
675 if (vNodes.size() != nPrevNodeCount)
677 nPrevNodeCount = vNodes.size();
678 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
683 // Find which sockets have data to receive
685 struct timeval timeout;
687 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
694 FD_ZERO(&fdsetError);
695 SOCKET hSocketMax = 0;
696 bool have_fds = false;
698 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) {
699 FD_SET(hListenSocket, &fdsetRecv);
700 hSocketMax = max(hSocketMax, hListenSocket);
705 BOOST_FOREACH(CNode* pnode, vNodes)
707 if (pnode->hSocket == INVALID_SOCKET)
709 FD_SET(pnode->hSocket, &fdsetRecv);
710 FD_SET(pnode->hSocket, &fdsetError);
711 hSocketMax = max(hSocketMax, pnode->hSocket);
714 TRY_LOCK(pnode->cs_vSend, lockSend);
715 if (lockSend && !pnode->vSend.empty())
716 FD_SET(pnode->hSocket, &fdsetSend);
721 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
722 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
723 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
724 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
727 if (nSelect == SOCKET_ERROR)
731 int nErr = WSAGetLastError();
732 printf("socket select error %d\n", nErr);
733 for (unsigned int i = 0; i <= hSocketMax; i++)
734 FD_SET(i, &fdsetRecv);
737 FD_ZERO(&fdsetError);
738 Sleep(timeout.tv_usec/1000);
743 // Accept new connections
745 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
746 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
749 struct sockaddr_storage sockaddr;
751 struct sockaddr sockaddr;
753 socklen_t len = sizeof(sockaddr);
754 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
758 if (hSocket != INVALID_SOCKET)
759 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
760 printf("Warning: Unknown socket family\n");
764 BOOST_FOREACH(CNode* pnode, vNodes)
769 if (hSocket == INVALID_SOCKET)
771 int nErr = WSAGetLastError();
772 if (nErr != WSAEWOULDBLOCK)
773 printf("socket error accept failed: %d\n", nErr);
775 else if (nInbound >= GetArgInt("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
778 LOCK(cs_setservAddNodeAddresses);
779 if (!setservAddNodeAddresses.count(addr))
780 closesocket(hSocket);
783 else if (CNode::IsBanned(addr))
785 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
786 closesocket(hSocket);
790 printf("accepted connection %s\n", addr.ToString().c_str());
791 CNode* pnode = new CNode(hSocket, addr, "", true);
795 vNodes.push_back(pnode);
802 // Service each socket
804 vector<CNode*> vNodesCopy;
808 BOOST_FOREACH(CNode* pnode, vNodesCopy)
811 BOOST_FOREACH(CNode* pnode, vNodesCopy)
819 if (pnode->hSocket == INVALID_SOCKET)
821 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
823 TRY_LOCK(pnode->cs_vRecv, lockRecv);
826 CDataStream& vRecv = pnode->vRecv;
827 uint64_t nPos = vRecv.size();
829 if (nPos > ReceiveBufferSize()) {
830 if (!pnode->fDisconnect)
831 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
832 pnode->CloseSocketDisconnect();
835 // typical socket buffer is 8K-64K
836 char pchBuf[0x10000];
837 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
840 vRecv.resize(nPos + nBytes);
841 memcpy(&vRecv[nPos], pchBuf, nBytes);
842 pnode->nLastRecv = GetTime();
843 pnode->nRecvBytes += nBytes;
844 pnode->RecordBytesRecv(nBytes);
846 else if (nBytes == 0)
848 // socket closed gracefully
849 if (!pnode->fDisconnect)
850 printf("socket closed\n");
851 pnode->CloseSocketDisconnect();
856 int nErr = WSAGetLastError();
857 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
859 if (!pnode->fDisconnect)
860 printf("socket recv error %d\n", nErr);
861 pnode->CloseSocketDisconnect();
871 if (pnode->hSocket == INVALID_SOCKET)
873 if (FD_ISSET(pnode->hSocket, &fdsetSend))
875 TRY_LOCK(pnode->cs_vSend, lockSend);
878 CDataStream& vSend = pnode->vSend;
881 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
884 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
885 pnode->nLastSend = GetTime();
886 pnode->nSendBytes += nBytes;
887 pnode->RecordBytesSent(nBytes);
892 int nErr = WSAGetLastError();
893 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
895 printf("socket send error %d\n", nErr);
896 pnode->CloseSocketDisconnect();
904 // Inactivity checking
906 if (pnode->vSend.empty())
907 pnode->nLastSendEmpty = GetTime();
908 if (GetTime() - pnode->nTimeConnected > 60)
910 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
912 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
913 pnode->fDisconnect = true;
915 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
917 printf("socket not sending\n");
918 pnode->fDisconnect = true;
920 else if (GetTime() - pnode->nLastRecv > 90*60)
922 printf("socket inactivity timeout\n");
923 pnode->fDisconnect = true;
929 BOOST_FOREACH(CNode* pnode, vNodesCopy)
938 // Each pair gives a source name and a seed name.
939 // The first name is used as information source for addrman.
940 // The second name should resolve to a list of seed addresses.
941 static const char *strDNSSeed[][2] = {
942 {"novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro"},
943 {"novacoin.ru", "dnsseed.novacoin.ru"},
944 {"novacoin.ru", "testseed.novacoin.ru"},
945 {"novaco.in", "dnsseed.novaco.in"},
948 void ThreadDNSAddressSeed(void* parg)
950 // Make this thread recognisable as the DNS seeding thread
951 RenameThread("novacoin-dnsseed");
955 vnThreadsRunning[THREAD_DNSSEED]++;
956 ThreadDNSAddressSeed2(parg);
957 vnThreadsRunning[THREAD_DNSSEED]--;
959 catch (std::exception& e) {
960 vnThreadsRunning[THREAD_DNSSEED]--;
961 PrintException(&e, "ThreadDNSAddressSeed()");
963 vnThreadsRunning[THREAD_DNSSEED]--;
964 throw; // support pthread_cancel()
966 printf("ThreadDNSAddressSeed exited\n");
969 void ThreadDNSAddressSeed2(void* parg)
971 printf("ThreadDNSAddressSeed started\n");
976 printf("Loading addresses from DNS seeds (could take a while)\n");
978 for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
979 if (HaveNameProxy()) {
980 AddOneShot(strDNSSeed[seed_idx][1]);
982 vector<CNetAddr> vaddr;
983 vector<CAddress> vAdd;
984 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
986 BOOST_FOREACH(CNetAddr& ip, vaddr)
988 CAddress addr = CAddress(CService(ip, GetDefaultPort()));
989 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
990 vAdd.push_back(addr);
994 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
999 printf("%d addresses found from DNS seeds\n", found);
1015 0xa52bf0da, 0x30aa43d8, 0x614488d5, 0x517b6fd5, 0xd4bf62d4, 0xb7d638d4, 0xbc12bcd1, 0xa2501bc6,
1016 0xfde617c6, 0x3337b1c6, 0x1dcd71c3, 0x2c1544c1, 0xe05f6ac1, 0x852f63c0, 0x3e2363c0, 0x15f563c0,
1017 0x430d63c0, 0x50d6a9c0, 0xf0a679c0, 0xefdeedbf, 0x7aaee8bc, 0x3a3dbbbc, 0xef218abc, 0x0bef78bc,
1018 0x8baa3eb2, 0x2bf913b2, 0x24ed9fb2, 0xb42289b2, 0x718a09b0, 0xe9433eb0, 0x559425b0, 0xc97e1fb0,
1019 0x18e1d4b0, 0x8f6cc1b0, 0xac3838ae, 0x86c0ffad, 0x6b0272a7, 0xa463f8a2, 0x6f17f3a2, 0xb3d6f3a2,
1020 0x9cd8f997, 0xd513fb94, 0x39e64880, 0x3859dd6f, 0x0b08fe6d, 0xe601fe6d, 0xeb44a26d, 0xfe53186c,
1021 0x203c2e68, 0x1c542868, 0x0caa8368, 0xb8748368, 0xccca4762, 0xc637555f, 0x638a545f, 0x59b2205f,
1022 0x52568c5f, 0xba568c5f, 0x8a568c5f, 0x31b0f45e, 0x54a0f45e, 0x37d6f15e, 0xc520175e, 0x7620175e,
1023 0xc310175e, 0x8e33b45e, 0x7abb5f5d, 0xd3014c5d, 0xa1e1485d, 0x9947645d, 0xfab8ff5c, 0xa979e65b,
1024 0xa879e65b, 0x9f79e65b, 0x9fa3d25b, 0x112a925b, 0x7b92905b, 0x60647a5b, 0x1e389d5a, 0x851afa59,
1025 0x0185ef59, 0x26549b59, 0x1c9efe57, 0xc54c1256, 0x1ad51955, 0x19d21955, 0x73c41955, 0x3f74ee55,
1026 0x633eea55, 0x6883d655, 0xfb72c655, 0x5360a653, 0x17c1ea52, 0xc661c852, 0x1ecdc852, 0x006a9752,
1027 0xf72d9252, 0x82650551, 0x36f1c851, 0x33f1c851, 0xd5c1864f, 0xb6bf1b4e, 0x96da184e, 0x40d0234d,
1028 0x9a96ab4c, 0x8fc2a84c, 0xb5dbd048, 0xf4644447, 0x2d51af47, 0xa9625445, 0x83f05243, 0x89672941,
1029 0x3a8bad3e, 0xf0a05436, 0x6ab7c936, 0x49971d32, 0xadd4482e, 0xcffd212e, 0x6730bc2e, 0x839aa12e,
1030 0x68d9692e, 0xc7183b25, 0x6c47bb25, 0x2490bb25, 0xad651c1f, 0x048a861f, 0x6937811f, 0x064b2d05,
1034 const char* pchTorSeed[] =
1036 "seedp4knqnoei57u.onion",
1037 "seedr3hhlepyi7fd.onion",
1038 "seed3uuomkclbiz4.onion",
1039 "seedeh7qck3ouff5.onion",
1040 "5rg3vq4jagckeckf.onion",
1041 "seedt3sraf53ajiy.onion",
1042 "seedg4qyccsg42oq.onion",
1043 "novaqrtoywpg7jly.onion",
1044 "seed3d5wolqbgrcb.onion",
1045 "seed24u5dwph3qw4.onion",
1046 "mj26ulzbs2oskgym.onion",
1047 "eqon4usunavt76m7.onion",
1048 "seedd3aldwpslzl3.onion"
1051 void DumpAddresses()
1053 int64_t nStart = GetTimeMillis();
1058 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1059 addrman.size(), GetTimeMillis() - nStart);
1062 void ThreadDumpAddress2(void* parg)
1064 printf("ThreadDumpAddress started\n");
1066 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1070 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1072 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1074 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1077 void ThreadDumpAddress(void* parg)
1079 // Make this thread recognisable as the address dumping thread
1080 RenameThread("novacoin-adrdump");
1084 ThreadDumpAddress2(parg);
1086 catch (std::exception& e) {
1087 PrintException(&e, "ThreadDumpAddress()");
1089 printf("ThreadDumpAddress exited\n");
1092 void ThreadOpenConnections(void* parg)
1094 // Make this thread recognisable as the connection opening thread
1095 RenameThread("novacoin-opencon");
1099 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1100 ThreadOpenConnections2(parg);
1101 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1103 catch (std::exception& e) {
1104 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1105 PrintException(&e, "ThreadOpenConnections()");
1107 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1108 PrintException(NULL, "ThreadOpenConnections()");
1110 printf("ThreadOpenConnections exited\n");
1113 void static ProcessOneShot()
1118 if (vOneShots.empty())
1120 strDest = vOneShots.front();
1121 vOneShots.pop_front();
1124 CSemaphoreGrant grant(*semOutbound, true);
1126 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1127 AddOneShot(strDest);
1131 void ThreadOpenConnections2(void* parg)
1133 printf("ThreadOpenConnections started\n");
1135 // Connect to specific addresses
1136 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1138 for (int64_t nLoop = 0;; nLoop++)
1141 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1144 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1145 for (int i = 0; i < 10 && i < nLoop; i++)
1156 // Initiate network connections
1157 int64_t nStart = GetTime();
1162 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1164 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1169 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1170 CSemaphoreGrant grant(*semOutbound);
1171 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1175 // Add seed nodes if IRC isn't working
1176 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1178 std::vector<CAddress> vAdd;
1179 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1181 // It'll only connect to one or two seed nodes because once it connects,
1182 // it'll get a pile of addresses with newer timestamps.
1183 // Seed nodes are given a random 'last seen time' of between one and two
1185 const int64_t nOneWeek = 7*24*60*60;
1187 memcpy(&ip, &pnSeed[i], sizeof(ip));
1188 CAddress addr(CService(ip, GetDefaultPort()));
1189 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1190 vAdd.push_back(addr);
1192 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1195 // Add Tor nodes if we have connection with onion router
1196 if (mapArgs.count("-tor"))
1198 std::vector<CAddress> vAdd;
1199 for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1201 const int64_t nOneWeek = 7*24*60*60;
1202 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1203 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1204 vAdd.push_back(addr);
1206 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1210 // Choose an address to connect to based on most recently seen
1212 CAddress addrConnect;
1214 // Only connect out to one peer per network group (/16 for IPv4).
1215 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1217 set<vector<unsigned char> > setConnected;
1220 BOOST_FOREACH(CNode* pnode, vNodes) {
1221 if (!pnode->fInbound) {
1222 setConnected.insert(pnode->addr.GetGroup());
1228 int64_t nANow = GetAdjustedTime();
1233 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1234 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1236 // if we selected an invalid address, restart
1237 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1240 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1241 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1242 // already-connected network ranges, ...) before trying new addrman addresses.
1247 if (IsLimited(addr))
1250 // only consider very recently tried nodes after 30 failed attempts
1251 if (nANow - addr.nLastTry < 600 && nTries < 30)
1254 // do not allow non-default ports, unless after 50 invalid addresses selected already
1255 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1262 if (addrConnect.IsValid())
1263 OpenNetworkConnection(addrConnect, &grant);
1267 void ThreadOpenAddedConnections(void* parg)
1269 // Make this thread recognisable as the connection opening thread
1270 RenameThread("novacoin-opencon");
1274 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1275 ThreadOpenAddedConnections2(parg);
1276 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1278 catch (std::exception& e) {
1279 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1280 PrintException(&e, "ThreadOpenAddedConnections()");
1282 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1283 PrintException(NULL, "ThreadOpenAddedConnections()");
1285 printf("ThreadOpenAddedConnections exited\n");
1288 void ThreadOpenAddedConnections2(void* parg)
1290 printf("ThreadOpenAddedConnections started\n");
1293 LOCK(cs_vAddedNodes);
1294 vAddedNodes = mapMultiArgs["-addnode"];
1297 if (HaveNameProxy()) {
1299 list<string> lAddresses(0);
1301 LOCK(cs_vAddedNodes);
1302 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1303 lAddresses.push_back(strAddNode);
1305 BOOST_FOREACH(string& strAddNode, lAddresses) {
1307 CSemaphoreGrant grant(*semOutbound);
1308 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1311 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1312 Sleep(120000); // Retry every 2 minutes
1313 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1318 for (uint32_t i = 0; true; i++)
1320 list<string> lAddresses(0);
1322 LOCK(cs_vAddedNodes);
1323 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1324 lAddresses.push_back(strAddNode);
1327 list<vector<CService> > lservAddressesToAdd(0);
1328 BOOST_FOREACH(string& strAddNode, lAddresses)
1330 vector<CService> vservNode(0);
1331 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1333 lservAddressesToAdd.push_back(vservNode);
1335 LOCK(cs_setservAddNodeAddresses);
1336 BOOST_FOREACH(CService& serv, vservNode)
1337 setservAddNodeAddresses.insert(serv);
1341 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1342 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1345 BOOST_FOREACH(CNode* pnode, vNodes)
1346 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1348 BOOST_FOREACH(CService& addrNode, *(it))
1349 if (pnode->addr == addrNode)
1351 it = lservAddressesToAdd.erase(it);
1352 if(it != lservAddressesToAdd.begin())
1356 if (it == lservAddressesToAdd.end())
1360 BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
1362 if (vserv.size() == 0)
1364 CSemaphoreGrant grant(*semOutbound);
1365 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1372 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1373 Sleep(120000); // Retry every 2 minutes
1374 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1380 // if successful, this moves the passed grant to the constructed node
1381 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1384 // Initiate outbound network connection
1389 if (IsLocal(addrConnect) ||
1390 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1391 FindNode(addrConnect.ToStringIPPort().c_str()))
1393 if (strDest && FindNode(strDest))
1396 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1397 CNode* pnode = ConnectNode(addrConnect, strDest);
1398 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1404 grantOutbound->MoveTo(pnode->grantOutbound);
1405 pnode->fNetworkNode = true;
1407 pnode->fOneShot = true;
1412 // for now, use a very simple selection metric: the node from which we received
1414 static int64_t NodeSyncScore(const CNode *pnode) {
1415 return pnode->nLastRecv;
1418 void static StartSync(const vector<CNode*> &vNodes) {
1419 CNode *pnodeNewSync = NULL;
1420 int64_t nBestScore = 0;
1422 // Iterate over all nodes
1423 BOOST_FOREACH(CNode* pnode, vNodes) {
1424 // check preconditions for allowing a sync
1425 if (!pnode->fClient && !pnode->fOneShot &&
1426 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1427 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1428 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1429 // if ok, compare node's score with the best so far
1430 int64_t nScore = NodeSyncScore(pnode);
1431 if (pnodeNewSync == NULL || nScore > nBestScore) {
1432 pnodeNewSync = pnode;
1433 nBestScore = nScore;
1437 // if a new sync candidate was found, start sync!
1439 pnodeNewSync->fStartSync = true;
1440 pnodeSync = pnodeNewSync;
1444 void ThreadMessageHandler(void* parg)
1446 // Make this thread recognisable as the message handling thread
1447 RenameThread("novacoin-msghand");
1451 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1452 ThreadMessageHandler2(parg);
1453 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1455 catch (std::exception& e) {
1456 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1457 PrintException(&e, "ThreadMessageHandler()");
1459 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1460 PrintException(NULL, "ThreadMessageHandler()");
1462 printf("ThreadMessageHandler exited\n");
1465 void ThreadMessageHandler2(void* parg)
1467 printf("ThreadMessageHandler started\n");
1468 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1471 bool fHaveSyncNode = false;
1472 vector<CNode*> vNodesCopy;
1475 vNodesCopy = vNodes;
1476 BOOST_FOREACH(CNode* pnode, vNodesCopy) {
1478 if (pnode == pnodeSync)
1479 fHaveSyncNode = true;
1484 StartSync(vNodesCopy);
1486 // Poll the connected nodes for messages
1487 CNode* pnodeTrickle = NULL;
1488 if (!vNodesCopy.empty())
1489 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1490 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1494 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1496 ProcessMessages(pnode);
1503 TRY_LOCK(pnode->cs_vSend, lockSend);
1505 SendMessages(pnode, pnode == pnodeTrickle);
1513 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1517 // Wait and allow messages to bunch up.
1518 // Reduce vnThreadsRunning so StopNode has permission to exit while
1519 // we're sleeping, but we must always check fShutdown after doing this.
1520 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1522 if (fRequestShutdown)
1524 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1535 bool BindListenPort(const CService &addrBind, string& strError)
1540 // Create socket for listening for incoming connections
1542 struct sockaddr_storage sockaddr;
1544 struct sockaddr sockaddr;
1546 socklen_t len = sizeof(sockaddr);
1547 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1549 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1550 printf("%s\n", strError.c_str());
1554 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1555 if (hListenSocket == INVALID_SOCKET)
1557 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1558 printf("%s\n", strError.c_str());
1564 // Different way of disabling SIGPIPE on BSD
1565 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1567 // Allow binding if the port is still in TIME_WAIT state after
1568 // the program was closed and restarted. Not an issue on windows!
1569 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1573 // Set to non-blocking, incoming connections will also inherit this
1574 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1576 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1579 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1580 printf("%s\n", strError.c_str());
1585 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1586 // and enable it by default or not. Try to enable it, if possible.
1587 if (addrBind.IsIPv6()) {
1590 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1592 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1596 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1597 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
1602 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1604 int nErr = WSAGetLastError();
1605 if (nErr == WSAEADDRINUSE)
1606 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1608 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1609 printf("%s\n", strError.c_str());
1610 closesocket(hListenSocket);
1613 printf("Bound to %s\n", addrBind.ToString().c_str());
1615 // Listen for incoming connections
1616 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1618 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1619 printf("%s\n", strError.c_str());
1620 closesocket(hListenSocket);
1624 vhListenSocket.push_back(hListenSocket);
1626 if (addrBind.IsRoutable() && fDiscover)
1627 AddLocal(addrBind, LOCAL_BIND);
1632 void static Discover()
1638 // Get local host IP
1639 char pszHostName[1000] = "";
1640 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1642 vector<CNetAddr> vaddr;
1643 if (LookupHost(pszHostName, vaddr))
1645 BOOST_FOREACH (const CNetAddr &addr, vaddr)
1647 AddLocal(addr, LOCAL_IF);
1652 // Get local host ip
1653 struct ifaddrs* myaddrs;
1654 if (getifaddrs(&myaddrs) == 0)
1656 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1658 if (ifa->ifa_addr == NULL) continue;
1659 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1660 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1661 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1662 if (ifa->ifa_addr->sa_family == AF_INET)
1664 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1665 CNetAddr addr(s4->sin_addr);
1666 if (AddLocal(addr, LOCAL_IF))
1667 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1670 else if (ifa->ifa_addr->sa_family == AF_INET6)
1672 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1673 CNetAddr addr(s6->sin6_addr);
1674 if (AddLocal(addr, LOCAL_IF))
1675 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1679 freeifaddrs(myaddrs);
1683 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1684 if (!IsLimited(NET_IPV4))
1685 NewThread(ThreadGetMyExternalIP, NULL);
1688 void StartNode(void* parg)
1690 // Make this thread recognisable as the startup thread
1691 RenameThread("novacoin-start");
1693 if (semOutbound == NULL) {
1694 // initialize semaphore
1695 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1696 semOutbound = new CSemaphore(nMaxOutbound);
1699 if (pnodeLocalHost == NULL)
1700 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1708 if (!GetBoolArg("-dnsseed", true))
1709 printf("DNS seeding disabled\n");
1711 if (!NewThread(ThreadDNSAddressSeed, NULL))
1712 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1714 // Get addresses from IRC and advertise ours
1715 if (!GetBoolArg("-irc", true))
1716 printf("IRC seeding disabled\n");
1718 if (!NewThread(ThreadIRCSeed, NULL))
1719 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1721 // Send and receive from sockets, accept connections
1722 if (!NewThread(ThreadSocketHandler, NULL))
1723 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1725 // Initiate outbound connections from -addnode
1726 if (!NewThread(ThreadOpenAddedConnections, NULL))
1727 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1729 // Initiate outbound connections
1730 if (!NewThread(ThreadOpenConnections, NULL))
1731 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1734 if (!NewThread(ThreadMessageHandler, NULL))
1735 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1737 // Dump network addresses
1738 if (!NewThread(ThreadDumpAddress, NULL))
1739 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1741 // Mine proof-of-stake blocks in the background
1742 if (!NewThread(ThreadStakeMiner, pwalletMain))
1743 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1745 // Trusted NTP server, it's localhost by default.
1746 strTrustedUpstream = GetArg("-ntp", "localhost");
1748 // Start periodical NTP sampling thread
1749 NewThread(ThreadNtpSamples, NULL);
1755 printf("StopNode()\n");
1757 nTransactionsUpdated++;
1758 int64_t nStart = GetTime();
1761 ThreadScriptCheckQuit();
1764 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1765 semOutbound->post();
1768 int nThreadsRunning = 0;
1769 for (int n = 0; n < THREAD_MAX; n++)
1770 nThreadsRunning += vnThreadsRunning[n];
1771 if (nThreadsRunning == 0)
1773 if (GetTime() - nStart > 20)
1777 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1778 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1779 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1780 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1781 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1782 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1783 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1784 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1785 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1786 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1787 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1804 BOOST_FOREACH(CNode* pnode, vNodes)
1805 if (pnode->hSocket != INVALID_SOCKET)
1806 closesocket(pnode->hSocket);
1807 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
1808 if (hListenSocket != INVALID_SOCKET)
1809 if (closesocket(hListenSocket) == SOCKET_ERROR)
1810 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1812 // clean up some globals (to help leak detection)
1813 BOOST_FOREACH(CNode *pnode, vNodes)
1815 BOOST_FOREACH(CNode *pnode, vNodesDisconnected)
1818 vNodesDisconnected.clear();
1821 delete pnodeLocalHost;
1822 pnodeLocalHost = NULL;
1825 // Shutdown Windows Sockets
1830 instance_of_cnetcleanup;
1832 void RelayTransaction(const CTransaction& tx, const uint256& hash)
1834 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1837 RelayTransaction(tx, hash, ss);
1840 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
1842 CInv inv(MSG_TX, hash);
1845 // Expire old relay messages
1846 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1848 mapRelay.erase(vRelayExpiration.front().second);
1849 vRelayExpiration.pop_front();
1852 // Save original serialized message so newer versions are preserved
1853 mapRelay.insert(std::make_pair(inv, ss));
1854 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
1857 RelayInventory(inv);
1860 void CNode::RecordBytesRecv(uint64_t bytes)
1862 LOCK(cs_totalBytesRecv);
1863 nTotalBytesRecv += bytes;
1866 void CNode::RecordBytesSent(uint64_t bytes)
1868 LOCK(cs_totalBytesSent);
1869 nTotalBytesSent += bytes;
1872 uint64_t CNode::GetTotalBytesRecv()
1874 LOCK(cs_totalBytesRecv);
1875 return nTotalBytesRecv;
1878 uint64_t CNode::GetTotalBytesSent()
1880 LOCK(cs_totalBytesSent);
1881 return nTotalBytesSent;