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: %s\n", NetworkErrorString(nErr).c_str());
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 %s\n", NetworkErrorString(WSAGetLastError()).c_str());
450 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
451 printf("ConnectSocket() : fcntl non-blocking setting failed, error %s\n", NetworkErrorString(errno).c_str());
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(const 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 %s\n", NetworkErrorString(nErr).c_str());
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))
958 struct sockaddr_storage sockaddr;
959 socklen_t len = sizeof(sockaddr);
960 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
964 if (hSocket != INVALID_SOCKET)
965 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
966 printf("Warning: Unknown socket family\n");
970 for(CNode* pnode : vNodes)
975 if (hSocket == INVALID_SOCKET)
977 int nErr = WSAGetLastError();
978 if (nErr != WSAEWOULDBLOCK)
979 printf("socket error accept failed: %s\n", NetworkErrorString(nErr).c_str());
981 else if (nInbound >= GetArgInt("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
983 printf("connection from %s dropped (overall limit)\n", addr.ToString().c_str());
984 CloseSocket(hSocket);
986 else if (CNode::IsBanned(addr))
988 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
989 CloseSocket(hSocket);
993 printf("accepted connection %s\n", addr.ToString().c_str());
994 CNode* pnode = new CNode(hSocket, addr, "", true);
998 vNodes.push_back(pnode);
1005 // Service each socket
1007 vector<CNode*> vNodesCopy;
1010 vNodesCopy = vNodes;
1011 for(CNode* pnode : vNodesCopy)
1014 for(CNode* pnode : vNodesCopy)
1022 if (pnode->hSocket == INVALID_SOCKET)
1024 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
1026 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1029 CDataStream& vRecv = pnode->vRecv;
1030 uint64_t nPos = vRecv.size();
1032 if (nPos > ReceiveBufferSize()) {
1033 if (!pnode->fDisconnect)
1034 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
1035 pnode->CloseSocketDisconnect();
1038 // typical socket buffer is 8K-64K
1039 char pchBuf[0x10000];
1040 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
1043 vRecv.resize(nPos + nBytes);
1044 memcpy(&vRecv[nPos], pchBuf, nBytes);
1045 pnode->nLastRecv = GetTime();
1046 pnode->nRecvBytes += nBytes;
1047 pnode->RecordBytesRecv(nBytes);
1049 else if (nBytes == 0)
1051 // socket closed gracefully
1052 if (!pnode->fDisconnect)
1053 printf("socket closed\n");
1054 pnode->CloseSocketDisconnect();
1056 else if (nBytes < 0)
1059 int nErr = WSAGetLastError();
1060 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
1062 if (!pnode->fDisconnect)
1063 printf("socket recv error %s\n", NetworkErrorString(nErr).c_str());
1064 pnode->CloseSocketDisconnect();
1074 if (pnode->hSocket == INVALID_SOCKET)
1076 if (FD_ISSET(pnode->hSocket, &fdsetSend))
1078 TRY_LOCK(pnode->cs_vSend, lockSend);
1081 CDataStream& vSend = pnode->vSend;
1084 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
1087 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
1088 pnode->nLastSend = GetTime();
1089 pnode->nSendBytes += nBytes;
1090 pnode->RecordBytesSent(nBytes);
1092 else if (nBytes < 0)
1095 int nErr = WSAGetLastError();
1096 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
1098 printf("socket send error %s\n", NetworkErrorString(nErr).c_str());
1099 pnode->CloseSocketDisconnect();
1107 // Inactivity checking
1109 if (pnode->vSend.empty())
1110 pnode->nLastSendEmpty = GetTime();
1111 if (GetTime() - pnode->nTimeConnected > 60)
1113 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
1115 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
1116 pnode->fDisconnect = true;
1118 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
1120 printf("socket not sending\n");
1121 pnode->fDisconnect = true;
1123 else if (GetTime() - pnode->nLastRecv > 90*60)
1125 printf("socket inactivity timeout\n");
1126 pnode->fDisconnect = true;
1132 for(CNode* pnode : vNodesCopy)
1140 void ThreadDNSAddressSeed(void* parg)
1142 // Make this thread recognisable as the DNS seeding thread
1143 RenameThread("novacoin-dnsseed");
1147 vnThreadsRunning[THREAD_DNSSEED]++;
1148 ThreadDNSAddressSeed2(parg);
1149 vnThreadsRunning[THREAD_DNSSEED]--;
1151 catch (exception& e) {
1152 vnThreadsRunning[THREAD_DNSSEED]--;
1153 PrintException(&e, "ThreadDNSAddressSeed()");
1155 vnThreadsRunning[THREAD_DNSSEED]--;
1156 throw; // support pthread_cancel()
1158 printf("ThreadDNSAddressSeed exited\n");
1161 void ThreadDNSAddressSeed2(void* parg)
1163 printf("ThreadDNSAddressSeed started\n");
1169 // Each pair gives a source name and a seed name.
1170 // The first name is used as information source for addrman.
1171 // The second name should resolve to a list of seed addresses.
1172 static const vector<pair <string, string> > vstrDNSSeed = {
1173 { "node.novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro" },
1174 { "novacoin.ru", "dnsseed.novacoin.ru" },
1175 { "novacoin.ru", "testseed.novacoin.ru" },
1176 { "novaco.in", "dnsseed.novaco.in" },
1178 printf("Loading addresses from DNS seeds (could take a while)\n");
1180 for (unsigned int seed_idx = 0; seed_idx < vstrDNSSeed.size(); seed_idx++) {
1181 if (HaveNameProxy()) {
1182 AddOneShot(vstrDNSSeed[seed_idx].second);
1184 vector<CNetAddr> vaddr;
1185 vector<CAddress> vAdd;
1186 if (LookupHost(vstrDNSSeed[seed_idx].second, vaddr))
1188 for(CNetAddr& ip : vaddr)
1190 auto addr = CAddress(CService(ip, GetDefaultPort()));
1191 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1192 vAdd.push_back(addr);
1196 addrman.Add(vAdd, CNetAddr(vstrDNSSeed[seed_idx].first, true));
1201 printf("%d addresses found from DNS seeds\n", found);
1204 void DumpAddresses()
1206 auto nStart = GetTimeMillis();
1211 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1212 addrman.size(), GetTimeMillis() - nStart);
1215 void ThreadDumpAddress2(void* parg)
1217 printf("ThreadDumpAddress started\n");
1219 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1223 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1225 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1227 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1230 void ThreadDumpAddress(void* parg)
1232 // Make this thread recognisable as the address dumping thread
1233 RenameThread("novacoin-adrdump");
1237 ThreadDumpAddress2(parg);
1239 catch (exception& e) {
1240 PrintException(&e, "ThreadDumpAddress()");
1242 printf("ThreadDumpAddress exited\n");
1245 void ThreadOpenConnections(void* parg)
1247 // Make this thread recognisable as the connection opening thread
1248 RenameThread("novacoin-opencon");
1252 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1253 ThreadOpenConnections2(parg);
1254 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1256 catch (exception& e) {
1257 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1258 PrintException(&e, "ThreadOpenConnections()");
1260 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1261 PrintException(NULL, "ThreadOpenConnections()");
1263 printf("ThreadOpenConnections exited\n");
1266 void static ProcessOneShot()
1271 if (vOneShots.empty())
1273 strDest = vOneShots.front();
1274 vOneShots.pop_front();
1277 CSemaphoreGrant grant(*semOutbound, true);
1279 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1280 AddOneShot(strDest);
1284 void ThreadOpenConnections2(void* parg)
1286 printf("ThreadOpenConnections started\n");
1288 // Connect to specific addresses
1289 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1291 for (int64_t nLoop = 0;; nLoop++)
1294 for(string strAddr : mapMultiArgs["-connect"])
1297 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1298 for (int i = 0; i < 10 && i < nLoop; i++)
1309 // Initiate network connections
1310 auto nStart = GetTime();
1315 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1317 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1322 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1323 CSemaphoreGrant grant(*semOutbound);
1324 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1328 // Add seed nodes if IRC isn't working
1329 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1331 vector<uint32_t> vnSeed =
1333 0x1c542868, 0x3859dd6f, 0x203c2e68, 0xf145a6bc, 0x638a545f, 0x325da346, 0x385da346, 0xfb2b8d5f,
1334 0x52568c5f, 0xa979e65b, 0x8de6485d, 0x9f79e65b, 0x048a861f, 0x3388b55f, 0x6ff0b45e, 0x17e81f5f,
1335 0x6c47bb25, 0x1ecdc852, 0x28263db9, 0x47824e5d, 0x36f1c851, 0x2bf913b2, 0x95923cb3, 0x84e63eb2,
1336 0xefdeedbf, 0x65200092, 0xf36f6805, 0x42692d05, 0x772c1955, 0xb6bf1b4e, 0x7abb5f5d, 0xdb2fa6bc,
1337 0x90e911bf, 0x82de565f, 0x694416b2, 0x0ab600bc, 0xfcecbe6d, 0x24ed9fb2, 0x1bb618c2, 0xc64765bb,
1338 0x4e3d62c3, 0xdba24baa, 0x4b7109b0, 0x12a12cc2, 0xfc01864f, 0x0b69e85b, 0x33922c1f, 0xac611bc6,
1339 0x2a257155, 0x991d5fc0, 0xbfdabcb1, 0x9b73ee55, 0x5bc2b95d, 0xdef0762e, 0x6ab7c936, 0x9c4416b2,
1340 0xd60d864f, 0x03671f1f, 0x3b5da346, 0xc6f5c851, 0x5411b2d4, 0xe7c25702, 0x63474fb0, 0x7e11c854,
1341 0x52381d5f, 0x72fdfe59, 0x51599a05, 0xfb12b2d4, 0xaee4f15e, 0xd0e3f15e, 0x2aa2805f, 0xa1caf15e,
1342 0x34fe425e, 0x46e1f15e, 0xd7c71955, 0xaeeff15e, 0x47c2af55, 0x563d89b2, 0x67980fd9, 0xc9def15e,
1343 0x9cc51eb9, 0xdaa7aa6b, 0x78e6871f, 0x0d5d2cb2, 0x7aedf15e, 0x9bcaf15e, 0xe5f7f15e, 0x501c1759,
1344 0xdfbc4980, 0xa7397f2e, 0x31ea1a02, 0x3a27655e, 0xaa86f05c, 0xdcddf15e, 0x64689cb2, 0xd4bf62d4,
1345 0xf093eab2, 0x98def15e, 0xb6c5f15e, 0x81e8f15e, 0xe5d2fe59, 0xa312786d, 0x4cf9fe59, 0x8a922c1f,
1346 0x00c7fe59, 0x1ade565f, 0x9e4116b2, 0x2c36983e, 0x68f8f15e, 0x51b7eab2, 0x76c51eb9, 0x9edd4980,
1347 0x90ef565f, 0x0dd80857, 0xd513fb94, 0xf5bdeab2, 0xa95277b0, 0x2cf2f15e, 0x1897eab2, 0x924416b2,
1348 0x985c9b59, 0x30aa43d8, 0xf9c6745f, 0xaf862e5f, 0xe0ceeab2, 0xb9b3eab2, 0x6da4eab2, 0xa4fdeab2,
1349 0x0fa6c125, 0xe38bbd05, 0x5d922c1f, 0x9bd0eab2, 0x73025e02, 0xc4fd794d, 0x8435b35f, 0x2d01bc2e,
1350 0xaa2a14d4, 0xa22b07cb, 0xebda6f4f, 0xddc6514e, 0xf23feab2, 0xea1e5256, 0x6147b45e, 0x47d21e4f,
1351 0x67c41c1f, 0x53ec1a02, 0x352e786d, 0x6bec1a02, 0x78fb4abe, 0xd3014c5d, 0x9fbbeab2, 0x1fc51eb9,
1352 0x720eeab2, 0x2db5eab2, 0xe8baf65c, 0x521b459e, 0x65c4955f, 0x0e7b915f, 0xa8f37e6d, 0x6d0b465f,
1353 0xfab8ff5c, 0xf7c27e6d, 0x7345a846, 0x4fd1a7d5, 0xdfc97e6d, 0x26c27e6d, 0xa9de36b2, 0xc615344d,
1354 0x28ceb95d, 0xa52d895e, 0x18c17e6d, 0x13ec1a02, 0x0ba37125, 0x6c3d344d, 0xb3922c1f, 0x506bbeb0,
1355 0x4d04994e, 0xa1bbe56d, 0xf62c344d, 0x0847d048, 0x4bdc6451, 0xc95b9a05, 0xbcd3a7d5, 0x29b57125,
1356 0x0c4d2cb2, 0xf2b8eab2, 0xc2d5b95d, 0x0185ef59, 0x30adeab2, 0xcaf0e92e, 0x756c344d, 0xfd9e252e,
1357 0xbe5ef3bc, 0x4689344d, 0xb223895e, 0xfcebeaad, 0xb7c0e92e, 0x993c1760, 0xe1e171b0, 0xb857e75b,
1358 0xbf10002e, 0xb55b2cb2, 0xa90e2cb2, 0x13d6f15e, 0xf8be9225, 0x14ddf15e, 0x06e90305, 0x82472cb2,
1360 vector<CAddress> vAdd;
1361 for (unsigned int i = 0; i < vnSeed.size(); i++)
1363 // It'll only connect to one or two seed nodes because once it connects,
1364 // it'll get a pile of addresses with newer timestamps.
1365 // Seed nodes are given a random 'last seen time' of between one and two
1368 memcpy(&ip, &vnSeed[i], sizeof(ip));
1369 CAddress addr(CService(ip, GetDefaultPort()));
1370 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1371 vAdd.push_back(addr);
1373 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1376 // Add Tor nodes if we have connection with onion router
1377 if (mapArgs.count("-tor"))
1379 const vector<string> vstrTorSeed =
1381 "seedp4knqnoei57u.onion",
1382 "seedr3hhlepyi7fd.onion",
1383 "seed3uuomkclbiz4.onion",
1384 "seedeh7qck3ouff5.onion",
1385 "5rg3vq4jagckeckf.onion",
1386 "seedt3sraf53ajiy.onion",
1387 "seedg4qyccsg42oq.onion",
1388 "novaqrtoywpg7jly.onion",
1389 "seed3d5wolqbgrcb.onion",
1390 "seed24u5dwph3qw4.onion",
1391 "mj26ulzbs2oskgym.onion",
1392 "eqon4usunavt76m7.onion",
1393 "seedd3aldwpslzl3.onion"
1395 vector<CAddress> vAdd;
1396 for (unsigned int i = 0; i < vstrTorSeed.size(); i++)
1398 CAddress addr(CService(vstrTorSeed[i], GetDefaultPort()));
1399 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1400 vAdd.push_back(addr);
1402 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1406 // Choose an address to connect to based on most recently seen
1408 CAddress addrConnect;
1410 // Only connect out to one peer per network group (/16 for IPv4).
1411 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1413 set<vector<unsigned char> > setConnected;
1416 for(CNode* pnode : vNodes) {
1417 if (!pnode->fInbound) {
1418 setConnected.insert(pnode->addr.GetGroup());
1424 auto nANow = GetAdjustedTime();
1429 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1430 auto addr = addrman.Select(10 + min(nOutbound,8)*10);
1432 // if we selected an invalid address, restart
1433 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1436 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1437 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1438 // already-connected network ranges, ...) before trying new addrman addresses.
1443 if (IsLimited(addr))
1446 // only consider very recently tried nodes after 30 failed attempts
1447 if (nANow - addr.nLastTry < 600 && nTries < 30)
1450 // do not allow non-default ports, unless after 50 invalid addresses selected already
1451 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1458 if (addrConnect.IsValid())
1459 OpenNetworkConnection(addrConnect, &grant);
1463 void ThreadOpenAddedConnections(void* parg)
1465 // Make this thread recognisable as the connection opening thread
1466 RenameThread("novacoin-opencon");
1470 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1471 ThreadOpenAddedConnections2(parg);
1472 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1474 catch (exception& e) {
1475 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1476 PrintException(&e, "ThreadOpenAddedConnections()");
1478 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1479 PrintException(NULL, "ThreadOpenAddedConnections()");
1481 printf("ThreadOpenAddedConnections exited\n");
1484 void ThreadOpenAddedConnections2(void* parg)
1486 printf("ThreadOpenAddedConnections started\n");
1489 LOCK(cs_vAddedNodes);
1490 vAddedNodes = mapMultiArgs["-addnode"];
1493 if (HaveNameProxy()) {
1495 list<string> lAddresses(0);
1497 LOCK(cs_vAddedNodes);
1498 for(string& strAddNode : vAddedNodes)
1499 lAddresses.push_back(strAddNode);
1501 for(string& strAddNode : lAddresses) {
1503 CSemaphoreGrant grant(*semOutbound);
1504 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1507 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1508 Sleep(120000); // Retry every 2 minutes
1509 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1514 for (uint32_t i = 0; true; i++)
1516 list<string> lAddresses(0);
1518 LOCK(cs_vAddedNodes);
1519 for(string& strAddNode : vAddedNodes)
1520 lAddresses.push_back(strAddNode);
1523 list<vector<CService> > lservAddressesToAdd(0);
1524 for(string& strAddNode : lAddresses)
1526 vector<CService> vservNode(0);
1527 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1529 lservAddressesToAdd.push_back(vservNode);
1531 LOCK(cs_setservAddNodeAddresses);
1532 for(CService& serv : vservNode)
1533 setservAddNodeAddresses.insert(serv);
1537 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1538 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1541 for(CNode* pnode : vNodes)
1542 for (auto it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1544 for(CService& addrNode : *(it))
1545 if (pnode->addr == addrNode)
1547 it = lservAddressesToAdd.erase(it);
1548 if(it != lservAddressesToAdd.begin())
1552 if (it == lservAddressesToAdd.end())
1556 for(vector<CService>& vserv : lservAddressesToAdd)
1558 if (vserv.size() == 0)
1560 CSemaphoreGrant grant(*semOutbound);
1561 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1568 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1569 Sleep(120000); // Retry every 2 minutes
1570 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1576 // if successful, this moves the passed grant to the constructed node
1577 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1580 // Initiate outbound network connection
1585 if (IsLocal(addrConnect) ||
1586 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1587 FindNode(addrConnect.ToStringIPPort().c_str()))
1589 if (strDest && FindNode(strDest))
1592 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1593 CNode* pnode = ConnectNode(addrConnect, strDest);
1594 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1600 grantOutbound->MoveTo(pnode->grantOutbound);
1601 pnode->fNetworkNode = true;
1603 pnode->fOneShot = true;
1608 // for now, use a very simple selection metric: the node from which we received
1610 static int64_t NodeSyncScore(const CNode *pnode) {
1611 return pnode->nLastRecv;
1614 void static StartSync(const vector<CNode*> &vNodes) {
1615 CNode *pnodeNewSync = NULL;
1616 int64_t nBestScore = 0;
1618 // Iterate over all nodes
1619 for(CNode* pnode : vNodes) {
1620 // check preconditions for allowing a sync
1621 if (!pnode->fClient && !pnode->fOneShot &&
1622 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1623 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1624 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1625 // if ok, compare node's score with the best so far
1626 int64_t nScore = NodeSyncScore(pnode);
1627 if (pnodeNewSync == NULL || nScore > nBestScore) {
1628 pnodeNewSync = pnode;
1629 nBestScore = nScore;
1633 // if a new sync candidate was found, start sync!
1635 pnodeNewSync->fStartSync = true;
1636 pnodeSync = pnodeNewSync;
1640 void ThreadMessageHandler(void* parg)
1642 // Make this thread recognisable as the message handling thread
1643 RenameThread("novacoin-msghand");
1647 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1648 ThreadMessageHandler2(parg);
1649 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1651 catch (exception& e) {
1652 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1653 PrintException(&e, "ThreadMessageHandler()");
1655 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1656 PrintException(NULL, "ThreadMessageHandler()");
1658 printf("ThreadMessageHandler exited\n");
1661 void ThreadMessageHandler2(void* parg)
1663 printf("ThreadMessageHandler started\n");
1664 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1667 bool fHaveSyncNode = false;
1668 vector<CNode*> vNodesCopy;
1671 vNodesCopy = vNodes;
1672 for(CNode* pnode : vNodesCopy) {
1674 if (pnode == pnodeSync)
1675 fHaveSyncNode = true;
1680 StartSync(vNodesCopy);
1682 // Poll the connected nodes for messages
1683 for(CNode* pnode : vNodesCopy)
1687 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1689 ProcessMessages(pnode);
1696 TRY_LOCK(pnode->cs_vSend, lockSend);
1698 SendMessages(pnode);
1706 for(CNode* pnode : vNodesCopy)
1710 // Wait and allow messages to bunch up.
1711 // Reduce vnThreadsRunning so StopNode has permission to exit while
1712 // we're sleeping, but we must always check fShutdown after doing this.
1713 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1715 if (fRequestShutdown)
1717 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1728 bool BindListenPort(const CService &addrBind, string& strError)
1733 // Create socket for listening for incoming connections
1734 struct sockaddr_storage sockaddr;
1735 socklen_t len = sizeof(sockaddr);
1736 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1738 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1739 printf("%s\n", strError.c_str());
1743 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1744 if (hListenSocket == INVALID_SOCKET)
1746 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %s)", NetworkErrorString(WSAGetLastError()).c_str());
1747 printf("%s\n", strError.c_str());
1753 // Different way of disabling SIGPIPE on BSD
1754 if (setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int)) == SOCKET_ERROR)
1756 printf("WARNING: setsockopt failed\n");
1757 //TODO: work around problem - may be add CloseSocket and return false?
1760 // Allow binding if the port is still in TIME_WAIT state after
1761 // the program was closed and restarted. Not an issue on windows!
1762 if (setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int)) == SOCKET_ERROR)
1764 printf("WARNING: setsockopt failed\n");
1765 //TODO: work around problem - may be add CloseSocket and return false?
1770 // Set to non-blocking, incoming connections will also inherit this
1771 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1773 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1776 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %s)", NetworkErrorString(WSAGetLastError()).c_str());
1777 printf("%s\n", strError.c_str());
1778 CloseSocket(hListenSocket);
1782 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1783 // and enable it by default or not. Try to enable it, if possible.
1784 if (addrBind.IsIPv6()) {
1787 if (setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int)) == SOCKET_ERROR)
1789 printf("WARNING: setsockopt failed\n");
1790 //TODO: work around problem - may be add CloseSocket and return false?
1793 if (setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int)) == SOCKET_ERROR)
1795 printf("WARNING: setsockopt failed\n");
1796 //TODO: work around problem - may be add CloseSocket and return false?
1801 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1802 if (setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int)) == SOCKET_ERROR)
1804 printf("WARNING: setsockopt failed\n");
1805 //TODO: work around problem - may be add CloseSocket and return false?
1810 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1812 int nErr = WSAGetLastError();
1813 if (nErr == WSAEADDRINUSE)
1814 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1816 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToString().c_str(), NetworkErrorString(nErr).c_str());
1817 printf("%s\n", strError.c_str());
1818 CloseSocket(hListenSocket);
1821 printf("Bound to %s\n", addrBind.ToString().c_str());
1823 // Listen for incoming connections
1824 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1826 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %s)", NetworkErrorString(WSAGetLastError()).c_str());
1827 printf("%s\n", strError.c_str());
1828 CloseSocket(hListenSocket);
1832 vhListenSocket.push_back(hListenSocket);
1834 if (addrBind.IsRoutable() && fDiscover)
1835 AddLocal(addrBind, LOCAL_BIND);
1840 void static Discover()
1846 // Get local host IP
1847 char pszHostName[1000] = "";
1848 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1850 vector<CNetAddr> vaddr;
1851 if (LookupHost(pszHostName, vaddr))
1853 for(const auto &addr : vaddr)
1855 AddLocal(addr, LOCAL_IF);
1860 // Get local host ip
1861 struct ifaddrs* myaddrs;
1862 if (getifaddrs(&myaddrs) == 0)
1864 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1866 if (ifa->ifa_addr == NULL) continue;
1867 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1868 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1869 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1870 if (ifa->ifa_addr->sa_family == AF_INET)
1872 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1873 CNetAddr addr(s4->sin_addr);
1874 if (AddLocal(addr, LOCAL_IF))
1875 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1877 else if (ifa->ifa_addr->sa_family == AF_INET6)
1879 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1880 CNetAddr addr(s6->sin6_addr);
1881 if (AddLocal(addr, LOCAL_IF))
1882 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1885 freeifaddrs(myaddrs);
1889 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1890 if (!IsLimited(NET_IPV4))
1891 NewThread(ThreadGetMyExternalIP, NULL);
1894 void StartNode(void* parg)
1896 // Make this thread recognisable as the startup thread
1897 RenameThread("novacoin-start");
1899 if (semOutbound == NULL) {
1900 // initialize semaphore
1901 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1902 semOutbound = new CSemaphore(nMaxOutbound);
1905 if (pnodeLocalHost == NULL)
1906 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1914 if (!GetBoolArg("-dnsseed", true))
1915 printf("DNS seeding disabled\n");
1917 if (!NewThread(ThreadDNSAddressSeed, NULL))
1918 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1920 // Get addresses from IRC and advertise ours
1921 if (!GetBoolArg("-irc", true))
1922 printf("IRC seeding disabled\n");
1924 if (!NewThread(ThreadIRCSeed, NULL))
1925 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1927 // Send and receive from sockets, accept connections
1928 if (!NewThread(ThreadSocketHandler, NULL))
1929 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1931 // Initiate outbound connections from -addnode
1932 if (!NewThread(ThreadOpenAddedConnections, NULL))
1933 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1935 // Initiate outbound connections
1936 if (!NewThread(ThreadOpenConnections, NULL))
1937 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1940 if (!NewThread(ThreadMessageHandler, NULL))
1941 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1943 // Dump network addresses
1944 if (!NewThread(ThreadDumpAddress, NULL))
1945 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1947 // Mine proof-of-stake blocks in the background
1948 if (!NewThread(ThreadStakeMiner, pwalletMain))
1949 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1951 // Trusted NTP server, it's localhost by default.
1952 strTrustedUpstream = GetArg("-ntp", "localhost");
1954 // Start periodical NTP sampling thread
1955 NewThread(ThreadNtpSamples, NULL);
1961 printf("StopNode()\n");
1963 nTransactionsUpdated++;
1964 auto nStart = GetTime();
1967 ThreadScriptCheckQuit();
1970 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1971 semOutbound->post();
1974 int nThreadsRunning = 0;
1975 for (int n = 0; n < THREAD_MAX; n++)
1976 nThreadsRunning += vnThreadsRunning[n];
1977 if (nThreadsRunning == 0)
1979 if (GetTime() - nStart > 20)
1983 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1984 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1985 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1986 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1987 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1988 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1989 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1990 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1991 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1992 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1993 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
2010 for(CNode* pnode : vNodes)
2011 if (pnode->hSocket != INVALID_SOCKET)
2012 CloseSocket(pnode->hSocket);
2013 for(SOCKET hListenSocket : vhListenSocket)
2014 if (hListenSocket != INVALID_SOCKET)
2015 if (!CloseSocket(hListenSocket))
2016 printf("CloseSocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError()).c_str());
2018 // clean up some globals (to help leak detection)
2019 for(CNode *pnode : vNodes)
2021 for(CNode *pnode : vNodesDisconnected)
2024 vNodesDisconnected.clear();
2027 delete pnodeLocalHost;
2028 pnodeLocalHost = NULL;
2031 // Shutdown Windows Sockets
2036 instance_of_cnetcleanup;
2038 inline void RelayInventory(const CInv& inv)
2040 // Put on lists to offer to the other nodes
2043 for(CNode* pnode : vNodes)
2044 pnode->PushInventory(inv);
2048 void RelayTransaction(const CTransaction& tx, const uint256& hash)
2050 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2053 RelayTransaction(tx, hash, ss);
2056 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
2058 CInv inv(MSG_TX, hash);
2061 // Expire old relay messages
2062 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
2064 mapRelay.erase(vRelayExpiration.front().second);
2065 vRelayExpiration.pop_front();
2068 // Save original serialized message so newer versions are preserved
2069 mapRelay.insert({inv, ss});
2070 vRelayExpiration.push_back({GetTime() + 15 * 60, inv});
2073 RelayInventory(inv);
2076 void CNode::RecordBytesRecv(uint64_t bytes)
2078 LOCK(cs_totalBytesRecv);
2079 nTotalBytesRecv += bytes;
2082 void CNode::RecordBytesSent(uint64_t bytes)
2084 LOCK(cs_totalBytesSent);
2085 nTotalBytesSent += bytes;
2088 uint64_t CNode::GetTotalBytesRecv()
2090 LOCK(cs_totalBytesRecv);
2091 return nTotalBytesRecv;
2094 uint64_t CNode::GetTotalBytesSent()
2096 LOCK(cs_totalBytesSent);
2097 return nTotalBytesSent;
2100 int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) {
2101 return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);