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 != 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);
454 // in case this fails, we'll empty the recv buffer when the CNode is deleted
455 TRY_LOCK(cs_vRecv, lockRecv);
459 // if this was the sync node, we'll need a new one
460 if (this == pnodeSync)
464 void CNode::Cleanup()
469 void CNode::PushVersion()
471 int64_t nTime = GetAdjustedTime();
472 CAddress addrYou, addrMe;
474 bool fHidden = false;
476 if (mapArgs.count("-torname")) {
477 // Our hidden service address
478 CService addrTorName(mapArgs["-torname"], GetListenPort());
480 if (addrTorName.IsValid()) {
482 addrMe = CAddress(addrTorName);
489 addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", nPortZero)));
490 addrMe = GetLocalAddress(&addr);
493 RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
494 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());
495 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
496 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
503 std::map<CNetAddr, int64_t> CNode::setBanned;
504 CCriticalSection CNode::cs_setBanned;
506 void CNode::ClearBanned()
511 bool CNode::IsBanned(CNetAddr ip)
513 bool fResult = false;
516 std::map<CNetAddr, int64_t>::iterator i = setBanned.find(ip);
517 if (i != setBanned.end())
519 int64_t t = (*i).second;
527 bool CNode::Misbehaving(int howmuch)
531 printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
535 nMisbehavior += howmuch;
536 if (nMisbehavior >= GetArgInt("-banscore", 100))
538 int64_t banTime = GetTime()+GetArg("-bantime", nOneDay); // Default 24-hour ban
539 printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
542 if (setBanned[addr] < banTime)
543 setBanned[addr] = banTime;
545 CloseSocketDisconnect();
548 printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
553 #define X(name) stats.name = name
554 void CNode::copyStats(CNodeStats &stats)
569 stats.fSyncNode = (this == pnodeSync);
582 void ThreadSocketHandler(void* parg)
584 // Make this thread recognisable as the networking thread
585 RenameThread("novacoin-net");
589 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
590 ThreadSocketHandler2(parg);
591 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
593 catch (std::exception& e) {
594 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
595 PrintException(&e, "ThreadSocketHandler()");
597 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
598 throw; // support pthread_cancel()
600 printf("ThreadSocketHandler exited\n");
603 static list<CNode*> vNodesDisconnected;
605 void ThreadSocketHandler2(void* parg)
607 printf("ThreadSocketHandler started\n");
608 size_t nPrevNodeCount = 0;
616 // Disconnect unused nodes
617 vector<CNode*> vNodesCopy = vNodes;
618 BOOST_FOREACH(CNode* pnode, vNodesCopy)
620 if (pnode->fDisconnect ||
621 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
623 // remove from vNodes
624 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
626 // release outbound grant (if any)
627 pnode->grantOutbound.Release();
629 // close socket and cleanup
630 pnode->CloseSocketDisconnect();
633 // hold in disconnected pool until all refs are released
634 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
635 if (pnode->fNetworkNode || pnode->fInbound)
637 vNodesDisconnected.push_back(pnode);
641 // Delete disconnected nodes
642 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
643 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
645 // wait until threads are done using it
646 if (pnode->GetRefCount() <= 0)
648 bool fDelete = false;
650 TRY_LOCK(pnode->cs_vSend, lockSend);
653 TRY_LOCK(pnode->cs_vRecv, lockRecv);
656 TRY_LOCK(pnode->cs_mapRequests, lockReq);
659 TRY_LOCK(pnode->cs_inventory, lockInv);
668 vNodesDisconnected.remove(pnode);
674 if (vNodes.size() != nPrevNodeCount)
676 nPrevNodeCount = vNodes.size();
677 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
682 // Find which sockets have data to receive
684 struct timeval timeout;
686 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
693 FD_ZERO(&fdsetError);
694 SOCKET hSocketMax = 0;
695 bool have_fds = false;
697 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) {
698 FD_SET(hListenSocket, &fdsetRecv);
699 hSocketMax = max(hSocketMax, hListenSocket);
704 BOOST_FOREACH(CNode* pnode, vNodes)
706 if (pnode->hSocket == INVALID_SOCKET)
708 FD_SET(pnode->hSocket, &fdsetRecv);
709 FD_SET(pnode->hSocket, &fdsetError);
710 hSocketMax = max(hSocketMax, pnode->hSocket);
713 TRY_LOCK(pnode->cs_vSend, lockSend);
714 if (lockSend && !pnode->vSend.empty())
715 FD_SET(pnode->hSocket, &fdsetSend);
720 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
721 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
722 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
723 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
726 if (nSelect == SOCKET_ERROR)
730 int nErr = WSAGetLastError();
731 printf("socket select error %d\n", nErr);
732 for (unsigned int i = 0; i <= hSocketMax; i++)
733 FD_SET(i, &fdsetRecv);
736 FD_ZERO(&fdsetError);
737 Sleep(timeout.tv_usec/1000);
742 // Accept new connections
744 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
745 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
748 struct sockaddr_storage sockaddr;
750 struct sockaddr sockaddr;
752 socklen_t len = sizeof(sockaddr);
753 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
757 if (hSocket != INVALID_SOCKET)
758 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
759 printf("Warning: Unknown socket family\n");
763 BOOST_FOREACH(CNode* pnode, vNodes)
768 if (hSocket == INVALID_SOCKET)
770 int nErr = WSAGetLastError();
771 if (nErr != WSAEWOULDBLOCK)
772 printf("socket error accept failed: %d\n", nErr);
774 else if (nInbound >= GetArgInt("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
777 LOCK(cs_setservAddNodeAddresses);
778 if (!setservAddNodeAddresses.count(addr))
779 CloseSocket(hSocket);
782 else if (CNode::IsBanned(addr))
784 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
785 CloseSocket(hSocket);
789 printf("accepted connection %s\n", addr.ToString().c_str());
790 CNode* pnode = new CNode(hSocket, addr, "", true);
794 vNodes.push_back(pnode);
801 // Service each socket
803 vector<CNode*> vNodesCopy;
807 BOOST_FOREACH(CNode* pnode, vNodesCopy)
810 BOOST_FOREACH(CNode* pnode, vNodesCopy)
818 if (pnode->hSocket == INVALID_SOCKET)
820 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
822 TRY_LOCK(pnode->cs_vRecv, lockRecv);
825 CDataStream& vRecv = pnode->vRecv;
826 uint64_t nPos = vRecv.size();
828 if (nPos > ReceiveBufferSize()) {
829 if (!pnode->fDisconnect)
830 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
831 pnode->CloseSocketDisconnect();
834 // typical socket buffer is 8K-64K
835 char pchBuf[0x10000];
836 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
839 vRecv.resize(nPos + nBytes);
840 memcpy(&vRecv[nPos], pchBuf, nBytes);
841 pnode->nLastRecv = GetTime();
842 pnode->nRecvBytes += nBytes;
843 pnode->RecordBytesRecv(nBytes);
845 else if (nBytes == 0)
847 // socket closed gracefully
848 if (!pnode->fDisconnect)
849 printf("socket closed\n");
850 pnode->CloseSocketDisconnect();
855 int nErr = WSAGetLastError();
856 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
858 if (!pnode->fDisconnect)
859 printf("socket recv error %d\n", nErr);
860 pnode->CloseSocketDisconnect();
870 if (pnode->hSocket == INVALID_SOCKET)
872 if (FD_ISSET(pnode->hSocket, &fdsetSend))
874 TRY_LOCK(pnode->cs_vSend, lockSend);
877 CDataStream& vSend = pnode->vSend;
880 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
883 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
884 pnode->nLastSend = GetTime();
885 pnode->nSendBytes += nBytes;
886 pnode->RecordBytesSent(nBytes);
891 int nErr = WSAGetLastError();
892 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
894 printf("socket send error %d\n", nErr);
895 pnode->CloseSocketDisconnect();
903 // Inactivity checking
905 if (pnode->vSend.empty())
906 pnode->nLastSendEmpty = GetTime();
907 if (GetTime() - pnode->nTimeConnected > 60)
909 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
911 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
912 pnode->fDisconnect = true;
914 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
916 printf("socket not sending\n");
917 pnode->fDisconnect = true;
919 else if (GetTime() - pnode->nLastRecv > 90*60)
921 printf("socket inactivity timeout\n");
922 pnode->fDisconnect = true;
928 BOOST_FOREACH(CNode* pnode, vNodesCopy)
937 // Each pair gives a source name and a seed name.
938 // The first name is used as information source for addrman.
939 // The second name should resolve to a list of seed addresses.
940 static const char *strDNSSeed[][2] = {
941 {"novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro"},
942 {"novacoin.ru", "dnsseed.novacoin.ru"},
943 {"novacoin.ru", "testseed.novacoin.ru"},
944 {"novaco.in", "dnsseed.novaco.in"},
947 void ThreadDNSAddressSeed(void* parg)
949 // Make this thread recognisable as the DNS seeding thread
950 RenameThread("novacoin-dnsseed");
954 vnThreadsRunning[THREAD_DNSSEED]++;
955 ThreadDNSAddressSeed2(parg);
956 vnThreadsRunning[THREAD_DNSSEED]--;
958 catch (std::exception& e) {
959 vnThreadsRunning[THREAD_DNSSEED]--;
960 PrintException(&e, "ThreadDNSAddressSeed()");
962 vnThreadsRunning[THREAD_DNSSEED]--;
963 throw; // support pthread_cancel()
965 printf("ThreadDNSAddressSeed exited\n");
968 void ThreadDNSAddressSeed2(void* parg)
970 printf("ThreadDNSAddressSeed started\n");
975 printf("Loading addresses from DNS seeds (could take a while)\n");
977 for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
978 if (HaveNameProxy()) {
979 AddOneShot(strDNSSeed[seed_idx][1]);
981 vector<CNetAddr> vaddr;
982 vector<CAddress> vAdd;
983 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
985 BOOST_FOREACH(CNetAddr& ip, vaddr)
987 CAddress addr = CAddress(CService(ip, GetDefaultPort()));
988 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
989 vAdd.push_back(addr);
993 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
998 printf("%d addresses found from DNS seeds\n", found);
1014 0xa52bf0da, 0x30aa43d8, 0x614488d5, 0x517b6fd5, 0xd4bf62d4, 0xb7d638d4, 0xbc12bcd1, 0xa2501bc6,
1015 0xfde617c6, 0x3337b1c6, 0x1dcd71c3, 0x2c1544c1, 0xe05f6ac1, 0x852f63c0, 0x3e2363c0, 0x15f563c0,
1016 0x430d63c0, 0x50d6a9c0, 0xf0a679c0, 0xefdeedbf, 0x7aaee8bc, 0x3a3dbbbc, 0xef218abc, 0x0bef78bc,
1017 0x8baa3eb2, 0x2bf913b2, 0x24ed9fb2, 0xb42289b2, 0x718a09b0, 0xe9433eb0, 0x559425b0, 0xc97e1fb0,
1018 0x18e1d4b0, 0x8f6cc1b0, 0xac3838ae, 0x86c0ffad, 0x6b0272a7, 0xa463f8a2, 0x6f17f3a2, 0xb3d6f3a2,
1019 0x9cd8f997, 0xd513fb94, 0x39e64880, 0x3859dd6f, 0x0b08fe6d, 0xe601fe6d, 0xeb44a26d, 0xfe53186c,
1020 0x203c2e68, 0x1c542868, 0x0caa8368, 0xb8748368, 0xccca4762, 0xc637555f, 0x638a545f, 0x59b2205f,
1021 0x52568c5f, 0xba568c5f, 0x8a568c5f, 0x31b0f45e, 0x54a0f45e, 0x37d6f15e, 0xc520175e, 0x7620175e,
1022 0xc310175e, 0x8e33b45e, 0x7abb5f5d, 0xd3014c5d, 0xa1e1485d, 0x9947645d, 0xfab8ff5c, 0xa979e65b,
1023 0xa879e65b, 0x9f79e65b, 0x9fa3d25b, 0x112a925b, 0x7b92905b, 0x60647a5b, 0x1e389d5a, 0x851afa59,
1024 0x0185ef59, 0x26549b59, 0x1c9efe57, 0xc54c1256, 0x1ad51955, 0x19d21955, 0x73c41955, 0x3f74ee55,
1025 0x633eea55, 0x6883d655, 0xfb72c655, 0x5360a653, 0x17c1ea52, 0xc661c852, 0x1ecdc852, 0x006a9752,
1026 0xf72d9252, 0x82650551, 0x36f1c851, 0x33f1c851, 0xd5c1864f, 0xb6bf1b4e, 0x96da184e, 0x40d0234d,
1027 0x9a96ab4c, 0x8fc2a84c, 0xb5dbd048, 0xf4644447, 0x2d51af47, 0xa9625445, 0x83f05243, 0x89672941,
1028 0x3a8bad3e, 0xf0a05436, 0x6ab7c936, 0x49971d32, 0xadd4482e, 0xcffd212e, 0x6730bc2e, 0x839aa12e,
1029 0x68d9692e, 0xc7183b25, 0x6c47bb25, 0x2490bb25, 0xad651c1f, 0x048a861f, 0x6937811f, 0x064b2d05,
1033 const char* pchTorSeed[] =
1035 "seedp4knqnoei57u.onion",
1036 "seedr3hhlepyi7fd.onion",
1037 "seed3uuomkclbiz4.onion",
1038 "seedeh7qck3ouff5.onion",
1039 "5rg3vq4jagckeckf.onion",
1040 "seedt3sraf53ajiy.onion",
1041 "seedg4qyccsg42oq.onion",
1042 "novaqrtoywpg7jly.onion",
1043 "seed3d5wolqbgrcb.onion",
1044 "seed24u5dwph3qw4.onion",
1045 "mj26ulzbs2oskgym.onion",
1046 "eqon4usunavt76m7.onion",
1047 "seedd3aldwpslzl3.onion"
1050 void DumpAddresses()
1052 int64_t nStart = GetTimeMillis();
1057 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1058 addrman.size(), GetTimeMillis() - nStart);
1061 void ThreadDumpAddress2(void* parg)
1063 printf("ThreadDumpAddress started\n");
1065 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1069 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1071 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1073 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1076 void ThreadDumpAddress(void* parg)
1078 // Make this thread recognisable as the address dumping thread
1079 RenameThread("novacoin-adrdump");
1083 ThreadDumpAddress2(parg);
1085 catch (std::exception& e) {
1086 PrintException(&e, "ThreadDumpAddress()");
1088 printf("ThreadDumpAddress exited\n");
1091 void ThreadOpenConnections(void* parg)
1093 // Make this thread recognisable as the connection opening thread
1094 RenameThread("novacoin-opencon");
1098 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1099 ThreadOpenConnections2(parg);
1100 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1102 catch (std::exception& e) {
1103 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1104 PrintException(&e, "ThreadOpenConnections()");
1106 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1107 PrintException(NULL, "ThreadOpenConnections()");
1109 printf("ThreadOpenConnections exited\n");
1112 void static ProcessOneShot()
1117 if (vOneShots.empty())
1119 strDest = vOneShots.front();
1120 vOneShots.pop_front();
1123 CSemaphoreGrant grant(*semOutbound, true);
1125 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1126 AddOneShot(strDest);
1130 void ThreadOpenConnections2(void* parg)
1132 printf("ThreadOpenConnections started\n");
1134 // Connect to specific addresses
1135 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1137 for (int64_t nLoop = 0;; nLoop++)
1140 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1143 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1144 for (int i = 0; i < 10 && i < nLoop; i++)
1155 // Initiate network connections
1156 int64_t nStart = GetTime();
1161 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1163 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1168 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1169 CSemaphoreGrant grant(*semOutbound);
1170 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1174 // Add seed nodes if IRC isn't working
1175 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1177 std::vector<CAddress> vAdd;
1178 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1180 // It'll only connect to one or two seed nodes because once it connects,
1181 // it'll get a pile of addresses with newer timestamps.
1182 // Seed nodes are given a random 'last seen time' of between one and two
1184 const int64_t nOneWeek = 7*24*60*60;
1186 memcpy(&ip, &pnSeed[i], sizeof(ip));
1187 CAddress addr(CService(ip, GetDefaultPort()));
1188 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1189 vAdd.push_back(addr);
1191 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1194 // Add Tor nodes if we have connection with onion router
1195 if (mapArgs.count("-tor"))
1197 std::vector<CAddress> vAdd;
1198 for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1200 const int64_t nOneWeek = 7*24*60*60;
1201 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1202 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1203 vAdd.push_back(addr);
1205 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1209 // Choose an address to connect to based on most recently seen
1211 CAddress addrConnect;
1213 // Only connect out to one peer per network group (/16 for IPv4).
1214 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1216 set<vector<unsigned char> > setConnected;
1219 BOOST_FOREACH(CNode* pnode, vNodes) {
1220 if (!pnode->fInbound) {
1221 setConnected.insert(pnode->addr.GetGroup());
1227 int64_t nANow = GetAdjustedTime();
1232 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1233 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1235 // if we selected an invalid address, restart
1236 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1239 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1240 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1241 // already-connected network ranges, ...) before trying new addrman addresses.
1246 if (IsLimited(addr))
1249 // only consider very recently tried nodes after 30 failed attempts
1250 if (nANow - addr.nLastTry < 600 && nTries < 30)
1253 // do not allow non-default ports, unless after 50 invalid addresses selected already
1254 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1261 if (addrConnect.IsValid())
1262 OpenNetworkConnection(addrConnect, &grant);
1266 void ThreadOpenAddedConnections(void* parg)
1268 // Make this thread recognisable as the connection opening thread
1269 RenameThread("novacoin-opencon");
1273 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1274 ThreadOpenAddedConnections2(parg);
1275 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1277 catch (std::exception& e) {
1278 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1279 PrintException(&e, "ThreadOpenAddedConnections()");
1281 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1282 PrintException(NULL, "ThreadOpenAddedConnections()");
1284 printf("ThreadOpenAddedConnections exited\n");
1287 void ThreadOpenAddedConnections2(void* parg)
1289 printf("ThreadOpenAddedConnections started\n");
1292 LOCK(cs_vAddedNodes);
1293 vAddedNodes = mapMultiArgs["-addnode"];
1296 if (HaveNameProxy()) {
1298 list<string> lAddresses(0);
1300 LOCK(cs_vAddedNodes);
1301 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1302 lAddresses.push_back(strAddNode);
1304 BOOST_FOREACH(string& strAddNode, lAddresses) {
1306 CSemaphoreGrant grant(*semOutbound);
1307 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1310 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1311 Sleep(120000); // Retry every 2 minutes
1312 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1317 for (uint32_t i = 0; true; i++)
1319 list<string> lAddresses(0);
1321 LOCK(cs_vAddedNodes);
1322 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1323 lAddresses.push_back(strAddNode);
1326 list<vector<CService> > lservAddressesToAdd(0);
1327 BOOST_FOREACH(string& strAddNode, lAddresses)
1329 vector<CService> vservNode(0);
1330 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1332 lservAddressesToAdd.push_back(vservNode);
1334 LOCK(cs_setservAddNodeAddresses);
1335 BOOST_FOREACH(CService& serv, vservNode)
1336 setservAddNodeAddresses.insert(serv);
1340 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1341 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1344 BOOST_FOREACH(CNode* pnode, vNodes)
1345 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1347 BOOST_FOREACH(CService& addrNode, *(it))
1348 if (pnode->addr == addrNode)
1350 it = lservAddressesToAdd.erase(it);
1351 if(it != lservAddressesToAdd.begin())
1355 if (it == lservAddressesToAdd.end())
1359 BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
1361 if (vserv.size() == 0)
1363 CSemaphoreGrant grant(*semOutbound);
1364 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1371 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1372 Sleep(120000); // Retry every 2 minutes
1373 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1379 // if successful, this moves the passed grant to the constructed node
1380 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1383 // Initiate outbound network connection
1388 if (IsLocal(addrConnect) ||
1389 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1390 FindNode(addrConnect.ToStringIPPort().c_str()))
1392 if (strDest && FindNode(strDest))
1395 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1396 CNode* pnode = ConnectNode(addrConnect, strDest);
1397 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1403 grantOutbound->MoveTo(pnode->grantOutbound);
1404 pnode->fNetworkNode = true;
1406 pnode->fOneShot = true;
1411 // for now, use a very simple selection metric: the node from which we received
1413 static int64_t NodeSyncScore(const CNode *pnode) {
1414 return pnode->nLastRecv;
1417 void static StartSync(const vector<CNode*> &vNodes) {
1418 CNode *pnodeNewSync = NULL;
1419 int64_t nBestScore = 0;
1421 // Iterate over all nodes
1422 BOOST_FOREACH(CNode* pnode, vNodes) {
1423 // check preconditions for allowing a sync
1424 if (!pnode->fClient && !pnode->fOneShot &&
1425 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1426 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1427 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1428 // if ok, compare node's score with the best so far
1429 int64_t nScore = NodeSyncScore(pnode);
1430 if (pnodeNewSync == NULL || nScore > nBestScore) {
1431 pnodeNewSync = pnode;
1432 nBestScore = nScore;
1436 // if a new sync candidate was found, start sync!
1438 pnodeNewSync->fStartSync = true;
1439 pnodeSync = pnodeNewSync;
1443 void ThreadMessageHandler(void* parg)
1445 // Make this thread recognisable as the message handling thread
1446 RenameThread("novacoin-msghand");
1450 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1451 ThreadMessageHandler2(parg);
1452 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1454 catch (std::exception& e) {
1455 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1456 PrintException(&e, "ThreadMessageHandler()");
1458 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1459 PrintException(NULL, "ThreadMessageHandler()");
1461 printf("ThreadMessageHandler exited\n");
1464 void ThreadMessageHandler2(void* parg)
1466 printf("ThreadMessageHandler started\n");
1467 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1470 bool fHaveSyncNode = false;
1471 vector<CNode*> vNodesCopy;
1474 vNodesCopy = vNodes;
1475 BOOST_FOREACH(CNode* pnode, vNodesCopy) {
1477 if (pnode == pnodeSync)
1478 fHaveSyncNode = true;
1483 StartSync(vNodesCopy);
1485 // Poll the connected nodes for messages
1486 CNode* pnodeTrickle = NULL;
1487 if (!vNodesCopy.empty())
1488 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1489 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1493 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1495 ProcessMessages(pnode);
1502 TRY_LOCK(pnode->cs_vSend, lockSend);
1504 SendMessages(pnode, pnode == pnodeTrickle);
1512 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1516 // Wait and allow messages to bunch up.
1517 // Reduce vnThreadsRunning so StopNode has permission to exit while
1518 // we're sleeping, but we must always check fShutdown after doing this.
1519 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1521 if (fRequestShutdown)
1523 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1534 bool BindListenPort(const CService &addrBind, string& strError)
1539 // Create socket for listening for incoming connections
1541 struct sockaddr_storage sockaddr;
1543 struct sockaddr sockaddr;
1545 socklen_t len = sizeof(sockaddr);
1546 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1548 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1549 printf("%s\n", strError.c_str());
1553 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1554 if (hListenSocket == INVALID_SOCKET)
1556 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1557 printf("%s\n", strError.c_str());
1563 // Different way of disabling SIGPIPE on BSD
1564 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1566 // Allow binding if the port is still in TIME_WAIT state after
1567 // the program was closed and restarted. Not an issue on windows!
1568 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1572 // Set to non-blocking, incoming connections will also inherit this
1573 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1575 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1578 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1579 printf("%s\n", strError.c_str());
1584 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1585 // and enable it by default or not. Try to enable it, if possible.
1586 if (addrBind.IsIPv6()) {
1589 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1591 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1595 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1596 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
1601 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1603 int nErr = WSAGetLastError();
1604 if (nErr == WSAEADDRINUSE)
1605 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1607 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1608 printf("%s\n", strError.c_str());
1609 CloseSocket(hListenSocket);
1612 printf("Bound to %s\n", addrBind.ToString().c_str());
1614 // Listen for incoming connections
1615 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1617 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1618 printf("%s\n", strError.c_str());
1619 CloseSocket(hListenSocket);
1623 vhListenSocket.push_back(hListenSocket);
1625 if (addrBind.IsRoutable() && fDiscover)
1626 AddLocal(addrBind, LOCAL_BIND);
1631 void static Discover()
1637 // Get local host IP
1638 char pszHostName[1000] = "";
1639 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1641 vector<CNetAddr> vaddr;
1642 if (LookupHost(pszHostName, vaddr))
1644 BOOST_FOREACH (const CNetAddr &addr, vaddr)
1646 AddLocal(addr, LOCAL_IF);
1651 // Get local host ip
1652 struct ifaddrs* myaddrs;
1653 if (getifaddrs(&myaddrs) == 0)
1655 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1657 if (ifa->ifa_addr == NULL) continue;
1658 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1659 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1660 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1661 if (ifa->ifa_addr->sa_family == AF_INET)
1663 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1664 CNetAddr addr(s4->sin_addr);
1665 if (AddLocal(addr, LOCAL_IF))
1666 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1669 else if (ifa->ifa_addr->sa_family == AF_INET6)
1671 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1672 CNetAddr addr(s6->sin6_addr);
1673 if (AddLocal(addr, LOCAL_IF))
1674 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1678 freeifaddrs(myaddrs);
1682 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1683 if (!IsLimited(NET_IPV4))
1684 NewThread(ThreadGetMyExternalIP, NULL);
1687 void StartNode(void* parg)
1689 // Make this thread recognisable as the startup thread
1690 RenameThread("novacoin-start");
1692 if (semOutbound == NULL) {
1693 // initialize semaphore
1694 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1695 semOutbound = new CSemaphore(nMaxOutbound);
1698 if (pnodeLocalHost == NULL)
1699 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1707 if (!GetBoolArg("-dnsseed", true))
1708 printf("DNS seeding disabled\n");
1710 if (!NewThread(ThreadDNSAddressSeed, NULL))
1711 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1713 // Get addresses from IRC and advertise ours
1714 if (!GetBoolArg("-irc", true))
1715 printf("IRC seeding disabled\n");
1717 if (!NewThread(ThreadIRCSeed, NULL))
1718 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1720 // Send and receive from sockets, accept connections
1721 if (!NewThread(ThreadSocketHandler, NULL))
1722 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1724 // Initiate outbound connections from -addnode
1725 if (!NewThread(ThreadOpenAddedConnections, NULL))
1726 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1728 // Initiate outbound connections
1729 if (!NewThread(ThreadOpenConnections, NULL))
1730 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1733 if (!NewThread(ThreadMessageHandler, NULL))
1734 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1736 // Dump network addresses
1737 if (!NewThread(ThreadDumpAddress, NULL))
1738 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1740 // Mine proof-of-stake blocks in the background
1741 if (!NewThread(ThreadStakeMiner, pwalletMain))
1742 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1744 // Trusted NTP server, it's localhost by default.
1745 strTrustedUpstream = GetArg("-ntp", "localhost");
1747 // Start periodical NTP sampling thread
1748 NewThread(ThreadNtpSamples, NULL);
1754 printf("StopNode()\n");
1756 nTransactionsUpdated++;
1757 int64_t nStart = GetTime();
1760 ThreadScriptCheckQuit();
1763 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1764 semOutbound->post();
1767 int nThreadsRunning = 0;
1768 for (int n = 0; n < THREAD_MAX; n++)
1769 nThreadsRunning += vnThreadsRunning[n];
1770 if (nThreadsRunning == 0)
1772 if (GetTime() - nStart > 20)
1776 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1777 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1778 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1779 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1780 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1781 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1782 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1783 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1784 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1785 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1786 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1803 BOOST_FOREACH(CNode* pnode, vNodes)
1804 if (pnode->hSocket != INVALID_SOCKET)
1805 CloseSocket(pnode->hSocket);
1806 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
1807 if (hListenSocket != INVALID_SOCKET)
1808 if (!CloseSocket(hListenSocket))
1809 printf("CloseSocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1811 // clean up some globals (to help leak detection)
1812 BOOST_FOREACH(CNode *pnode, vNodes)
1814 BOOST_FOREACH(CNode *pnode, vNodesDisconnected)
1817 vNodesDisconnected.clear();
1820 delete pnodeLocalHost;
1821 pnodeLocalHost = NULL;
1824 // Shutdown Windows Sockets
1829 instance_of_cnetcleanup;
1831 void RelayTransaction(const CTransaction& tx, const uint256& hash)
1833 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1836 RelayTransaction(tx, hash, ss);
1839 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
1841 CInv inv(MSG_TX, hash);
1844 // Expire old relay messages
1845 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1847 mapRelay.erase(vRelayExpiration.front().second);
1848 vRelayExpiration.pop_front();
1851 // Save original serialized message so newer versions are preserved
1852 mapRelay.insert(std::make_pair(inv, ss));
1853 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
1856 RelayInventory(inv);
1859 void CNode::RecordBytesRecv(uint64_t bytes)
1861 LOCK(cs_totalBytesRecv);
1862 nTotalBytesRecv += bytes;
1865 void CNode::RecordBytesSent(uint64_t bytes)
1867 LOCK(cs_totalBytesSent);
1868 nTotalBytesSent += bytes;
1871 uint64_t CNode::GetTotalBytesRecv()
1873 LOCK(cs_totalBytesRecv);
1874 return nTotalBytesRecv;
1877 uint64_t CNode::GetTotalBytesSent()
1879 LOCK(cs_totalBytesSent);
1880 return nTotalBytesSent;