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"
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 std::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 std::array<int, THREAD_MAX> vnThreadsRunning;
61 static std::vector<SOCKET> vhListenSocket;
64 std::vector<CNode*> vNodes;
65 CCriticalSection cs_vNodes;
66 std::map<CInv, CDataStream> mapRelay;
67 std::deque<std::pair<int64_t, CInv> > vRelayExpiration;
68 CCriticalSection cs_mapRelay;
69 std::map<CInv, int64_t> mapAlreadyAskedFor;
71 static std::deque<std::string> vOneShots;
72 CCriticalSection cs_vOneShots;
74 std::set<CNetAddr> setservAddNodeAddresses;
75 CCriticalSection cs_setservAddNodeAddresses;
77 std::vector<std::string> vAddedNodes;
78 CCriticalSection cs_vAddedNodes;
80 static CSemaphore *semOutbound = NULL;
82 inline void RelayInventory(const CInv& inv)
84 // Put on lists to offer to the other nodes
87 for (CNode* pnode : vNodes)
88 pnode->PushInventory(inv);
92 void AddOneShot(std::string strDest)
95 vOneShots.push_back(strDest);
98 unsigned short GetListenPort()
100 return (unsigned short)(GetArg("-port", GetDefaultPort()));
103 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
105 // Filter out duplicate requests
106 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
108 pindexLastGetBlocksBegin = pindexBegin;
109 hashLastGetBlocksEnd = hashEnd;
111 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
114 // find 'best' local address for a particular peer
115 bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
121 int nBestReachability = -1;
123 LOCK(cs_mapLocalHost);
124 for (auto it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
126 int nScore = (*it).second.nScore;
127 int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
128 if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
130 addr = CService((*it).first, (*it).second.nPort);
131 nBestReachability = nReachability;
136 return nBestScore >= 0;
139 // get best local address for a particular peer as a CAddress
140 CAddress GetLocalAddress(const CNetAddr *paddrPeer)
142 CAddress ret(CService("0.0.0.0", nPortZero), 0);
144 if (GetLocal(addr, paddrPeer))
146 ret = CAddress(addr);
147 ret.nServices = nLocalServices;
148 ret.nTime = GetAdjustedTime();
153 bool RecvLine(SOCKET hSocket, std::string& strLine)
159 int nBytes = recv(hSocket, &c, 1, 0);
167 if (strLine.size() >= 9000)
170 else if (nBytes <= 0)
176 int nErr = WSAGetLastError();
177 if (nErr == WSAEMSGSIZE)
179 if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
185 if (!strLine.empty())
190 printf("socket closed\n");
196 int nErr = WSAGetLastError();
197 printf("recv failed: %d\n", nErr);
204 // used when scores of local addresses may have changed
205 // pushes better local address to peers
206 void static AdvertizeLocal()
209 for (CNode* pnode : vNodes)
211 if (pnode->fSuccessfullyConnected)
213 CAddress addrLocal = GetLocalAddress(&pnode->addr);
214 if (addrLocal.IsRoutable() && (CService)addrLocal != pnode->addrLocal)
216 pnode->PushAddress(addrLocal);
217 pnode->addrLocal = addrLocal;
223 void SetReachable(enum Network net, bool fFlag)
225 LOCK(cs_mapLocalHost);
226 vfReachable[net] = fFlag;
227 if (net == NET_IPV6 && fFlag)
228 vfReachable[NET_IPV4] = true;
231 int GetnScore(const CService& addr)
233 LOCK(cs_mapLocalHost);
234 if (mapLocalHost.count(addr) == LOCAL_NONE)
236 return mapLocalHost[addr].nScore;
240 // Is our peer's addrLocal potentially useful as an external IP source?
241 bool IsPeerAddrLocalGood(CNode *pnode)
243 return fDiscover && pnode->addr.IsRoutable() && pnode->addrLocal.IsRoutable() &&
244 !IsLimited(pnode->addrLocal.GetNetwork());
247 // pushes our own address to a peer
248 void AdvertiseLocal(CNode *pnode)
250 if (!fNoListen && pnode->fSuccessfullyConnected)
252 CAddress addrLocal = GetLocalAddress(&pnode->addr);
253 // If discovery is enabled, sometimes give our peer the address it
254 // tells us that it sees us as in case it has a better idea of our
255 // address than we do.
256 if (IsPeerAddrLocalGood(pnode) && (!addrLocal.IsRoutable() ||
257 GetRand((GetnScore(addrLocal) > LOCAL_MANUAL) ? 8:2) == 0))
259 addrLocal.SetIP(pnode->addrLocal);
261 if (addrLocal.IsRoutable())
263 printf("AdvertiseLocal: advertising address %s\n", addrLocal.ToString().c_str());
264 pnode->PushAddress(addrLocal);
269 // learn a new local address
270 bool AddLocal(const CService& addr, int nScore)
272 if (!addr.IsRoutable())
275 if (!fDiscover && nScore < LOCAL_MANUAL)
281 printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
284 LOCK(cs_mapLocalHost);
285 bool fAlready = mapLocalHost.count(addr) > 0;
286 LocalServiceInfo &info = mapLocalHost[addr];
287 if (!fAlready || nScore >= info.nScore) {
288 info.nScore = nScore + (fAlready ? 1 : 0);
289 info.nPort = addr.GetPort();
291 SetReachable(addr.GetNetwork());
299 bool AddLocal(const CNetAddr &addr, int nScore)
301 return AddLocal(CService(addr, GetListenPort()), nScore);
304 /** Make a particular network entirely off-limits (no automatic connects to it) */
305 void SetLimited(enum Network net, bool fLimited)
307 if (net == NET_UNROUTABLE)
309 LOCK(cs_mapLocalHost);
310 vfLimited[net] = fLimited;
313 bool IsLimited(enum Network net)
315 LOCK(cs_mapLocalHost);
316 return vfLimited[net];
319 bool IsLimited(const CNetAddr &addr)
321 return IsLimited(addr.GetNetwork());
324 /** vote for a local address */
325 bool SeenLocal(const CService& addr)
328 LOCK(cs_mapLocalHost);
329 if (mapLocalHost.count(addr) == 0)
331 mapLocalHost[addr].nScore++;
339 /** check whether a given address is potentially local */
340 bool IsLocal(const CService& addr)
342 LOCK(cs_mapLocalHost);
343 return mapLocalHost.count(addr) > 0;
346 /** check whether a given address is in a network we can probably connect to */
347 bool IsReachable(const CNetAddr& addr)
349 LOCK(cs_mapLocalHost);
350 enum Network net = addr.GetNetwork();
351 return vfReachable[net] && !vfLimited[net];
354 extern int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv);
356 // We now get our external IP from the IRC server first and only use this as a backup
357 bool GetMyExternalIP(CNetAddr& ipRet)
359 struct sockaddr_in mapped;
360 uint64_t rnd = std::numeric_limits<uint64_t>::max();
362 int rc = GetExternalIPbySTUN(rnd, &mapped, &srv);
364 ipRet = CNetAddr(mapped.sin_addr);
365 printf("GetExternalIPbySTUN(%" PRIu64 ") returned %s in attempt %d; Server=%s\n", rnd, ipRet.ToStringIP().c_str(), rc, srv);
371 void ThreadGetMyExternalIP(void* parg)
373 // Make this thread recognisable as the external IP detection thread
374 RenameThread("novacoin-ext-ip");
376 CNetAddr addrLocalHost;
377 if (GetMyExternalIP(addrLocalHost))
379 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
380 AddLocal(addrLocalHost, LOCAL_HTTP);
388 void AddressCurrentlyConnected(const CService& addr)
390 addrman.Connected(addr);
396 uint64_t CNode::nTotalBytesRecv = 0;
397 uint64_t CNode::nTotalBytesSent = 0;
398 CCriticalSection CNode::cs_totalBytesRecv;
399 CCriticalSection CNode::cs_totalBytesSent;
401 CNode* FindNode(const CNetAddr& ip)
404 for (CNode* pnode : vNodes)
405 if ((CNetAddr)pnode->addr == ip)
410 CNode* FindNode(std::string addrName)
413 for (CNode* pnode : vNodes)
414 if (pnode->addrName == addrName)
419 CNode* FindNode(const CService& addr)
422 for (CNode* pnode : vNodes)
423 if ((CService)pnode->addr == addr)
428 CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64_t nTimeout)
430 if (pszDest == NULL) {
431 if (IsLocal(addrConnect))
434 // Look for an existing connection
435 CNode* pnode = FindNode((CService)addrConnect);
439 pnode->AddRef(nTimeout);
448 printf("trying connection %s lastseen=%.1fhrs\n",
449 pszDest ? pszDest : addrConnect.ToString().c_str(),
450 pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
454 if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
456 addrman.Attempt(addrConnect);
459 printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
461 // Set to non-blocking
464 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
465 printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
467 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
468 printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
472 CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
474 pnode->AddRef(nTimeout);
480 vNodes.push_back(pnode);
483 pnode->nTimeConnected = GetTime();
492 void CNode::CloseSocketDisconnect()
495 if (hSocket != INVALID_SOCKET)
497 printf("disconnecting node %s\n", addrName.c_str());
498 CloseSocket(hSocket);
502 // in case this fails, we'll empty the recv buffer when the CNode is deleted
503 TRY_LOCK(cs_vRecv, lockRecv);
507 // if this was the sync node, we'll need a new one
508 if (this == pnodeSync)
512 void CNode::Cleanup()
516 void CNode::EndMessage()
518 if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
520 printf("dropmessages DROPPING SEND MESSAGE\n");
525 if (nHeaderStart < 0) {
526 LEAVE_CRITICAL_SECTION(cs_vSend);
531 uint32_t nSize = (uint32_t) vSend.size() - nMessageStart;
532 memcpy((char*)&vSend[nHeaderStart] + CMessageHeader::MESSAGE_SIZE_OFFSET, &nSize, sizeof(nSize));
535 uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end());
536 uint32_t nChecksum = 0;
537 memcpy(&nChecksum, &hash, sizeof(nChecksum));
538 assert(nMessageStart - nHeaderStart >= CMessageHeader::CHECKSUM_OFFSET + sizeof(nChecksum));
539 memcpy((char*)&vSend[nHeaderStart] + CMessageHeader::CHECKSUM_OFFSET, &nChecksum, sizeof(nChecksum));
542 printf("(%d bytes)\n", nSize);
546 nMessageStart = std::numeric_limits<uint32_t>::max();
547 LEAVE_CRITICAL_SECTION(cs_vSend);
550 void CNode::PushVersion()
552 int64_t nTime = GetAdjustedTime();
553 CAddress addrYou, addrMe;
555 bool fHidden = false;
557 if (mapArgs.count("-torname")) {
558 // Our hidden service address
559 CService addrTorName(mapArgs["-torname"], GetListenPort());
561 if (addrTorName.IsValid()) {
563 addrMe = CAddress(addrTorName);
570 addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", nPortZero)));
571 addrMe = GetLocalAddress(&addr);
574 GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
575 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());
576 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
577 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<std::string>()), nBestHeight);
584 std::map<CNetAddr, int64_t> CNode::setBanned;
585 CCriticalSection CNode::cs_setBanned;
587 void CNode::ClearBanned()
592 bool CNode::IsBanned(CNetAddr ip)
594 bool fResult = false;
597 std::map<CNetAddr, int64_t>::iterator i = setBanned.find(ip);
598 if (i != setBanned.end())
600 int64_t t = (*i).second;
608 bool CNode::Misbehaving(int howmuch)
612 printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
616 nMisbehavior += howmuch;
617 if (nMisbehavior >= GetArgInt("-banscore", 100))
619 int64_t banTime = GetTime()+GetArg("-bantime", nOneDay); // Default 24-hour ban
620 printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
623 if (setBanned[addr] < banTime)
624 setBanned[addr] = banTime;
626 CloseSocketDisconnect();
629 printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
634 #define X(name) stats.name = name
635 void CNode::copyStats(CNodeStats &stats)
650 stats.fSyncNode = (this == pnodeSync);
654 void Release(CNode* node) {
662 void ThreadSocketHandler(void* parg)
664 // Make this thread recognisable as the networking thread
665 RenameThread("novacoin-net");
669 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
670 ThreadSocketHandler2(parg);
671 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
673 catch (std::exception& e) {
674 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
675 PrintException(&e, "ThreadSocketHandler()");
677 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
678 throw; // support pthread_cancel()
680 printf("ThreadSocketHandler exited\n");
683 static std::list<CNode*> vNodesDisconnected;
685 void ThreadSocketHandler2(void* parg)
687 printf("ThreadSocketHandler started\n");
688 size_t nPrevNodeCount = 0;
696 // Disconnect unused nodes
697 std::vector<CNode*> vNodesCopy = vNodes;
698 for (CNode* pnode : vNodesCopy)
700 if (pnode->fDisconnect ||
701 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
703 // remove from vNodes
704 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
706 // release outbound grant (if any)
707 pnode->grantOutbound.Release();
709 // close socket and cleanup
710 pnode->CloseSocketDisconnect();
713 // hold in disconnected pool until all refs are released
714 pnode->nReleaseTime = std::max(pnode->nReleaseTime, GetTime() + 15 * 60);
715 if (pnode->fNetworkNode || pnode->fInbound)
717 vNodesDisconnected.push_back(pnode);
721 // Delete disconnected nodes
722 std::list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
723 for (CNode* pnode : vNodesDisconnectedCopy)
725 // wait until threads are done using it
726 if (pnode->GetRefCount() <= 0)
728 bool fDelete = false;
730 TRY_LOCK(pnode->cs_vSend, lockSend);
733 TRY_LOCK(pnode->cs_vRecv, lockRecv);
736 TRY_LOCK(pnode->cs_inventory, lockInv);
744 vNodesDisconnected.remove(pnode);
750 if (vNodes.size() != nPrevNodeCount)
752 nPrevNodeCount = vNodes.size();
753 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
758 // Find which sockets have data to receive
760 struct timeval timeout;
762 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
769 FD_ZERO(&fdsetError);
770 SOCKET hSocketMax = 0;
771 bool have_fds = false;
773 for (SOCKET hListenSocket : vhListenSocket) {
774 FD_SET(hListenSocket, &fdsetRecv);
775 hSocketMax = std::max(hSocketMax, hListenSocket);
780 for (CNode* pnode : vNodes)
782 if (pnode->hSocket == INVALID_SOCKET)
784 FD_SET(pnode->hSocket, &fdsetRecv);
785 FD_SET(pnode->hSocket, &fdsetError);
786 hSocketMax = std::max(hSocketMax, pnode->hSocket);
789 TRY_LOCK(pnode->cs_vSend, lockSend);
790 if (lockSend && !pnode->vSend.empty())
791 FD_SET(pnode->hSocket, &fdsetSend);
796 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
797 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
798 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
799 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
802 if (nSelect == SOCKET_ERROR)
806 int nErr = WSAGetLastError();
807 printf("socket select error %d\n", nErr);
808 for (unsigned int i = 0; i <= hSocketMax; i++)
809 FD_SET(i, &fdsetRecv);
812 FD_ZERO(&fdsetError);
813 Sleep(timeout.tv_usec/1000);
818 // Accept new connections
820 for (SOCKET hListenSocket : vhListenSocket)
821 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
824 struct sockaddr_storage sockaddr;
826 struct sockaddr sockaddr;
828 socklen_t len = sizeof(sockaddr);
829 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
833 if (hSocket != INVALID_SOCKET)
834 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
835 printf("Warning: Unknown socket family\n");
839 for (CNode* pnode : vNodes)
844 if (hSocket == INVALID_SOCKET)
846 int nErr = WSAGetLastError();
847 if (nErr != WSAEWOULDBLOCK)
848 printf("socket error accept failed: %d\n", nErr);
850 else if (nInbound >= GetArgInt("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
853 LOCK(cs_setservAddNodeAddresses);
854 if (!setservAddNodeAddresses.count(addr))
855 CloseSocket(hSocket);
858 else if (CNode::IsBanned(addr))
860 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
861 CloseSocket(hSocket);
865 printf("accepted connection %s\n", addr.ToString().c_str());
866 CNode* pnode = new CNode(hSocket, addr, "", true);
870 vNodes.push_back(pnode);
877 // Service each socket
879 std::vector<CNode*> vNodesCopy;
883 for (CNode* pnode : vNodesCopy)
886 for (CNode* pnode : vNodesCopy)
894 if (pnode->hSocket == INVALID_SOCKET)
896 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
898 TRY_LOCK(pnode->cs_vRecv, lockRecv);
901 CDataStream& vRecv = pnode->vRecv;
902 uint64_t nPos = vRecv.size();
904 if (nPos > ReceiveBufferSize()) {
905 if (!pnode->fDisconnect)
906 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
907 pnode->CloseSocketDisconnect();
910 // typical socket buffer is 8K-64K
911 char pchBuf[0x10000];
912 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
915 vRecv.resize(nPos + nBytes);
916 memcpy(&vRecv[nPos], pchBuf, nBytes);
917 pnode->nLastRecv = GetTime();
918 pnode->nRecvBytes += nBytes;
919 pnode->RecordBytesRecv(nBytes);
921 else if (nBytes == 0)
923 // socket closed gracefully
924 if (!pnode->fDisconnect)
925 printf("socket closed\n");
926 pnode->CloseSocketDisconnect();
931 int nErr = WSAGetLastError();
932 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
934 if (!pnode->fDisconnect)
935 printf("socket recv error %d\n", nErr);
936 pnode->CloseSocketDisconnect();
946 if (pnode->hSocket == INVALID_SOCKET)
948 if (FD_ISSET(pnode->hSocket, &fdsetSend))
950 TRY_LOCK(pnode->cs_vSend, lockSend);
953 CDataStream& vSend = pnode->vSend;
956 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
959 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
960 pnode->nLastSend = GetTime();
961 pnode->nSendBytes += nBytes;
962 pnode->RecordBytesSent(nBytes);
967 int nErr = WSAGetLastError();
968 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
970 printf("socket send error %d\n", nErr);
971 pnode->CloseSocketDisconnect();
979 // Inactivity checking
981 if (pnode->vSend.empty())
982 pnode->nLastSendEmpty = GetTime();
983 if (GetTime() - pnode->nTimeConnected > 60)
985 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
987 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
988 pnode->fDisconnect = true;
990 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
992 printf("socket not sending\n");
993 pnode->fDisconnect = true;
995 else if (GetTime() - pnode->nLastRecv > 90*60)
997 printf("socket inactivity timeout\n");
998 pnode->fDisconnect = true;
1004 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
1012 // Each pair gives a source name and a seed name.
1013 // The first name is used as information source for addrman.
1014 // The second name should resolve to a list of seed addresses.
1015 static const char *strDNSSeed[][2] = {
1016 {"node.novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro"},
1017 {"novacoin.ru", "dnsseed.novacoin.ru"},
1018 {"novacoin.ru", "testseed.novacoin.ru"},
1019 {"novaco.in", "dnsseed.novaco.in"},
1022 void ThreadDNSAddressSeed(void* parg)
1024 // Make this thread recognisable as the DNS seeding thread
1025 RenameThread("novacoin-dnsseed");
1029 vnThreadsRunning[THREAD_DNSSEED]++;
1030 ThreadDNSAddressSeed2(parg);
1031 vnThreadsRunning[THREAD_DNSSEED]--;
1033 catch (std::exception& e) {
1034 vnThreadsRunning[THREAD_DNSSEED]--;
1035 PrintException(&e, "ThreadDNSAddressSeed()");
1037 vnThreadsRunning[THREAD_DNSSEED]--;
1038 throw; // support pthread_cancel()
1040 printf("ThreadDNSAddressSeed exited\n");
1043 void ThreadDNSAddressSeed2(void* parg)
1045 printf("ThreadDNSAddressSeed started\n");
1050 printf("Loading addresses from DNS seeds (could take a while)\n");
1052 for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1053 if (HaveNameProxy()) {
1054 AddOneShot(strDNSSeed[seed_idx][1]);
1056 std::vector<CNetAddr> vaddr;
1057 std::vector<CAddress> vAdd;
1058 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
1060 for (CNetAddr& ip : vaddr)
1062 CAddress addr = CAddress(CService(ip, GetDefaultPort()));
1063 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1064 vAdd.push_back(addr);
1068 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
1073 printf("%d addresses found from DNS seeds\n", found);
1089 0x1c542868, 0x3859dd6f, 0x203c2e68, 0xf145a6bc, 0x638a545f, 0x325da346, 0x385da346, 0xfb2b8d5f,
1090 0x52568c5f, 0xa979e65b, 0x8de6485d, 0x9f79e65b, 0x048a861f, 0x3388b55f, 0x6ff0b45e, 0x17e81f5f,
1091 0x6c47bb25, 0x1ecdc852, 0x28263db9, 0x47824e5d, 0x36f1c851, 0x2bf913b2, 0x95923cb3, 0x84e63eb2,
1092 0xefdeedbf, 0x65200092, 0xf36f6805, 0x42692d05, 0x772c1955, 0xb6bf1b4e, 0x7abb5f5d, 0xdb2fa6bc,
1093 0x90e911bf, 0x82de565f, 0x694416b2, 0x0ab600bc, 0xfcecbe6d, 0x24ed9fb2, 0x1bb618c2, 0xc64765bb,
1094 0x4e3d62c3, 0xdba24baa, 0x4b7109b0, 0x12a12cc2, 0xfc01864f, 0x0b69e85b, 0x33922c1f, 0xac611bc6,
1095 0x2a257155, 0x991d5fc0, 0xbfdabcb1, 0x9b73ee55, 0x5bc2b95d, 0xdef0762e, 0x6ab7c936, 0x9c4416b2,
1096 0xd60d864f, 0x03671f1f, 0x3b5da346, 0xc6f5c851, 0x5411b2d4, 0xe7c25702, 0x63474fb0, 0x7e11c854,
1097 0x52381d5f, 0x72fdfe59, 0x51599a05, 0xfb12b2d4, 0xaee4f15e, 0xd0e3f15e, 0x2aa2805f, 0xa1caf15e,
1098 0x34fe425e, 0x46e1f15e, 0xd7c71955, 0xaeeff15e, 0x47c2af55, 0x563d89b2, 0x67980fd9, 0xc9def15e,
1099 0x9cc51eb9, 0xdaa7aa6b, 0x78e6871f, 0x0d5d2cb2, 0x7aedf15e, 0x9bcaf15e, 0xe5f7f15e, 0x501c1759,
1100 0xdfbc4980, 0xa7397f2e, 0x31ea1a02, 0x3a27655e, 0xaa86f05c, 0xdcddf15e, 0x64689cb2, 0xd4bf62d4,
1101 0xf093eab2, 0x98def15e, 0xb6c5f15e, 0x81e8f15e, 0xe5d2fe59, 0xa312786d, 0x4cf9fe59, 0x8a922c1f,
1102 0x00c7fe59, 0x1ade565f, 0x9e4116b2, 0x2c36983e, 0x68f8f15e, 0x51b7eab2, 0x76c51eb9, 0x9edd4980,
1103 0x90ef565f, 0x0dd80857, 0xd513fb94, 0xf5bdeab2, 0xa95277b0, 0x2cf2f15e, 0x1897eab2, 0x924416b2,
1104 0x985c9b59, 0x30aa43d8, 0xf9c6745f, 0xaf862e5f, 0xe0ceeab2, 0xb9b3eab2, 0x6da4eab2, 0xa4fdeab2,
1105 0x0fa6c125, 0xe38bbd05, 0x5d922c1f, 0x9bd0eab2, 0x73025e02, 0xc4fd794d, 0x8435b35f, 0x2d01bc2e,
1106 0xaa2a14d4, 0xa22b07cb, 0xebda6f4f, 0xddc6514e, 0xf23feab2, 0xea1e5256, 0x6147b45e, 0x47d21e4f,
1107 0x67c41c1f, 0x53ec1a02, 0x352e786d, 0x6bec1a02, 0x78fb4abe, 0xd3014c5d, 0x9fbbeab2, 0x1fc51eb9,
1108 0x720eeab2, 0x2db5eab2, 0xe8baf65c, 0x521b459e, 0x65c4955f, 0x0e7b915f, 0xa8f37e6d, 0x6d0b465f,
1109 0xfab8ff5c, 0xf7c27e6d, 0x7345a846, 0x4fd1a7d5, 0xdfc97e6d, 0x26c27e6d, 0xa9de36b2, 0xc615344d,
1110 0x28ceb95d, 0xa52d895e, 0x18c17e6d, 0x13ec1a02, 0x0ba37125, 0x6c3d344d, 0xb3922c1f, 0x506bbeb0,
1111 0x4d04994e, 0xa1bbe56d, 0xf62c344d, 0x0847d048, 0x4bdc6451, 0xc95b9a05, 0xbcd3a7d5, 0x29b57125,
1112 0x0c4d2cb2, 0xf2b8eab2, 0xc2d5b95d, 0x0185ef59, 0x30adeab2, 0xcaf0e92e, 0x756c344d, 0xfd9e252e,
1113 0xbe5ef3bc, 0x4689344d, 0xb223895e, 0xfcebeaad, 0xb7c0e92e, 0x993c1760, 0xe1e171b0, 0xb857e75b,
1114 0xbf10002e, 0xb55b2cb2, 0xa90e2cb2, 0x13d6f15e, 0xf8be9225, 0x14ddf15e, 0x06e90305, 0x82472cb2,
1117 const char* pchTorSeed[] =
1119 "seedp4knqnoei57u.onion",
1120 "seedr3hhlepyi7fd.onion",
1121 "seed3uuomkclbiz4.onion",
1122 "seedeh7qck3ouff5.onion",
1123 "5rg3vq4jagckeckf.onion",
1124 "seedt3sraf53ajiy.onion",
1125 "seedg4qyccsg42oq.onion",
1126 "novaqrtoywpg7jly.onion",
1127 "seed3d5wolqbgrcb.onion",
1128 "seed24u5dwph3qw4.onion",
1129 "mj26ulzbs2oskgym.onion",
1130 "eqon4usunavt76m7.onion",
1131 "seedd3aldwpslzl3.onion"
1134 void DumpAddresses()
1136 int64_t nStart = GetTimeMillis();
1141 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1142 addrman.size(), GetTimeMillis() - nStart);
1145 void ThreadDumpAddress2(void* parg)
1147 printf("ThreadDumpAddress started\n");
1149 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1153 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1155 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1157 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1160 void ThreadDumpAddress(void* parg)
1162 // Make this thread recognisable as the address dumping thread
1163 RenameThread("novacoin-adrdump");
1167 ThreadDumpAddress2(parg);
1169 catch (std::exception& e) {
1170 PrintException(&e, "ThreadDumpAddress()");
1172 printf("ThreadDumpAddress exited\n");
1175 void ThreadOpenConnections(void* parg)
1177 // Make this thread recognisable as the connection opening thread
1178 RenameThread("novacoin-opencon");
1182 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1183 ThreadOpenConnections2(parg);
1184 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1186 catch (std::exception& e) {
1187 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1188 PrintException(&e, "ThreadOpenConnections()");
1190 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1191 PrintException(NULL, "ThreadOpenConnections()");
1193 printf("ThreadOpenConnections exited\n");
1196 void static ProcessOneShot()
1198 std::string strDest;
1201 if (vOneShots.empty())
1203 strDest = vOneShots.front();
1204 vOneShots.pop_front();
1207 CSemaphoreGrant grant(*semOutbound, true);
1209 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1210 AddOneShot(strDest);
1214 void ThreadOpenConnections2(void* parg)
1216 printf("ThreadOpenConnections started\n");
1218 // Connect to specific addresses
1219 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1221 for (int64_t nLoop = 0;; nLoop++)
1224 for (std::string strAddr : mapMultiArgs["-connect"])
1227 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1228 for (int i = 0; i < 10 && i < nLoop; i++)
1239 // Initiate network connections
1240 int64_t nStart = GetTime();
1245 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1247 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1252 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1253 CSemaphoreGrant grant(*semOutbound);
1254 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1258 // Add seed nodes if IRC isn't working
1259 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1261 std::vector<CAddress> vAdd;
1262 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1264 // It'll only connect to one or two seed nodes because once it connects,
1265 // it'll get a pile of addresses with newer timestamps.
1266 // Seed nodes are given a random 'last seen time' of between one and two
1269 memcpy(&ip, &pnSeed[i], sizeof(ip));
1270 CAddress addr(CService(ip, GetDefaultPort()));
1271 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1272 vAdd.push_back(addr);
1274 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1277 // Add Tor nodes if we have connection with onion router
1278 if (mapArgs.count("-tor"))
1280 std::vector<CAddress> vAdd;
1281 for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1283 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1284 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1285 vAdd.push_back(addr);
1287 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1291 // Choose an address to connect to based on most recently seen
1293 CAddress addrConnect;
1295 // Only connect out to one peer per network group (/16 for IPv4).
1296 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1298 std::set<std::vector<unsigned char> > setConnected;
1301 for (CNode* pnode : vNodes) {
1302 if (!pnode->fInbound) {
1303 setConnected.insert(pnode->addr.GetGroup());
1309 int64_t nANow = GetAdjustedTime();
1314 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1315 CAddress addr = addrman.Select(10 + std::min(nOutbound,8)*10);
1317 // if we selected an invalid address, restart
1318 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1321 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1322 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1323 // already-connected network ranges, ...) before trying new addrman addresses.
1328 if (IsLimited(addr))
1331 // only consider very recently tried nodes after 30 failed attempts
1332 if (nANow - addr.nLastTry < 600 && nTries < 30)
1335 // do not allow non-default ports, unless after 50 invalid addresses selected already
1336 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1343 if (addrConnect.IsValid())
1344 OpenNetworkConnection(addrConnect, &grant);
1348 void ThreadOpenAddedConnections(void* parg)
1350 // Make this thread recognisable as the connection opening thread
1351 RenameThread("novacoin-opencon");
1355 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1356 ThreadOpenAddedConnections2(parg);
1357 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1359 catch (std::exception& e) {
1360 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1361 PrintException(&e, "ThreadOpenAddedConnections()");
1363 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1364 PrintException(NULL, "ThreadOpenAddedConnections()");
1366 printf("ThreadOpenAddedConnections exited\n");
1369 void ThreadOpenAddedConnections2(void* parg)
1371 printf("ThreadOpenAddedConnections started\n");
1374 LOCK(cs_vAddedNodes);
1375 vAddedNodes = mapMultiArgs["-addnode"];
1378 if (HaveNameProxy()) {
1380 std::list<std::string> lAddresses(0);
1382 LOCK(cs_vAddedNodes);
1383 for (std::string& strAddNode : vAddedNodes)
1384 lAddresses.push_back(strAddNode);
1386 for (std::string& strAddNode : lAddresses) {
1388 CSemaphoreGrant grant(*semOutbound);
1389 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1392 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1393 Sleep(120000); // Retry every 2 minutes
1394 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1399 for (uint32_t i = 0; true; i++)
1401 std::list<std::string> lAddresses(0);
1403 LOCK(cs_vAddedNodes);
1404 for (std::string& strAddNode : vAddedNodes)
1405 lAddresses.push_back(strAddNode);
1408 std::list<std::vector<CService> > lservAddressesToAdd(0);
1409 for (std::string& strAddNode : lAddresses)
1411 std::vector<CService> vservNode(0);
1412 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1414 lservAddressesToAdd.push_back(vservNode);
1416 LOCK(cs_setservAddNodeAddresses);
1417 for (CService& serv : vservNode)
1418 setservAddNodeAddresses.insert(serv);
1422 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1423 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1426 for (CNode* pnode : vNodes)
1427 for (auto it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1429 for (CService& addrNode : *(it))
1430 if (pnode->addr == addrNode)
1432 it = lservAddressesToAdd.erase(it);
1433 if(it != lservAddressesToAdd.begin())
1437 if (it == lservAddressesToAdd.end())
1441 for (std::vector<CService>& vserv : lservAddressesToAdd)
1443 if (vserv.size() == 0)
1445 CSemaphoreGrant grant(*semOutbound);
1446 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1453 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1454 Sleep(120000); // Retry every 2 minutes
1455 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1461 // if successful, this moves the passed grant to the constructed node
1462 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1465 // Initiate outbound network connection
1470 if (IsLocal(addrConnect) ||
1471 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1472 FindNode(addrConnect.ToStringIPPort().c_str()))
1474 if (strDest && FindNode(strDest))
1477 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1478 CNode* pnode = ConnectNode(addrConnect, strDest);
1479 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1485 grantOutbound->MoveTo(pnode->grantOutbound);
1486 pnode->fNetworkNode = true;
1488 pnode->fOneShot = true;
1493 // for now, use a very simple selection metric: the node from which we received
1495 static int64_t NodeSyncScore(const CNode *pnode) {
1496 return pnode->nLastRecv;
1499 void static StartSync(const std::vector<CNode*> &vNodes) {
1500 CNode *pnodeNewSync = NULL;
1501 int64_t nBestScore = 0;
1503 // Iterate over all nodes
1504 for (CNode* pnode : vNodes) {
1505 // check preconditions for allowing a sync
1506 if (!pnode->fClient && !pnode->fOneShot &&
1507 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1508 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1509 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1510 // if ok, compare node's score with the best so far
1511 int64_t nScore = NodeSyncScore(pnode);
1512 if (pnodeNewSync == NULL || nScore > nBestScore) {
1513 pnodeNewSync = pnode;
1514 nBestScore = nScore;
1518 // if a new sync candidate was found, start sync!
1520 pnodeNewSync->fStartSync = true;
1521 pnodeSync = pnodeNewSync;
1525 void ThreadMessageHandler(void* parg)
1527 // Make this thread recognisable as the message handling thread
1528 RenameThread("novacoin-msghand");
1532 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1533 ThreadMessageHandler2(parg);
1534 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1536 catch (std::exception& e) {
1537 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1538 PrintException(&e, "ThreadMessageHandler()");
1540 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1541 PrintException(NULL, "ThreadMessageHandler()");
1543 printf("ThreadMessageHandler exited\n");
1546 void ThreadMessageHandler2(void* parg)
1548 printf("ThreadMessageHandler started\n");
1549 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1552 bool fHaveSyncNode = false;
1553 std::vector<CNode*> vNodesCopy;
1556 vNodesCopy = vNodes;
1557 for (CNode* pnode : vNodesCopy) {
1559 if (pnode == pnodeSync)
1560 fHaveSyncNode = true;
1565 StartSync(vNodesCopy);
1567 // Poll the connected nodes for messages
1568 for (CNode* pnode : vNodesCopy)
1572 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1574 if (!ProcessMessages(pnode)) {
1575 pnode->CloseSocketDisconnect();
1576 if (pnode == pnodeSync)
1577 fHaveSyncNode = false;
1586 TRY_LOCK(pnode->cs_vSend, lockSend);
1588 SendMessages(pnode);
1596 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
1599 // Wait and allow messages to bunch up.
1600 // Reduce vnThreadsRunning so StopNode has permission to exit while
1601 // we're sleeping, but we must always check fShutdown after doing this.
1602 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1604 if (fRequestShutdown)
1606 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1617 bool BindListenPort(const CService &addrBind, std::string& strError)
1622 // Create socket for listening for incoming connections
1624 struct sockaddr_storage sockaddr;
1626 struct sockaddr sockaddr;
1628 socklen_t len = sizeof(sockaddr);
1629 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1631 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1632 printf("%s\n", strError.c_str());
1636 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1637 if (hListenSocket == INVALID_SOCKET)
1639 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1640 printf("%s\n", strError.c_str());
1646 // Different way of disabling SIGPIPE on BSD
1647 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1649 // Allow binding if the port is still in TIME_WAIT state after
1650 // the program was closed and restarted. Not an issue on windows!
1651 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1655 // Set to non-blocking, incoming connections will also inherit this
1656 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1658 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1661 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1662 printf("%s\n", strError.c_str());
1667 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1668 // and enable it by default or not. Try to enable it, if possible.
1669 if (addrBind.IsIPv6()) {
1672 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1674 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1678 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1679 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
1684 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1686 int nErr = WSAGetLastError();
1687 if (nErr == WSAEADDRINUSE)
1688 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1690 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1691 printf("%s\n", strError.c_str());
1692 CloseSocket(hListenSocket);
1695 printf("Bound to %s\n", addrBind.ToString().c_str());
1697 // Listen for incoming connections
1698 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1700 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1701 printf("%s\n", strError.c_str());
1702 CloseSocket(hListenSocket);
1706 vhListenSocket.push_back(hListenSocket);
1708 if (addrBind.IsRoutable() && fDiscover)
1709 AddLocal(addrBind, LOCAL_BIND);
1714 void static Discover()
1720 // Get local host IP
1721 char pszHostName[1000] = "";
1722 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1724 std::vector<CNetAddr> vaddr;
1725 if (LookupHost(pszHostName, vaddr))
1727 for (const CNetAddr &addr : vaddr)
1729 AddLocal(addr, LOCAL_IF);
1734 // Get local host ip
1735 struct ifaddrs* myaddrs;
1736 if (getifaddrs(&myaddrs) == 0)
1738 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1740 if (ifa->ifa_addr == NULL) continue;
1741 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1742 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1743 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1744 if (ifa->ifa_addr->sa_family == AF_INET)
1746 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1747 CNetAddr addr(s4->sin_addr);
1748 if (AddLocal(addr, LOCAL_IF))
1749 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1752 else if (ifa->ifa_addr->sa_family == AF_INET6)
1754 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1755 CNetAddr addr(s6->sin6_addr);
1756 if (AddLocal(addr, LOCAL_IF))
1757 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1761 freeifaddrs(myaddrs);
1765 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1766 if (!IsLimited(NET_IPV4))
1767 NewThread(ThreadGetMyExternalIP, NULL);
1770 void StartNode(void* parg)
1772 // Make this thread recognisable as the startup thread
1773 RenameThread("novacoin-start");
1775 if (semOutbound == NULL) {
1776 // initialize semaphore
1777 int nMaxOutbound = std::min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1778 semOutbound = new CSemaphore(nMaxOutbound);
1781 if (pnodeLocalHost == NULL)
1782 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1790 if (!GetBoolArg("-dnsseed", true))
1791 printf("DNS seeding disabled\n");
1793 if (!NewThread(ThreadDNSAddressSeed, NULL))
1794 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1796 // Get addresses from IRC and advertise ours
1797 if (!GetBoolArg("-irc", true))
1798 printf("IRC seeding disabled\n");
1800 if (!NewThread(ThreadIRCSeed, NULL))
1801 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1803 // Send and receive from sockets, accept connections
1804 if (!NewThread(ThreadSocketHandler, NULL))
1805 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1807 // Initiate outbound connections from -addnode
1808 if (!NewThread(ThreadOpenAddedConnections, NULL))
1809 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1811 // Initiate outbound connections
1812 if (!NewThread(ThreadOpenConnections, NULL))
1813 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1816 if (!NewThread(ThreadMessageHandler, NULL))
1817 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1819 // Dump network addresses
1820 if (!NewThread(ThreadDumpAddress, NULL))
1821 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1823 // Mine proof-of-stake blocks in the background
1824 if (!NewThread(ThreadStakeMiner, pwalletMain))
1825 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1827 // Trusted NTP server, it's localhost by default.
1828 strTrustedUpstream = GetArg("-ntp", "localhost");
1830 // Start periodical NTP sampling thread
1831 NewThread(ThreadNtpSamples, NULL);
1837 printf("StopNode()\n");
1839 nTransactionsUpdated++;
1840 int64_t nStart = GetTime();
1843 ThreadScriptCheckQuit();
1846 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1847 semOutbound->post();
1850 int nThreadsRunning = 0;
1851 for (int n = 0; n < THREAD_MAX; n++)
1852 nThreadsRunning += vnThreadsRunning[n];
1853 if (nThreadsRunning == 0)
1855 if (GetTime() - nStart > 20)
1859 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1860 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1861 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1862 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1863 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1864 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1865 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1866 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1867 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1868 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1869 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1886 for (CNode* pnode : vNodes)
1887 if (pnode->hSocket != INVALID_SOCKET)
1888 CloseSocket(pnode->hSocket);
1889 for (SOCKET hListenSocket : vhListenSocket)
1890 if (hListenSocket != INVALID_SOCKET)
1891 if (!CloseSocket(hListenSocket))
1892 printf("CloseSocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1894 // clean up some globals (to help leak detection)
1895 for (CNode *pnode : vNodes)
1897 for (CNode *pnode : vNodesDisconnected)
1900 vNodesDisconnected.clear();
1903 delete pnodeLocalHost;
1904 pnodeLocalHost = NULL;
1907 // Shutdown Windows Sockets
1912 instance_of_cnetcleanup;
1914 void RelayTransaction(const CTransaction& tx, const uint256& hash)
1916 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1919 RelayTransaction(tx, hash, ss);
1922 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
1924 CInv inv(MSG_TX, hash);
1927 // Expire old relay messages
1928 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1930 mapRelay.erase(vRelayExpiration.front().second);
1931 vRelayExpiration.pop_front();
1934 // Save original serialized message so newer versions are preserved
1935 mapRelay.insert(std::make_pair(inv, ss));
1936 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
1939 RelayInventory(inv);
1942 void CNode::RecordBytesRecv(uint64_t bytes)
1944 LOCK(cs_totalBytesRecv);
1945 nTotalBytesRecv += bytes;
1948 void CNode::RecordBytesSent(uint64_t bytes)
1950 LOCK(cs_totalBytesSent);
1951 nTotalBytesSent += bytes;
1954 uint64_t CNode::GetTotalBytesRecv()
1956 LOCK(cs_totalBytesRecv);
1957 return nTotalBytesRecv;
1960 uint64_t CNode::GetTotalBytesSent()
1962 LOCK(cs_totalBytesSent);
1963 return nTotalBytesSent;
1965 int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) {
1966 return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);