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);
793 void ThreadSocketHandler(void* parg)
795 // Make this thread recognisable as the networking thread
796 RenameThread("novacoin-net");
800 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
801 ThreadSocketHandler2(parg);
802 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
804 catch (exception& e) {
805 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
806 PrintException(&e, "ThreadSocketHandler()");
808 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
809 throw; // support pthread_cancel()
811 printf("ThreadSocketHandler exited\n");
814 static list<CNode*> vNodesDisconnected;
816 void ThreadSocketHandler2(void* parg)
818 printf("ThreadSocketHandler started\n");
819 size_t nPrevNodeCount = 0;
827 // Disconnect unused nodes
828 vector<CNode*> vNodesCopy = vNodes;
829 for(CNode* pnode : vNodesCopy)
831 if (pnode->fDisconnect ||
832 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
834 // remove from vNodes
835 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
837 // release outbound grant (if any)
838 pnode->grantOutbound.Release();
840 // close socket and cleanup
841 pnode->CloseSocketDisconnect();
844 // hold in disconnected pool until all refs are released
845 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
846 if (pnode->fNetworkNode || pnode->fInbound)
848 vNodesDisconnected.push_back(pnode);
852 // Delete disconnected nodes
853 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
854 for(CNode* pnode : vNodesDisconnectedCopy)
856 // wait until threads are done using it
857 if (pnode->GetRefCount() <= 0)
859 bool fDelete = false;
861 TRY_LOCK(pnode->cs_vSend, lockSend);
864 TRY_LOCK(pnode->cs_vRecv, lockRecv);
867 TRY_LOCK(pnode->cs_mapRequests, lockReq);
870 TRY_LOCK(pnode->cs_inventory, lockInv);
879 vNodesDisconnected.remove(pnode);
885 if (vNodes.size() != nPrevNodeCount)
887 nPrevNodeCount = vNodes.size();
888 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
893 // Find which sockets have data to receive
895 struct timeval timeout;
897 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
904 FD_ZERO(&fdsetError);
905 SOCKET hSocketMax = 0;
906 bool have_fds = false;
908 for(SOCKET hListenSocket : vhListenSocket) {
909 FD_SET(hListenSocket, &fdsetRecv);
910 hSocketMax = max(hSocketMax, hListenSocket);
915 for(CNode* pnode : vNodes)
917 if (pnode->hSocket == INVALID_SOCKET)
919 FD_SET(pnode->hSocket, &fdsetRecv);
920 FD_SET(pnode->hSocket, &fdsetError);
921 hSocketMax = max(hSocketMax, pnode->hSocket);
924 TRY_LOCK(pnode->cs_vSend, lockSend);
925 if (lockSend && !pnode->vSend.empty())
926 FD_SET(pnode->hSocket, &fdsetSend);
931 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
932 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
933 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
934 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
937 if (nSelect == SOCKET_ERROR)
941 int nErr = WSAGetLastError();
942 printf("socket select error %d\n", nErr);
943 for (unsigned int i = 0; i <= hSocketMax; i++)
944 FD_SET(i, &fdsetRecv);
947 FD_ZERO(&fdsetError);
948 Sleep(timeout.tv_usec/1000);
953 // Accept new connections
955 for(SOCKET hListenSocket : vhListenSocket)
956 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
959 struct sockaddr_storage sockaddr;
961 struct sockaddr sockaddr;
963 socklen_t len = sizeof(sockaddr);
964 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
968 if (hSocket != INVALID_SOCKET)
969 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
970 printf("Warning: Unknown socket family\n");
974 for(CNode* pnode : vNodes)
979 if (hSocket == INVALID_SOCKET)
981 int nErr = WSAGetLastError();
982 if (nErr != WSAEWOULDBLOCK)
983 printf("socket error accept failed: %d\n", nErr);
985 else if (nInbound >= GetArgInt("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
988 LOCK(cs_setservAddNodeAddresses);
989 if (!setservAddNodeAddresses.count(addr))
990 CloseSocket(hSocket);
993 else if (CNode::IsBanned(addr))
995 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
996 CloseSocket(hSocket);
1000 printf("accepted connection %s\n", addr.ToString().c_str());
1001 CNode* pnode = new CNode(hSocket, addr, "", true);
1005 vNodes.push_back(pnode);
1012 // Service each socket
1014 vector<CNode*> vNodesCopy;
1017 vNodesCopy = vNodes;
1018 for(CNode* pnode : vNodesCopy)
1021 for(CNode* pnode : vNodesCopy)
1029 if (pnode->hSocket == INVALID_SOCKET)
1031 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
1033 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1036 CDataStream& vRecv = pnode->vRecv;
1037 uint64_t nPos = vRecv.size();
1039 if (nPos > ReceiveBufferSize()) {
1040 if (!pnode->fDisconnect)
1041 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
1042 pnode->CloseSocketDisconnect();
1045 // typical socket buffer is 8K-64K
1046 char pchBuf[0x10000];
1047 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
1050 vRecv.resize(nPos + nBytes);
1051 memcpy(&vRecv[nPos], pchBuf, nBytes);
1052 pnode->nLastRecv = GetTime();
1053 pnode->nRecvBytes += nBytes;
1054 pnode->RecordBytesRecv(nBytes);
1056 else if (nBytes == 0)
1058 // socket closed gracefully
1059 if (!pnode->fDisconnect)
1060 printf("socket closed\n");
1061 pnode->CloseSocketDisconnect();
1063 else if (nBytes < 0)
1066 int nErr = WSAGetLastError();
1067 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
1069 if (!pnode->fDisconnect)
1070 printf("socket recv error %d\n", nErr);
1071 pnode->CloseSocketDisconnect();
1081 if (pnode->hSocket == INVALID_SOCKET)
1083 if (FD_ISSET(pnode->hSocket, &fdsetSend))
1085 TRY_LOCK(pnode->cs_vSend, lockSend);
1088 CDataStream& vSend = pnode->vSend;
1091 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
1094 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
1095 pnode->nLastSend = GetTime();
1096 pnode->nSendBytes += nBytes;
1097 pnode->RecordBytesSent(nBytes);
1099 else if (nBytes < 0)
1102 int nErr = WSAGetLastError();
1103 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
1105 printf("socket send error %d\n", nErr);
1106 pnode->CloseSocketDisconnect();
1114 // Inactivity checking
1116 if (pnode->vSend.empty())
1117 pnode->nLastSendEmpty = GetTime();
1118 if (GetTime() - pnode->nTimeConnected > 60)
1120 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
1122 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
1123 pnode->fDisconnect = true;
1125 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
1127 printf("socket not sending\n");
1128 pnode->fDisconnect = true;
1130 else if (GetTime() - pnode->nLastRecv > 90*60)
1132 printf("socket inactivity timeout\n");
1133 pnode->fDisconnect = true;
1139 for(CNode* pnode : vNodesCopy)
1147 void ThreadDNSAddressSeed(void* parg)
1149 // Make this thread recognisable as the DNS seeding thread
1150 RenameThread("novacoin-dnsseed");
1154 vnThreadsRunning[THREAD_DNSSEED]++;
1155 ThreadDNSAddressSeed2(parg);
1156 vnThreadsRunning[THREAD_DNSSEED]--;
1158 catch (exception& e) {
1159 vnThreadsRunning[THREAD_DNSSEED]--;
1160 PrintException(&e, "ThreadDNSAddressSeed()");
1162 vnThreadsRunning[THREAD_DNSSEED]--;
1163 throw; // support pthread_cancel()
1165 printf("ThreadDNSAddressSeed exited\n");
1168 void ThreadDNSAddressSeed2(void* parg)
1170 printf("ThreadDNSAddressSeed started\n");
1176 // Each pair gives a source name and a seed name.
1177 // The first name is used as information source for addrman.
1178 // The second name should resolve to a list of seed addresses.
1179 static const vector<pair <string, string> > vstrDNSSeed = {
1180 { "node.novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro" },
1181 { "novacoin.ru", "dnsseed.novacoin.ru" },
1182 { "novacoin.ru", "testseed.novacoin.ru" },
1183 { "novaco.in", "dnsseed.novaco.in" },
1185 printf("Loading addresses from DNS seeds (could take a while)\n");
1187 for (unsigned int seed_idx = 0; seed_idx < vstrDNSSeed.size(); seed_idx++) {
1188 if (HaveNameProxy()) {
1189 AddOneShot(vstrDNSSeed[seed_idx].second);
1191 vector<CNetAddr> vaddr;
1192 vector<CAddress> vAdd;
1193 if (LookupHost(vstrDNSSeed[seed_idx].second, vaddr))
1195 for(CNetAddr& ip : vaddr)
1197 auto addr = CAddress(CService(ip, GetDefaultPort()));
1198 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1199 vAdd.push_back(addr);
1203 addrman.Add(vAdd, CNetAddr(vstrDNSSeed[seed_idx].first, true));
1208 printf("%d addresses found from DNS seeds\n", found);
1211 void DumpAddresses()
1213 auto nStart = GetTimeMillis();
1218 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1219 addrman.size(), GetTimeMillis() - nStart);
1222 void ThreadDumpAddress2(void* parg)
1224 printf("ThreadDumpAddress started\n");
1226 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1230 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1232 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1234 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1237 void ThreadDumpAddress(void* parg)
1239 // Make this thread recognisable as the address dumping thread
1240 RenameThread("novacoin-adrdump");
1244 ThreadDumpAddress2(parg);
1246 catch (exception& e) {
1247 PrintException(&e, "ThreadDumpAddress()");
1249 printf("ThreadDumpAddress exited\n");
1252 void ThreadOpenConnections(void* parg)
1254 // Make this thread recognisable as the connection opening thread
1255 RenameThread("novacoin-opencon");
1259 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1260 ThreadOpenConnections2(parg);
1261 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1263 catch (exception& e) {
1264 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1265 PrintException(&e, "ThreadOpenConnections()");
1267 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1268 PrintException(NULL, "ThreadOpenConnections()");
1270 printf("ThreadOpenConnections exited\n");
1273 void static ProcessOneShot()
1278 if (vOneShots.empty())
1280 strDest = vOneShots.front();
1281 vOneShots.pop_front();
1284 CSemaphoreGrant grant(*semOutbound, true);
1286 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1287 AddOneShot(strDest);
1291 void ThreadOpenConnections2(void* parg)
1293 printf("ThreadOpenConnections started\n");
1295 // Connect to specific addresses
1296 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1298 for (int64_t nLoop = 0;; nLoop++)
1301 for(string strAddr : mapMultiArgs["-connect"])
1304 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1305 for (int i = 0; i < 10 && i < nLoop; i++)
1316 // Initiate network connections
1317 auto nStart = GetTime();
1322 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1324 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1329 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1330 CSemaphoreGrant grant(*semOutbound);
1331 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1335 // Add seed nodes if IRC isn't working
1336 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1338 vector<uint32_t> vnSeed =
1340 0x1c542868, 0x3859dd6f, 0x203c2e68, 0xf145a6bc, 0x638a545f, 0x325da346, 0x385da346, 0xfb2b8d5f,
1341 0x52568c5f, 0xa979e65b, 0x8de6485d, 0x9f79e65b, 0x048a861f, 0x3388b55f, 0x6ff0b45e, 0x17e81f5f,
1342 0x6c47bb25, 0x1ecdc852, 0x28263db9, 0x47824e5d, 0x36f1c851, 0x2bf913b2, 0x95923cb3, 0x84e63eb2,
1343 0xefdeedbf, 0x65200092, 0xf36f6805, 0x42692d05, 0x772c1955, 0xb6bf1b4e, 0x7abb5f5d, 0xdb2fa6bc,
1344 0x90e911bf, 0x82de565f, 0x694416b2, 0x0ab600bc, 0xfcecbe6d, 0x24ed9fb2, 0x1bb618c2, 0xc64765bb,
1345 0x4e3d62c3, 0xdba24baa, 0x4b7109b0, 0x12a12cc2, 0xfc01864f, 0x0b69e85b, 0x33922c1f, 0xac611bc6,
1346 0x2a257155, 0x991d5fc0, 0xbfdabcb1, 0x9b73ee55, 0x5bc2b95d, 0xdef0762e, 0x6ab7c936, 0x9c4416b2,
1347 0xd60d864f, 0x03671f1f, 0x3b5da346, 0xc6f5c851, 0x5411b2d4, 0xe7c25702, 0x63474fb0, 0x7e11c854,
1348 0x52381d5f, 0x72fdfe59, 0x51599a05, 0xfb12b2d4, 0xaee4f15e, 0xd0e3f15e, 0x2aa2805f, 0xa1caf15e,
1349 0x34fe425e, 0x46e1f15e, 0xd7c71955, 0xaeeff15e, 0x47c2af55, 0x563d89b2, 0x67980fd9, 0xc9def15e,
1350 0x9cc51eb9, 0xdaa7aa6b, 0x78e6871f, 0x0d5d2cb2, 0x7aedf15e, 0x9bcaf15e, 0xe5f7f15e, 0x501c1759,
1351 0xdfbc4980, 0xa7397f2e, 0x31ea1a02, 0x3a27655e, 0xaa86f05c, 0xdcddf15e, 0x64689cb2, 0xd4bf62d4,
1352 0xf093eab2, 0x98def15e, 0xb6c5f15e, 0x81e8f15e, 0xe5d2fe59, 0xa312786d, 0x4cf9fe59, 0x8a922c1f,
1353 0x00c7fe59, 0x1ade565f, 0x9e4116b2, 0x2c36983e, 0x68f8f15e, 0x51b7eab2, 0x76c51eb9, 0x9edd4980,
1354 0x90ef565f, 0x0dd80857, 0xd513fb94, 0xf5bdeab2, 0xa95277b0, 0x2cf2f15e, 0x1897eab2, 0x924416b2,
1355 0x985c9b59, 0x30aa43d8, 0xf9c6745f, 0xaf862e5f, 0xe0ceeab2, 0xb9b3eab2, 0x6da4eab2, 0xa4fdeab2,
1356 0x0fa6c125, 0xe38bbd05, 0x5d922c1f, 0x9bd0eab2, 0x73025e02, 0xc4fd794d, 0x8435b35f, 0x2d01bc2e,
1357 0xaa2a14d4, 0xa22b07cb, 0xebda6f4f, 0xddc6514e, 0xf23feab2, 0xea1e5256, 0x6147b45e, 0x47d21e4f,
1358 0x67c41c1f, 0x53ec1a02, 0x352e786d, 0x6bec1a02, 0x78fb4abe, 0xd3014c5d, 0x9fbbeab2, 0x1fc51eb9,
1359 0x720eeab2, 0x2db5eab2, 0xe8baf65c, 0x521b459e, 0x65c4955f, 0x0e7b915f, 0xa8f37e6d, 0x6d0b465f,
1360 0xfab8ff5c, 0xf7c27e6d, 0x7345a846, 0x4fd1a7d5, 0xdfc97e6d, 0x26c27e6d, 0xa9de36b2, 0xc615344d,
1361 0x28ceb95d, 0xa52d895e, 0x18c17e6d, 0x13ec1a02, 0x0ba37125, 0x6c3d344d, 0xb3922c1f, 0x506bbeb0,
1362 0x4d04994e, 0xa1bbe56d, 0xf62c344d, 0x0847d048, 0x4bdc6451, 0xc95b9a05, 0xbcd3a7d5, 0x29b57125,
1363 0x0c4d2cb2, 0xf2b8eab2, 0xc2d5b95d, 0x0185ef59, 0x30adeab2, 0xcaf0e92e, 0x756c344d, 0xfd9e252e,
1364 0xbe5ef3bc, 0x4689344d, 0xb223895e, 0xfcebeaad, 0xb7c0e92e, 0x993c1760, 0xe1e171b0, 0xb857e75b,
1365 0xbf10002e, 0xb55b2cb2, 0xa90e2cb2, 0x13d6f15e, 0xf8be9225, 0x14ddf15e, 0x06e90305, 0x82472cb2,
1367 vector<CAddress> vAdd;
1368 for (unsigned int i = 0; i < vnSeed.size(); i++)
1370 // It'll only connect to one or two seed nodes because once it connects,
1371 // it'll get a pile of addresses with newer timestamps.
1372 // Seed nodes are given a random 'last seen time' of between one and two
1375 memcpy(&ip, &vnSeed[i], sizeof(ip));
1376 CAddress addr(CService(ip, GetDefaultPort()));
1377 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1378 vAdd.push_back(addr);
1380 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1383 // Add Tor nodes if we have connection with onion router
1384 if (mapArgs.count("-tor"))
1386 const vector<string> vstrTorSeed =
1388 "seedp4knqnoei57u.onion",
1389 "seedr3hhlepyi7fd.onion",
1390 "seed3uuomkclbiz4.onion",
1391 "seedeh7qck3ouff5.onion",
1392 "5rg3vq4jagckeckf.onion",
1393 "seedt3sraf53ajiy.onion",
1394 "seedg4qyccsg42oq.onion",
1395 "novaqrtoywpg7jly.onion",
1396 "seed3d5wolqbgrcb.onion",
1397 "seed24u5dwph3qw4.onion",
1398 "mj26ulzbs2oskgym.onion",
1399 "eqon4usunavt76m7.onion",
1400 "seedd3aldwpslzl3.onion"
1402 vector<CAddress> vAdd;
1403 for (unsigned int i = 0; i < vstrTorSeed.size(); i++)
1405 CAddress addr(CService(vstrTorSeed[i], GetDefaultPort()));
1406 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1407 vAdd.push_back(addr);
1409 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1413 // Choose an address to connect to based on most recently seen
1415 CAddress addrConnect;
1417 // Only connect out to one peer per network group (/16 for IPv4).
1418 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1420 set<vector<unsigned char> > setConnected;
1423 for(CNode* pnode : vNodes) {
1424 if (!pnode->fInbound) {
1425 setConnected.insert(pnode->addr.GetGroup());
1431 auto nANow = GetAdjustedTime();
1436 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1437 auto addr = addrman.Select(10 + min(nOutbound,8)*10);
1439 // if we selected an invalid address, restart
1440 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1443 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1444 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1445 // already-connected network ranges, ...) before trying new addrman addresses.
1450 if (IsLimited(addr))
1453 // only consider very recently tried nodes after 30 failed attempts
1454 if (nANow - addr.nLastTry < 600 && nTries < 30)
1457 // do not allow non-default ports, unless after 50 invalid addresses selected already
1458 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1465 if (addrConnect.IsValid())
1466 OpenNetworkConnection(addrConnect, &grant);
1470 void ThreadOpenAddedConnections(void* parg)
1472 // Make this thread recognisable as the connection opening thread
1473 RenameThread("novacoin-opencon");
1477 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1478 ThreadOpenAddedConnections2(parg);
1479 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1481 catch (exception& e) {
1482 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1483 PrintException(&e, "ThreadOpenAddedConnections()");
1485 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1486 PrintException(NULL, "ThreadOpenAddedConnections()");
1488 printf("ThreadOpenAddedConnections exited\n");
1491 void ThreadOpenAddedConnections2(void* parg)
1493 printf("ThreadOpenAddedConnections started\n");
1496 LOCK(cs_vAddedNodes);
1497 vAddedNodes = mapMultiArgs["-addnode"];
1500 if (HaveNameProxy()) {
1502 list<string> lAddresses(0);
1504 LOCK(cs_vAddedNodes);
1505 for(string& strAddNode : vAddedNodes)
1506 lAddresses.push_back(strAddNode);
1508 for(string& strAddNode : lAddresses) {
1510 CSemaphoreGrant grant(*semOutbound);
1511 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1514 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1515 Sleep(120000); // Retry every 2 minutes
1516 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1521 for (uint32_t i = 0; true; i++)
1523 list<string> lAddresses(0);
1525 LOCK(cs_vAddedNodes);
1526 for(string& strAddNode : vAddedNodes)
1527 lAddresses.push_back(strAddNode);
1530 list<vector<CService> > lservAddressesToAdd(0);
1531 for(string& strAddNode : lAddresses)
1533 vector<CService> vservNode(0);
1534 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1536 lservAddressesToAdd.push_back(vservNode);
1538 LOCK(cs_setservAddNodeAddresses);
1539 for(CService& serv : vservNode)
1540 setservAddNodeAddresses.insert(serv);
1544 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1545 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1548 for(CNode* pnode : vNodes)
1549 for (auto it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1551 for(CService& addrNode : *(it))
1552 if (pnode->addr == addrNode)
1554 it = lservAddressesToAdd.erase(it);
1555 if(it != lservAddressesToAdd.begin())
1559 if (it == lservAddressesToAdd.end())
1563 for(vector<CService>& vserv : lservAddressesToAdd)
1565 if (vserv.size() == 0)
1567 CSemaphoreGrant grant(*semOutbound);
1568 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1575 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1576 Sleep(120000); // Retry every 2 minutes
1577 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1583 // if successful, this moves the passed grant to the constructed node
1584 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1587 // Initiate outbound network connection
1592 if (IsLocal(addrConnect) ||
1593 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1594 FindNode(addrConnect.ToStringIPPort().c_str()))
1596 if (strDest && FindNode(strDest))
1599 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1600 CNode* pnode = ConnectNode(addrConnect, strDest);
1601 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1607 grantOutbound->MoveTo(pnode->grantOutbound);
1608 pnode->fNetworkNode = true;
1610 pnode->fOneShot = true;
1615 // for now, use a very simple selection metric: the node from which we received
1617 static int64_t NodeSyncScore(const CNode *pnode) {
1618 return pnode->nLastRecv;
1621 void static StartSync(const vector<CNode*> &vNodes) {
1622 CNode *pnodeNewSync = NULL;
1623 int64_t nBestScore = 0;
1625 // Iterate over all nodes
1626 for(CNode* pnode : vNodes) {
1627 // check preconditions for allowing a sync
1628 if (!pnode->fClient && !pnode->fOneShot &&
1629 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1630 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1631 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1632 // if ok, compare node's score with the best so far
1633 int64_t nScore = NodeSyncScore(pnode);
1634 if (pnodeNewSync == NULL || nScore > nBestScore) {
1635 pnodeNewSync = pnode;
1636 nBestScore = nScore;
1640 // if a new sync candidate was found, start sync!
1642 pnodeNewSync->fStartSync = true;
1643 pnodeSync = pnodeNewSync;
1647 void ThreadMessageHandler(void* parg)
1649 // Make this thread recognisable as the message handling thread
1650 RenameThread("novacoin-msghand");
1654 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1655 ThreadMessageHandler2(parg);
1656 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1658 catch (exception& e) {
1659 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1660 PrintException(&e, "ThreadMessageHandler()");
1662 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1663 PrintException(NULL, "ThreadMessageHandler()");
1665 printf("ThreadMessageHandler exited\n");
1668 void ThreadMessageHandler2(void* parg)
1670 printf("ThreadMessageHandler started\n");
1671 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1674 bool fHaveSyncNode = false;
1675 vector<CNode*> vNodesCopy;
1678 vNodesCopy = vNodes;
1679 for(CNode* pnode : vNodesCopy) {
1681 if (pnode == pnodeSync)
1682 fHaveSyncNode = true;
1687 StartSync(vNodesCopy);
1689 // Poll the connected nodes for messages
1690 for(CNode* pnode : vNodesCopy)
1694 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1696 ProcessMessages(pnode);
1703 TRY_LOCK(pnode->cs_vSend, lockSend);
1705 SendMessages(pnode);
1713 for(CNode* pnode : vNodesCopy)
1717 // Wait and allow messages to bunch up.
1718 // Reduce vnThreadsRunning so StopNode has permission to exit while
1719 // we're sleeping, but we must always check fShutdown after doing this.
1720 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1722 if (fRequestShutdown)
1724 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1735 bool BindListenPort(const CService &addrBind, string& strError)
1740 // Create socket for listening for incoming connections
1742 struct sockaddr_storage sockaddr;
1744 struct sockaddr sockaddr;
1746 socklen_t len = sizeof(sockaddr);
1747 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1749 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1750 printf("%s\n", strError.c_str());
1754 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1755 if (hListenSocket == INVALID_SOCKET)
1757 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1758 printf("%s\n", strError.c_str());
1764 // Different way of disabling SIGPIPE on BSD
1765 if (setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int)) == SOCKET_ERROR)
1767 printf("WARNING: setsockopt failed\n");
1768 //TODO: work around problem - may be add CloseSocket and return false?
1771 // Allow binding if the port is still in TIME_WAIT state after
1772 // the program was closed and restarted. Not an issue on windows!
1773 if (setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int)) == SOCKET_ERROR)
1775 printf("WARNING: setsockopt failed\n");
1776 //TODO: work around problem - may be add CloseSocket and return false?
1781 // Set to non-blocking, incoming connections will also inherit this
1782 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1784 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1787 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1788 printf("%s\n", strError.c_str());
1789 CloseSocket(hListenSocket);
1794 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1795 // and enable it by default or not. Try to enable it, if possible.
1796 if (addrBind.IsIPv6()) {
1799 if (setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int)) == SOCKET_ERROR)
1801 printf("WARNING: setsockopt failed\n");
1802 //TODO: work around problem - may be add CloseSocket and return false?
1805 if (setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int)) == SOCKET_ERROR)
1807 printf("WARNING: setsockopt failed\n");
1808 //TODO: work around problem - may be add CloseSocket and return false?
1813 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1814 if (setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int)) == SOCKET_ERROR)
1816 printf("WARNING: setsockopt failed\n");
1817 //TODO: work around problem - may be add CloseSocket and return false?
1823 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1825 int nErr = WSAGetLastError();
1826 if (nErr == WSAEADDRINUSE)
1827 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1829 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1830 printf("%s\n", strError.c_str());
1831 CloseSocket(hListenSocket);
1834 printf("Bound to %s\n", addrBind.ToString().c_str());
1836 // Listen for incoming connections
1837 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1839 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1840 printf("%s\n", strError.c_str());
1841 CloseSocket(hListenSocket);
1845 vhListenSocket.push_back(hListenSocket);
1847 if (addrBind.IsRoutable() && fDiscover)
1848 AddLocal(addrBind, LOCAL_BIND);
1853 void static Discover()
1859 // Get local host IP
1860 char pszHostName[1000] = "";
1861 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1863 vector<CNetAddr> vaddr;
1864 if (LookupHost(pszHostName, vaddr))
1866 for(const auto &addr : vaddr)
1868 AddLocal(addr, LOCAL_IF);
1873 // Get local host ip
1874 struct ifaddrs* myaddrs;
1875 if (getifaddrs(&myaddrs) == 0)
1877 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1879 if (ifa->ifa_addr == NULL) continue;
1880 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1881 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1882 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1883 if (ifa->ifa_addr->sa_family == AF_INET)
1885 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1886 CNetAddr addr(s4->sin_addr);
1887 if (AddLocal(addr, LOCAL_IF))
1888 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1891 else if (ifa->ifa_addr->sa_family == AF_INET6)
1893 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1894 CNetAddr addr(s6->sin6_addr);
1895 if (AddLocal(addr, LOCAL_IF))
1896 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1900 freeifaddrs(myaddrs);
1904 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1905 if (!IsLimited(NET_IPV4))
1906 NewThread(ThreadGetMyExternalIP, NULL);
1909 void StartNode(void* parg)
1911 // Make this thread recognisable as the startup thread
1912 RenameThread("novacoin-start");
1914 if (semOutbound == NULL) {
1915 // initialize semaphore
1916 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1917 semOutbound = new CSemaphore(nMaxOutbound);
1920 if (pnodeLocalHost == NULL)
1921 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1929 if (!GetBoolArg("-dnsseed", true))
1930 printf("DNS seeding disabled\n");
1932 if (!NewThread(ThreadDNSAddressSeed, NULL))
1933 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1935 // Get addresses from IRC and advertise ours
1936 if (!GetBoolArg("-irc", true))
1937 printf("IRC seeding disabled\n");
1939 if (!NewThread(ThreadIRCSeed, NULL))
1940 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1942 // Send and receive from sockets, accept connections
1943 if (!NewThread(ThreadSocketHandler, NULL))
1944 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1946 // Initiate outbound connections from -addnode
1947 if (!NewThread(ThreadOpenAddedConnections, NULL))
1948 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1950 // Initiate outbound connections
1951 if (!NewThread(ThreadOpenConnections, NULL))
1952 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1955 if (!NewThread(ThreadMessageHandler, NULL))
1956 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1958 // Dump network addresses
1959 if (!NewThread(ThreadDumpAddress, NULL))
1960 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1962 // Mine proof-of-stake blocks in the background
1963 if (!NewThread(ThreadStakeMiner, pwalletMain))
1964 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1966 // Trusted NTP server, it's localhost by default.
1967 strTrustedUpstream = GetArg("-ntp", "localhost");
1969 // Start periodical NTP sampling thread
1970 NewThread(ThreadNtpSamples, NULL);
1976 printf("StopNode()\n");
1978 nTransactionsUpdated++;
1979 auto nStart = GetTime();
1982 ThreadScriptCheckQuit();
1985 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1986 semOutbound->post();
1989 int nThreadsRunning = 0;
1990 for (int n = 0; n < THREAD_MAX; n++)
1991 nThreadsRunning += vnThreadsRunning[n];
1992 if (nThreadsRunning == 0)
1994 if (GetTime() - nStart > 20)
1998 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1999 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
2000 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
2001 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
2002 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
2003 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
2004 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
2005 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
2006 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
2007 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
2008 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
2025 for(CNode* pnode : vNodes)
2026 if (pnode->hSocket != INVALID_SOCKET)
2027 CloseSocket(pnode->hSocket);
2028 for(SOCKET hListenSocket : vhListenSocket)
2029 if (hListenSocket != INVALID_SOCKET)
2030 if (!CloseSocket(hListenSocket))
2031 printf("CloseSocket(hListenSocket) failed with error %d\n", WSAGetLastError());
2033 // clean up some globals (to help leak detection)
2034 for(CNode *pnode : vNodes)
2036 for(CNode *pnode : vNodesDisconnected)
2039 vNodesDisconnected.clear();
2042 delete pnodeLocalHost;
2043 pnodeLocalHost = NULL;
2046 // Shutdown Windows Sockets
2051 instance_of_cnetcleanup;
2053 inline void RelayInventory(const CInv& inv)
2055 // Put on lists to offer to the other nodes
2058 for(CNode* pnode : vNodes)
2059 pnode->PushInventory(inv);
2063 void RelayTransaction(const CTransaction& tx, const uint256& hash)
2065 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2068 RelayTransaction(tx, hash, ss);
2071 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
2073 CInv inv(MSG_TX, hash);
2076 // Expire old relay messages
2077 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
2079 mapRelay.erase(vRelayExpiration.front().second);
2080 vRelayExpiration.pop_front();
2083 // Save original serialized message so newer versions are preserved
2084 mapRelay.insert({inv, ss});
2085 vRelayExpiration.push_back({GetTime() + 15 * 60, inv});
2088 RelayInventory(inv);
2091 void CNode::RecordBytesRecv(uint64_t bytes)
2093 LOCK(cs_totalBytesRecv);
2094 nTotalBytesRecv += bytes;
2097 void CNode::RecordBytesSent(uint64_t bytes)
2099 LOCK(cs_totalBytesSent);
2100 nTotalBytesSent += bytes;
2103 uint64_t CNode::GetTotalBytesRecv()
2105 LOCK(cs_totalBytesRecv);
2106 return nTotalBytesRecv;
2109 uint64_t CNode::GetTotalBytesSent()
2111 LOCK(cs_totalBytesSent);
2112 return nTotalBytesSent;
2114 int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) {
2115 return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);