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 "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 {"node.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 0x1c542868, 0x3859dd6f, 0x203c2e68, 0xf145a6bc, 0x638a545f, 0x325da346, 0x385da346, 0xfb2b8d5f,
1051 0x52568c5f, 0xa979e65b, 0x8de6485d, 0x9f79e65b, 0x048a861f, 0x3388b55f, 0x6ff0b45e, 0x17e81f5f,
1052 0x6c47bb25, 0x1ecdc852, 0x28263db9, 0x47824e5d, 0x36f1c851, 0x2bf913b2, 0x95923cb3, 0x84e63eb2,
1053 0xefdeedbf, 0x65200092, 0xf36f6805, 0x42692d05, 0x772c1955, 0xb6bf1b4e, 0x7abb5f5d, 0xdb2fa6bc,
1054 0x90e911bf, 0x82de565f, 0x694416b2, 0x0ab600bc, 0xfcecbe6d, 0x24ed9fb2, 0x1bb618c2, 0xc64765bb,
1055 0x4e3d62c3, 0xdba24baa, 0x4b7109b0, 0x12a12cc2, 0xfc01864f, 0x0b69e85b, 0x33922c1f, 0xac611bc6,
1056 0x2a257155, 0x991d5fc0, 0xbfdabcb1, 0x9b73ee55, 0x5bc2b95d, 0xdef0762e, 0x6ab7c936, 0x9c4416b2,
1057 0xd60d864f, 0x03671f1f, 0x3b5da346, 0xc6f5c851, 0x5411b2d4, 0xe7c25702, 0x63474fb0, 0x7e11c854,
1058 0x52381d5f, 0x72fdfe59, 0x51599a05, 0xfb12b2d4, 0xaee4f15e, 0xd0e3f15e, 0x2aa2805f, 0xa1caf15e,
1059 0x34fe425e, 0x46e1f15e, 0xd7c71955, 0xaeeff15e, 0x47c2af55, 0x563d89b2, 0x67980fd9, 0xc9def15e,
1060 0x9cc51eb9, 0xdaa7aa6b, 0x78e6871f, 0x0d5d2cb2, 0x7aedf15e, 0x9bcaf15e, 0xe5f7f15e, 0x501c1759,
1061 0xdfbc4980, 0xa7397f2e, 0x31ea1a02, 0x3a27655e, 0xaa86f05c, 0xdcddf15e, 0x64689cb2, 0xd4bf62d4,
1062 0xf093eab2, 0x98def15e, 0xb6c5f15e, 0x81e8f15e, 0xe5d2fe59, 0xa312786d, 0x4cf9fe59, 0x8a922c1f,
1063 0x00c7fe59, 0x1ade565f, 0x9e4116b2, 0x2c36983e, 0x68f8f15e, 0x51b7eab2, 0x76c51eb9, 0x9edd4980,
1064 0x90ef565f, 0x0dd80857, 0xd513fb94, 0xf5bdeab2, 0xa95277b0, 0x2cf2f15e, 0x1897eab2, 0x924416b2,
1065 0x985c9b59, 0x30aa43d8, 0xf9c6745f, 0xaf862e5f, 0xe0ceeab2, 0xb9b3eab2, 0x6da4eab2, 0xa4fdeab2,
1066 0x0fa6c125, 0xe38bbd05, 0x5d922c1f, 0x9bd0eab2, 0x73025e02, 0xc4fd794d, 0x8435b35f, 0x2d01bc2e,
1067 0xaa2a14d4, 0xa22b07cb, 0xebda6f4f, 0xddc6514e, 0xf23feab2, 0xea1e5256, 0x6147b45e, 0x47d21e4f,
1068 0x67c41c1f, 0x53ec1a02, 0x352e786d, 0x6bec1a02, 0x78fb4abe, 0xd3014c5d, 0x9fbbeab2, 0x1fc51eb9,
1069 0x720eeab2, 0x2db5eab2, 0xe8baf65c, 0x521b459e, 0x65c4955f, 0x0e7b915f, 0xa8f37e6d, 0x6d0b465f,
1070 0xfab8ff5c, 0xf7c27e6d, 0x7345a846, 0x4fd1a7d5, 0xdfc97e6d, 0x26c27e6d, 0xa9de36b2, 0xc615344d,
1071 0x28ceb95d, 0xa52d895e, 0x18c17e6d, 0x13ec1a02, 0x0ba37125, 0x6c3d344d, 0xb3922c1f, 0x506bbeb0,
1072 0x4d04994e, 0xa1bbe56d, 0xf62c344d, 0x0847d048, 0x4bdc6451, 0xc95b9a05, 0xbcd3a7d5, 0x29b57125,
1073 0x0c4d2cb2, 0xf2b8eab2, 0xc2d5b95d, 0x0185ef59, 0x30adeab2, 0xcaf0e92e, 0x756c344d, 0xfd9e252e,
1074 0xbe5ef3bc, 0x4689344d, 0xb223895e, 0xfcebeaad, 0xb7c0e92e, 0x993c1760, 0xe1e171b0, 0xb857e75b,
1075 0xbf10002e, 0xb55b2cb2, 0xa90e2cb2, 0x13d6f15e, 0xf8be9225, 0x14ddf15e, 0x06e90305, 0x82472cb2,
1078 const char* pchTorSeed[] =
1080 "seedp4knqnoei57u.onion",
1081 "seedr3hhlepyi7fd.onion",
1082 "seed3uuomkclbiz4.onion",
1083 "seedeh7qck3ouff5.onion",
1084 "5rg3vq4jagckeckf.onion",
1085 "seedt3sraf53ajiy.onion",
1086 "seedg4qyccsg42oq.onion",
1087 "novaqrtoywpg7jly.onion",
1088 "seed3d5wolqbgrcb.onion",
1089 "seed24u5dwph3qw4.onion",
1090 "mj26ulzbs2oskgym.onion",
1091 "eqon4usunavt76m7.onion",
1092 "seedd3aldwpslzl3.onion"
1095 void DumpAddresses()
1097 int64_t nStart = GetTimeMillis();
1102 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1103 addrman.size(), GetTimeMillis() - nStart);
1106 void ThreadDumpAddress2(void* parg)
1108 printf("ThreadDumpAddress started\n");
1110 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1114 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1116 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1118 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1121 void ThreadDumpAddress(void* parg)
1123 // Make this thread recognisable as the address dumping thread
1124 RenameThread("novacoin-adrdump");
1128 ThreadDumpAddress2(parg);
1130 catch (std::exception& e) {
1131 PrintException(&e, "ThreadDumpAddress()");
1133 printf("ThreadDumpAddress exited\n");
1136 void ThreadOpenConnections(void* parg)
1138 // Make this thread recognisable as the connection opening thread
1139 RenameThread("novacoin-opencon");
1143 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1144 ThreadOpenConnections2(parg);
1145 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1147 catch (std::exception& e) {
1148 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1149 PrintException(&e, "ThreadOpenConnections()");
1151 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1152 PrintException(NULL, "ThreadOpenConnections()");
1154 printf("ThreadOpenConnections exited\n");
1157 void static ProcessOneShot()
1162 if (vOneShots.empty())
1164 strDest = vOneShots.front();
1165 vOneShots.pop_front();
1168 CSemaphoreGrant grant(*semOutbound, true);
1170 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1171 AddOneShot(strDest);
1175 void ThreadOpenConnections2(void* parg)
1177 printf("ThreadOpenConnections started\n");
1179 // Connect to specific addresses
1180 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1182 for (int64_t nLoop = 0;; nLoop++)
1185 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1188 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1189 for (int i = 0; i < 10 && i < nLoop; i++)
1200 // Initiate network connections
1201 int64_t nStart = GetTime();
1206 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1208 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1213 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1214 CSemaphoreGrant grant(*semOutbound);
1215 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1219 // Add seed nodes if IRC isn't working
1220 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1222 std::vector<CAddress> vAdd;
1223 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1225 // It'll only connect to one or two seed nodes because once it connects,
1226 // it'll get a pile of addresses with newer timestamps.
1227 // Seed nodes are given a random 'last seen time' of between one and two
1230 memcpy(&ip, &pnSeed[i], sizeof(ip));
1231 CAddress addr(CService(ip, GetDefaultPort()));
1232 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1233 vAdd.push_back(addr);
1235 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1238 // Add Tor nodes if we have connection with onion router
1239 if (mapArgs.count("-tor"))
1241 std::vector<CAddress> vAdd;
1242 for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1244 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1245 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1246 vAdd.push_back(addr);
1248 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1252 // Choose an address to connect to based on most recently seen
1254 CAddress addrConnect;
1256 // Only connect out to one peer per network group (/16 for IPv4).
1257 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1259 set<vector<unsigned char> > setConnected;
1262 BOOST_FOREACH(CNode* pnode, vNodes) {
1263 if (!pnode->fInbound) {
1264 setConnected.insert(pnode->addr.GetGroup());
1270 int64_t nANow = GetAdjustedTime();
1275 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1276 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1278 // if we selected an invalid address, restart
1279 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1282 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1283 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1284 // already-connected network ranges, ...) before trying new addrman addresses.
1289 if (IsLimited(addr))
1292 // only consider very recently tried nodes after 30 failed attempts
1293 if (nANow - addr.nLastTry < 600 && nTries < 30)
1296 // do not allow non-default ports, unless after 50 invalid addresses selected already
1297 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1304 if (addrConnect.IsValid())
1305 OpenNetworkConnection(addrConnect, &grant);
1309 void ThreadOpenAddedConnections(void* parg)
1311 // Make this thread recognisable as the connection opening thread
1312 RenameThread("novacoin-opencon");
1316 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1317 ThreadOpenAddedConnections2(parg);
1318 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1320 catch (std::exception& e) {
1321 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1322 PrintException(&e, "ThreadOpenAddedConnections()");
1324 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1325 PrintException(NULL, "ThreadOpenAddedConnections()");
1327 printf("ThreadOpenAddedConnections exited\n");
1330 void ThreadOpenAddedConnections2(void* parg)
1332 printf("ThreadOpenAddedConnections started\n");
1335 LOCK(cs_vAddedNodes);
1336 vAddedNodes = mapMultiArgs["-addnode"];
1339 if (HaveNameProxy()) {
1341 list<string> lAddresses(0);
1343 LOCK(cs_vAddedNodes);
1344 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1345 lAddresses.push_back(strAddNode);
1347 BOOST_FOREACH(string& strAddNode, lAddresses) {
1349 CSemaphoreGrant grant(*semOutbound);
1350 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1353 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1354 Sleep(120000); // Retry every 2 minutes
1355 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1360 for (uint32_t i = 0; true; i++)
1362 list<string> lAddresses(0);
1364 LOCK(cs_vAddedNodes);
1365 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1366 lAddresses.push_back(strAddNode);
1369 list<vector<CService> > lservAddressesToAdd(0);
1370 BOOST_FOREACH(string& strAddNode, lAddresses)
1372 vector<CService> vservNode(0);
1373 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1375 lservAddressesToAdd.push_back(vservNode);
1377 LOCK(cs_setservAddNodeAddresses);
1378 BOOST_FOREACH(CService& serv, vservNode)
1379 setservAddNodeAddresses.insert(serv);
1383 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1384 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1387 BOOST_FOREACH(CNode* pnode, vNodes)
1388 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1390 BOOST_FOREACH(CService& addrNode, *(it))
1391 if (pnode->addr == addrNode)
1393 it = lservAddressesToAdd.erase(it);
1394 if(it != lservAddressesToAdd.begin())
1398 if (it == lservAddressesToAdd.end())
1402 BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
1404 if (vserv.size() == 0)
1406 CSemaphoreGrant grant(*semOutbound);
1407 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1414 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1415 Sleep(120000); // Retry every 2 minutes
1416 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1422 // if successful, this moves the passed grant to the constructed node
1423 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1426 // Initiate outbound network connection
1431 if (IsLocal(addrConnect) ||
1432 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1433 FindNode(addrConnect.ToStringIPPort().c_str()))
1435 if (strDest && FindNode(strDest))
1438 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1439 CNode* pnode = ConnectNode(addrConnect, strDest);
1440 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1446 grantOutbound->MoveTo(pnode->grantOutbound);
1447 pnode->fNetworkNode = true;
1449 pnode->fOneShot = true;
1454 // for now, use a very simple selection metric: the node from which we received
1456 static int64_t NodeSyncScore(const CNode *pnode) {
1457 return pnode->nLastRecv;
1460 void static StartSync(const vector<CNode*> &vNodes) {
1461 CNode *pnodeNewSync = NULL;
1462 int64_t nBestScore = 0;
1464 // Iterate over all nodes
1465 BOOST_FOREACH(CNode* pnode, vNodes) {
1466 // check preconditions for allowing a sync
1467 if (!pnode->fClient && !pnode->fOneShot &&
1468 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1469 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1470 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1471 // if ok, compare node's score with the best so far
1472 int64_t nScore = NodeSyncScore(pnode);
1473 if (pnodeNewSync == NULL || nScore > nBestScore) {
1474 pnodeNewSync = pnode;
1475 nBestScore = nScore;
1479 // if a new sync candidate was found, start sync!
1481 pnodeNewSync->fStartSync = true;
1482 pnodeSync = pnodeNewSync;
1486 void ThreadMessageHandler(void* parg)
1488 // Make this thread recognisable as the message handling thread
1489 RenameThread("novacoin-msghand");
1493 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1494 ThreadMessageHandler2(parg);
1495 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1497 catch (std::exception& e) {
1498 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1499 PrintException(&e, "ThreadMessageHandler()");
1501 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1502 PrintException(NULL, "ThreadMessageHandler()");
1504 printf("ThreadMessageHandler exited\n");
1507 void ThreadMessageHandler2(void* parg)
1509 printf("ThreadMessageHandler started\n");
1510 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1513 bool fHaveSyncNode = false;
1514 vector<CNode*> vNodesCopy;
1517 vNodesCopy = vNodes;
1518 BOOST_FOREACH(CNode* pnode, vNodesCopy) {
1520 if (pnode == pnodeSync)
1521 fHaveSyncNode = true;
1526 StartSync(vNodesCopy);
1528 // Poll the connected nodes for messages
1529 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1533 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1535 if (!ProcessMessages(pnode)) {
1536 pnode->CloseSocketDisconnect();
1537 if (pnode == pnodeSync)
1538 fHaveSyncNode = false;
1547 TRY_LOCK(pnode->cs_vSend, lockSend);
1549 SendMessages(pnode);
1557 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
1560 // Wait and allow messages to bunch up.
1561 // Reduce vnThreadsRunning so StopNode has permission to exit while
1562 // we're sleeping, but we must always check fShutdown after doing this.
1563 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1565 if (fRequestShutdown)
1567 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1578 bool BindListenPort(const CService &addrBind, string& strError)
1583 // Create socket for listening for incoming connections
1585 struct sockaddr_storage sockaddr;
1587 struct sockaddr sockaddr;
1589 socklen_t len = sizeof(sockaddr);
1590 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1592 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1593 printf("%s\n", strError.c_str());
1597 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1598 if (hListenSocket == INVALID_SOCKET)
1600 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1601 printf("%s\n", strError.c_str());
1607 // Different way of disabling SIGPIPE on BSD
1608 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1610 // Allow binding if the port is still in TIME_WAIT state after
1611 // the program was closed and restarted. Not an issue on windows!
1612 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1616 // Set to non-blocking, incoming connections will also inherit this
1617 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1619 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1622 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1623 printf("%s\n", strError.c_str());
1628 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1629 // and enable it by default or not. Try to enable it, if possible.
1630 if (addrBind.IsIPv6()) {
1633 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1635 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1639 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1640 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
1645 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1647 int nErr = WSAGetLastError();
1648 if (nErr == WSAEADDRINUSE)
1649 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1651 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1652 printf("%s\n", strError.c_str());
1653 CloseSocket(hListenSocket);
1656 printf("Bound to %s\n", addrBind.ToString().c_str());
1658 // Listen for incoming connections
1659 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1661 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1662 printf("%s\n", strError.c_str());
1663 CloseSocket(hListenSocket);
1667 vhListenSocket.push_back(hListenSocket);
1669 if (addrBind.IsRoutable() && fDiscover)
1670 AddLocal(addrBind, LOCAL_BIND);
1675 void static Discover()
1681 // Get local host IP
1682 char pszHostName[1000] = "";
1683 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1685 vector<CNetAddr> vaddr;
1686 if (LookupHost(pszHostName, vaddr))
1688 BOOST_FOREACH (const CNetAddr &addr, vaddr)
1690 AddLocal(addr, LOCAL_IF);
1695 // Get local host ip
1696 struct ifaddrs* myaddrs;
1697 if (getifaddrs(&myaddrs) == 0)
1699 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1701 if (ifa->ifa_addr == NULL) continue;
1702 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1703 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1704 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1705 if (ifa->ifa_addr->sa_family == AF_INET)
1707 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1708 CNetAddr addr(s4->sin_addr);
1709 if (AddLocal(addr, LOCAL_IF))
1710 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1713 else if (ifa->ifa_addr->sa_family == AF_INET6)
1715 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1716 CNetAddr addr(s6->sin6_addr);
1717 if (AddLocal(addr, LOCAL_IF))
1718 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1722 freeifaddrs(myaddrs);
1726 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1727 if (!IsLimited(NET_IPV4))
1728 NewThread(ThreadGetMyExternalIP, NULL);
1731 void StartNode(void* parg)
1733 // Make this thread recognisable as the startup thread
1734 RenameThread("novacoin-start");
1736 if (semOutbound == NULL) {
1737 // initialize semaphore
1738 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1739 semOutbound = new CSemaphore(nMaxOutbound);
1742 if (pnodeLocalHost == NULL)
1743 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1751 if (!GetBoolArg("-dnsseed", true))
1752 printf("DNS seeding disabled\n");
1754 if (!NewThread(ThreadDNSAddressSeed, NULL))
1755 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1757 // Get addresses from IRC and advertise ours
1758 if (!GetBoolArg("-irc", true))
1759 printf("IRC seeding disabled\n");
1761 if (!NewThread(ThreadIRCSeed, NULL))
1762 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1764 // Send and receive from sockets, accept connections
1765 if (!NewThread(ThreadSocketHandler, NULL))
1766 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1768 // Initiate outbound connections from -addnode
1769 if (!NewThread(ThreadOpenAddedConnections, NULL))
1770 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1772 // Initiate outbound connections
1773 if (!NewThread(ThreadOpenConnections, NULL))
1774 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1777 if (!NewThread(ThreadMessageHandler, NULL))
1778 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1780 // Dump network addresses
1781 if (!NewThread(ThreadDumpAddress, NULL))
1782 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1784 // Mine proof-of-stake blocks in the background
1785 if (!NewThread(ThreadStakeMiner, pwalletMain))
1786 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1788 // Trusted NTP server, it's localhost by default.
1789 strTrustedUpstream = GetArg("-ntp", "localhost");
1791 // Start periodical NTP sampling thread
1792 NewThread(ThreadNtpSamples, NULL);
1798 printf("StopNode()\n");
1800 nTransactionsUpdated++;
1801 int64_t nStart = GetTime();
1804 ThreadScriptCheckQuit();
1807 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1808 semOutbound->post();
1811 int nThreadsRunning = 0;
1812 for (int n = 0; n < THREAD_MAX; n++)
1813 nThreadsRunning += vnThreadsRunning[n];
1814 if (nThreadsRunning == 0)
1816 if (GetTime() - nStart > 20)
1820 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1821 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1822 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1823 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1824 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1825 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1826 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1827 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1828 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1829 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1830 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1847 BOOST_FOREACH(CNode* pnode, vNodes)
1848 if (pnode->hSocket != INVALID_SOCKET)
1849 CloseSocket(pnode->hSocket);
1850 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
1851 if (hListenSocket != INVALID_SOCKET)
1852 if (!CloseSocket(hListenSocket))
1853 printf("CloseSocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1855 // clean up some globals (to help leak detection)
1856 BOOST_FOREACH(CNode *pnode, vNodes)
1858 BOOST_FOREACH(CNode *pnode, vNodesDisconnected)
1861 vNodesDisconnected.clear();
1864 delete pnodeLocalHost;
1865 pnodeLocalHost = NULL;
1868 // Shutdown Windows Sockets
1873 instance_of_cnetcleanup;
1875 void RelayTransaction(const CTransaction& tx, const uint256& hash)
1877 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1880 RelayTransaction(tx, hash, ss);
1883 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
1885 CInv inv(MSG_TX, hash);
1888 // Expire old relay messages
1889 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1891 mapRelay.erase(vRelayExpiration.front().second);
1892 vRelayExpiration.pop_front();
1895 // Save original serialized message so newer versions are preserved
1896 mapRelay.insert(std::make_pair(inv, ss));
1897 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
1900 RelayInventory(inv);
1903 void CNode::RecordBytesRecv(uint64_t bytes)
1905 LOCK(cs_totalBytesRecv);
1906 nTotalBytesRecv += bytes;
1909 void CNode::RecordBytesSent(uint64_t bytes)
1911 LOCK(cs_totalBytesSent);
1912 nTotalBytesSent += bytes;
1915 uint64_t CNode::GetTotalBytesRecv()
1917 LOCK(cs_totalBytesRecv);
1918 return nTotalBytesRecv;
1921 uint64_t CNode::GetTotalBytesSent()
1923 LOCK(cs_totalBytesSent);
1924 return nTotalBytesSent;
1926 int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) {
1927 return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);