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);
573 void Release(CNode* node) {
581 void ThreadSocketHandler(void* parg)
583 // Make this thread recognisable as the networking thread
584 RenameThread("novacoin-net");
588 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
589 ThreadSocketHandler2(parg);
590 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
592 catch (std::exception& e) {
593 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
594 PrintException(&e, "ThreadSocketHandler()");
596 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
597 throw; // support pthread_cancel()
599 printf("ThreadSocketHandler exited\n");
602 static list<CNode*> vNodesDisconnected;
604 void ThreadSocketHandler2(void* parg)
606 printf("ThreadSocketHandler started\n");
607 size_t nPrevNodeCount = 0;
615 // Disconnect unused nodes
616 vector<CNode*> vNodesCopy = vNodes;
617 BOOST_FOREACH(CNode* pnode, vNodesCopy)
619 if (pnode->fDisconnect ||
620 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
622 // remove from vNodes
623 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
625 // release outbound grant (if any)
626 pnode->grantOutbound.Release();
628 // close socket and cleanup
629 pnode->CloseSocketDisconnect();
632 // hold in disconnected pool until all refs are released
633 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
634 if (pnode->fNetworkNode || pnode->fInbound)
636 vNodesDisconnected.push_back(pnode);
640 // Delete disconnected nodes
641 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
642 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
644 // wait until threads are done using it
645 if (pnode->GetRefCount() <= 0)
647 bool fDelete = false;
649 TRY_LOCK(pnode->cs_vSend, lockSend);
652 TRY_LOCK(pnode->cs_vRecv, lockRecv);
655 TRY_LOCK(pnode->cs_mapRequests, lockReq);
658 TRY_LOCK(pnode->cs_inventory, lockInv);
667 vNodesDisconnected.remove(pnode);
673 if (vNodes.size() != nPrevNodeCount)
675 nPrevNodeCount = vNodes.size();
676 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
681 // Find which sockets have data to receive
683 struct timeval timeout;
685 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
692 FD_ZERO(&fdsetError);
693 SOCKET hSocketMax = 0;
694 bool have_fds = false;
696 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) {
697 FD_SET(hListenSocket, &fdsetRecv);
698 hSocketMax = max(hSocketMax, hListenSocket);
703 BOOST_FOREACH(CNode* pnode, vNodes)
705 if (pnode->hSocket == INVALID_SOCKET)
707 FD_SET(pnode->hSocket, &fdsetRecv);
708 FD_SET(pnode->hSocket, &fdsetError);
709 hSocketMax = max(hSocketMax, pnode->hSocket);
712 TRY_LOCK(pnode->cs_vSend, lockSend);
713 if (lockSend && !pnode->vSend.empty())
714 FD_SET(pnode->hSocket, &fdsetSend);
719 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
720 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
721 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
722 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
725 if (nSelect == SOCKET_ERROR)
729 int nErr = WSAGetLastError();
730 printf("socket select error %d\n", nErr);
731 for (unsigned int i = 0; i <= hSocketMax; i++)
732 FD_SET(i, &fdsetRecv);
735 FD_ZERO(&fdsetError);
736 Sleep(timeout.tv_usec/1000);
741 // Accept new connections
743 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
744 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
747 struct sockaddr_storage sockaddr;
749 struct sockaddr sockaddr;
751 socklen_t len = sizeof(sockaddr);
752 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
756 if (hSocket != INVALID_SOCKET)
757 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
758 printf("Warning: Unknown socket family\n");
762 BOOST_FOREACH(CNode* pnode, vNodes)
767 if (hSocket == INVALID_SOCKET)
769 int nErr = WSAGetLastError();
770 if (nErr != WSAEWOULDBLOCK)
771 printf("socket error accept failed: %d\n", nErr);
773 else if (nInbound >= GetArgInt("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
776 LOCK(cs_setservAddNodeAddresses);
777 if (!setservAddNodeAddresses.count(addr))
778 CloseSocket(hSocket);
781 else if (CNode::IsBanned(addr))
783 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
784 CloseSocket(hSocket);
788 printf("accepted connection %s\n", addr.ToString().c_str());
789 CNode* pnode = new CNode(hSocket, addr, "", true);
793 vNodes.push_back(pnode);
800 // Service each socket
802 vector<CNode*> vNodesCopy;
806 BOOST_FOREACH(CNode* pnode, vNodesCopy)
809 BOOST_FOREACH(CNode* pnode, vNodesCopy)
817 if (pnode->hSocket == INVALID_SOCKET)
819 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
821 TRY_LOCK(pnode->cs_vRecv, lockRecv);
824 CDataStream& vRecv = pnode->vRecv;
825 uint64_t nPos = vRecv.size();
827 if (nPos > ReceiveBufferSize()) {
828 if (!pnode->fDisconnect)
829 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
830 pnode->CloseSocketDisconnect();
833 // typical socket buffer is 8K-64K
834 char pchBuf[0x10000];
835 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
838 vRecv.resize(nPos + nBytes);
839 memcpy(&vRecv[nPos], pchBuf, nBytes);
840 pnode->nLastRecv = GetTime();
841 pnode->nRecvBytes += nBytes;
842 pnode->RecordBytesRecv(nBytes);
844 else if (nBytes == 0)
846 // socket closed gracefully
847 if (!pnode->fDisconnect)
848 printf("socket closed\n");
849 pnode->CloseSocketDisconnect();
854 int nErr = WSAGetLastError();
855 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
857 if (!pnode->fDisconnect)
858 printf("socket recv error %d\n", nErr);
859 pnode->CloseSocketDisconnect();
869 if (pnode->hSocket == INVALID_SOCKET)
871 if (FD_ISSET(pnode->hSocket, &fdsetSend))
873 TRY_LOCK(pnode->cs_vSend, lockSend);
876 CDataStream& vSend = pnode->vSend;
879 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
882 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
883 pnode->nLastSend = GetTime();
884 pnode->nSendBytes += nBytes;
885 pnode->RecordBytesSent(nBytes);
890 int nErr = WSAGetLastError();
891 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
893 printf("socket send error %d\n", nErr);
894 pnode->CloseSocketDisconnect();
902 // Inactivity checking
904 if (pnode->vSend.empty())
905 pnode->nLastSendEmpty = GetTime();
906 if (GetTime() - pnode->nTimeConnected > 60)
908 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
910 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
911 pnode->fDisconnect = true;
913 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
915 printf("socket not sending\n");
916 pnode->fDisconnect = true;
918 else if (GetTime() - pnode->nLastRecv > 90*60)
920 printf("socket inactivity timeout\n");
921 pnode->fDisconnect = true;
927 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
935 // Each pair gives a source name and a seed name.
936 // The first name is used as information source for addrman.
937 // The second name should resolve to a list of seed addresses.
938 static const char *strDNSSeed[][2] = {
939 {"novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro"},
940 {"novacoin.ru", "dnsseed.novacoin.ru"},
941 {"novacoin.ru", "testseed.novacoin.ru"},
942 {"novaco.in", "dnsseed.novaco.in"},
945 void ThreadDNSAddressSeed(void* parg)
947 // Make this thread recognisable as the DNS seeding thread
948 RenameThread("novacoin-dnsseed");
952 vnThreadsRunning[THREAD_DNSSEED]++;
953 ThreadDNSAddressSeed2(parg);
954 vnThreadsRunning[THREAD_DNSSEED]--;
956 catch (std::exception& e) {
957 vnThreadsRunning[THREAD_DNSSEED]--;
958 PrintException(&e, "ThreadDNSAddressSeed()");
960 vnThreadsRunning[THREAD_DNSSEED]--;
961 throw; // support pthread_cancel()
963 printf("ThreadDNSAddressSeed exited\n");
966 void ThreadDNSAddressSeed2(void* parg)
968 printf("ThreadDNSAddressSeed started\n");
973 printf("Loading addresses from DNS seeds (could take a while)\n");
975 for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
976 if (HaveNameProxy()) {
977 AddOneShot(strDNSSeed[seed_idx][1]);
979 vector<CNetAddr> vaddr;
980 vector<CAddress> vAdd;
981 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
983 BOOST_FOREACH(CNetAddr& ip, vaddr)
985 CAddress addr = CAddress(CService(ip, GetDefaultPort()));
986 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
987 vAdd.push_back(addr);
991 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
996 printf("%d addresses found from DNS seeds\n", found);
1012 0xa52bf0da, 0x30aa43d8, 0x614488d5, 0x517b6fd5, 0xd4bf62d4, 0xb7d638d4, 0xbc12bcd1, 0xa2501bc6,
1013 0xfde617c6, 0x3337b1c6, 0x1dcd71c3, 0x2c1544c1, 0xe05f6ac1, 0x852f63c0, 0x3e2363c0, 0x15f563c0,
1014 0x430d63c0, 0x50d6a9c0, 0xf0a679c0, 0xefdeedbf, 0x7aaee8bc, 0x3a3dbbbc, 0xef218abc, 0x0bef78bc,
1015 0x8baa3eb2, 0x2bf913b2, 0x24ed9fb2, 0xb42289b2, 0x718a09b0, 0xe9433eb0, 0x559425b0, 0xc97e1fb0,
1016 0x18e1d4b0, 0x8f6cc1b0, 0xac3838ae, 0x86c0ffad, 0x6b0272a7, 0xa463f8a2, 0x6f17f3a2, 0xb3d6f3a2,
1017 0x9cd8f997, 0xd513fb94, 0x39e64880, 0x3859dd6f, 0x0b08fe6d, 0xe601fe6d, 0xeb44a26d, 0xfe53186c,
1018 0x203c2e68, 0x1c542868, 0x0caa8368, 0xb8748368, 0xccca4762, 0xc637555f, 0x638a545f, 0x59b2205f,
1019 0x52568c5f, 0xba568c5f, 0x8a568c5f, 0x31b0f45e, 0x54a0f45e, 0x37d6f15e, 0xc520175e, 0x7620175e,
1020 0xc310175e, 0x8e33b45e, 0x7abb5f5d, 0xd3014c5d, 0xa1e1485d, 0x9947645d, 0xfab8ff5c, 0xa979e65b,
1021 0xa879e65b, 0x9f79e65b, 0x9fa3d25b, 0x112a925b, 0x7b92905b, 0x60647a5b, 0x1e389d5a, 0x851afa59,
1022 0x0185ef59, 0x26549b59, 0x1c9efe57, 0xc54c1256, 0x1ad51955, 0x19d21955, 0x73c41955, 0x3f74ee55,
1023 0x633eea55, 0x6883d655, 0xfb72c655, 0x5360a653, 0x17c1ea52, 0xc661c852, 0x1ecdc852, 0x006a9752,
1024 0xf72d9252, 0x82650551, 0x36f1c851, 0x33f1c851, 0xd5c1864f, 0xb6bf1b4e, 0x96da184e, 0x40d0234d,
1025 0x9a96ab4c, 0x8fc2a84c, 0xb5dbd048, 0xf4644447, 0x2d51af47, 0xa9625445, 0x83f05243, 0x89672941,
1026 0x3a8bad3e, 0xf0a05436, 0x6ab7c936, 0x49971d32, 0xadd4482e, 0xcffd212e, 0x6730bc2e, 0x839aa12e,
1027 0x68d9692e, 0xc7183b25, 0x6c47bb25, 0x2490bb25, 0xad651c1f, 0x048a861f, 0x6937811f, 0x064b2d05,
1031 const char* pchTorSeed[] =
1033 "seedp4knqnoei57u.onion",
1034 "seedr3hhlepyi7fd.onion",
1035 "seed3uuomkclbiz4.onion",
1036 "seedeh7qck3ouff5.onion",
1037 "5rg3vq4jagckeckf.onion",
1038 "seedt3sraf53ajiy.onion",
1039 "seedg4qyccsg42oq.onion",
1040 "novaqrtoywpg7jly.onion",
1041 "seed3d5wolqbgrcb.onion",
1042 "seed24u5dwph3qw4.onion",
1043 "mj26ulzbs2oskgym.onion",
1044 "eqon4usunavt76m7.onion",
1045 "seedd3aldwpslzl3.onion"
1048 void DumpAddresses()
1050 int64_t nStart = GetTimeMillis();
1055 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1056 addrman.size(), GetTimeMillis() - nStart);
1059 void ThreadDumpAddress2(void* parg)
1061 printf("ThreadDumpAddress started\n");
1063 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1067 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1069 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1071 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1074 void ThreadDumpAddress(void* parg)
1076 // Make this thread recognisable as the address dumping thread
1077 RenameThread("novacoin-adrdump");
1081 ThreadDumpAddress2(parg);
1083 catch (std::exception& e) {
1084 PrintException(&e, "ThreadDumpAddress()");
1086 printf("ThreadDumpAddress exited\n");
1089 void ThreadOpenConnections(void* parg)
1091 // Make this thread recognisable as the connection opening thread
1092 RenameThread("novacoin-opencon");
1096 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1097 ThreadOpenConnections2(parg);
1098 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1100 catch (std::exception& e) {
1101 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1102 PrintException(&e, "ThreadOpenConnections()");
1104 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1105 PrintException(NULL, "ThreadOpenConnections()");
1107 printf("ThreadOpenConnections exited\n");
1110 void static ProcessOneShot()
1115 if (vOneShots.empty())
1117 strDest = vOneShots.front();
1118 vOneShots.pop_front();
1121 CSemaphoreGrant grant(*semOutbound, true);
1123 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1124 AddOneShot(strDest);
1128 void ThreadOpenConnections2(void* parg)
1130 printf("ThreadOpenConnections started\n");
1132 // Connect to specific addresses
1133 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1135 for (int64_t nLoop = 0;; nLoop++)
1138 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1141 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1142 for (int i = 0; i < 10 && i < nLoop; i++)
1153 // Initiate network connections
1154 int64_t nStart = GetTime();
1159 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1161 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1166 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1167 CSemaphoreGrant grant(*semOutbound);
1168 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1172 // Add seed nodes if IRC isn't working
1173 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1175 std::vector<CAddress> vAdd;
1176 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1178 // It'll only connect to one or two seed nodes because once it connects,
1179 // it'll get a pile of addresses with newer timestamps.
1180 // Seed nodes are given a random 'last seen time' of between one and two
1183 memcpy(&ip, &pnSeed[i], sizeof(ip));
1184 CAddress addr(CService(ip, GetDefaultPort()));
1185 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1186 vAdd.push_back(addr);
1188 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1191 // Add Tor nodes if we have connection with onion router
1192 if (mapArgs.count("-tor"))
1194 std::vector<CAddress> vAdd;
1195 for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1197 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1198 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1199 vAdd.push_back(addr);
1201 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1205 // Choose an address to connect to based on most recently seen
1207 CAddress addrConnect;
1209 // Only connect out to one peer per network group (/16 for IPv4).
1210 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1212 set<vector<unsigned char> > setConnected;
1215 BOOST_FOREACH(CNode* pnode, vNodes) {
1216 if (!pnode->fInbound) {
1217 setConnected.insert(pnode->addr.GetGroup());
1223 int64_t nANow = GetAdjustedTime();
1228 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1229 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1231 // if we selected an invalid address, restart
1232 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1235 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1236 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1237 // already-connected network ranges, ...) before trying new addrman addresses.
1242 if (IsLimited(addr))
1245 // only consider very recently tried nodes after 30 failed attempts
1246 if (nANow - addr.nLastTry < 600 && nTries < 30)
1249 // do not allow non-default ports, unless after 50 invalid addresses selected already
1250 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1257 if (addrConnect.IsValid())
1258 OpenNetworkConnection(addrConnect, &grant);
1262 void ThreadOpenAddedConnections(void* parg)
1264 // Make this thread recognisable as the connection opening thread
1265 RenameThread("novacoin-opencon");
1269 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1270 ThreadOpenAddedConnections2(parg);
1271 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1273 catch (std::exception& e) {
1274 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1275 PrintException(&e, "ThreadOpenAddedConnections()");
1277 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1278 PrintException(NULL, "ThreadOpenAddedConnections()");
1280 printf("ThreadOpenAddedConnections exited\n");
1283 void ThreadOpenAddedConnections2(void* parg)
1285 printf("ThreadOpenAddedConnections started\n");
1288 LOCK(cs_vAddedNodes);
1289 vAddedNodes = mapMultiArgs["-addnode"];
1292 if (HaveNameProxy()) {
1294 list<string> lAddresses(0);
1296 LOCK(cs_vAddedNodes);
1297 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1298 lAddresses.push_back(strAddNode);
1300 BOOST_FOREACH(string& strAddNode, lAddresses) {
1302 CSemaphoreGrant grant(*semOutbound);
1303 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1306 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1307 Sleep(120000); // Retry every 2 minutes
1308 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1313 for (uint32_t i = 0; true; i++)
1315 list<string> lAddresses(0);
1317 LOCK(cs_vAddedNodes);
1318 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1319 lAddresses.push_back(strAddNode);
1322 list<vector<CService> > lservAddressesToAdd(0);
1323 BOOST_FOREACH(string& strAddNode, lAddresses)
1325 vector<CService> vservNode(0);
1326 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1328 lservAddressesToAdd.push_back(vservNode);
1330 LOCK(cs_setservAddNodeAddresses);
1331 BOOST_FOREACH(CService& serv, vservNode)
1332 setservAddNodeAddresses.insert(serv);
1336 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1337 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1340 BOOST_FOREACH(CNode* pnode, vNodes)
1341 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1343 BOOST_FOREACH(CService& addrNode, *(it))
1344 if (pnode->addr == addrNode)
1346 it = lservAddressesToAdd.erase(it);
1347 if(it != lservAddressesToAdd.begin())
1351 if (it == lservAddressesToAdd.end())
1355 BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
1357 if (vserv.size() == 0)
1359 CSemaphoreGrant grant(*semOutbound);
1360 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1367 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1368 Sleep(120000); // Retry every 2 minutes
1369 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1375 // if successful, this moves the passed grant to the constructed node
1376 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1379 // Initiate outbound network connection
1384 if (IsLocal(addrConnect) ||
1385 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1386 FindNode(addrConnect.ToStringIPPort().c_str()))
1388 if (strDest && FindNode(strDest))
1391 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1392 CNode* pnode = ConnectNode(addrConnect, strDest);
1393 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1399 grantOutbound->MoveTo(pnode->grantOutbound);
1400 pnode->fNetworkNode = true;
1402 pnode->fOneShot = true;
1407 // for now, use a very simple selection metric: the node from which we received
1409 static int64_t NodeSyncScore(const CNode *pnode) {
1410 return pnode->nLastRecv;
1413 void static StartSync(const vector<CNode*> &vNodes) {
1414 CNode *pnodeNewSync = NULL;
1415 int64_t nBestScore = 0;
1417 // Iterate over all nodes
1418 BOOST_FOREACH(CNode* pnode, vNodes) {
1419 // check preconditions for allowing a sync
1420 if (!pnode->fClient && !pnode->fOneShot &&
1421 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1422 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1423 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1424 // if ok, compare node's score with the best so far
1425 int64_t nScore = NodeSyncScore(pnode);
1426 if (pnodeNewSync == NULL || nScore > nBestScore) {
1427 pnodeNewSync = pnode;
1428 nBestScore = nScore;
1432 // if a new sync candidate was found, start sync!
1434 pnodeNewSync->fStartSync = true;
1435 pnodeSync = pnodeNewSync;
1439 void ThreadMessageHandler(void* parg)
1441 // Make this thread recognisable as the message handling thread
1442 RenameThread("novacoin-msghand");
1446 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1447 ThreadMessageHandler2(parg);
1448 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1450 catch (std::exception& e) {
1451 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1452 PrintException(&e, "ThreadMessageHandler()");
1454 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1455 PrintException(NULL, "ThreadMessageHandler()");
1457 printf("ThreadMessageHandler exited\n");
1460 void ThreadMessageHandler2(void* parg)
1462 printf("ThreadMessageHandler started\n");
1463 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1466 bool fHaveSyncNode = false;
1467 vector<CNode*> vNodesCopy;
1470 vNodesCopy = vNodes;
1471 BOOST_FOREACH(CNode* pnode, vNodesCopy) {
1473 if (pnode == pnodeSync)
1474 fHaveSyncNode = true;
1479 StartSync(vNodesCopy);
1481 // Poll the connected nodes for messages
1482 CNode* pnodeTrickle = NULL;
1483 if (!vNodesCopy.empty())
1484 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1485 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1489 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1491 ProcessMessages(pnode);
1498 TRY_LOCK(pnode->cs_vSend, lockSend);
1500 SendMessages(pnode, pnode == pnodeTrickle);
1508 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
1511 // Wait and allow messages to bunch up.
1512 // Reduce vnThreadsRunning so StopNode has permission to exit while
1513 // we're sleeping, but we must always check fShutdown after doing this.
1514 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1516 if (fRequestShutdown)
1518 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1529 bool BindListenPort(const CService &addrBind, string& strError)
1534 // Create socket for listening for incoming connections
1536 struct sockaddr_storage sockaddr;
1538 struct sockaddr sockaddr;
1540 socklen_t len = sizeof(sockaddr);
1541 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1543 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1544 printf("%s\n", strError.c_str());
1548 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1549 if (hListenSocket == INVALID_SOCKET)
1551 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1552 printf("%s\n", strError.c_str());
1558 // Different way of disabling SIGPIPE on BSD
1559 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1561 // Allow binding if the port is still in TIME_WAIT state after
1562 // the program was closed and restarted. Not an issue on windows!
1563 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1567 // Set to non-blocking, incoming connections will also inherit this
1568 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1570 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1573 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1574 printf("%s\n", strError.c_str());
1579 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1580 // and enable it by default or not. Try to enable it, if possible.
1581 if (addrBind.IsIPv6()) {
1584 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1586 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1590 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1591 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
1596 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1598 int nErr = WSAGetLastError();
1599 if (nErr == WSAEADDRINUSE)
1600 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1602 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1603 printf("%s\n", strError.c_str());
1604 CloseSocket(hListenSocket);
1607 printf("Bound to %s\n", addrBind.ToString().c_str());
1609 // Listen for incoming connections
1610 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1612 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1613 printf("%s\n", strError.c_str());
1614 CloseSocket(hListenSocket);
1618 vhListenSocket.push_back(hListenSocket);
1620 if (addrBind.IsRoutable() && fDiscover)
1621 AddLocal(addrBind, LOCAL_BIND);
1626 void static Discover()
1632 // Get local host IP
1633 char pszHostName[1000] = "";
1634 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1636 vector<CNetAddr> vaddr;
1637 if (LookupHost(pszHostName, vaddr))
1639 BOOST_FOREACH (const CNetAddr &addr, vaddr)
1641 AddLocal(addr, LOCAL_IF);
1646 // Get local host ip
1647 struct ifaddrs* myaddrs;
1648 if (getifaddrs(&myaddrs) == 0)
1650 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1652 if (ifa->ifa_addr == NULL) continue;
1653 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1654 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1655 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1656 if (ifa->ifa_addr->sa_family == AF_INET)
1658 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1659 CNetAddr addr(s4->sin_addr);
1660 if (AddLocal(addr, LOCAL_IF))
1661 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1664 else if (ifa->ifa_addr->sa_family == AF_INET6)
1666 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1667 CNetAddr addr(s6->sin6_addr);
1668 if (AddLocal(addr, LOCAL_IF))
1669 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1673 freeifaddrs(myaddrs);
1677 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1678 if (!IsLimited(NET_IPV4))
1679 NewThread(ThreadGetMyExternalIP, NULL);
1682 void StartNode(void* parg)
1684 // Make this thread recognisable as the startup thread
1685 RenameThread("novacoin-start");
1687 if (semOutbound == NULL) {
1688 // initialize semaphore
1689 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1690 semOutbound = new CSemaphore(nMaxOutbound);
1693 if (pnodeLocalHost == NULL)
1694 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1702 if (!GetBoolArg("-dnsseed", true))
1703 printf("DNS seeding disabled\n");
1705 if (!NewThread(ThreadDNSAddressSeed, NULL))
1706 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1708 // Get addresses from IRC and advertise ours
1709 if (!GetBoolArg("-irc", true))
1710 printf("IRC seeding disabled\n");
1712 if (!NewThread(ThreadIRCSeed, NULL))
1713 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1715 // Send and receive from sockets, accept connections
1716 if (!NewThread(ThreadSocketHandler, NULL))
1717 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1719 // Initiate outbound connections from -addnode
1720 if (!NewThread(ThreadOpenAddedConnections, NULL))
1721 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1723 // Initiate outbound connections
1724 if (!NewThread(ThreadOpenConnections, NULL))
1725 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1728 if (!NewThread(ThreadMessageHandler, NULL))
1729 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1731 // Dump network addresses
1732 if (!NewThread(ThreadDumpAddress, NULL))
1733 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1735 // Mine proof-of-stake blocks in the background
1736 if (!NewThread(ThreadStakeMiner, pwalletMain))
1737 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1739 // Trusted NTP server, it's localhost by default.
1740 strTrustedUpstream = GetArg("-ntp", "localhost");
1742 // Start periodical NTP sampling thread
1743 NewThread(ThreadNtpSamples, NULL);
1749 printf("StopNode()\n");
1751 nTransactionsUpdated++;
1752 int64_t nStart = GetTime();
1755 ThreadScriptCheckQuit();
1758 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1759 semOutbound->post();
1762 int nThreadsRunning = 0;
1763 for (int n = 0; n < THREAD_MAX; n++)
1764 nThreadsRunning += vnThreadsRunning[n];
1765 if (nThreadsRunning == 0)
1767 if (GetTime() - nStart > 20)
1771 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1772 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1773 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1774 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1775 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1776 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1777 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1778 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1779 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1780 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1781 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1798 BOOST_FOREACH(CNode* pnode, vNodes)
1799 if (pnode->hSocket != INVALID_SOCKET)
1800 CloseSocket(pnode->hSocket);
1801 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
1802 if (hListenSocket != INVALID_SOCKET)
1803 if (!CloseSocket(hListenSocket))
1804 printf("CloseSocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1806 // clean up some globals (to help leak detection)
1807 BOOST_FOREACH(CNode *pnode, vNodes)
1809 BOOST_FOREACH(CNode *pnode, vNodesDisconnected)
1812 vNodesDisconnected.clear();
1815 delete pnodeLocalHost;
1816 pnodeLocalHost = NULL;
1819 // Shutdown Windows Sockets
1824 instance_of_cnetcleanup;
1826 void RelayTransaction(const CTransaction& tx, const uint256& hash)
1828 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1831 RelayTransaction(tx, hash, ss);
1834 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
1836 CInv inv(MSG_TX, hash);
1839 // Expire old relay messages
1840 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1842 mapRelay.erase(vRelayExpiration.front().second);
1843 vRelayExpiration.pop_front();
1846 // Save original serialized message so newer versions are preserved
1847 mapRelay.insert(std::make_pair(inv, ss));
1848 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
1851 RelayInventory(inv);
1854 void CNode::RecordBytesRecv(uint64_t bytes)
1856 LOCK(cs_totalBytesRecv);
1857 nTotalBytesRecv += bytes;
1860 void CNode::RecordBytesSent(uint64_t bytes)
1862 LOCK(cs_totalBytesSent);
1863 nTotalBytesSent += bytes;
1866 uint64_t CNode::GetTotalBytesRecv()
1868 LOCK(cs_totalBytesRecv);
1869 return nTotalBytesRecv;
1872 uint64_t CNode::GetTotalBytesSent()
1874 LOCK(cs_totalBytesSent);
1875 return nTotalBytesSent;