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"
17 static const int MAX_OUTBOUND_CONNECTIONS = 16;
19 void ThreadMessageHandler2(void* parg);
20 void ThreadSocketHandler2(void* parg);
21 void ThreadOpenConnections2(void* parg);
22 void ThreadOpenAddedConnections2(void* parg);
23 void ThreadDNSAddressSeed2(void* parg);
25 // Fix for ancient MinGW versions, that don't have defined these in ws2tcpip.h.
26 // Todo: Can be removed when our pull-tester is upgraded to a modern MinGW version.
28 #ifndef PROTECTION_LEVEL_UNRESTRICTED
29 #define PROTECTION_LEVEL_UNRESTRICTED 10
31 #ifndef IPV6_PROTECTION_LEVEL
32 #define IPV6_PROTECTION_LEVEL 23
36 struct LocalServiceInfo {
42 // Global state variables
45 bool fDiscover = true;
46 uint64_t nLocalServices = (fClient ? 0 : NODE_NETWORK);
47 static CCriticalSection cs_mapLocalHost;
48 static map<CNetAddr, LocalServiceInfo> mapLocalHost;
49 static bool vfReachable[NET_MAX] = {};
50 static bool vfLimited[NET_MAX] = {};
51 static CNode* pnodeLocalHost = NULL;
52 static CNode* pnodeSync = NULL;
53 CAddress addrSeenByPeer(CService("0.0.0.0", nPortZero), nLocalServices);
54 uint64_t nLocalHostNonce = 0;
55 array<int, THREAD_MAX> vnThreadsRunning;
56 static vector<SOCKET> vhListenSocket;
59 vector<CNode*> vNodes;
60 CCriticalSection cs_vNodes;
61 map<CInv, CDataStream> mapRelay;
62 deque<pair<int64_t, CInv> > vRelayExpiration;
63 CCriticalSection cs_mapRelay;
64 map<CInv, int64_t> mapAlreadyAskedFor;
66 static deque<string> vOneShots;
67 CCriticalSection cs_vOneShots;
69 set<CNetAddr> setservAddNodeAddresses;
70 CCriticalSection cs_setservAddNodeAddresses;
72 vector<string> vAddedNodes;
73 CCriticalSection cs_vAddedNodes;
75 static CSemaphore *semOutbound = NULL;
77 void AddOneShot(string strDest)
80 vOneShots.push_back(strDest);
83 uint16_t GetListenPort()
85 return static_cast<uint16_t>(GetArg("-port", GetDefaultPort()));
88 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
90 // Filter out duplicate requests
91 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
93 pindexLastGetBlocksBegin = pindexBegin;
94 hashLastGetBlocksEnd = hashEnd;
96 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
99 // find 'best' local address for a particular peer
100 bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
106 int nBestReachability = -1;
108 LOCK(cs_mapLocalHost);
109 for (auto it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
111 int nScore = (*it).second.nScore;
112 int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
113 if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
115 addr = CService((*it).first, (*it).second.nPort);
116 nBestReachability = nReachability;
121 return nBestScore >= 0;
124 // get best local address for a particular peer as a CAddress
125 CAddress GetLocalAddress(const CNetAddr *paddrPeer)
127 CAddress ret(CService("0.0.0.0", nPortZero), 0);
129 if (GetLocal(addr, paddrPeer))
131 ret = CAddress(addr);
132 ret.nServices = nLocalServices;
133 ret.nTime = GetAdjustedTime();
138 bool RecvLine(SOCKET hSocket, string& strLine)
144 int nBytes = recv(hSocket, &c, 1, 0);
152 if (strLine.size() >= 9000)
155 else if (nBytes <= 0)
161 int nErr = WSAGetLastError();
162 if (nErr == WSAEMSGSIZE)
164 if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
170 if (!strLine.empty())
175 printf("socket closed\n");
181 int nErr = WSAGetLastError();
182 printf("recv failed: %d\n", nErr);
189 // used when scores of local addresses may have changed
190 // pushes better local address to peers
191 void static AdvertizeLocal()
194 for(CNode* pnode : vNodes)
196 if (pnode->fSuccessfullyConnected)
198 auto addrLocal = GetLocalAddress(&pnode->addr);
199 if (addrLocal.IsRoutable() && (CService)addrLocal != pnode->addrLocal)
201 pnode->PushAddress(addrLocal);
202 pnode->addrLocal = addrLocal;
208 void SetReachable(enum Network net, bool fFlag)
210 LOCK(cs_mapLocalHost);
211 vfReachable[net] = fFlag;
212 if (net == NET_IPV6 && fFlag)
213 vfReachable[NET_IPV4] = true;
216 int GetnScore(const CService& addr)
218 LOCK(cs_mapLocalHost);
219 if (mapLocalHost.count(addr) == LOCAL_NONE)
221 return mapLocalHost[addr].nScore;
225 // Is our peer's addrLocal potentially useful as an external IP source?
226 bool IsPeerAddrLocalGood(CNode *pnode)
228 return fDiscover && pnode->addr.IsRoutable() && pnode->addrLocal.IsRoutable() &&
229 !IsLimited(pnode->addrLocal.GetNetwork());
232 // pushes our own address to a peer
233 void AdvertiseLocal(CNode *pnode)
235 if (!fNoListen && pnode->fSuccessfullyConnected)
237 auto addrLocal = GetLocalAddress(&pnode->addr);
238 // If discovery is enabled, sometimes give our peer the address it
239 // tells us that it sees us as in case it has a better idea of our
240 // address than we do.
241 if (IsPeerAddrLocalGood(pnode) && (!addrLocal.IsRoutable() ||
242 GetRand((GetnScore(addrLocal) > LOCAL_MANUAL) ? 8:2) == 0))
244 addrLocal.SetIP(pnode->addrLocal);
246 if (addrLocal.IsRoutable())
248 printf("AdvertiseLocal: advertising address %s\n", addrLocal.ToString().c_str());
249 pnode->PushAddress(addrLocal);
254 // learn a new local address
255 bool AddLocal(const CService& addr, int nScore)
257 if (!addr.IsRoutable())
260 if (!fDiscover && nScore < LOCAL_MANUAL)
266 printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
269 LOCK(cs_mapLocalHost);
270 bool fAlready = mapLocalHost.count(addr) > 0;
271 LocalServiceInfo &info = mapLocalHost[addr];
272 if (!fAlready || nScore >= info.nScore) {
273 info.nScore = nScore + (fAlready ? 1 : 0);
274 info.nPort = addr.GetPort();
276 SetReachable(addr.GetNetwork());
284 bool AddLocal(const CNetAddr &addr, int nScore)
286 return AddLocal(CService(addr, GetListenPort()), nScore);
289 /** Make a particular network entirely off-limits (no automatic connects to it) */
290 void SetLimited(enum Network net, bool fLimited)
292 if (net == NET_UNROUTABLE)
294 LOCK(cs_mapLocalHost);
295 vfLimited[net] = fLimited;
298 bool IsLimited(enum Network net)
300 LOCK(cs_mapLocalHost);
301 return vfLimited[net];
304 bool IsLimited(const CNetAddr &addr)
306 return IsLimited(addr.GetNetwork());
309 /** vote for a local address */
310 bool SeenLocal(const CService& addr)
313 LOCK(cs_mapLocalHost);
314 if (mapLocalHost.count(addr) == 0)
316 mapLocalHost[addr].nScore++;
324 /** check whether a given address is potentially local */
325 bool IsLocal(const CService& addr)
327 LOCK(cs_mapLocalHost);
328 return mapLocalHost.count(addr) > 0;
331 /** check whether a given address is in a network we can probably connect to */
332 bool IsReachable(const CNetAddr& addr)
334 LOCK(cs_mapLocalHost);
335 enum Network net = addr.GetNetwork();
336 return vfReachable[net] && !vfLimited[net];
339 extern int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv);
341 // We now get our external IP from the IRC server first and only use this as a backup
342 bool GetMyExternalIP(CNetAddr& ipRet)
344 struct sockaddr_in mapped = {};
345 auto rnd = GetRand(numeric_limits<uint64_t>::max());
347 int rc = GetExternalIPbySTUN(rnd, &mapped, &srv);
349 ipRet = CNetAddr(mapped.sin_addr);
351 printf("GetExternalIPbySTUN(%" PRIu64 ") returned %s in attempt %d; Server=%s\n", rnd, ipRet.ToStringIP().c_str(), rc, srv);
358 void ThreadGetMyExternalIP(void* parg)
360 // Make this thread recognisable as the external IP detection thread
361 RenameThread("novacoin-ext-ip");
363 CNetAddr addrLocalHost;
364 if (GetMyExternalIP(addrLocalHost))
366 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
367 AddLocal(addrLocalHost, LOCAL_HTTP);
371 void AddressCurrentlyConnected(const CService& addr)
373 addrman.Connected(addr);
379 uint64_t CNode::nTotalBytesRecv = 0;
380 uint64_t CNode::nTotalBytesSent = 0;
381 CCriticalSection CNode::cs_totalBytesRecv;
382 CCriticalSection CNode::cs_totalBytesSent;
384 CNode* FindNode(const CNetAddr& ip)
387 for(CNode* pnode : vNodes)
388 if ((CNetAddr)pnode->addr == ip)
393 CNode* FindNode(string addrName)
396 for(CNode* pnode : vNodes)
397 if (pnode->addrName == addrName)
402 CNode* FindNode(const CService& addr)
405 for(CNode* pnode : vNodes)
406 if ((CService)pnode->addr == addr)
411 CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64_t nTimeout)
413 if (pszDest == NULL) {
414 if (IsLocal(addrConnect))
417 // Look for an existing connection
418 CNode* pnode = FindNode((CService)addrConnect);
422 pnode->AddRef(nTimeout);
431 printf("trying connection %s lastseen=%.1fhrs\n",
432 pszDest ? pszDest : addrConnect.ToString().c_str(),
433 pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
437 if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
439 addrman.Attempt(addrConnect);
442 printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
444 // Set to non-blocking
447 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
448 printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
450 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
451 printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
455 CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
457 pnode->AddRef(nTimeout);
463 vNodes.push_back(pnode);
466 pnode->nTimeConnected = GetTime();
475 CNode::CNode(SOCKET hSocketIn, CAddress addrIn, string addrNameIn, bool fInboundIn) : vSend(SER_NETWORK, MIN_PROTO_VERSION), vRecv(SER_NETWORK, MIN_PROTO_VERSION)
483 nLastSendEmpty = GetTime();
484 nTimeConnected = GetTime();
486 nMessageStart = numeric_limits<uint32_t>::max();
488 addrName = addrNameIn.empty() ? addr.ToStringIPPort() : addrNameIn;
492 fClient = false; // set by version message
493 fInbound = fInboundIn;
494 fNetworkNode = false;
495 fSuccessfullyConnected = false;
500 pindexLastGetBlocksBegin = 0;
501 hashLastGetBlocksEnd = 0;
502 nStartingHeight = -1;
503 nNextLocalAddrSend = 0;
509 hashCheckpointKnown = 0;
510 setInventoryKnown.max_size((size_t)SendBufferSize() / 1000);
512 // Be shy and don't send version until we hear
513 if (hSocket != INVALID_SOCKET && !fInbound)
519 if (hSocket != INVALID_SOCKET)
521 CloseSocket(hSocket);
525 int CNode::GetRefCount()
527 return max(nRefCount, 0) + (GetTime() < nReleaseTime ? 1 : 0);
530 CNode* CNode::AddRef(int64_t nTimeout)
533 nReleaseTime = max(nReleaseTime, GetTime() + nTimeout);
539 void CNode::Release()
544 void CNode::AddAddressKnown(const CAddress& addr)
546 setAddrKnown.insert(addr);
549 void CNode::PushAddress(const CAddress& addr)
551 // Known checking here is only to save space from duplicates.
552 // SendMessages will filter it again for knowns that were added
553 // after addresses were pushed.
554 if (addr.IsValid() && !setAddrKnown.count(addr))
555 vAddrToSend.push_back(addr);
558 void CNode::AddInventoryKnown(const CInv& inv)
562 setInventoryKnown.insert(inv);
566 void CNode::PushInventory(const CInv& inv)
570 if (!setInventoryKnown.count(inv))
571 vInventoryToSend.push_back(inv);
575 void CNode::AskFor(const CInv& inv)
577 // We're using mapAskFor as a priority queue,
578 // the key is the earliest time the request can be sent
579 int64_t& nRequestTime = mapAlreadyAskedFor[inv];
581 printf("askfor %s %" PRId64 " (%s)\n", inv.ToString().c_str(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str());
583 // Make sure not to reuse time indexes to keep things in the same order
584 int64_t nNow = (GetTime() - 1) * 1000000;
585 static int64_t nLastTime;
587 nNow = max(nNow, nLastTime);
590 // Each retry is 2 minutes after the last
591 nRequestTime = max(nRequestTime + 2 * 60 * 1000000, nNow);
592 mapAskFor.insert({ nRequestTime, inv });
595 void CNode::BeginMessage(const char* pszCommand)
597 ENTER_CRITICAL_SECTION(cs_vSend);
598 if (nHeaderStart != -1)
600 nHeaderStart = (int32_t)vSend.size();
601 vSend << CMessageHeader(pszCommand, 0);
602 nMessageStart = (uint32_t)vSend.size();
604 printf("sending: %s ", pszCommand);
607 void CNode::AbortMessage()
609 if (nHeaderStart < 0)
611 vSend.resize(nHeaderStart);
613 nMessageStart = numeric_limits<uint32_t>::max();
614 LEAVE_CRITICAL_SECTION(cs_vSend);
617 printf("(aborted)\n");
620 void CNode::EndMessage()
622 if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
624 printf("dropmessages DROPPING SEND MESSAGE\n");
629 if (nHeaderStart < 0)
633 uint32_t nSize = (uint32_t) vSend.size() - nMessageStart;
634 memcpy((char*)&vSend[nHeaderStart] + CMessageHeader::MESSAGE_SIZE_OFFSET, &nSize, sizeof(nSize));
637 auto hash = Hash(vSend.begin() + nMessageStart, vSend.end());
638 uint32_t nChecksum = 0;
639 memcpy(&nChecksum, &hash, sizeof(nChecksum));
640 assert(nMessageStart - nHeaderStart >= CMessageHeader::CHECKSUM_OFFSET + sizeof(nChecksum));
641 memcpy((char*)&vSend[nHeaderStart] + CMessageHeader::CHECKSUM_OFFSET, &nChecksum, sizeof(nChecksum));
644 printf("(%d bytes)\n", nSize);
648 nMessageStart = numeric_limits<uint32_t>::max();
649 LEAVE_CRITICAL_SECTION(cs_vSend);
652 void CNode::EndMessageAbortIfEmpty()
654 if (nHeaderStart < 0)
656 int nSize = (int) vSend.size() - nMessageStart;
663 void CNode::CloseSocketDisconnect()
666 if (hSocket != INVALID_SOCKET)
668 printf("disconnecting node %s\n", addrName.c_str());
669 CloseSocket(hSocket);
673 // in case this fails, we'll empty the recv buffer when the CNode is deleted
674 TRY_LOCK(cs_vRecv, lockRecv);
678 // if this was the sync node, we'll need a new one
679 if (this == pnodeSync)
683 void CNode::Cleanup()
688 void CNode::PushVersion()
690 auto nTime = GetAdjustedTime();
691 CAddress addrYou, addrMe;
693 bool fHidden = false;
695 if (mapArgs.count("-torname")) {
696 // Our hidden service address
697 CService addrTorName(mapArgs["-torname"], GetListenPort());
699 if (addrTorName.IsValid()) {
701 addrMe = CAddress(addrTorName);
708 addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", nPortZero)));
709 addrMe = GetLocalAddress(&addr);
712 RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
713 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());
714 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
715 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, vector<string>()), nBestHeight);
722 map<CNetAddr, int64_t> CNode::setBanned;
723 CCriticalSection CNode::cs_setBanned;
725 void CNode::ClearBanned()
730 bool CNode::IsBanned(CNetAddr ip)
732 bool fResult = false;
735 auto i = setBanned.find(ip);
736 if (i != setBanned.end())
738 auto t = (*i).second;
746 bool CNode::Misbehaving(int howmuch)
750 printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
754 nMisbehavior += howmuch;
755 if (nMisbehavior >= GetArgInt("-banscore", 100))
757 auto banTime = GetTime()+GetArg("-bantime", nOneDay); // Default 24-hour ban
758 printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
761 if (setBanned[addr] < banTime)
762 setBanned[addr] = banTime;
764 CloseSocketDisconnect();
767 printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
772 #define X(name) stats.name = name
773 void CNode::copyStats(CNodeStats &stats)
788 stats.fSyncNode = (this == pnodeSync);
792 void Release(CNode* node) {
800 void ThreadSocketHandler(void* parg)
802 // Make this thread recognisable as the networking thread
803 RenameThread("novacoin-net");
807 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
808 ThreadSocketHandler2(parg);
809 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
811 catch (exception& e) {
812 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
813 PrintException(&e, "ThreadSocketHandler()");
815 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
816 throw; // support pthread_cancel()
818 printf("ThreadSocketHandler exited\n");
821 static list<CNode*> vNodesDisconnected;
823 void ThreadSocketHandler2(void* parg)
825 printf("ThreadSocketHandler started\n");
826 size_t nPrevNodeCount = 0;
834 // Disconnect unused nodes
835 vector<CNode*> vNodesCopy = vNodes;
836 for(CNode* pnode : vNodesCopy)
838 if (pnode->fDisconnect ||
839 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
841 // remove from vNodes
842 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
844 // release outbound grant (if any)
845 pnode->grantOutbound.Release();
847 // close socket and cleanup
848 pnode->CloseSocketDisconnect();
851 // hold in disconnected pool until all refs are released
852 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
853 if (pnode->fNetworkNode || pnode->fInbound)
855 vNodesDisconnected.push_back(pnode);
859 // Delete disconnected nodes
860 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
861 for(CNode* pnode : vNodesDisconnectedCopy)
863 // wait until threads are done using it
864 if (pnode->GetRefCount() <= 0)
866 bool fDelete = false;
868 TRY_LOCK(pnode->cs_vSend, lockSend);
871 TRY_LOCK(pnode->cs_vRecv, lockRecv);
874 TRY_LOCK(pnode->cs_mapRequests, lockReq);
877 TRY_LOCK(pnode->cs_inventory, lockInv);
886 vNodesDisconnected.remove(pnode);
892 if (vNodes.size() != nPrevNodeCount)
894 nPrevNodeCount = vNodes.size();
895 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
900 // Find which sockets have data to receive
902 struct timeval timeout;
904 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
911 FD_ZERO(&fdsetError);
912 SOCKET hSocketMax = 0;
913 bool have_fds = false;
915 for(SOCKET hListenSocket : vhListenSocket) {
916 FD_SET(hListenSocket, &fdsetRecv);
917 hSocketMax = max(hSocketMax, hListenSocket);
922 for(CNode* pnode : vNodes)
924 if (pnode->hSocket == INVALID_SOCKET)
926 FD_SET(pnode->hSocket, &fdsetRecv);
927 FD_SET(pnode->hSocket, &fdsetError);
928 hSocketMax = max(hSocketMax, pnode->hSocket);
931 TRY_LOCK(pnode->cs_vSend, lockSend);
932 if (lockSend && !pnode->vSend.empty())
933 FD_SET(pnode->hSocket, &fdsetSend);
938 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
939 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
940 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
941 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
944 if (nSelect == SOCKET_ERROR)
948 int nErr = WSAGetLastError();
949 printf("socket select error %d\n", nErr);
950 for (unsigned int i = 0; i <= hSocketMax; i++)
951 FD_SET(i, &fdsetRecv);
954 FD_ZERO(&fdsetError);
955 Sleep(timeout.tv_usec/1000);
960 // Accept new connections
962 for(SOCKET hListenSocket : vhListenSocket)
963 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
966 struct sockaddr_storage sockaddr;
968 struct sockaddr sockaddr;
970 socklen_t len = sizeof(sockaddr);
971 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
975 if (hSocket != INVALID_SOCKET)
976 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
977 printf("Warning: Unknown socket family\n");
981 for(CNode* pnode : vNodes)
986 if (hSocket == INVALID_SOCKET)
988 int nErr = WSAGetLastError();
989 if (nErr != WSAEWOULDBLOCK)
990 printf("socket error accept failed: %d\n", nErr);
992 else if (nInbound >= GetArgInt("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
995 LOCK(cs_setservAddNodeAddresses);
996 if (!setservAddNodeAddresses.count(addr))
997 CloseSocket(hSocket);
1000 else if (CNode::IsBanned(addr))
1002 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
1003 CloseSocket(hSocket);
1007 printf("accepted connection %s\n", addr.ToString().c_str());
1008 CNode* pnode = new CNode(hSocket, addr, "", true);
1012 vNodes.push_back(pnode);
1019 // Service each socket
1021 vector<CNode*> vNodesCopy;
1024 vNodesCopy = vNodes;
1025 for(CNode* pnode : vNodesCopy)
1028 for(CNode* pnode : vNodesCopy)
1036 if (pnode->hSocket == INVALID_SOCKET)
1038 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
1040 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1043 CDataStream& vRecv = pnode->vRecv;
1044 uint64_t nPos = vRecv.size();
1046 if (nPos > ReceiveBufferSize()) {
1047 if (!pnode->fDisconnect)
1048 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
1049 pnode->CloseSocketDisconnect();
1052 // typical socket buffer is 8K-64K
1053 char pchBuf[0x10000];
1054 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
1057 vRecv.resize(nPos + nBytes);
1058 memcpy(&vRecv[nPos], pchBuf, nBytes);
1059 pnode->nLastRecv = GetTime();
1060 pnode->nRecvBytes += nBytes;
1061 pnode->RecordBytesRecv(nBytes);
1063 else if (nBytes == 0)
1065 // socket closed gracefully
1066 if (!pnode->fDisconnect)
1067 printf("socket closed\n");
1068 pnode->CloseSocketDisconnect();
1070 else if (nBytes < 0)
1073 int nErr = WSAGetLastError();
1074 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
1076 if (!pnode->fDisconnect)
1077 printf("socket recv error %d\n", nErr);
1078 pnode->CloseSocketDisconnect();
1088 if (pnode->hSocket == INVALID_SOCKET)
1090 if (FD_ISSET(pnode->hSocket, &fdsetSend))
1092 TRY_LOCK(pnode->cs_vSend, lockSend);
1095 CDataStream& vSend = pnode->vSend;
1098 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
1101 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
1102 pnode->nLastSend = GetTime();
1103 pnode->nSendBytes += nBytes;
1104 pnode->RecordBytesSent(nBytes);
1106 else if (nBytes < 0)
1109 int nErr = WSAGetLastError();
1110 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
1112 printf("socket send error %d\n", nErr);
1113 pnode->CloseSocketDisconnect();
1121 // Inactivity checking
1123 if (pnode->vSend.empty())
1124 pnode->nLastSendEmpty = GetTime();
1125 if (GetTime() - pnode->nTimeConnected > 60)
1127 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
1129 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
1130 pnode->fDisconnect = true;
1132 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
1134 printf("socket not sending\n");
1135 pnode->fDisconnect = true;
1137 else if (GetTime() - pnode->nLastRecv > 90*60)
1139 printf("socket inactivity timeout\n");
1140 pnode->fDisconnect = true;
1146 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
1153 void ThreadDNSAddressSeed(void* parg)
1155 // Make this thread recognisable as the DNS seeding thread
1156 RenameThread("novacoin-dnsseed");
1160 vnThreadsRunning[THREAD_DNSSEED]++;
1161 ThreadDNSAddressSeed2(parg);
1162 vnThreadsRunning[THREAD_DNSSEED]--;
1164 catch (exception& e) {
1165 vnThreadsRunning[THREAD_DNSSEED]--;
1166 PrintException(&e, "ThreadDNSAddressSeed()");
1168 vnThreadsRunning[THREAD_DNSSEED]--;
1169 throw; // support pthread_cancel()
1171 printf("ThreadDNSAddressSeed exited\n");
1174 void ThreadDNSAddressSeed2(void* parg)
1176 printf("ThreadDNSAddressSeed started\n");
1182 // Each pair gives a source name and a seed name.
1183 // The first name is used as information source for addrman.
1184 // The second name should resolve to a list of seed addresses.
1185 static const vector<pair <string, string> > vstrDNSSeed = {
1186 { "node.novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro" },
1187 { "novacoin.ru", "dnsseed.novacoin.ru" },
1188 { "novacoin.ru", "testseed.novacoin.ru" },
1189 { "novaco.in", "dnsseed.novaco.in" },
1191 printf("Loading addresses from DNS seeds (could take a while)\n");
1193 for (unsigned int seed_idx = 0; seed_idx < vstrDNSSeed.size(); seed_idx++) {
1194 if (HaveNameProxy()) {
1195 AddOneShot(vstrDNSSeed[seed_idx].second);
1197 vector<CNetAddr> vaddr;
1198 vector<CAddress> vAdd;
1199 if (LookupHost(vstrDNSSeed[seed_idx].second, vaddr))
1201 for(CNetAddr& ip : vaddr)
1203 auto addr = CAddress(CService(ip, GetDefaultPort()));
1204 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1205 vAdd.push_back(addr);
1209 addrman.Add(vAdd, CNetAddr(vstrDNSSeed[seed_idx].first, true));
1214 printf("%d addresses found from DNS seeds\n", found);
1217 void DumpAddresses()
1219 auto nStart = GetTimeMillis();
1224 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1225 addrman.size(), GetTimeMillis() - nStart);
1228 void ThreadDumpAddress2(void* parg)
1230 printf("ThreadDumpAddress started\n");
1232 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1236 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1238 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1240 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1243 void ThreadDumpAddress(void* parg)
1245 // Make this thread recognisable as the address dumping thread
1246 RenameThread("novacoin-adrdump");
1250 ThreadDumpAddress2(parg);
1252 catch (exception& e) {
1253 PrintException(&e, "ThreadDumpAddress()");
1255 printf("ThreadDumpAddress exited\n");
1258 void ThreadOpenConnections(void* parg)
1260 // Make this thread recognisable as the connection opening thread
1261 RenameThread("novacoin-opencon");
1265 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1266 ThreadOpenConnections2(parg);
1267 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1269 catch (exception& e) {
1270 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1271 PrintException(&e, "ThreadOpenConnections()");
1273 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1274 PrintException(NULL, "ThreadOpenConnections()");
1276 printf("ThreadOpenConnections exited\n");
1279 void static ProcessOneShot()
1284 if (vOneShots.empty())
1286 strDest = vOneShots.front();
1287 vOneShots.pop_front();
1290 CSemaphoreGrant grant(*semOutbound, true);
1292 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1293 AddOneShot(strDest);
1297 void ThreadOpenConnections2(void* parg)
1299 printf("ThreadOpenConnections started\n");
1301 // Connect to specific addresses
1302 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1304 for (int64_t nLoop = 0;; nLoop++)
1307 for(string strAddr : mapMultiArgs["-connect"])
1310 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1311 for (int i = 0; i < 10 && i < nLoop; i++)
1322 // Initiate network connections
1323 auto nStart = GetTime();
1328 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1330 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1335 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1336 CSemaphoreGrant grant(*semOutbound);
1337 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1341 // Add seed nodes if IRC isn't working
1342 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1344 vector<uint32_t> vnSeed =
1346 0x1c542868, 0x3859dd6f, 0x203c2e68, 0xf145a6bc, 0x638a545f, 0x325da346, 0x385da346, 0xfb2b8d5f,
1347 0x52568c5f, 0xa979e65b, 0x8de6485d, 0x9f79e65b, 0x048a861f, 0x3388b55f, 0x6ff0b45e, 0x17e81f5f,
1348 0x6c47bb25, 0x1ecdc852, 0x28263db9, 0x47824e5d, 0x36f1c851, 0x2bf913b2, 0x95923cb3, 0x84e63eb2,
1349 0xefdeedbf, 0x65200092, 0xf36f6805, 0x42692d05, 0x772c1955, 0xb6bf1b4e, 0x7abb5f5d, 0xdb2fa6bc,
1350 0x90e911bf, 0x82de565f, 0x694416b2, 0x0ab600bc, 0xfcecbe6d, 0x24ed9fb2, 0x1bb618c2, 0xc64765bb,
1351 0x4e3d62c3, 0xdba24baa, 0x4b7109b0, 0x12a12cc2, 0xfc01864f, 0x0b69e85b, 0x33922c1f, 0xac611bc6,
1352 0x2a257155, 0x991d5fc0, 0xbfdabcb1, 0x9b73ee55, 0x5bc2b95d, 0xdef0762e, 0x6ab7c936, 0x9c4416b2,
1353 0xd60d864f, 0x03671f1f, 0x3b5da346, 0xc6f5c851, 0x5411b2d4, 0xe7c25702, 0x63474fb0, 0x7e11c854,
1354 0x52381d5f, 0x72fdfe59, 0x51599a05, 0xfb12b2d4, 0xaee4f15e, 0xd0e3f15e, 0x2aa2805f, 0xa1caf15e,
1355 0x34fe425e, 0x46e1f15e, 0xd7c71955, 0xaeeff15e, 0x47c2af55, 0x563d89b2, 0x67980fd9, 0xc9def15e,
1356 0x9cc51eb9, 0xdaa7aa6b, 0x78e6871f, 0x0d5d2cb2, 0x7aedf15e, 0x9bcaf15e, 0xe5f7f15e, 0x501c1759,
1357 0xdfbc4980, 0xa7397f2e, 0x31ea1a02, 0x3a27655e, 0xaa86f05c, 0xdcddf15e, 0x64689cb2, 0xd4bf62d4,
1358 0xf093eab2, 0x98def15e, 0xb6c5f15e, 0x81e8f15e, 0xe5d2fe59, 0xa312786d, 0x4cf9fe59, 0x8a922c1f,
1359 0x00c7fe59, 0x1ade565f, 0x9e4116b2, 0x2c36983e, 0x68f8f15e, 0x51b7eab2, 0x76c51eb9, 0x9edd4980,
1360 0x90ef565f, 0x0dd80857, 0xd513fb94, 0xf5bdeab2, 0xa95277b0, 0x2cf2f15e, 0x1897eab2, 0x924416b2,
1361 0x985c9b59, 0x30aa43d8, 0xf9c6745f, 0xaf862e5f, 0xe0ceeab2, 0xb9b3eab2, 0x6da4eab2, 0xa4fdeab2,
1362 0x0fa6c125, 0xe38bbd05, 0x5d922c1f, 0x9bd0eab2, 0x73025e02, 0xc4fd794d, 0x8435b35f, 0x2d01bc2e,
1363 0xaa2a14d4, 0xa22b07cb, 0xebda6f4f, 0xddc6514e, 0xf23feab2, 0xea1e5256, 0x6147b45e, 0x47d21e4f,
1364 0x67c41c1f, 0x53ec1a02, 0x352e786d, 0x6bec1a02, 0x78fb4abe, 0xd3014c5d, 0x9fbbeab2, 0x1fc51eb9,
1365 0x720eeab2, 0x2db5eab2, 0xe8baf65c, 0x521b459e, 0x65c4955f, 0x0e7b915f, 0xa8f37e6d, 0x6d0b465f,
1366 0xfab8ff5c, 0xf7c27e6d, 0x7345a846, 0x4fd1a7d5, 0xdfc97e6d, 0x26c27e6d, 0xa9de36b2, 0xc615344d,
1367 0x28ceb95d, 0xa52d895e, 0x18c17e6d, 0x13ec1a02, 0x0ba37125, 0x6c3d344d, 0xb3922c1f, 0x506bbeb0,
1368 0x4d04994e, 0xa1bbe56d, 0xf62c344d, 0x0847d048, 0x4bdc6451, 0xc95b9a05, 0xbcd3a7d5, 0x29b57125,
1369 0x0c4d2cb2, 0xf2b8eab2, 0xc2d5b95d, 0x0185ef59, 0x30adeab2, 0xcaf0e92e, 0x756c344d, 0xfd9e252e,
1370 0xbe5ef3bc, 0x4689344d, 0xb223895e, 0xfcebeaad, 0xb7c0e92e, 0x993c1760, 0xe1e171b0, 0xb857e75b,
1371 0xbf10002e, 0xb55b2cb2, 0xa90e2cb2, 0x13d6f15e, 0xf8be9225, 0x14ddf15e, 0x06e90305, 0x82472cb2,
1373 vector<CAddress> vAdd;
1374 for (unsigned int i = 0; i < vnSeed.size(); i++)
1376 // It'll only connect to one or two seed nodes because once it connects,
1377 // it'll get a pile of addresses with newer timestamps.
1378 // Seed nodes are given a random 'last seen time' of between one and two
1381 memcpy(&ip, &vnSeed[i], sizeof(ip));
1382 CAddress addr(CService(ip, GetDefaultPort()));
1383 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1384 vAdd.push_back(addr);
1386 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1389 // Add Tor nodes if we have connection with onion router
1390 if (mapArgs.count("-tor"))
1392 const vector<string> vstrTorSeed =
1394 "seedp4knqnoei57u.onion",
1395 "seedr3hhlepyi7fd.onion",
1396 "seed3uuomkclbiz4.onion",
1397 "seedeh7qck3ouff5.onion",
1398 "5rg3vq4jagckeckf.onion",
1399 "seedt3sraf53ajiy.onion",
1400 "seedg4qyccsg42oq.onion",
1401 "novaqrtoywpg7jly.onion",
1402 "seed3d5wolqbgrcb.onion",
1403 "seed24u5dwph3qw4.onion",
1404 "mj26ulzbs2oskgym.onion",
1405 "eqon4usunavt76m7.onion",
1406 "seedd3aldwpslzl3.onion"
1408 vector<CAddress> vAdd;
1409 for (unsigned int i = 0; i < vstrTorSeed.size(); i++)
1411 CAddress addr(CService(vstrTorSeed[i], GetDefaultPort()));
1412 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1413 vAdd.push_back(addr);
1415 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1419 // Choose an address to connect to based on most recently seen
1421 CAddress addrConnect;
1423 // Only connect out to one peer per network group (/16 for IPv4).
1424 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1426 set<vector<unsigned char> > setConnected;
1429 for(CNode* pnode : vNodes) {
1430 if (!pnode->fInbound) {
1431 setConnected.insert(pnode->addr.GetGroup());
1437 auto nANow = GetAdjustedTime();
1442 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1443 auto addr = addrman.Select(10 + min(nOutbound,8)*10);
1445 // if we selected an invalid address, restart
1446 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1449 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1450 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1451 // already-connected network ranges, ...) before trying new addrman addresses.
1456 if (IsLimited(addr))
1459 // only consider very recently tried nodes after 30 failed attempts
1460 if (nANow - addr.nLastTry < 600 && nTries < 30)
1463 // do not allow non-default ports, unless after 50 invalid addresses selected already
1464 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1471 if (addrConnect.IsValid())
1472 OpenNetworkConnection(addrConnect, &grant);
1476 void ThreadOpenAddedConnections(void* parg)
1478 // Make this thread recognisable as the connection opening thread
1479 RenameThread("novacoin-opencon");
1483 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1484 ThreadOpenAddedConnections2(parg);
1485 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1487 catch (exception& e) {
1488 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1489 PrintException(&e, "ThreadOpenAddedConnections()");
1491 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1492 PrintException(NULL, "ThreadOpenAddedConnections()");
1494 printf("ThreadOpenAddedConnections exited\n");
1497 void ThreadOpenAddedConnections2(void* parg)
1499 printf("ThreadOpenAddedConnections started\n");
1502 LOCK(cs_vAddedNodes);
1503 vAddedNodes = mapMultiArgs["-addnode"];
1506 if (HaveNameProxy()) {
1508 list<string> lAddresses(0);
1510 LOCK(cs_vAddedNodes);
1511 for(string& strAddNode : vAddedNodes)
1512 lAddresses.push_back(strAddNode);
1514 for(string& strAddNode : lAddresses) {
1516 CSemaphoreGrant grant(*semOutbound);
1517 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1520 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1521 Sleep(120000); // Retry every 2 minutes
1522 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1527 for (uint32_t i = 0; true; i++)
1529 list<string> lAddresses(0);
1531 LOCK(cs_vAddedNodes);
1532 for(string& strAddNode : vAddedNodes)
1533 lAddresses.push_back(strAddNode);
1536 list<vector<CService> > lservAddressesToAdd(0);
1537 for(string& strAddNode : lAddresses)
1539 vector<CService> vservNode(0);
1540 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1542 lservAddressesToAdd.push_back(vservNode);
1544 LOCK(cs_setservAddNodeAddresses);
1545 for(CService& serv : vservNode)
1546 setservAddNodeAddresses.insert(serv);
1550 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1551 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1554 for(CNode* pnode : vNodes)
1555 for (auto it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1557 for(CService& addrNode : *(it))
1558 if (pnode->addr == addrNode)
1560 it = lservAddressesToAdd.erase(it);
1561 if(it != lservAddressesToAdd.begin())
1565 if (it == lservAddressesToAdd.end())
1569 for(vector<CService>& vserv : lservAddressesToAdd)
1571 if (vserv.size() == 0)
1573 CSemaphoreGrant grant(*semOutbound);
1574 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1581 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1582 Sleep(120000); // Retry every 2 minutes
1583 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1589 // if successful, this moves the passed grant to the constructed node
1590 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1593 // Initiate outbound network connection
1598 if (IsLocal(addrConnect) ||
1599 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1600 FindNode(addrConnect.ToStringIPPort().c_str()))
1602 if (strDest && FindNode(strDest))
1605 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1606 CNode* pnode = ConnectNode(addrConnect, strDest);
1607 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1613 grantOutbound->MoveTo(pnode->grantOutbound);
1614 pnode->fNetworkNode = true;
1616 pnode->fOneShot = true;
1621 // for now, use a very simple selection metric: the node from which we received
1623 static int64_t NodeSyncScore(const CNode *pnode) {
1624 return pnode->nLastRecv;
1627 void static StartSync(const vector<CNode*> &vNodes) {
1628 CNode *pnodeNewSync = NULL;
1629 int64_t nBestScore = 0;
1631 // Iterate over all nodes
1632 for(CNode* pnode : vNodes) {
1633 // check preconditions for allowing a sync
1634 if (!pnode->fClient && !pnode->fOneShot &&
1635 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1636 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1637 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1638 // if ok, compare node's score with the best so far
1639 int64_t nScore = NodeSyncScore(pnode);
1640 if (pnodeNewSync == NULL || nScore > nBestScore) {
1641 pnodeNewSync = pnode;
1642 nBestScore = nScore;
1646 // if a new sync candidate was found, start sync!
1648 pnodeNewSync->fStartSync = true;
1649 pnodeSync = pnodeNewSync;
1653 void ThreadMessageHandler(void* parg)
1655 // Make this thread recognisable as the message handling thread
1656 RenameThread("novacoin-msghand");
1660 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1661 ThreadMessageHandler2(parg);
1662 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1664 catch (exception& e) {
1665 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1666 PrintException(&e, "ThreadMessageHandler()");
1668 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1669 PrintException(NULL, "ThreadMessageHandler()");
1671 printf("ThreadMessageHandler exited\n");
1674 void ThreadMessageHandler2(void* parg)
1676 printf("ThreadMessageHandler started\n");
1677 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1680 bool fHaveSyncNode = false;
1681 vector<CNode*> vNodesCopy;
1684 vNodesCopy = vNodes;
1685 for(CNode* pnode : vNodesCopy) {
1687 if (pnode == pnodeSync)
1688 fHaveSyncNode = true;
1693 StartSync(vNodesCopy);
1695 // Poll the connected nodes for messages
1696 for(CNode* pnode : vNodesCopy)
1700 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1702 ProcessMessages(pnode);
1709 TRY_LOCK(pnode->cs_vSend, lockSend);
1711 SendMessages(pnode);
1719 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
1722 // Wait and allow messages to bunch up.
1723 // Reduce vnThreadsRunning so StopNode has permission to exit while
1724 // we're sleeping, but we must always check fShutdown after doing this.
1725 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1727 if (fRequestShutdown)
1729 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1740 bool BindListenPort(const CService &addrBind, string& strError)
1745 // Create socket for listening for incoming connections
1747 struct sockaddr_storage sockaddr;
1749 struct sockaddr sockaddr;
1751 socklen_t len = sizeof(sockaddr);
1752 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1754 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1755 printf("%s\n", strError.c_str());
1759 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1760 if (hListenSocket == INVALID_SOCKET)
1762 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1763 printf("%s\n", strError.c_str());
1769 // Different way of disabling SIGPIPE on BSD
1770 if (setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int)) == SOCKET_ERROR)
1772 printf("WARNING: setsockopt failed\n");
1773 //TODO: work around problem - may be add CloseSocket and return false?
1776 // Allow binding if the port is still in TIME_WAIT state after
1777 // the program was closed and restarted. Not an issue on windows!
1778 if (setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int)) == SOCKET_ERROR)
1780 printf("WARNING: setsockopt failed\n");
1781 //TODO: work around problem - may be add CloseSocket and return false?
1786 // Set to non-blocking, incoming connections will also inherit this
1787 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1789 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1792 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1793 printf("%s\n", strError.c_str());
1794 CloseSocket(hListenSocket);
1799 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1800 // and enable it by default or not. Try to enable it, if possible.
1801 if (addrBind.IsIPv6()) {
1804 if (setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int)) == SOCKET_ERROR)
1806 printf("WARNING: setsockopt failed\n");
1807 //TODO: work around problem - may be add CloseSocket and return false?
1810 if (setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int)) == SOCKET_ERROR)
1812 printf("WARNING: setsockopt failed\n");
1813 //TODO: work around problem - may be add CloseSocket and return false?
1818 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1819 if (setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int)) == SOCKET_ERROR)
1821 printf("WARNING: setsockopt failed\n");
1822 //TODO: work around problem - may be add CloseSocket and return false?
1828 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1830 int nErr = WSAGetLastError();
1831 if (nErr == WSAEADDRINUSE)
1832 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1834 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1835 printf("%s\n", strError.c_str());
1836 CloseSocket(hListenSocket);
1839 printf("Bound to %s\n", addrBind.ToString().c_str());
1841 // Listen for incoming connections
1842 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1844 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1845 printf("%s\n", strError.c_str());
1846 CloseSocket(hListenSocket);
1850 vhListenSocket.push_back(hListenSocket);
1852 if (addrBind.IsRoutable() && fDiscover)
1853 AddLocal(addrBind, LOCAL_BIND);
1858 void static Discover()
1864 // Get local host IP
1865 char pszHostName[1000] = "";
1866 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1868 vector<CNetAddr> vaddr;
1869 if (LookupHost(pszHostName, vaddr))
1871 for(const auto &addr : vaddr)
1873 AddLocal(addr, LOCAL_IF);
1878 // Get local host ip
1879 struct ifaddrs* myaddrs;
1880 if (getifaddrs(&myaddrs) == 0)
1882 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1884 if (ifa->ifa_addr == NULL) continue;
1885 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1886 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1887 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1888 if (ifa->ifa_addr->sa_family == AF_INET)
1890 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1891 CNetAddr addr(s4->sin_addr);
1892 if (AddLocal(addr, LOCAL_IF))
1893 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1896 else if (ifa->ifa_addr->sa_family == AF_INET6)
1898 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1899 CNetAddr addr(s6->sin6_addr);
1900 if (AddLocal(addr, LOCAL_IF))
1901 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1905 freeifaddrs(myaddrs);
1909 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1910 if (!IsLimited(NET_IPV4))
1911 NewThread(ThreadGetMyExternalIP, NULL);
1914 void StartNode(void* parg)
1916 // Make this thread recognisable as the startup thread
1917 RenameThread("novacoin-start");
1919 if (semOutbound == NULL) {
1920 // initialize semaphore
1921 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1922 semOutbound = new CSemaphore(nMaxOutbound);
1925 if (pnodeLocalHost == NULL)
1926 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1934 if (!GetBoolArg("-dnsseed", true))
1935 printf("DNS seeding disabled\n");
1937 if (!NewThread(ThreadDNSAddressSeed, NULL))
1938 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1940 // Get addresses from IRC and advertise ours
1941 if (!GetBoolArg("-irc", true))
1942 printf("IRC seeding disabled\n");
1944 if (!NewThread(ThreadIRCSeed, NULL))
1945 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1947 // Send and receive from sockets, accept connections
1948 if (!NewThread(ThreadSocketHandler, NULL))
1949 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1951 // Initiate outbound connections from -addnode
1952 if (!NewThread(ThreadOpenAddedConnections, NULL))
1953 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1955 // Initiate outbound connections
1956 if (!NewThread(ThreadOpenConnections, NULL))
1957 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1960 if (!NewThread(ThreadMessageHandler, NULL))
1961 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1963 // Dump network addresses
1964 if (!NewThread(ThreadDumpAddress, NULL))
1965 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1967 // Mine proof-of-stake blocks in the background
1968 if (!NewThread(ThreadStakeMiner, pwalletMain))
1969 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1971 // Trusted NTP server, it's localhost by default.
1972 strTrustedUpstream = GetArg("-ntp", "localhost");
1974 // Start periodical NTP sampling thread
1975 NewThread(ThreadNtpSamples, NULL);
1981 printf("StopNode()\n");
1983 nTransactionsUpdated++;
1984 auto nStart = GetTime();
1987 ThreadScriptCheckQuit();
1990 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1991 semOutbound->post();
1994 int nThreadsRunning = 0;
1995 for (int n = 0; n < THREAD_MAX; n++)
1996 nThreadsRunning += vnThreadsRunning[n];
1997 if (nThreadsRunning == 0)
1999 if (GetTime() - nStart > 20)
2003 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
2004 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
2005 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
2006 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
2007 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
2008 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
2009 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
2010 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
2011 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
2012 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
2013 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
2030 for(CNode* pnode : vNodes)
2031 if (pnode->hSocket != INVALID_SOCKET)
2032 CloseSocket(pnode->hSocket);
2033 for(SOCKET hListenSocket : vhListenSocket)
2034 if (hListenSocket != INVALID_SOCKET)
2035 if (!CloseSocket(hListenSocket))
2036 printf("CloseSocket(hListenSocket) failed with error %d\n", WSAGetLastError());
2038 // clean up some globals (to help leak detection)
2039 for(CNode *pnode : vNodes)
2041 for(CNode *pnode : vNodesDisconnected)
2044 vNodesDisconnected.clear();
2047 delete pnodeLocalHost;
2048 pnodeLocalHost = NULL;
2051 // Shutdown Windows Sockets
2056 instance_of_cnetcleanup;
2058 inline void RelayInventory(const CInv& inv)
2060 // Put on lists to offer to the other nodes
2063 for(CNode* pnode : vNodes)
2064 pnode->PushInventory(inv);
2068 void RelayTransaction(const CTransaction& tx, const uint256& hash)
2070 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2073 RelayTransaction(tx, hash, ss);
2076 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
2078 CInv inv(MSG_TX, hash);
2081 // Expire old relay messages
2082 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
2084 mapRelay.erase(vRelayExpiration.front().second);
2085 vRelayExpiration.pop_front();
2088 // Save original serialized message so newer versions are preserved
2089 mapRelay.insert({inv, ss});
2090 vRelayExpiration.push_back({GetTime() + 15 * 60, inv});
2093 RelayInventory(inv);
2096 void CNode::RecordBytesRecv(uint64_t bytes)
2098 LOCK(cs_totalBytesRecv);
2099 nTotalBytesRecv += bytes;
2102 void CNode::RecordBytesSent(uint64_t bytes)
2104 LOCK(cs_totalBytesSent);
2105 nTotalBytesSent += bytes;
2108 uint64_t CNode::GetTotalBytesRecv()
2110 LOCK(cs_totalBytesRecv);
2111 return nTotalBytesRecv;
2114 uint64_t CNode::GetTotalBytesSent()
2116 LOCK(cs_totalBytesSent);
2117 return nTotalBytesSent;
2119 int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) {
2120 return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);