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
1185 memcpy(&ip, &pnSeed[i], sizeof(ip));
1186 CAddress addr(CService(ip, GetDefaultPort()));
1187 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1188 vAdd.push_back(addr);
1190 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1193 // Add Tor nodes if we have connection with onion router
1194 if (mapArgs.count("-tor"))
1196 std::vector<CAddress> vAdd;
1197 for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1199 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1200 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1201 vAdd.push_back(addr);
1203 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1207 // Choose an address to connect to based on most recently seen
1209 CAddress addrConnect;
1211 // Only connect out to one peer per network group (/16 for IPv4).
1212 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1214 set<vector<unsigned char> > setConnected;
1217 BOOST_FOREACH(CNode* pnode, vNodes) {
1218 if (!pnode->fInbound) {
1219 setConnected.insert(pnode->addr.GetGroup());
1225 int64_t nANow = GetAdjustedTime();
1230 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1231 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1233 // if we selected an invalid address, restart
1234 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1237 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1238 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1239 // already-connected network ranges, ...) before trying new addrman addresses.
1244 if (IsLimited(addr))
1247 // only consider very recently tried nodes after 30 failed attempts
1248 if (nANow - addr.nLastTry < 600 && nTries < 30)
1251 // do not allow non-default ports, unless after 50 invalid addresses selected already
1252 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1259 if (addrConnect.IsValid())
1260 OpenNetworkConnection(addrConnect, &grant);
1264 void ThreadOpenAddedConnections(void* parg)
1266 // Make this thread recognisable as the connection opening thread
1267 RenameThread("novacoin-opencon");
1271 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1272 ThreadOpenAddedConnections2(parg);
1273 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1275 catch (std::exception& e) {
1276 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1277 PrintException(&e, "ThreadOpenAddedConnections()");
1279 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1280 PrintException(NULL, "ThreadOpenAddedConnections()");
1282 printf("ThreadOpenAddedConnections exited\n");
1285 void ThreadOpenAddedConnections2(void* parg)
1287 printf("ThreadOpenAddedConnections started\n");
1290 LOCK(cs_vAddedNodes);
1291 vAddedNodes = mapMultiArgs["-addnode"];
1294 if (HaveNameProxy()) {
1296 list<string> lAddresses(0);
1298 LOCK(cs_vAddedNodes);
1299 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1300 lAddresses.push_back(strAddNode);
1302 BOOST_FOREACH(string& strAddNode, lAddresses) {
1304 CSemaphoreGrant grant(*semOutbound);
1305 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1308 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1309 Sleep(120000); // Retry every 2 minutes
1310 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1315 for (uint32_t i = 0; true; i++)
1317 list<string> lAddresses(0);
1319 LOCK(cs_vAddedNodes);
1320 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1321 lAddresses.push_back(strAddNode);
1324 list<vector<CService> > lservAddressesToAdd(0);
1325 BOOST_FOREACH(string& strAddNode, lAddresses)
1327 vector<CService> vservNode(0);
1328 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1330 lservAddressesToAdd.push_back(vservNode);
1332 LOCK(cs_setservAddNodeAddresses);
1333 BOOST_FOREACH(CService& serv, vservNode)
1334 setservAddNodeAddresses.insert(serv);
1338 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1339 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1342 BOOST_FOREACH(CNode* pnode, vNodes)
1343 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1345 BOOST_FOREACH(CService& addrNode, *(it))
1346 if (pnode->addr == addrNode)
1348 it = lservAddressesToAdd.erase(it);
1349 if(it != lservAddressesToAdd.begin())
1353 if (it == lservAddressesToAdd.end())
1357 BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
1359 if (vserv.size() == 0)
1361 CSemaphoreGrant grant(*semOutbound);
1362 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1369 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1370 Sleep(120000); // Retry every 2 minutes
1371 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1377 // if successful, this moves the passed grant to the constructed node
1378 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1381 // Initiate outbound network connection
1386 if (IsLocal(addrConnect) ||
1387 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1388 FindNode(addrConnect.ToStringIPPort().c_str()))
1390 if (strDest && FindNode(strDest))
1393 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1394 CNode* pnode = ConnectNode(addrConnect, strDest);
1395 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1401 grantOutbound->MoveTo(pnode->grantOutbound);
1402 pnode->fNetworkNode = true;
1404 pnode->fOneShot = true;
1409 // for now, use a very simple selection metric: the node from which we received
1411 static int64_t NodeSyncScore(const CNode *pnode) {
1412 return pnode->nLastRecv;
1415 void static StartSync(const vector<CNode*> &vNodes) {
1416 CNode *pnodeNewSync = NULL;
1417 int64_t nBestScore = 0;
1419 // Iterate over all nodes
1420 BOOST_FOREACH(CNode* pnode, vNodes) {
1421 // check preconditions for allowing a sync
1422 if (!pnode->fClient && !pnode->fOneShot &&
1423 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1424 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1425 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1426 // if ok, compare node's score with the best so far
1427 int64_t nScore = NodeSyncScore(pnode);
1428 if (pnodeNewSync == NULL || nScore > nBestScore) {
1429 pnodeNewSync = pnode;
1430 nBestScore = nScore;
1434 // if a new sync candidate was found, start sync!
1436 pnodeNewSync->fStartSync = true;
1437 pnodeSync = pnodeNewSync;
1441 void ThreadMessageHandler(void* parg)
1443 // Make this thread recognisable as the message handling thread
1444 RenameThread("novacoin-msghand");
1448 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1449 ThreadMessageHandler2(parg);
1450 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1452 catch (std::exception& e) {
1453 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1454 PrintException(&e, "ThreadMessageHandler()");
1456 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1457 PrintException(NULL, "ThreadMessageHandler()");
1459 printf("ThreadMessageHandler exited\n");
1462 void ThreadMessageHandler2(void* parg)
1464 printf("ThreadMessageHandler started\n");
1465 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1468 bool fHaveSyncNode = false;
1469 vector<CNode*> vNodesCopy;
1472 vNodesCopy = vNodes;
1473 BOOST_FOREACH(CNode* pnode, vNodesCopy) {
1475 if (pnode == pnodeSync)
1476 fHaveSyncNode = true;
1481 StartSync(vNodesCopy);
1483 // Poll the connected nodes for messages
1484 CNode* pnodeTrickle = NULL;
1485 if (!vNodesCopy.empty())
1486 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1487 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1491 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1493 ProcessMessages(pnode);
1500 TRY_LOCK(pnode->cs_vSend, lockSend);
1502 SendMessages(pnode, pnode == pnodeTrickle);
1510 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1514 // Wait and allow messages to bunch up.
1515 // Reduce vnThreadsRunning so StopNode has permission to exit while
1516 // we're sleeping, but we must always check fShutdown after doing this.
1517 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1519 if (fRequestShutdown)
1521 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1532 bool BindListenPort(const CService &addrBind, string& strError)
1537 // Create socket for listening for incoming connections
1539 struct sockaddr_storage sockaddr;
1541 struct sockaddr sockaddr;
1543 socklen_t len = sizeof(sockaddr);
1544 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1546 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1547 printf("%s\n", strError.c_str());
1551 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1552 if (hListenSocket == INVALID_SOCKET)
1554 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1555 printf("%s\n", strError.c_str());
1561 // Different way of disabling SIGPIPE on BSD
1562 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1564 // Allow binding if the port is still in TIME_WAIT state after
1565 // the program was closed and restarted. Not an issue on windows!
1566 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1570 // Set to non-blocking, incoming connections will also inherit this
1571 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1573 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1576 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1577 printf("%s\n", strError.c_str());
1582 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1583 // and enable it by default or not. Try to enable it, if possible.
1584 if (addrBind.IsIPv6()) {
1587 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1589 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1593 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1594 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
1599 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1601 int nErr = WSAGetLastError();
1602 if (nErr == WSAEADDRINUSE)
1603 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1605 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1606 printf("%s\n", strError.c_str());
1607 CloseSocket(hListenSocket);
1610 printf("Bound to %s\n", addrBind.ToString().c_str());
1612 // Listen for incoming connections
1613 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1615 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1616 printf("%s\n", strError.c_str());
1617 CloseSocket(hListenSocket);
1621 vhListenSocket.push_back(hListenSocket);
1623 if (addrBind.IsRoutable() && fDiscover)
1624 AddLocal(addrBind, LOCAL_BIND);
1629 void static Discover()
1635 // Get local host IP
1636 char pszHostName[1000] = "";
1637 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1639 vector<CNetAddr> vaddr;
1640 if (LookupHost(pszHostName, vaddr))
1642 BOOST_FOREACH (const CNetAddr &addr, vaddr)
1644 AddLocal(addr, LOCAL_IF);
1649 // Get local host ip
1650 struct ifaddrs* myaddrs;
1651 if (getifaddrs(&myaddrs) == 0)
1653 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1655 if (ifa->ifa_addr == NULL) continue;
1656 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1657 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1658 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1659 if (ifa->ifa_addr->sa_family == AF_INET)
1661 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1662 CNetAddr addr(s4->sin_addr);
1663 if (AddLocal(addr, LOCAL_IF))
1664 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1667 else if (ifa->ifa_addr->sa_family == AF_INET6)
1669 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1670 CNetAddr addr(s6->sin6_addr);
1671 if (AddLocal(addr, LOCAL_IF))
1672 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1676 freeifaddrs(myaddrs);
1680 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1681 if (!IsLimited(NET_IPV4))
1682 NewThread(ThreadGetMyExternalIP, NULL);
1685 void StartNode(void* parg)
1687 // Make this thread recognisable as the startup thread
1688 RenameThread("novacoin-start");
1690 if (semOutbound == NULL) {
1691 // initialize semaphore
1692 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1693 semOutbound = new CSemaphore(nMaxOutbound);
1696 if (pnodeLocalHost == NULL)
1697 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1705 if (!GetBoolArg("-dnsseed", true))
1706 printf("DNS seeding disabled\n");
1708 if (!NewThread(ThreadDNSAddressSeed, NULL))
1709 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1711 // Get addresses from IRC and advertise ours
1712 if (!GetBoolArg("-irc", true))
1713 printf("IRC seeding disabled\n");
1715 if (!NewThread(ThreadIRCSeed, NULL))
1716 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1718 // Send and receive from sockets, accept connections
1719 if (!NewThread(ThreadSocketHandler, NULL))
1720 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1722 // Initiate outbound connections from -addnode
1723 if (!NewThread(ThreadOpenAddedConnections, NULL))
1724 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1726 // Initiate outbound connections
1727 if (!NewThread(ThreadOpenConnections, NULL))
1728 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1731 if (!NewThread(ThreadMessageHandler, NULL))
1732 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1734 // Dump network addresses
1735 if (!NewThread(ThreadDumpAddress, NULL))
1736 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1738 // Mine proof-of-stake blocks in the background
1739 if (!NewThread(ThreadStakeMiner, pwalletMain))
1740 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1742 // Trusted NTP server, it's localhost by default.
1743 strTrustedUpstream = GetArg("-ntp", "localhost");
1745 // Start periodical NTP sampling thread
1746 NewThread(ThreadNtpSamples, NULL);
1752 printf("StopNode()\n");
1754 nTransactionsUpdated++;
1755 int64_t nStart = GetTime();
1758 ThreadScriptCheckQuit();
1761 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1762 semOutbound->post();
1765 int nThreadsRunning = 0;
1766 for (int n = 0; n < THREAD_MAX; n++)
1767 nThreadsRunning += vnThreadsRunning[n];
1768 if (nThreadsRunning == 0)
1770 if (GetTime() - nStart > 20)
1774 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1775 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1776 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1777 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1778 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1779 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1780 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1781 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1782 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1783 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1784 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1801 BOOST_FOREACH(CNode* pnode, vNodes)
1802 if (pnode->hSocket != INVALID_SOCKET)
1803 CloseSocket(pnode->hSocket);
1804 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
1805 if (hListenSocket != INVALID_SOCKET)
1806 if (!CloseSocket(hListenSocket))
1807 printf("CloseSocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1809 // clean up some globals (to help leak detection)
1810 BOOST_FOREACH(CNode *pnode, vNodes)
1812 BOOST_FOREACH(CNode *pnode, vNodesDisconnected)
1815 vNodesDisconnected.clear();
1818 delete pnodeLocalHost;
1819 pnodeLocalHost = NULL;
1822 // Shutdown Windows Sockets
1827 instance_of_cnetcleanup;
1829 void RelayTransaction(const CTransaction& tx, const uint256& hash)
1831 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1834 RelayTransaction(tx, hash, ss);
1837 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
1839 CInv inv(MSG_TX, hash);
1842 // Expire old relay messages
1843 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1845 mapRelay.erase(vRelayExpiration.front().second);
1846 vRelayExpiration.pop_front();
1849 // Save original serialized message so newer versions are preserved
1850 mapRelay.insert(std::make_pair(inv, ss));
1851 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
1854 RelayInventory(inv);
1857 void CNode::RecordBytesRecv(uint64_t bytes)
1859 LOCK(cs_totalBytesRecv);
1860 nTotalBytesRecv += bytes;
1863 void CNode::RecordBytesSent(uint64_t bytes)
1865 LOCK(cs_totalBytesSent);
1866 nTotalBytesSent += bytes;
1869 uint64_t CNode::GetTotalBytesRecv()
1871 LOCK(cs_totalBytesRecv);
1872 return nTotalBytesRecv;
1875 uint64_t CNode::GetTotalBytesSent()
1877 LOCK(cs_totalBytesSent);
1878 return nTotalBytesSent;