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());
1798 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1799 // and enable it by default or not. Try to enable it, if possible.
1800 if (addrBind.IsIPv6()) {
1803 if (setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int)) == SOCKET_ERROR)
1805 printf("WARNING: setsockopt failed\n");
1806 //TODO: work around problem - may be add CloseSocket and return false?
1809 if (setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int)) == SOCKET_ERROR)
1811 printf("WARNING: setsockopt failed\n");
1812 //TODO: work around problem - may be add CloseSocket and return false?
1817 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1818 if (setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int)) == SOCKET_ERROR)
1820 printf("WARNING: setsockopt failed\n");
1821 //TODO: work around problem - may be add CloseSocket and return false?
1827 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1829 int nErr = WSAGetLastError();
1830 if (nErr == WSAEADDRINUSE)
1831 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1833 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1834 printf("%s\n", strError.c_str());
1835 CloseSocket(hListenSocket);
1838 printf("Bound to %s\n", addrBind.ToString().c_str());
1840 // Listen for incoming connections
1841 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1843 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1844 printf("%s\n", strError.c_str());
1845 CloseSocket(hListenSocket);
1849 vhListenSocket.push_back(hListenSocket);
1851 if (addrBind.IsRoutable() && fDiscover)
1852 AddLocal(addrBind, LOCAL_BIND);
1857 void static Discover()
1863 // Get local host IP
1864 char pszHostName[1000] = "";
1865 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1867 vector<CNetAddr> vaddr;
1868 if (LookupHost(pszHostName, vaddr))
1870 for(const auto &addr : vaddr)
1872 AddLocal(addr, LOCAL_IF);
1877 // Get local host ip
1878 struct ifaddrs* myaddrs;
1879 if (getifaddrs(&myaddrs) == 0)
1881 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1883 if (ifa->ifa_addr == NULL) continue;
1884 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1885 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1886 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1887 if (ifa->ifa_addr->sa_family == AF_INET)
1889 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1890 CNetAddr addr(s4->sin_addr);
1891 if (AddLocal(addr, LOCAL_IF))
1892 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1895 else if (ifa->ifa_addr->sa_family == AF_INET6)
1897 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1898 CNetAddr addr(s6->sin6_addr);
1899 if (AddLocal(addr, LOCAL_IF))
1900 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1904 freeifaddrs(myaddrs);
1908 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1909 if (!IsLimited(NET_IPV4))
1910 NewThread(ThreadGetMyExternalIP, NULL);
1913 void StartNode(void* parg)
1915 // Make this thread recognisable as the startup thread
1916 RenameThread("novacoin-start");
1918 if (semOutbound == NULL) {
1919 // initialize semaphore
1920 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1921 semOutbound = new CSemaphore(nMaxOutbound);
1924 if (pnodeLocalHost == NULL)
1925 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1933 if (!GetBoolArg("-dnsseed", true))
1934 printf("DNS seeding disabled\n");
1936 if (!NewThread(ThreadDNSAddressSeed, NULL))
1937 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1939 // Get addresses from IRC and advertise ours
1940 if (!GetBoolArg("-irc", true))
1941 printf("IRC seeding disabled\n");
1943 if (!NewThread(ThreadIRCSeed, NULL))
1944 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1946 // Send and receive from sockets, accept connections
1947 if (!NewThread(ThreadSocketHandler, NULL))
1948 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1950 // Initiate outbound connections from -addnode
1951 if (!NewThread(ThreadOpenAddedConnections, NULL))
1952 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1954 // Initiate outbound connections
1955 if (!NewThread(ThreadOpenConnections, NULL))
1956 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1959 if (!NewThread(ThreadMessageHandler, NULL))
1960 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1962 // Dump network addresses
1963 if (!NewThread(ThreadDumpAddress, NULL))
1964 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1966 // Mine proof-of-stake blocks in the background
1967 if (!NewThread(ThreadStakeMiner, pwalletMain))
1968 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1970 // Trusted NTP server, it's localhost by default.
1971 strTrustedUpstream = GetArg("-ntp", "localhost");
1973 // Start periodical NTP sampling thread
1974 NewThread(ThreadNtpSamples, NULL);
1980 printf("StopNode()\n");
1982 nTransactionsUpdated++;
1983 auto nStart = GetTime();
1986 ThreadScriptCheckQuit();
1989 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1990 semOutbound->post();
1993 int nThreadsRunning = 0;
1994 for (int n = 0; n < THREAD_MAX; n++)
1995 nThreadsRunning += vnThreadsRunning[n];
1996 if (nThreadsRunning == 0)
1998 if (GetTime() - nStart > 20)
2002 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
2003 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
2004 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
2005 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
2006 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
2007 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
2008 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
2009 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
2010 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
2011 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
2012 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
2029 for(CNode* pnode : vNodes)
2030 if (pnode->hSocket != INVALID_SOCKET)
2031 CloseSocket(pnode->hSocket);
2032 for(SOCKET hListenSocket : vhListenSocket)
2033 if (hListenSocket != INVALID_SOCKET)
2034 if (!CloseSocket(hListenSocket))
2035 printf("CloseSocket(hListenSocket) failed with error %d\n", WSAGetLastError());
2037 // clean up some globals (to help leak detection)
2038 for(CNode *pnode : vNodes)
2040 for(CNode *pnode : vNodesDisconnected)
2043 vNodesDisconnected.clear();
2046 delete pnodeLocalHost;
2047 pnodeLocalHost = NULL;
2050 // Shutdown Windows Sockets
2055 instance_of_cnetcleanup;
2057 inline void RelayInventory(const CInv& inv)
2059 // Put on lists to offer to the other nodes
2062 for(CNode* pnode : vNodes)
2063 pnode->PushInventory(inv);
2067 void RelayTransaction(const CTransaction& tx, const uint256& hash)
2069 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2072 RelayTransaction(tx, hash, ss);
2075 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
2077 CInv inv(MSG_TX, hash);
2080 // Expire old relay messages
2081 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
2083 mapRelay.erase(vRelayExpiration.front().second);
2084 vRelayExpiration.pop_front();
2087 // Save original serialized message so newer versions are preserved
2088 mapRelay.insert({inv, ss});
2089 vRelayExpiration.push_back({GetTime() + 15 * 60, inv});
2092 RelayInventory(inv);
2095 void CNode::RecordBytesRecv(uint64_t bytes)
2097 LOCK(cs_totalBytesRecv);
2098 nTotalBytesRecv += bytes;
2101 void CNode::RecordBytesSent(uint64_t bytes)
2103 LOCK(cs_totalBytesSent);
2104 nTotalBytesSent += bytes;
2107 uint64_t CNode::GetTotalBytesRecv()
2109 LOCK(cs_totalBytesRecv);
2110 return nTotalBytesRecv;
2113 uint64_t CNode::GetTotalBytesSent()
2115 LOCK(cs_totalBytesSent);
2116 return nTotalBytesSent;
2118 int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) {
2119 return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);