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)
984 LOCK(cs_setservAddNodeAddresses);
985 if (!setservAddNodeAddresses.count(addr))
986 CloseSocket(hSocket);
989 else if (CNode::IsBanned(addr))
991 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
992 CloseSocket(hSocket);
996 printf("accepted connection %s\n", addr.ToString().c_str());
997 CNode* pnode = new CNode(hSocket, addr, "", true);
1001 vNodes.push_back(pnode);
1008 // Service each socket
1010 vector<CNode*> vNodesCopy;
1013 vNodesCopy = vNodes;
1014 for(CNode* pnode : vNodesCopy)
1017 for(CNode* pnode : vNodesCopy)
1025 if (pnode->hSocket == INVALID_SOCKET)
1027 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
1029 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1032 CDataStream& vRecv = pnode->vRecv;
1033 uint64_t nPos = vRecv.size();
1035 if (nPos > ReceiveBufferSize()) {
1036 if (!pnode->fDisconnect)
1037 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
1038 pnode->CloseSocketDisconnect();
1041 // typical socket buffer is 8K-64K
1042 char pchBuf[0x10000];
1043 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
1046 vRecv.resize(nPos + nBytes);
1047 memcpy(&vRecv[nPos], pchBuf, nBytes);
1048 pnode->nLastRecv = GetTime();
1049 pnode->nRecvBytes += nBytes;
1050 pnode->RecordBytesRecv(nBytes);
1052 else if (nBytes == 0)
1054 // socket closed gracefully
1055 if (!pnode->fDisconnect)
1056 printf("socket closed\n");
1057 pnode->CloseSocketDisconnect();
1059 else if (nBytes < 0)
1062 int nErr = WSAGetLastError();
1063 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
1065 if (!pnode->fDisconnect)
1066 printf("socket recv error %s\n", NetworkErrorString(nErr).c_str());
1067 pnode->CloseSocketDisconnect();
1077 if (pnode->hSocket == INVALID_SOCKET)
1079 if (FD_ISSET(pnode->hSocket, &fdsetSend))
1081 TRY_LOCK(pnode->cs_vSend, lockSend);
1084 CDataStream& vSend = pnode->vSend;
1087 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
1090 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
1091 pnode->nLastSend = GetTime();
1092 pnode->nSendBytes += nBytes;
1093 pnode->RecordBytesSent(nBytes);
1095 else if (nBytes < 0)
1098 int nErr = WSAGetLastError();
1099 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
1101 printf("socket send error %s\n", NetworkErrorString(nErr).c_str());
1102 pnode->CloseSocketDisconnect();
1110 // Inactivity checking
1112 if (pnode->vSend.empty())
1113 pnode->nLastSendEmpty = GetTime();
1114 if (GetTime() - pnode->nTimeConnected > 60)
1116 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
1118 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
1119 pnode->fDisconnect = true;
1121 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
1123 printf("socket not sending\n");
1124 pnode->fDisconnect = true;
1126 else if (GetTime() - pnode->nLastRecv > 90*60)
1128 printf("socket inactivity timeout\n");
1129 pnode->fDisconnect = true;
1135 for(CNode* pnode : vNodesCopy)
1143 void ThreadDNSAddressSeed(void* parg)
1145 // Make this thread recognisable as the DNS seeding thread
1146 RenameThread("novacoin-dnsseed");
1150 vnThreadsRunning[THREAD_DNSSEED]++;
1151 ThreadDNSAddressSeed2(parg);
1152 vnThreadsRunning[THREAD_DNSSEED]--;
1154 catch (exception& e) {
1155 vnThreadsRunning[THREAD_DNSSEED]--;
1156 PrintException(&e, "ThreadDNSAddressSeed()");
1158 vnThreadsRunning[THREAD_DNSSEED]--;
1159 throw; // support pthread_cancel()
1161 printf("ThreadDNSAddressSeed exited\n");
1164 void ThreadDNSAddressSeed2(void* parg)
1166 printf("ThreadDNSAddressSeed started\n");
1172 // Each pair gives a source name and a seed name.
1173 // The first name is used as information source for addrman.
1174 // The second name should resolve to a list of seed addresses.
1175 static const vector<pair <string, string> > vstrDNSSeed = {
1176 { "node.novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro" },
1177 { "novacoin.ru", "dnsseed.novacoin.ru" },
1178 { "novacoin.ru", "testseed.novacoin.ru" },
1179 { "novaco.in", "dnsseed.novaco.in" },
1181 printf("Loading addresses from DNS seeds (could take a while)\n");
1183 for (unsigned int seed_idx = 0; seed_idx < vstrDNSSeed.size(); seed_idx++) {
1184 if (HaveNameProxy()) {
1185 AddOneShot(vstrDNSSeed[seed_idx].second);
1187 vector<CNetAddr> vaddr;
1188 vector<CAddress> vAdd;
1189 if (LookupHost(vstrDNSSeed[seed_idx].second, vaddr))
1191 for(CNetAddr& ip : vaddr)
1193 auto addr = CAddress(CService(ip, GetDefaultPort()));
1194 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1195 vAdd.push_back(addr);
1199 addrman.Add(vAdd, CNetAddr(vstrDNSSeed[seed_idx].first, true));
1204 printf("%d addresses found from DNS seeds\n", found);
1207 void DumpAddresses()
1209 auto nStart = GetTimeMillis();
1214 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1215 addrman.size(), GetTimeMillis() - nStart);
1218 void ThreadDumpAddress2(void* parg)
1220 printf("ThreadDumpAddress started\n");
1222 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1226 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1228 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1230 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1233 void ThreadDumpAddress(void* parg)
1235 // Make this thread recognisable as the address dumping thread
1236 RenameThread("novacoin-adrdump");
1240 ThreadDumpAddress2(parg);
1242 catch (exception& e) {
1243 PrintException(&e, "ThreadDumpAddress()");
1245 printf("ThreadDumpAddress exited\n");
1248 void ThreadOpenConnections(void* parg)
1250 // Make this thread recognisable as the connection opening thread
1251 RenameThread("novacoin-opencon");
1255 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1256 ThreadOpenConnections2(parg);
1257 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1259 catch (exception& e) {
1260 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1261 PrintException(&e, "ThreadOpenConnections()");
1263 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1264 PrintException(NULL, "ThreadOpenConnections()");
1266 printf("ThreadOpenConnections exited\n");
1269 void static ProcessOneShot()
1274 if (vOneShots.empty())
1276 strDest = vOneShots.front();
1277 vOneShots.pop_front();
1280 CSemaphoreGrant grant(*semOutbound, true);
1282 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1283 AddOneShot(strDest);
1287 void ThreadOpenConnections2(void* parg)
1289 printf("ThreadOpenConnections started\n");
1291 // Connect to specific addresses
1292 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1294 for (int64_t nLoop = 0;; nLoop++)
1297 for(string strAddr : mapMultiArgs["-connect"])
1300 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1301 for (int i = 0; i < 10 && i < nLoop; i++)
1312 // Initiate network connections
1313 auto nStart = GetTime();
1318 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1320 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1325 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1326 CSemaphoreGrant grant(*semOutbound);
1327 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1331 // Add seed nodes if IRC isn't working
1332 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1334 vector<uint32_t> vnSeed =
1336 0x1c542868, 0x3859dd6f, 0x203c2e68, 0xf145a6bc, 0x638a545f, 0x325da346, 0x385da346, 0xfb2b8d5f,
1337 0x52568c5f, 0xa979e65b, 0x8de6485d, 0x9f79e65b, 0x048a861f, 0x3388b55f, 0x6ff0b45e, 0x17e81f5f,
1338 0x6c47bb25, 0x1ecdc852, 0x28263db9, 0x47824e5d, 0x36f1c851, 0x2bf913b2, 0x95923cb3, 0x84e63eb2,
1339 0xefdeedbf, 0x65200092, 0xf36f6805, 0x42692d05, 0x772c1955, 0xb6bf1b4e, 0x7abb5f5d, 0xdb2fa6bc,
1340 0x90e911bf, 0x82de565f, 0x694416b2, 0x0ab600bc, 0xfcecbe6d, 0x24ed9fb2, 0x1bb618c2, 0xc64765bb,
1341 0x4e3d62c3, 0xdba24baa, 0x4b7109b0, 0x12a12cc2, 0xfc01864f, 0x0b69e85b, 0x33922c1f, 0xac611bc6,
1342 0x2a257155, 0x991d5fc0, 0xbfdabcb1, 0x9b73ee55, 0x5bc2b95d, 0xdef0762e, 0x6ab7c936, 0x9c4416b2,
1343 0xd60d864f, 0x03671f1f, 0x3b5da346, 0xc6f5c851, 0x5411b2d4, 0xe7c25702, 0x63474fb0, 0x7e11c854,
1344 0x52381d5f, 0x72fdfe59, 0x51599a05, 0xfb12b2d4, 0xaee4f15e, 0xd0e3f15e, 0x2aa2805f, 0xa1caf15e,
1345 0x34fe425e, 0x46e1f15e, 0xd7c71955, 0xaeeff15e, 0x47c2af55, 0x563d89b2, 0x67980fd9, 0xc9def15e,
1346 0x9cc51eb9, 0xdaa7aa6b, 0x78e6871f, 0x0d5d2cb2, 0x7aedf15e, 0x9bcaf15e, 0xe5f7f15e, 0x501c1759,
1347 0xdfbc4980, 0xa7397f2e, 0x31ea1a02, 0x3a27655e, 0xaa86f05c, 0xdcddf15e, 0x64689cb2, 0xd4bf62d4,
1348 0xf093eab2, 0x98def15e, 0xb6c5f15e, 0x81e8f15e, 0xe5d2fe59, 0xa312786d, 0x4cf9fe59, 0x8a922c1f,
1349 0x00c7fe59, 0x1ade565f, 0x9e4116b2, 0x2c36983e, 0x68f8f15e, 0x51b7eab2, 0x76c51eb9, 0x9edd4980,
1350 0x90ef565f, 0x0dd80857, 0xd513fb94, 0xf5bdeab2, 0xa95277b0, 0x2cf2f15e, 0x1897eab2, 0x924416b2,
1351 0x985c9b59, 0x30aa43d8, 0xf9c6745f, 0xaf862e5f, 0xe0ceeab2, 0xb9b3eab2, 0x6da4eab2, 0xa4fdeab2,
1352 0x0fa6c125, 0xe38bbd05, 0x5d922c1f, 0x9bd0eab2, 0x73025e02, 0xc4fd794d, 0x8435b35f, 0x2d01bc2e,
1353 0xaa2a14d4, 0xa22b07cb, 0xebda6f4f, 0xddc6514e, 0xf23feab2, 0xea1e5256, 0x6147b45e, 0x47d21e4f,
1354 0x67c41c1f, 0x53ec1a02, 0x352e786d, 0x6bec1a02, 0x78fb4abe, 0xd3014c5d, 0x9fbbeab2, 0x1fc51eb9,
1355 0x720eeab2, 0x2db5eab2, 0xe8baf65c, 0x521b459e, 0x65c4955f, 0x0e7b915f, 0xa8f37e6d, 0x6d0b465f,
1356 0xfab8ff5c, 0xf7c27e6d, 0x7345a846, 0x4fd1a7d5, 0xdfc97e6d, 0x26c27e6d, 0xa9de36b2, 0xc615344d,
1357 0x28ceb95d, 0xa52d895e, 0x18c17e6d, 0x13ec1a02, 0x0ba37125, 0x6c3d344d, 0xb3922c1f, 0x506bbeb0,
1358 0x4d04994e, 0xa1bbe56d, 0xf62c344d, 0x0847d048, 0x4bdc6451, 0xc95b9a05, 0xbcd3a7d5, 0x29b57125,
1359 0x0c4d2cb2, 0xf2b8eab2, 0xc2d5b95d, 0x0185ef59, 0x30adeab2, 0xcaf0e92e, 0x756c344d, 0xfd9e252e,
1360 0xbe5ef3bc, 0x4689344d, 0xb223895e, 0xfcebeaad, 0xb7c0e92e, 0x993c1760, 0xe1e171b0, 0xb857e75b,
1361 0xbf10002e, 0xb55b2cb2, 0xa90e2cb2, 0x13d6f15e, 0xf8be9225, 0x14ddf15e, 0x06e90305, 0x82472cb2,
1363 vector<CAddress> vAdd;
1364 for (unsigned int i = 0; i < vnSeed.size(); i++)
1366 // It'll only connect to one or two seed nodes because once it connects,
1367 // it'll get a pile of addresses with newer timestamps.
1368 // Seed nodes are given a random 'last seen time' of between one and two
1371 memcpy(&ip, &vnSeed[i], sizeof(ip));
1372 CAddress addr(CService(ip, GetDefaultPort()));
1373 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1374 vAdd.push_back(addr);
1376 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1379 // Add Tor nodes if we have connection with onion router
1380 if (mapArgs.count("-tor"))
1382 const vector<string> vstrTorSeed =
1384 "seedp4knqnoei57u.onion",
1385 "seedr3hhlepyi7fd.onion",
1386 "seed3uuomkclbiz4.onion",
1387 "seedeh7qck3ouff5.onion",
1388 "5rg3vq4jagckeckf.onion",
1389 "seedt3sraf53ajiy.onion",
1390 "seedg4qyccsg42oq.onion",
1391 "novaqrtoywpg7jly.onion",
1392 "seed3d5wolqbgrcb.onion",
1393 "seed24u5dwph3qw4.onion",
1394 "mj26ulzbs2oskgym.onion",
1395 "eqon4usunavt76m7.onion",
1396 "seedd3aldwpslzl3.onion"
1398 vector<CAddress> vAdd;
1399 for (unsigned int i = 0; i < vstrTorSeed.size(); i++)
1401 CAddress addr(CService(vstrTorSeed[i], GetDefaultPort()));
1402 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1403 vAdd.push_back(addr);
1405 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1409 // Choose an address to connect to based on most recently seen
1411 CAddress addrConnect;
1413 // Only connect out to one peer per network group (/16 for IPv4).
1414 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1416 set<vector<unsigned char> > setConnected;
1419 for(CNode* pnode : vNodes) {
1420 if (!pnode->fInbound) {
1421 setConnected.insert(pnode->addr.GetGroup());
1427 auto nANow = GetAdjustedTime();
1432 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1433 auto addr = addrman.Select(10 + min(nOutbound,8)*10);
1435 // if we selected an invalid address, restart
1436 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1439 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1440 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1441 // already-connected network ranges, ...) before trying new addrman addresses.
1446 if (IsLimited(addr))
1449 // only consider very recently tried nodes after 30 failed attempts
1450 if (nANow - addr.nLastTry < 600 && nTries < 30)
1453 // do not allow non-default ports, unless after 50 invalid addresses selected already
1454 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1461 if (addrConnect.IsValid())
1462 OpenNetworkConnection(addrConnect, &grant);
1466 void ThreadOpenAddedConnections(void* parg)
1468 // Make this thread recognisable as the connection opening thread
1469 RenameThread("novacoin-opencon");
1473 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1474 ThreadOpenAddedConnections2(parg);
1475 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1477 catch (exception& e) {
1478 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1479 PrintException(&e, "ThreadOpenAddedConnections()");
1481 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1482 PrintException(NULL, "ThreadOpenAddedConnections()");
1484 printf("ThreadOpenAddedConnections exited\n");
1487 void ThreadOpenAddedConnections2(void* parg)
1489 printf("ThreadOpenAddedConnections started\n");
1492 LOCK(cs_vAddedNodes);
1493 vAddedNodes = mapMultiArgs["-addnode"];
1496 if (HaveNameProxy()) {
1498 list<string> lAddresses(0);
1500 LOCK(cs_vAddedNodes);
1501 for(string& strAddNode : vAddedNodes)
1502 lAddresses.push_back(strAddNode);
1504 for(string& strAddNode : lAddresses) {
1506 CSemaphoreGrant grant(*semOutbound);
1507 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1510 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1511 Sleep(120000); // Retry every 2 minutes
1512 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1517 for (uint32_t i = 0; true; i++)
1519 list<string> lAddresses(0);
1521 LOCK(cs_vAddedNodes);
1522 for(string& strAddNode : vAddedNodes)
1523 lAddresses.push_back(strAddNode);
1526 list<vector<CService> > lservAddressesToAdd(0);
1527 for(string& strAddNode : lAddresses)
1529 vector<CService> vservNode(0);
1530 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1532 lservAddressesToAdd.push_back(vservNode);
1534 LOCK(cs_setservAddNodeAddresses);
1535 for(CService& serv : vservNode)
1536 setservAddNodeAddresses.insert(serv);
1540 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1541 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1544 for(CNode* pnode : vNodes)
1545 for (auto it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1547 for(CService& addrNode : *(it))
1548 if (pnode->addr == addrNode)
1550 it = lservAddressesToAdd.erase(it);
1551 if(it != lservAddressesToAdd.begin())
1555 if (it == lservAddressesToAdd.end())
1559 for(vector<CService>& vserv : lservAddressesToAdd)
1561 if (vserv.size() == 0)
1563 CSemaphoreGrant grant(*semOutbound);
1564 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1571 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1572 Sleep(120000); // Retry every 2 minutes
1573 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1579 // if successful, this moves the passed grant to the constructed node
1580 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1583 // Initiate outbound network connection
1588 if (IsLocal(addrConnect) ||
1589 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1590 FindNode(addrConnect.ToStringIPPort().c_str()))
1592 if (strDest && FindNode(strDest))
1595 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1596 CNode* pnode = ConnectNode(addrConnect, strDest);
1597 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1603 grantOutbound->MoveTo(pnode->grantOutbound);
1604 pnode->fNetworkNode = true;
1606 pnode->fOneShot = true;
1611 // for now, use a very simple selection metric: the node from which we received
1613 static int64_t NodeSyncScore(const CNode *pnode) {
1614 return pnode->nLastRecv;
1617 void static StartSync(const vector<CNode*> &vNodes) {
1618 CNode *pnodeNewSync = NULL;
1619 int64_t nBestScore = 0;
1621 // Iterate over all nodes
1622 for(CNode* pnode : vNodes) {
1623 // check preconditions for allowing a sync
1624 if (!pnode->fClient && !pnode->fOneShot &&
1625 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1626 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1627 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1628 // if ok, compare node's score with the best so far
1629 int64_t nScore = NodeSyncScore(pnode);
1630 if (pnodeNewSync == NULL || nScore > nBestScore) {
1631 pnodeNewSync = pnode;
1632 nBestScore = nScore;
1636 // if a new sync candidate was found, start sync!
1638 pnodeNewSync->fStartSync = true;
1639 pnodeSync = pnodeNewSync;
1643 void ThreadMessageHandler(void* parg)
1645 // Make this thread recognisable as the message handling thread
1646 RenameThread("novacoin-msghand");
1650 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1651 ThreadMessageHandler2(parg);
1652 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1654 catch (exception& e) {
1655 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1656 PrintException(&e, "ThreadMessageHandler()");
1658 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1659 PrintException(NULL, "ThreadMessageHandler()");
1661 printf("ThreadMessageHandler exited\n");
1664 void ThreadMessageHandler2(void* parg)
1666 printf("ThreadMessageHandler started\n");
1667 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1670 bool fHaveSyncNode = false;
1671 vector<CNode*> vNodesCopy;
1674 vNodesCopy = vNodes;
1675 for(CNode* pnode : vNodesCopy) {
1677 if (pnode == pnodeSync)
1678 fHaveSyncNode = true;
1683 StartSync(vNodesCopy);
1685 // Poll the connected nodes for messages
1686 for(CNode* pnode : vNodesCopy)
1690 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1692 ProcessMessages(pnode);
1699 TRY_LOCK(pnode->cs_vSend, lockSend);
1701 SendMessages(pnode);
1709 for(CNode* pnode : vNodesCopy)
1713 // Wait and allow messages to bunch up.
1714 // Reduce vnThreadsRunning so StopNode has permission to exit while
1715 // we're sleeping, but we must always check fShutdown after doing this.
1716 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1718 if (fRequestShutdown)
1720 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1731 bool BindListenPort(const CService &addrBind, string& strError)
1736 // Create socket for listening for incoming connections
1737 struct sockaddr_storage sockaddr;
1738 socklen_t len = sizeof(sockaddr);
1739 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1741 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1742 printf("%s\n", strError.c_str());
1746 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1747 if (hListenSocket == INVALID_SOCKET)
1749 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %s)", NetworkErrorString(WSAGetLastError()).c_str());
1750 printf("%s\n", strError.c_str());
1756 // Different way of disabling SIGPIPE on BSD
1757 if (setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int)) == SOCKET_ERROR)
1759 printf("WARNING: setsockopt failed\n");
1760 //TODO: work around problem - may be add CloseSocket and return false?
1763 // Allow binding if the port is still in TIME_WAIT state after
1764 // the program was closed and restarted. Not an issue on windows!
1765 if (setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int)) == SOCKET_ERROR)
1767 printf("WARNING: setsockopt failed\n");
1768 //TODO: work around problem - may be add CloseSocket and return false?
1773 // Set to non-blocking, incoming connections will also inherit this
1774 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1776 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1779 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %s)", NetworkErrorString(WSAGetLastError()).c_str());
1780 printf("%s\n", strError.c_str());
1781 CloseSocket(hListenSocket);
1785 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1786 // and enable it by default or not. Try to enable it, if possible.
1787 if (addrBind.IsIPv6()) {
1790 if (setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int)) == SOCKET_ERROR)
1792 printf("WARNING: setsockopt failed\n");
1793 //TODO: work around problem - may be add CloseSocket and return false?
1796 if (setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int)) == SOCKET_ERROR)
1798 printf("WARNING: setsockopt failed\n");
1799 //TODO: work around problem - may be add CloseSocket and return false?
1804 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1805 if (setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int)) == SOCKET_ERROR)
1807 printf("WARNING: setsockopt failed\n");
1808 //TODO: work around problem - may be add CloseSocket and return false?
1813 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1815 int nErr = WSAGetLastError();
1816 if (nErr == WSAEADDRINUSE)
1817 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1819 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToString().c_str(), NetworkErrorString(nErr).c_str());
1820 printf("%s\n", strError.c_str());
1821 CloseSocket(hListenSocket);
1824 printf("Bound to %s\n", addrBind.ToString().c_str());
1826 // Listen for incoming connections
1827 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1829 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %s)", NetworkErrorString(WSAGetLastError()).c_str());
1830 printf("%s\n", strError.c_str());
1831 CloseSocket(hListenSocket);
1835 vhListenSocket.push_back(hListenSocket);
1837 if (addrBind.IsRoutable() && fDiscover)
1838 AddLocal(addrBind, LOCAL_BIND);
1843 void static Discover()
1849 // Get local host IP
1850 char pszHostName[1000] = "";
1851 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1853 vector<CNetAddr> vaddr;
1854 if (LookupHost(pszHostName, vaddr))
1856 for(const auto &addr : vaddr)
1858 AddLocal(addr, LOCAL_IF);
1863 // Get local host ip
1864 struct ifaddrs* myaddrs;
1865 if (getifaddrs(&myaddrs) == 0)
1867 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1869 if (ifa->ifa_addr == NULL) continue;
1870 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1871 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1872 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1873 if (ifa->ifa_addr->sa_family == AF_INET)
1875 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1876 CNetAddr addr(s4->sin_addr);
1877 if (AddLocal(addr, LOCAL_IF))
1878 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1880 else if (ifa->ifa_addr->sa_family == AF_INET6)
1882 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1883 CNetAddr addr(s6->sin6_addr);
1884 if (AddLocal(addr, LOCAL_IF))
1885 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1888 freeifaddrs(myaddrs);
1892 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1893 if (!IsLimited(NET_IPV4))
1894 NewThread(ThreadGetMyExternalIP, NULL);
1897 void StartNode(void* parg)
1899 // Make this thread recognisable as the startup thread
1900 RenameThread("novacoin-start");
1902 if (semOutbound == NULL) {
1903 // initialize semaphore
1904 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1905 semOutbound = new CSemaphore(nMaxOutbound);
1908 if (pnodeLocalHost == NULL)
1909 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1917 if (!GetBoolArg("-dnsseed", true))
1918 printf("DNS seeding disabled\n");
1920 if (!NewThread(ThreadDNSAddressSeed, NULL))
1921 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1923 // Get addresses from IRC and advertise ours
1924 if (!GetBoolArg("-irc", true))
1925 printf("IRC seeding disabled\n");
1927 if (!NewThread(ThreadIRCSeed, NULL))
1928 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1930 // Send and receive from sockets, accept connections
1931 if (!NewThread(ThreadSocketHandler, NULL))
1932 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1934 // Initiate outbound connections from -addnode
1935 if (!NewThread(ThreadOpenAddedConnections, NULL))
1936 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1938 // Initiate outbound connections
1939 if (!NewThread(ThreadOpenConnections, NULL))
1940 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1943 if (!NewThread(ThreadMessageHandler, NULL))
1944 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1946 // Dump network addresses
1947 if (!NewThread(ThreadDumpAddress, NULL))
1948 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1950 // Mine proof-of-stake blocks in the background
1951 if (!NewThread(ThreadStakeMiner, pwalletMain))
1952 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1954 // Trusted NTP server, it's localhost by default.
1955 strTrustedUpstream = GetArg("-ntp", "localhost");
1957 // Start periodical NTP sampling thread
1958 NewThread(ThreadNtpSamples, NULL);
1964 printf("StopNode()\n");
1966 nTransactionsUpdated++;
1967 auto nStart = GetTime();
1970 ThreadScriptCheckQuit();
1973 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1974 semOutbound->post();
1977 int nThreadsRunning = 0;
1978 for (int n = 0; n < THREAD_MAX; n++)
1979 nThreadsRunning += vnThreadsRunning[n];
1980 if (nThreadsRunning == 0)
1982 if (GetTime() - nStart > 20)
1986 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1987 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1988 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1989 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1990 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1991 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1992 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1993 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1994 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1995 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1996 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
2013 for(CNode* pnode : vNodes)
2014 if (pnode->hSocket != INVALID_SOCKET)
2015 CloseSocket(pnode->hSocket);
2016 for(SOCKET hListenSocket : vhListenSocket)
2017 if (hListenSocket != INVALID_SOCKET)
2018 if (!CloseSocket(hListenSocket))
2019 printf("CloseSocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError()).c_str());
2021 // clean up some globals (to help leak detection)
2022 for(CNode *pnode : vNodes)
2024 for(CNode *pnode : vNodesDisconnected)
2027 vNodesDisconnected.clear();
2030 delete pnodeLocalHost;
2031 pnodeLocalHost = NULL;
2034 // Shutdown Windows Sockets
2039 instance_of_cnetcleanup;
2041 inline void RelayInventory(const CInv& inv)
2043 // Put on lists to offer to the other nodes
2046 for(CNode* pnode : vNodes)
2047 pnode->PushInventory(inv);
2051 void RelayTransaction(const CTransaction& tx, const uint256& hash)
2053 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2056 RelayTransaction(tx, hash, ss);
2059 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
2061 CInv inv(MSG_TX, hash);
2064 // Expire old relay messages
2065 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
2067 mapRelay.erase(vRelayExpiration.front().second);
2068 vRelayExpiration.pop_front();
2071 // Save original serialized message so newer versions are preserved
2072 mapRelay.insert({inv, ss});
2073 vRelayExpiration.push_back({GetTime() + 15 * 60, inv});
2076 RelayInventory(inv);
2079 void CNode::RecordBytesRecv(uint64_t bytes)
2081 LOCK(cs_totalBytesRecv);
2082 nTotalBytesRecv += bytes;
2085 void CNode::RecordBytesSent(uint64_t bytes)
2087 LOCK(cs_totalBytesSent);
2088 nTotalBytesSent += bytes;
2091 uint64_t CNode::GetTotalBytesRecv()
2093 LOCK(cs_totalBytesRecv);
2094 return nTotalBytesRecv;
2097 uint64_t CNode::GetTotalBytesSent()
2099 LOCK(cs_totalBytesSent);
2100 return nTotalBytesSent;
2103 int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) {
2104 return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);