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 int GetnScore(const CService& addr)
223 LOCK(cs_mapLocalHost);
224 if (mapLocalHost.count(addr) == LOCAL_NONE)
226 return mapLocalHost[addr].nScore;
230 // Is our peer's addrLocal potentially useful as an external IP source?
231 bool IsPeerAddrLocalGood(CNode *pnode)
233 return fDiscover && pnode->addr.IsRoutable() && pnode->addrLocal.IsRoutable() &&
234 !IsLimited(pnode->addrLocal.GetNetwork());
237 // pushes our own address to a peer
238 void AdvertiseLocal(CNode *pnode)
240 if (!fNoListen && pnode->fSuccessfullyConnected)
242 CAddress addrLocal = GetLocalAddress(&pnode->addr);
243 // If discovery is enabled, sometimes give our peer the address it
244 // tells us that it sees us as in case it has a better idea of our
245 // address than we do.
246 if (IsPeerAddrLocalGood(pnode) && (!addrLocal.IsRoutable() ||
247 GetRand((GetnScore(addrLocal) > LOCAL_MANUAL) ? 8:2) == 0))
249 addrLocal.SetIP(pnode->addrLocal);
251 if (addrLocal.IsRoutable())
253 printf("AdvertiseLocal: advertising address %s\n", addrLocal.ToString().c_str());
254 pnode->PushAddress(addrLocal);
259 // learn a new local address
260 bool AddLocal(const CService& addr, int nScore)
262 if (!addr.IsRoutable())
265 if (!fDiscover && nScore < LOCAL_MANUAL)
271 printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
274 LOCK(cs_mapLocalHost);
275 bool fAlready = mapLocalHost.count(addr) > 0;
276 LocalServiceInfo &info = mapLocalHost[addr];
277 if (!fAlready || nScore >= info.nScore) {
278 info.nScore = nScore + (fAlready ? 1 : 0);
279 info.nPort = addr.GetPort();
281 SetReachable(addr.GetNetwork());
289 bool AddLocal(const CNetAddr &addr, int nScore)
291 return AddLocal(CService(addr, GetListenPort()), nScore);
294 /** Make a particular network entirely off-limits (no automatic connects to it) */
295 void SetLimited(enum Network net, bool fLimited)
297 if (net == NET_UNROUTABLE)
299 LOCK(cs_mapLocalHost);
300 vfLimited[net] = fLimited;
303 bool IsLimited(enum Network net)
305 LOCK(cs_mapLocalHost);
306 return vfLimited[net];
309 bool IsLimited(const CNetAddr &addr)
311 return IsLimited(addr.GetNetwork());
314 /** vote for a local address */
315 bool SeenLocal(const CService& addr)
318 LOCK(cs_mapLocalHost);
319 if (mapLocalHost.count(addr) == 0)
321 mapLocalHost[addr].nScore++;
329 /** check whether a given address is potentially local */
330 bool IsLocal(const CService& addr)
332 LOCK(cs_mapLocalHost);
333 return mapLocalHost.count(addr) > 0;
336 /** check whether a given address is in a network we can probably connect to */
337 bool IsReachable(const CNetAddr& addr)
339 LOCK(cs_mapLocalHost);
340 enum Network net = addr.GetNetwork();
341 return vfReachable[net] && !vfLimited[net];
344 extern int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv);
346 // We now get our external IP from the IRC server first and only use this as a backup
347 bool GetMyExternalIP(CNetAddr& ipRet)
349 struct sockaddr_in mapped;
350 uint64_t rnd = std::numeric_limits<uint64_t>::max();
352 int rc = GetExternalIPbySTUN(rnd, &mapped, &srv);
354 ipRet = CNetAddr(mapped.sin_addr);
355 printf("GetExternalIPbySTUN(%" PRIu64 ") returned %s in attempt %d; Server=%s\n", rnd, ipRet.ToStringIP().c_str(), rc, srv);
361 void ThreadGetMyExternalIP(void* parg)
363 // Make this thread recognisable as the external IP detection thread
364 RenameThread("novacoin-ext-ip");
366 CNetAddr addrLocalHost;
367 if (GetMyExternalIP(addrLocalHost))
369 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
370 AddLocal(addrLocalHost, LOCAL_HTTP);
378 void AddressCurrentlyConnected(const CService& addr)
380 addrman.Connected(addr);
386 uint64_t CNode::nTotalBytesRecv = 0;
387 uint64_t CNode::nTotalBytesSent = 0;
388 CCriticalSection CNode::cs_totalBytesRecv;
389 CCriticalSection CNode::cs_totalBytesSent;
391 CNode* FindNode(const CNetAddr& ip)
394 BOOST_FOREACH(CNode* pnode, vNodes)
395 if ((CNetAddr)pnode->addr == ip)
400 CNode* FindNode(std::string addrName)
403 BOOST_FOREACH(CNode* pnode, vNodes)
404 if (pnode->addrName == addrName)
409 CNode* FindNode(const CService& addr)
412 BOOST_FOREACH(CNode* pnode, vNodes)
413 if ((CService)pnode->addr == addr)
418 CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64_t nTimeout)
420 if (pszDest == NULL) {
421 if (IsLocal(addrConnect))
424 // Look for an existing connection
425 CNode* pnode = FindNode((CService)addrConnect);
429 pnode->AddRef(nTimeout);
438 printf("trying connection %s lastseen=%.1fhrs\n",
439 pszDest ? pszDest : addrConnect.ToString().c_str(),
440 pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
444 if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
446 addrman.Attempt(addrConnect);
449 printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
451 // Set to non-blocking
454 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
455 printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
457 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
458 printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
462 CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
464 pnode->AddRef(nTimeout);
470 vNodes.push_back(pnode);
473 pnode->nTimeConnected = GetTime();
482 void CNode::CloseSocketDisconnect()
485 if (hSocket != INVALID_SOCKET)
487 printf("disconnecting node %s\n", addrName.c_str());
488 CloseSocket(hSocket);
492 // in case this fails, we'll empty the recv buffer when the CNode is deleted
493 TRY_LOCK(cs_vRecv, lockRecv);
497 // if this was the sync node, we'll need a new one
498 if (this == pnodeSync)
502 void CNode::Cleanup()
507 void CNode::PushVersion()
509 int64_t nTime = GetAdjustedTime();
510 CAddress addrYou, addrMe;
512 bool fHidden = false;
514 if (mapArgs.count("-torname")) {
515 // Our hidden service address
516 CService addrTorName(mapArgs["-torname"], GetListenPort());
518 if (addrTorName.IsValid()) {
520 addrMe = CAddress(addrTorName);
527 addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", nPortZero)));
528 addrMe = GetLocalAddress(&addr);
531 RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
532 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());
533 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
534 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
541 std::map<CNetAddr, int64_t> CNode::setBanned;
542 CCriticalSection CNode::cs_setBanned;
544 void CNode::ClearBanned()
549 bool CNode::IsBanned(CNetAddr ip)
551 bool fResult = false;
554 std::map<CNetAddr, int64_t>::iterator i = setBanned.find(ip);
555 if (i != setBanned.end())
557 int64_t t = (*i).second;
565 bool CNode::Misbehaving(int howmuch)
569 printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
573 nMisbehavior += howmuch;
574 if (nMisbehavior >= GetArgInt("-banscore", 100))
576 int64_t banTime = GetTime()+GetArg("-bantime", nOneDay); // Default 24-hour ban
577 printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
580 if (setBanned[addr] < banTime)
581 setBanned[addr] = banTime;
583 CloseSocketDisconnect();
586 printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
591 #define X(name) stats.name = name
592 void CNode::copyStats(CNodeStats &stats)
607 stats.fSyncNode = (this == pnodeSync);
611 void Release(CNode* node) {
619 void ThreadSocketHandler(void* parg)
621 // Make this thread recognisable as the networking thread
622 RenameThread("novacoin-net");
626 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
627 ThreadSocketHandler2(parg);
628 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
630 catch (std::exception& e) {
631 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
632 PrintException(&e, "ThreadSocketHandler()");
634 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
635 throw; // support pthread_cancel()
637 printf("ThreadSocketHandler exited\n");
640 static list<CNode*> vNodesDisconnected;
642 void ThreadSocketHandler2(void* parg)
644 printf("ThreadSocketHandler started\n");
645 size_t nPrevNodeCount = 0;
653 // Disconnect unused nodes
654 vector<CNode*> vNodesCopy = vNodes;
655 BOOST_FOREACH(CNode* pnode, vNodesCopy)
657 if (pnode->fDisconnect ||
658 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
660 // remove from vNodes
661 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
663 // release outbound grant (if any)
664 pnode->grantOutbound.Release();
666 // close socket and cleanup
667 pnode->CloseSocketDisconnect();
670 // hold in disconnected pool until all refs are released
671 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
672 if (pnode->fNetworkNode || pnode->fInbound)
674 vNodesDisconnected.push_back(pnode);
678 // Delete disconnected nodes
679 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
680 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
682 // wait until threads are done using it
683 if (pnode->GetRefCount() <= 0)
685 bool fDelete = false;
687 TRY_LOCK(pnode->cs_vSend, lockSend);
690 TRY_LOCK(pnode->cs_vRecv, lockRecv);
693 TRY_LOCK(pnode->cs_mapRequests, lockReq);
696 TRY_LOCK(pnode->cs_inventory, lockInv);
705 vNodesDisconnected.remove(pnode);
711 if (vNodes.size() != nPrevNodeCount)
713 nPrevNodeCount = vNodes.size();
714 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
719 // Find which sockets have data to receive
721 struct timeval timeout;
723 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
730 FD_ZERO(&fdsetError);
731 SOCKET hSocketMax = 0;
732 bool have_fds = false;
734 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) {
735 FD_SET(hListenSocket, &fdsetRecv);
736 hSocketMax = max(hSocketMax, hListenSocket);
741 BOOST_FOREACH(CNode* pnode, vNodes)
743 if (pnode->hSocket == INVALID_SOCKET)
745 FD_SET(pnode->hSocket, &fdsetRecv);
746 FD_SET(pnode->hSocket, &fdsetError);
747 hSocketMax = max(hSocketMax, pnode->hSocket);
750 TRY_LOCK(pnode->cs_vSend, lockSend);
751 if (lockSend && !pnode->vSend.empty())
752 FD_SET(pnode->hSocket, &fdsetSend);
757 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
758 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
759 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
760 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
763 if (nSelect == SOCKET_ERROR)
767 int nErr = WSAGetLastError();
768 printf("socket select error %d\n", nErr);
769 for (unsigned int i = 0; i <= hSocketMax; i++)
770 FD_SET(i, &fdsetRecv);
773 FD_ZERO(&fdsetError);
774 Sleep(timeout.tv_usec/1000);
779 // Accept new connections
781 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
782 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
785 struct sockaddr_storage sockaddr;
787 struct sockaddr sockaddr;
789 socklen_t len = sizeof(sockaddr);
790 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
794 if (hSocket != INVALID_SOCKET)
795 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
796 printf("Warning: Unknown socket family\n");
800 BOOST_FOREACH(CNode* pnode, vNodes)
805 if (hSocket == INVALID_SOCKET)
807 int nErr = WSAGetLastError();
808 if (nErr != WSAEWOULDBLOCK)
809 printf("socket error accept failed: %d\n", nErr);
811 else if (nInbound >= GetArgInt("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
814 LOCK(cs_setservAddNodeAddresses);
815 if (!setservAddNodeAddresses.count(addr))
816 CloseSocket(hSocket);
819 else if (CNode::IsBanned(addr))
821 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
822 CloseSocket(hSocket);
826 printf("accepted connection %s\n", addr.ToString().c_str());
827 CNode* pnode = new CNode(hSocket, addr, "", true);
831 vNodes.push_back(pnode);
838 // Service each socket
840 vector<CNode*> vNodesCopy;
844 BOOST_FOREACH(CNode* pnode, vNodesCopy)
847 BOOST_FOREACH(CNode* pnode, vNodesCopy)
855 if (pnode->hSocket == INVALID_SOCKET)
857 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
859 TRY_LOCK(pnode->cs_vRecv, lockRecv);
862 CDataStream& vRecv = pnode->vRecv;
863 uint64_t nPos = vRecv.size();
865 if (nPos > ReceiveBufferSize()) {
866 if (!pnode->fDisconnect)
867 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
868 pnode->CloseSocketDisconnect();
871 // typical socket buffer is 8K-64K
872 char pchBuf[0x10000];
873 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
876 vRecv.resize(nPos + nBytes);
877 memcpy(&vRecv[nPos], pchBuf, nBytes);
878 pnode->nLastRecv = GetTime();
879 pnode->nRecvBytes += nBytes;
880 pnode->RecordBytesRecv(nBytes);
882 else if (nBytes == 0)
884 // socket closed gracefully
885 if (!pnode->fDisconnect)
886 printf("socket closed\n");
887 pnode->CloseSocketDisconnect();
892 int nErr = WSAGetLastError();
893 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
895 if (!pnode->fDisconnect)
896 printf("socket recv error %d\n", nErr);
897 pnode->CloseSocketDisconnect();
907 if (pnode->hSocket == INVALID_SOCKET)
909 if (FD_ISSET(pnode->hSocket, &fdsetSend))
911 TRY_LOCK(pnode->cs_vSend, lockSend);
914 CDataStream& vSend = pnode->vSend;
917 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
920 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
921 pnode->nLastSend = GetTime();
922 pnode->nSendBytes += nBytes;
923 pnode->RecordBytesSent(nBytes);
928 int nErr = WSAGetLastError();
929 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
931 printf("socket send error %d\n", nErr);
932 pnode->CloseSocketDisconnect();
940 // Inactivity checking
942 if (pnode->vSend.empty())
943 pnode->nLastSendEmpty = GetTime();
944 if (GetTime() - pnode->nTimeConnected > 60)
946 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
948 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
949 pnode->fDisconnect = true;
951 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
953 printf("socket not sending\n");
954 pnode->fDisconnect = true;
956 else if (GetTime() - pnode->nLastRecv > 90*60)
958 printf("socket inactivity timeout\n");
959 pnode->fDisconnect = true;
965 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
973 // Each pair gives a source name and a seed name.
974 // The first name is used as information source for addrman.
975 // The second name should resolve to a list of seed addresses.
976 static const char *strDNSSeed[][2] = {
977 {"novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro"},
978 {"novacoin.ru", "dnsseed.novacoin.ru"},
979 {"novacoin.ru", "testseed.novacoin.ru"},
980 {"novaco.in", "dnsseed.novaco.in"},
983 void ThreadDNSAddressSeed(void* parg)
985 // Make this thread recognisable as the DNS seeding thread
986 RenameThread("novacoin-dnsseed");
990 vnThreadsRunning[THREAD_DNSSEED]++;
991 ThreadDNSAddressSeed2(parg);
992 vnThreadsRunning[THREAD_DNSSEED]--;
994 catch (std::exception& e) {
995 vnThreadsRunning[THREAD_DNSSEED]--;
996 PrintException(&e, "ThreadDNSAddressSeed()");
998 vnThreadsRunning[THREAD_DNSSEED]--;
999 throw; // support pthread_cancel()
1001 printf("ThreadDNSAddressSeed exited\n");
1004 void ThreadDNSAddressSeed2(void* parg)
1006 printf("ThreadDNSAddressSeed started\n");
1011 printf("Loading addresses from DNS seeds (could take a while)\n");
1013 for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1014 if (HaveNameProxy()) {
1015 AddOneShot(strDNSSeed[seed_idx][1]);
1017 vector<CNetAddr> vaddr;
1018 vector<CAddress> vAdd;
1019 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
1021 BOOST_FOREACH(CNetAddr& ip, vaddr)
1023 CAddress addr = CAddress(CService(ip, GetDefaultPort()));
1024 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1025 vAdd.push_back(addr);
1029 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
1034 printf("%d addresses found from DNS seeds\n", found);
1050 0xa52bf0da, 0x30aa43d8, 0x614488d5, 0x517b6fd5, 0xd4bf62d4, 0xb7d638d4, 0xbc12bcd1, 0xa2501bc6,
1051 0xfde617c6, 0x3337b1c6, 0x1dcd71c3, 0x2c1544c1, 0xe05f6ac1, 0x852f63c0, 0x3e2363c0, 0x15f563c0,
1052 0x430d63c0, 0x50d6a9c0, 0xf0a679c0, 0xefdeedbf, 0x7aaee8bc, 0x3a3dbbbc, 0xef218abc, 0x0bef78bc,
1053 0x8baa3eb2, 0x2bf913b2, 0x24ed9fb2, 0xb42289b2, 0x718a09b0, 0xe9433eb0, 0x559425b0, 0xc97e1fb0,
1054 0x18e1d4b0, 0x8f6cc1b0, 0xac3838ae, 0x86c0ffad, 0x6b0272a7, 0xa463f8a2, 0x6f17f3a2, 0xb3d6f3a2,
1055 0x9cd8f997, 0xd513fb94, 0x39e64880, 0x3859dd6f, 0x0b08fe6d, 0xe601fe6d, 0xeb44a26d, 0xfe53186c,
1056 0x203c2e68, 0x1c542868, 0x0caa8368, 0xb8748368, 0xccca4762, 0xc637555f, 0x638a545f, 0x59b2205f,
1057 0x52568c5f, 0xba568c5f, 0x8a568c5f, 0x31b0f45e, 0x54a0f45e, 0x37d6f15e, 0xc520175e, 0x7620175e,
1058 0xc310175e, 0x8e33b45e, 0x7abb5f5d, 0xd3014c5d, 0xa1e1485d, 0x9947645d, 0xfab8ff5c, 0xa979e65b,
1059 0xa879e65b, 0x9f79e65b, 0x9fa3d25b, 0x112a925b, 0x7b92905b, 0x60647a5b, 0x1e389d5a, 0x851afa59,
1060 0x0185ef59, 0x26549b59, 0x1c9efe57, 0xc54c1256, 0x1ad51955, 0x19d21955, 0x73c41955, 0x3f74ee55,
1061 0x633eea55, 0x6883d655, 0xfb72c655, 0x5360a653, 0x17c1ea52, 0xc661c852, 0x1ecdc852, 0x006a9752,
1062 0xf72d9252, 0x82650551, 0x36f1c851, 0x33f1c851, 0xd5c1864f, 0xb6bf1b4e, 0x96da184e, 0x40d0234d,
1063 0x9a96ab4c, 0x8fc2a84c, 0xb5dbd048, 0xf4644447, 0x2d51af47, 0xa9625445, 0x83f05243, 0x89672941,
1064 0x3a8bad3e, 0xf0a05436, 0x6ab7c936, 0x49971d32, 0xadd4482e, 0xcffd212e, 0x6730bc2e, 0x839aa12e,
1065 0x68d9692e, 0xc7183b25, 0x6c47bb25, 0x2490bb25, 0xad651c1f, 0x048a861f, 0x6937811f, 0x064b2d05,
1069 const char* pchTorSeed[] =
1071 "seedp4knqnoei57u.onion",
1072 "seedr3hhlepyi7fd.onion",
1073 "seed3uuomkclbiz4.onion",
1074 "seedeh7qck3ouff5.onion",
1075 "5rg3vq4jagckeckf.onion",
1076 "seedt3sraf53ajiy.onion",
1077 "seedg4qyccsg42oq.onion",
1078 "novaqrtoywpg7jly.onion",
1079 "seed3d5wolqbgrcb.onion",
1080 "seed24u5dwph3qw4.onion",
1081 "mj26ulzbs2oskgym.onion",
1082 "eqon4usunavt76m7.onion",
1083 "seedd3aldwpslzl3.onion"
1086 void DumpAddresses()
1088 int64_t nStart = GetTimeMillis();
1093 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1094 addrman.size(), GetTimeMillis() - nStart);
1097 void ThreadDumpAddress2(void* parg)
1099 printf("ThreadDumpAddress started\n");
1101 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1105 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1107 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1109 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1112 void ThreadDumpAddress(void* parg)
1114 // Make this thread recognisable as the address dumping thread
1115 RenameThread("novacoin-adrdump");
1119 ThreadDumpAddress2(parg);
1121 catch (std::exception& e) {
1122 PrintException(&e, "ThreadDumpAddress()");
1124 printf("ThreadDumpAddress exited\n");
1127 void ThreadOpenConnections(void* parg)
1129 // Make this thread recognisable as the connection opening thread
1130 RenameThread("novacoin-opencon");
1134 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1135 ThreadOpenConnections2(parg);
1136 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1138 catch (std::exception& e) {
1139 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1140 PrintException(&e, "ThreadOpenConnections()");
1142 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1143 PrintException(NULL, "ThreadOpenConnections()");
1145 printf("ThreadOpenConnections exited\n");
1148 void static ProcessOneShot()
1153 if (vOneShots.empty())
1155 strDest = vOneShots.front();
1156 vOneShots.pop_front();
1159 CSemaphoreGrant grant(*semOutbound, true);
1161 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1162 AddOneShot(strDest);
1166 void ThreadOpenConnections2(void* parg)
1168 printf("ThreadOpenConnections started\n");
1170 // Connect to specific addresses
1171 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1173 for (int64_t nLoop = 0;; nLoop++)
1176 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1179 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1180 for (int i = 0; i < 10 && i < nLoop; i++)
1191 // Initiate network connections
1192 int64_t nStart = GetTime();
1197 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1199 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1204 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1205 CSemaphoreGrant grant(*semOutbound);
1206 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1210 // Add seed nodes if IRC isn't working
1211 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1213 std::vector<CAddress> vAdd;
1214 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1216 // It'll only connect to one or two seed nodes because once it connects,
1217 // it'll get a pile of addresses with newer timestamps.
1218 // Seed nodes are given a random 'last seen time' of between one and two
1221 memcpy(&ip, &pnSeed[i], sizeof(ip));
1222 CAddress addr(CService(ip, GetDefaultPort()));
1223 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1224 vAdd.push_back(addr);
1226 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1229 // Add Tor nodes if we have connection with onion router
1230 if (mapArgs.count("-tor"))
1232 std::vector<CAddress> vAdd;
1233 for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1235 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1236 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1237 vAdd.push_back(addr);
1239 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1243 // Choose an address to connect to based on most recently seen
1245 CAddress addrConnect;
1247 // Only connect out to one peer per network group (/16 for IPv4).
1248 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1250 set<vector<unsigned char> > setConnected;
1253 BOOST_FOREACH(CNode* pnode, vNodes) {
1254 if (!pnode->fInbound) {
1255 setConnected.insert(pnode->addr.GetGroup());
1261 int64_t nANow = GetAdjustedTime();
1266 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1267 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1269 // if we selected an invalid address, restart
1270 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1273 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1274 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1275 // already-connected network ranges, ...) before trying new addrman addresses.
1280 if (IsLimited(addr))
1283 // only consider very recently tried nodes after 30 failed attempts
1284 if (nANow - addr.nLastTry < 600 && nTries < 30)
1287 // do not allow non-default ports, unless after 50 invalid addresses selected already
1288 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1295 if (addrConnect.IsValid())
1296 OpenNetworkConnection(addrConnect, &grant);
1300 void ThreadOpenAddedConnections(void* parg)
1302 // Make this thread recognisable as the connection opening thread
1303 RenameThread("novacoin-opencon");
1307 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1308 ThreadOpenAddedConnections2(parg);
1309 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1311 catch (std::exception& e) {
1312 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1313 PrintException(&e, "ThreadOpenAddedConnections()");
1315 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1316 PrintException(NULL, "ThreadOpenAddedConnections()");
1318 printf("ThreadOpenAddedConnections exited\n");
1321 void ThreadOpenAddedConnections2(void* parg)
1323 printf("ThreadOpenAddedConnections started\n");
1326 LOCK(cs_vAddedNodes);
1327 vAddedNodes = mapMultiArgs["-addnode"];
1330 if (HaveNameProxy()) {
1332 list<string> lAddresses(0);
1334 LOCK(cs_vAddedNodes);
1335 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1336 lAddresses.push_back(strAddNode);
1338 BOOST_FOREACH(string& strAddNode, lAddresses) {
1340 CSemaphoreGrant grant(*semOutbound);
1341 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1344 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1345 Sleep(120000); // Retry every 2 minutes
1346 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1351 for (uint32_t i = 0; true; i++)
1353 list<string> lAddresses(0);
1355 LOCK(cs_vAddedNodes);
1356 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1357 lAddresses.push_back(strAddNode);
1360 list<vector<CService> > lservAddressesToAdd(0);
1361 BOOST_FOREACH(string& strAddNode, lAddresses)
1363 vector<CService> vservNode(0);
1364 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1366 lservAddressesToAdd.push_back(vservNode);
1368 LOCK(cs_setservAddNodeAddresses);
1369 BOOST_FOREACH(CService& serv, vservNode)
1370 setservAddNodeAddresses.insert(serv);
1374 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1375 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1378 BOOST_FOREACH(CNode* pnode, vNodes)
1379 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1381 BOOST_FOREACH(CService& addrNode, *(it))
1382 if (pnode->addr == addrNode)
1384 it = lservAddressesToAdd.erase(it);
1385 if(it != lservAddressesToAdd.begin())
1389 if (it == lservAddressesToAdd.end())
1393 BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
1395 if (vserv.size() == 0)
1397 CSemaphoreGrant grant(*semOutbound);
1398 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1405 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1406 Sleep(120000); // Retry every 2 minutes
1407 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1413 // if successful, this moves the passed grant to the constructed node
1414 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1417 // Initiate outbound network connection
1422 if (IsLocal(addrConnect) ||
1423 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1424 FindNode(addrConnect.ToStringIPPort().c_str()))
1426 if (strDest && FindNode(strDest))
1429 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1430 CNode* pnode = ConnectNode(addrConnect, strDest);
1431 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1437 grantOutbound->MoveTo(pnode->grantOutbound);
1438 pnode->fNetworkNode = true;
1440 pnode->fOneShot = true;
1445 // for now, use a very simple selection metric: the node from which we received
1447 static int64_t NodeSyncScore(const CNode *pnode) {
1448 return pnode->nLastRecv;
1451 void static StartSync(const vector<CNode*> &vNodes) {
1452 CNode *pnodeNewSync = NULL;
1453 int64_t nBestScore = 0;
1455 // Iterate over all nodes
1456 BOOST_FOREACH(CNode* pnode, vNodes) {
1457 // check preconditions for allowing a sync
1458 if (!pnode->fClient && !pnode->fOneShot &&
1459 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1460 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1461 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1462 // if ok, compare node's score with the best so far
1463 int64_t nScore = NodeSyncScore(pnode);
1464 if (pnodeNewSync == NULL || nScore > nBestScore) {
1465 pnodeNewSync = pnode;
1466 nBestScore = nScore;
1470 // if a new sync candidate was found, start sync!
1472 pnodeNewSync->fStartSync = true;
1473 pnodeSync = pnodeNewSync;
1477 void ThreadMessageHandler(void* parg)
1479 // Make this thread recognisable as the message handling thread
1480 RenameThread("novacoin-msghand");
1484 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1485 ThreadMessageHandler2(parg);
1486 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1488 catch (std::exception& e) {
1489 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1490 PrintException(&e, "ThreadMessageHandler()");
1492 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1493 PrintException(NULL, "ThreadMessageHandler()");
1495 printf("ThreadMessageHandler exited\n");
1498 void ThreadMessageHandler2(void* parg)
1500 printf("ThreadMessageHandler started\n");
1501 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1504 bool fHaveSyncNode = false;
1505 vector<CNode*> vNodesCopy;
1508 vNodesCopy = vNodes;
1509 BOOST_FOREACH(CNode* pnode, vNodesCopy) {
1511 if (pnode == pnodeSync)
1512 fHaveSyncNode = true;
1517 StartSync(vNodesCopy);
1519 // Poll the connected nodes for messages
1520 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1524 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1526 ProcessMessages(pnode);
1533 TRY_LOCK(pnode->cs_vSend, lockSend);
1535 SendMessages(pnode);
1543 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
1546 // Wait and allow messages to bunch up.
1547 // Reduce vnThreadsRunning so StopNode has permission to exit while
1548 // we're sleeping, but we must always check fShutdown after doing this.
1549 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1551 if (fRequestShutdown)
1553 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1564 bool BindListenPort(const CService &addrBind, string& strError)
1569 // Create socket for listening for incoming connections
1571 struct sockaddr_storage sockaddr;
1573 struct sockaddr sockaddr;
1575 socklen_t len = sizeof(sockaddr);
1576 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1578 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1579 printf("%s\n", strError.c_str());
1583 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1584 if (hListenSocket == INVALID_SOCKET)
1586 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1587 printf("%s\n", strError.c_str());
1593 // Different way of disabling SIGPIPE on BSD
1594 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1596 // Allow binding if the port is still in TIME_WAIT state after
1597 // the program was closed and restarted. Not an issue on windows!
1598 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1602 // Set to non-blocking, incoming connections will also inherit this
1603 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1605 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1608 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1609 printf("%s\n", strError.c_str());
1614 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1615 // and enable it by default or not. Try to enable it, if possible.
1616 if (addrBind.IsIPv6()) {
1619 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1621 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1625 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1626 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
1631 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1633 int nErr = WSAGetLastError();
1634 if (nErr == WSAEADDRINUSE)
1635 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1637 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1638 printf("%s\n", strError.c_str());
1639 CloseSocket(hListenSocket);
1642 printf("Bound to %s\n", addrBind.ToString().c_str());
1644 // Listen for incoming connections
1645 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1647 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1648 printf("%s\n", strError.c_str());
1649 CloseSocket(hListenSocket);
1653 vhListenSocket.push_back(hListenSocket);
1655 if (addrBind.IsRoutable() && fDiscover)
1656 AddLocal(addrBind, LOCAL_BIND);
1661 void static Discover()
1667 // Get local host IP
1668 char pszHostName[1000] = "";
1669 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1671 vector<CNetAddr> vaddr;
1672 if (LookupHost(pszHostName, vaddr))
1674 BOOST_FOREACH (const CNetAddr &addr, vaddr)
1676 AddLocal(addr, LOCAL_IF);
1681 // Get local host ip
1682 struct ifaddrs* myaddrs;
1683 if (getifaddrs(&myaddrs) == 0)
1685 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1687 if (ifa->ifa_addr == NULL) continue;
1688 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1689 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1690 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1691 if (ifa->ifa_addr->sa_family == AF_INET)
1693 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1694 CNetAddr addr(s4->sin_addr);
1695 if (AddLocal(addr, LOCAL_IF))
1696 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1699 else if (ifa->ifa_addr->sa_family == AF_INET6)
1701 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1702 CNetAddr addr(s6->sin6_addr);
1703 if (AddLocal(addr, LOCAL_IF))
1704 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1708 freeifaddrs(myaddrs);
1712 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1713 if (!IsLimited(NET_IPV4))
1714 NewThread(ThreadGetMyExternalIP, NULL);
1717 void StartNode(void* parg)
1719 // Make this thread recognisable as the startup thread
1720 RenameThread("novacoin-start");
1722 if (semOutbound == NULL) {
1723 // initialize semaphore
1724 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1725 semOutbound = new CSemaphore(nMaxOutbound);
1728 if (pnodeLocalHost == NULL)
1729 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1737 if (!GetBoolArg("-dnsseed", true))
1738 printf("DNS seeding disabled\n");
1740 if (!NewThread(ThreadDNSAddressSeed, NULL))
1741 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1743 // Get addresses from IRC and advertise ours
1744 if (!GetBoolArg("-irc", true))
1745 printf("IRC seeding disabled\n");
1747 if (!NewThread(ThreadIRCSeed, NULL))
1748 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1750 // Send and receive from sockets, accept connections
1751 if (!NewThread(ThreadSocketHandler, NULL))
1752 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1754 // Initiate outbound connections from -addnode
1755 if (!NewThread(ThreadOpenAddedConnections, NULL))
1756 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1758 // Initiate outbound connections
1759 if (!NewThread(ThreadOpenConnections, NULL))
1760 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1763 if (!NewThread(ThreadMessageHandler, NULL))
1764 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1766 // Dump network addresses
1767 if (!NewThread(ThreadDumpAddress, NULL))
1768 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1770 // Mine proof-of-stake blocks in the background
1771 if (!NewThread(ThreadStakeMiner, pwalletMain))
1772 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1774 // Trusted NTP server, it's localhost by default.
1775 strTrustedUpstream = GetArg("-ntp", "localhost");
1777 // Start periodical NTP sampling thread
1778 NewThread(ThreadNtpSamples, NULL);
1784 printf("StopNode()\n");
1786 nTransactionsUpdated++;
1787 int64_t nStart = GetTime();
1790 ThreadScriptCheckQuit();
1793 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1794 semOutbound->post();
1797 int nThreadsRunning = 0;
1798 for (int n = 0; n < THREAD_MAX; n++)
1799 nThreadsRunning += vnThreadsRunning[n];
1800 if (nThreadsRunning == 0)
1802 if (GetTime() - nStart > 20)
1806 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1807 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1808 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1809 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1810 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1811 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1812 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1813 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1814 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1815 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1816 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1833 BOOST_FOREACH(CNode* pnode, vNodes)
1834 if (pnode->hSocket != INVALID_SOCKET)
1835 CloseSocket(pnode->hSocket);
1836 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
1837 if (hListenSocket != INVALID_SOCKET)
1838 if (!CloseSocket(hListenSocket))
1839 printf("CloseSocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1841 // clean up some globals (to help leak detection)
1842 BOOST_FOREACH(CNode *pnode, vNodes)
1844 BOOST_FOREACH(CNode *pnode, vNodesDisconnected)
1847 vNodesDisconnected.clear();
1850 delete pnodeLocalHost;
1851 pnodeLocalHost = NULL;
1854 // Shutdown Windows Sockets
1859 instance_of_cnetcleanup;
1861 void RelayTransaction(const CTransaction& tx, const uint256& hash)
1863 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1866 RelayTransaction(tx, hash, ss);
1869 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
1871 CInv inv(MSG_TX, hash);
1874 // Expire old relay messages
1875 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1877 mapRelay.erase(vRelayExpiration.front().second);
1878 vRelayExpiration.pop_front();
1881 // Save original serialized message so newer versions are preserved
1882 mapRelay.insert(std::make_pair(inv, ss));
1883 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
1886 RelayInventory(inv);
1889 void CNode::RecordBytesRecv(uint64_t bytes)
1891 LOCK(cs_totalBytesRecv);
1892 nTotalBytesRecv += bytes;
1895 void CNode::RecordBytesSent(uint64_t bytes)
1897 LOCK(cs_totalBytesSent);
1898 nTotalBytesSent += bytes;
1901 uint64_t CNode::GetTotalBytesRecv()
1903 LOCK(cs_totalBytesRecv);
1904 return nTotalBytesRecv;
1907 uint64_t CNode::GetTotalBytesSent()
1909 LOCK(cs_totalBytesSent);
1910 return nTotalBytesSent;
1912 int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) {
1913 return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);