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 "interface.h"
23 static const int MAX_OUTBOUND_CONNECTIONS = 16;
25 void ThreadMessageHandler2(void* parg);
26 void ThreadSocketHandler2(void* parg);
27 void ThreadOpenConnections2(void* parg);
28 void ThreadOpenAddedConnections2(void* parg);
29 void ThreadDNSAddressSeed2(void* parg);
31 // Fix for ancient MinGW versions, that don't have defined these in ws2tcpip.h.
32 // Todo: Can be removed when our pull-tester is upgraded to a modern MinGW version.
34 #ifndef PROTECTION_LEVEL_UNRESTRICTED
35 #define PROTECTION_LEVEL_UNRESTRICTED 10
37 #ifndef IPV6_PROTECTION_LEVEL
38 #define IPV6_PROTECTION_LEVEL 23
42 struct LocalServiceInfo {
48 // Global state variables
51 bool fDiscover = true;
52 uint64_t nLocalServices = (fClient ? 0 : NODE_NETWORK);
53 static CCriticalSection cs_mapLocalHost;
54 static map<CNetAddr, LocalServiceInfo> mapLocalHost;
55 static bool vfReachable[NET_MAX] = {};
56 static bool vfLimited[NET_MAX] = {};
57 static CNode* pnodeLocalHost = NULL;
58 static CNode* pnodeSync = NULL;
59 CAddress addrSeenByPeer(CService("0.0.0.0", nPortZero), nLocalServices);
60 uint64_t nLocalHostNonce = 0;
61 std::array<int, THREAD_MAX> vnThreadsRunning;
62 static std::vector<SOCKET> vhListenSocket;
65 vector<CNode*> vNodes;
66 CCriticalSection cs_vNodes;
67 map<CInv, CDataStream> mapRelay;
68 deque<pair<int64_t, CInv> > vRelayExpiration;
69 CCriticalSection cs_mapRelay;
70 map<CInv, int64_t> mapAlreadyAskedFor;
72 static deque<string> vOneShots;
73 CCriticalSection cs_vOneShots;
75 set<CNetAddr> setservAddNodeAddresses;
76 CCriticalSection cs_setservAddNodeAddresses;
78 vector<std::string> vAddedNodes;
79 CCriticalSection cs_vAddedNodes;
81 static CSemaphore *semOutbound = NULL;
83 inline void RelayInventory(const CInv& inv)
85 // Put on lists to offer to the other nodes
88 for (CNode* pnode : vNodes)
89 pnode->PushInventory(inv);
93 void AddOneShot(string strDest)
96 vOneShots.push_back(strDest);
99 unsigned short GetListenPort()
101 return (unsigned short)(GetArg("-port", GetDefaultPort()));
104 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
106 // Filter out duplicate requests
107 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
109 pindexLastGetBlocksBegin = pindexBegin;
110 hashLastGetBlocksEnd = hashEnd;
112 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
115 // find 'best' local address for a particular peer
116 bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
122 int nBestReachability = -1;
124 LOCK(cs_mapLocalHost);
125 for (map<CNetAddr, LocalServiceInfo>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
127 int nScore = (*it).second.nScore;
128 int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
129 if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
131 addr = CService((*it).first, (*it).second.nPort);
132 nBestReachability = nReachability;
137 return nBestScore >= 0;
140 // get best local address for a particular peer as a CAddress
141 CAddress GetLocalAddress(const CNetAddr *paddrPeer)
143 CAddress ret(CService("0.0.0.0", nPortZero), 0);
145 if (GetLocal(addr, paddrPeer))
147 ret = CAddress(addr);
148 ret.nServices = nLocalServices;
149 ret.nTime = GetAdjustedTime();
154 bool RecvLine(SOCKET hSocket, string& strLine)
160 int nBytes = recv(hSocket, &c, 1, 0);
168 if (strLine.size() >= 9000)
171 else if (nBytes <= 0)
177 int nErr = WSAGetLastError();
178 if (nErr == WSAEMSGSIZE)
180 if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
186 if (!strLine.empty())
191 printf("socket closed\n");
197 int nErr = WSAGetLastError();
198 printf("recv failed: %d\n", nErr);
205 // used when scores of local addresses may have changed
206 // pushes better local address to peers
207 void static AdvertizeLocal()
210 for (CNode* pnode : vNodes)
212 if (pnode->fSuccessfullyConnected)
214 CAddress addrLocal = GetLocalAddress(&pnode->addr);
215 if (addrLocal.IsRoutable() && (CService)addrLocal != pnode->addrLocal)
217 pnode->PushAddress(addrLocal);
218 pnode->addrLocal = addrLocal;
224 void SetReachable(enum Network net, bool fFlag)
226 LOCK(cs_mapLocalHost);
227 vfReachable[net] = fFlag;
228 if (net == NET_IPV6 && fFlag)
229 vfReachable[NET_IPV4] = true;
232 int GetnScore(const CService& addr)
234 LOCK(cs_mapLocalHost);
235 if (mapLocalHost.count(addr) == LOCAL_NONE)
237 return mapLocalHost[addr].nScore;
241 // Is our peer's addrLocal potentially useful as an external IP source?
242 bool IsPeerAddrLocalGood(CNode *pnode)
244 return fDiscover && pnode->addr.IsRoutable() && pnode->addrLocal.IsRoutable() &&
245 !IsLimited(pnode->addrLocal.GetNetwork());
248 // pushes our own address to a peer
249 void AdvertiseLocal(CNode *pnode)
251 if (!fNoListen && pnode->fSuccessfullyConnected)
253 CAddress addrLocal = GetLocalAddress(&pnode->addr);
254 // If discovery is enabled, sometimes give our peer the address it
255 // tells us that it sees us as in case it has a better idea of our
256 // address than we do.
257 if (IsPeerAddrLocalGood(pnode) && (!addrLocal.IsRoutable() ||
258 GetRand((GetnScore(addrLocal) > LOCAL_MANUAL) ? 8:2) == 0))
260 addrLocal.SetIP(pnode->addrLocal);
262 if (addrLocal.IsRoutable())
264 printf("AdvertiseLocal: advertising address %s\n", addrLocal.ToString().c_str());
265 pnode->PushAddress(addrLocal);
270 // learn a new local address
271 bool AddLocal(const CService& addr, int nScore)
273 if (!addr.IsRoutable())
276 if (!fDiscover && nScore < LOCAL_MANUAL)
282 printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
285 LOCK(cs_mapLocalHost);
286 bool fAlready = mapLocalHost.count(addr) > 0;
287 LocalServiceInfo &info = mapLocalHost[addr];
288 if (!fAlready || nScore >= info.nScore) {
289 info.nScore = nScore + (fAlready ? 1 : 0);
290 info.nPort = addr.GetPort();
292 SetReachable(addr.GetNetwork());
300 bool AddLocal(const CNetAddr &addr, int nScore)
302 return AddLocal(CService(addr, GetListenPort()), nScore);
305 /** Make a particular network entirely off-limits (no automatic connects to it) */
306 void SetLimited(enum Network net, bool fLimited)
308 if (net == NET_UNROUTABLE)
310 LOCK(cs_mapLocalHost);
311 vfLimited[net] = fLimited;
314 bool IsLimited(enum Network net)
316 LOCK(cs_mapLocalHost);
317 return vfLimited[net];
320 bool IsLimited(const CNetAddr &addr)
322 return IsLimited(addr.GetNetwork());
325 /** vote for a local address */
326 bool SeenLocal(const CService& addr)
329 LOCK(cs_mapLocalHost);
330 if (mapLocalHost.count(addr) == 0)
332 mapLocalHost[addr].nScore++;
340 /** check whether a given address is potentially local */
341 bool IsLocal(const CService& addr)
343 LOCK(cs_mapLocalHost);
344 return mapLocalHost.count(addr) > 0;
347 /** check whether a given address is in a network we can probably connect to */
348 bool IsReachable(const CNetAddr& addr)
350 LOCK(cs_mapLocalHost);
351 enum Network net = addr.GetNetwork();
352 return vfReachable[net] && !vfLimited[net];
355 extern int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv);
357 // We now get our external IP from the IRC server first and only use this as a backup
358 bool GetMyExternalIP(CNetAddr& ipRet)
360 struct sockaddr_in mapped;
361 uint64_t rnd = std::numeric_limits<uint64_t>::max();
363 int rc = GetExternalIPbySTUN(rnd, &mapped, &srv);
365 ipRet = CNetAddr(mapped.sin_addr);
366 printf("GetExternalIPbySTUN(%" PRIu64 ") returned %s in attempt %d; Server=%s\n", rnd, ipRet.ToStringIP().c_str(), rc, srv);
372 void ThreadGetMyExternalIP(void* parg)
374 // Make this thread recognisable as the external IP detection thread
375 RenameThread("novacoin-ext-ip");
377 CNetAddr addrLocalHost;
378 if (GetMyExternalIP(addrLocalHost))
380 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
381 AddLocal(addrLocalHost, LOCAL_HTTP);
389 void AddressCurrentlyConnected(const CService& addr)
391 addrman.Connected(addr);
397 uint64_t CNode::nTotalBytesRecv = 0;
398 uint64_t CNode::nTotalBytesSent = 0;
399 CCriticalSection CNode::cs_totalBytesRecv;
400 CCriticalSection CNode::cs_totalBytesSent;
402 CNode* FindNode(const CNetAddr& ip)
405 for (CNode* pnode : vNodes)
406 if ((CNetAddr)pnode->addr == ip)
411 CNode* FindNode(std::string addrName)
414 for (CNode* pnode : vNodes)
415 if (pnode->addrName == addrName)
420 CNode* FindNode(const CService& addr)
423 for (CNode* pnode : vNodes)
424 if ((CService)pnode->addr == addr)
429 CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64_t nTimeout)
431 if (pszDest == NULL) {
432 if (IsLocal(addrConnect))
435 // Look for an existing connection
436 CNode* pnode = FindNode((CService)addrConnect);
440 pnode->AddRef(nTimeout);
449 printf("trying connection %s lastseen=%.1fhrs\n",
450 pszDest ? pszDest : addrConnect.ToString().c_str(),
451 pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
455 if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
457 addrman.Attempt(addrConnect);
460 printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
462 // Set to non-blocking
465 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
466 printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
468 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
469 printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
473 CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
475 pnode->AddRef(nTimeout);
481 vNodes.push_back(pnode);
484 pnode->nTimeConnected = GetTime();
493 void CNode::CloseSocketDisconnect()
496 if (hSocket != INVALID_SOCKET)
498 printf("disconnecting node %s\n", addrName.c_str());
499 CloseSocket(hSocket);
503 // in case this fails, we'll empty the recv buffer when the CNode is deleted
504 TRY_LOCK(cs_vRecv, lockRecv);
508 // if this was the sync node, we'll need a new one
509 if (this == pnodeSync)
513 void CNode::Cleanup()
517 void CNode::EndMessage()
519 if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
521 printf("dropmessages DROPPING SEND MESSAGE\n");
526 if (nHeaderStart < 0) {
527 LEAVE_CRITICAL_SECTION(cs_vSend);
532 uint32_t nSize = (uint32_t) vSend.size() - nMessageStart;
533 memcpy((char*)&vSend[nHeaderStart] + CMessageHeader::MESSAGE_SIZE_OFFSET, &nSize, sizeof(nSize));
536 uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end());
537 uint32_t nChecksum = 0;
538 memcpy(&nChecksum, &hash, sizeof(nChecksum));
539 assert(nMessageStart - nHeaderStart >= CMessageHeader::CHECKSUM_OFFSET + sizeof(nChecksum));
540 memcpy((char*)&vSend[nHeaderStart] + CMessageHeader::CHECKSUM_OFFSET, &nChecksum, sizeof(nChecksum));
543 printf("(%d bytes)\n", nSize);
547 nMessageStart = std::numeric_limits<uint32_t>::max();
548 LEAVE_CRITICAL_SECTION(cs_vSend);
551 void CNode::PushVersion()
553 int64_t nTime = GetAdjustedTime();
554 CAddress addrYou, addrMe;
556 bool fHidden = false;
558 if (mapArgs.count("-torname")) {
559 // Our hidden service address
560 CService addrTorName(mapArgs["-torname"], GetListenPort());
562 if (addrTorName.IsValid()) {
564 addrMe = CAddress(addrTorName);
571 addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", nPortZero)));
572 addrMe = GetLocalAddress(&addr);
575 GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
576 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());
577 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
578 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
585 std::map<CNetAddr, int64_t> CNode::setBanned;
586 CCriticalSection CNode::cs_setBanned;
588 void CNode::ClearBanned()
593 bool CNode::IsBanned(CNetAddr ip)
595 bool fResult = false;
598 std::map<CNetAddr, int64_t>::iterator i = setBanned.find(ip);
599 if (i != setBanned.end())
601 int64_t t = (*i).second;
609 bool CNode::Misbehaving(int howmuch)
613 printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
617 nMisbehavior += howmuch;
618 if (nMisbehavior >= GetArgInt("-banscore", 100))
620 int64_t banTime = GetTime()+GetArg("-bantime", nOneDay); // Default 24-hour ban
621 printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
624 if (setBanned[addr] < banTime)
625 setBanned[addr] = banTime;
627 CloseSocketDisconnect();
630 printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
635 #define X(name) stats.name = name
636 void CNode::copyStats(CNodeStats &stats)
651 stats.fSyncNode = (this == pnodeSync);
655 void Release(CNode* node) {
663 void ThreadSocketHandler(void* parg)
665 // Make this thread recognisable as the networking thread
666 RenameThread("novacoin-net");
670 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
671 ThreadSocketHandler2(parg);
672 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
674 catch (std::exception& e) {
675 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
676 PrintException(&e, "ThreadSocketHandler()");
678 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
679 throw; // support pthread_cancel()
681 printf("ThreadSocketHandler exited\n");
684 static list<CNode*> vNodesDisconnected;
686 void ThreadSocketHandler2(void* parg)
688 printf("ThreadSocketHandler started\n");
689 size_t nPrevNodeCount = 0;
697 // Disconnect unused nodes
698 vector<CNode*> vNodesCopy = vNodes;
699 for (CNode* pnode : vNodesCopy)
701 if (pnode->fDisconnect ||
702 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
704 // remove from vNodes
705 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
707 // release outbound grant (if any)
708 pnode->grantOutbound.Release();
710 // close socket and cleanup
711 pnode->CloseSocketDisconnect();
714 // hold in disconnected pool until all refs are released
715 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
716 if (pnode->fNetworkNode || pnode->fInbound)
718 vNodesDisconnected.push_back(pnode);
722 // Delete disconnected nodes
723 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
724 for (CNode* pnode : vNodesDisconnectedCopy)
726 // wait until threads are done using it
727 if (pnode->GetRefCount() <= 0)
729 bool fDelete = false;
731 TRY_LOCK(pnode->cs_vSend, lockSend);
734 TRY_LOCK(pnode->cs_vRecv, lockRecv);
737 TRY_LOCK(pnode->cs_mapRequests, lockReq);
740 TRY_LOCK(pnode->cs_inventory, lockInv);
749 vNodesDisconnected.remove(pnode);
755 if (vNodes.size() != nPrevNodeCount)
757 nPrevNodeCount = vNodes.size();
758 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
763 // Find which sockets have data to receive
765 struct timeval timeout;
767 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
774 FD_ZERO(&fdsetError);
775 SOCKET hSocketMax = 0;
776 bool have_fds = false;
778 for (SOCKET hListenSocket : vhListenSocket) {
779 FD_SET(hListenSocket, &fdsetRecv);
780 hSocketMax = max(hSocketMax, hListenSocket);
785 for (CNode* pnode : vNodes)
787 if (pnode->hSocket == INVALID_SOCKET)
789 FD_SET(pnode->hSocket, &fdsetRecv);
790 FD_SET(pnode->hSocket, &fdsetError);
791 hSocketMax = max(hSocketMax, pnode->hSocket);
794 TRY_LOCK(pnode->cs_vSend, lockSend);
795 if (lockSend && !pnode->vSend.empty())
796 FD_SET(pnode->hSocket, &fdsetSend);
801 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
802 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
803 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
804 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
807 if (nSelect == SOCKET_ERROR)
811 int nErr = WSAGetLastError();
812 printf("socket select error %d\n", nErr);
813 for (unsigned int i = 0; i <= hSocketMax; i++)
814 FD_SET(i, &fdsetRecv);
817 FD_ZERO(&fdsetError);
818 Sleep(timeout.tv_usec/1000);
823 // Accept new connections
825 for (SOCKET hListenSocket : vhListenSocket)
826 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
829 struct sockaddr_storage sockaddr;
831 struct sockaddr sockaddr;
833 socklen_t len = sizeof(sockaddr);
834 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
838 if (hSocket != INVALID_SOCKET)
839 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
840 printf("Warning: Unknown socket family\n");
844 for (CNode* pnode : vNodes)
849 if (hSocket == INVALID_SOCKET)
851 int nErr = WSAGetLastError();
852 if (nErr != WSAEWOULDBLOCK)
853 printf("socket error accept failed: %d\n", nErr);
855 else if (nInbound >= GetArgInt("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
858 LOCK(cs_setservAddNodeAddresses);
859 if (!setservAddNodeAddresses.count(addr))
860 CloseSocket(hSocket);
863 else if (CNode::IsBanned(addr))
865 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
866 CloseSocket(hSocket);
870 printf("accepted connection %s\n", addr.ToString().c_str());
871 CNode* pnode = new CNode(hSocket, addr, "", true);
875 vNodes.push_back(pnode);
882 // Service each socket
884 vector<CNode*> vNodesCopy;
888 for (CNode* pnode : vNodesCopy)
891 for (CNode* pnode : vNodesCopy)
899 if (pnode->hSocket == INVALID_SOCKET)
901 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
903 TRY_LOCK(pnode->cs_vRecv, lockRecv);
906 CDataStream& vRecv = pnode->vRecv;
907 uint64_t nPos = vRecv.size();
909 if (nPos > ReceiveBufferSize()) {
910 if (!pnode->fDisconnect)
911 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
912 pnode->CloseSocketDisconnect();
915 // typical socket buffer is 8K-64K
916 char pchBuf[0x10000];
917 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
920 vRecv.resize(nPos + nBytes);
921 memcpy(&vRecv[nPos], pchBuf, nBytes);
922 pnode->nLastRecv = GetTime();
923 pnode->nRecvBytes += nBytes;
924 pnode->RecordBytesRecv(nBytes);
926 else if (nBytes == 0)
928 // socket closed gracefully
929 if (!pnode->fDisconnect)
930 printf("socket closed\n");
931 pnode->CloseSocketDisconnect();
936 int nErr = WSAGetLastError();
937 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
939 if (!pnode->fDisconnect)
940 printf("socket recv error %d\n", nErr);
941 pnode->CloseSocketDisconnect();
951 if (pnode->hSocket == INVALID_SOCKET)
953 if (FD_ISSET(pnode->hSocket, &fdsetSend))
955 TRY_LOCK(pnode->cs_vSend, lockSend);
958 CDataStream& vSend = pnode->vSend;
961 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
964 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
965 pnode->nLastSend = GetTime();
966 pnode->nSendBytes += nBytes;
967 pnode->RecordBytesSent(nBytes);
972 int nErr = WSAGetLastError();
973 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
975 printf("socket send error %d\n", nErr);
976 pnode->CloseSocketDisconnect();
984 // Inactivity checking
986 if (pnode->vSend.empty())
987 pnode->nLastSendEmpty = GetTime();
988 if (GetTime() - pnode->nTimeConnected > 60)
990 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
992 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
993 pnode->fDisconnect = true;
995 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
997 printf("socket not sending\n");
998 pnode->fDisconnect = true;
1000 else if (GetTime() - pnode->nLastRecv > 90*60)
1002 printf("socket inactivity timeout\n");
1003 pnode->fDisconnect = true;
1009 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
1017 // Each pair gives a source name and a seed name.
1018 // The first name is used as information source for addrman.
1019 // The second name should resolve to a list of seed addresses.
1020 static const char *strDNSSeed[][2] = {
1021 {"node.novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro"},
1022 {"novacoin.ru", "dnsseed.novacoin.ru"},
1023 {"novacoin.ru", "testseed.novacoin.ru"},
1024 {"novaco.in", "dnsseed.novaco.in"},
1027 void ThreadDNSAddressSeed(void* parg)
1029 // Make this thread recognisable as the DNS seeding thread
1030 RenameThread("novacoin-dnsseed");
1034 vnThreadsRunning[THREAD_DNSSEED]++;
1035 ThreadDNSAddressSeed2(parg);
1036 vnThreadsRunning[THREAD_DNSSEED]--;
1038 catch (std::exception& e) {
1039 vnThreadsRunning[THREAD_DNSSEED]--;
1040 PrintException(&e, "ThreadDNSAddressSeed()");
1042 vnThreadsRunning[THREAD_DNSSEED]--;
1043 throw; // support pthread_cancel()
1045 printf("ThreadDNSAddressSeed exited\n");
1048 void ThreadDNSAddressSeed2(void* parg)
1050 printf("ThreadDNSAddressSeed started\n");
1055 printf("Loading addresses from DNS seeds (could take a while)\n");
1057 for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1058 if (HaveNameProxy()) {
1059 AddOneShot(strDNSSeed[seed_idx][1]);
1061 vector<CNetAddr> vaddr;
1062 vector<CAddress> vAdd;
1063 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
1065 for (CNetAddr& ip : vaddr)
1067 CAddress addr = CAddress(CService(ip, GetDefaultPort()));
1068 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1069 vAdd.push_back(addr);
1073 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
1078 printf("%d addresses found from DNS seeds\n", found);
1094 0x1c542868, 0x3859dd6f, 0x203c2e68, 0xf145a6bc, 0x638a545f, 0x325da346, 0x385da346, 0xfb2b8d5f,
1095 0x52568c5f, 0xa979e65b, 0x8de6485d, 0x9f79e65b, 0x048a861f, 0x3388b55f, 0x6ff0b45e, 0x17e81f5f,
1096 0x6c47bb25, 0x1ecdc852, 0x28263db9, 0x47824e5d, 0x36f1c851, 0x2bf913b2, 0x95923cb3, 0x84e63eb2,
1097 0xefdeedbf, 0x65200092, 0xf36f6805, 0x42692d05, 0x772c1955, 0xb6bf1b4e, 0x7abb5f5d, 0xdb2fa6bc,
1098 0x90e911bf, 0x82de565f, 0x694416b2, 0x0ab600bc, 0xfcecbe6d, 0x24ed9fb2, 0x1bb618c2, 0xc64765bb,
1099 0x4e3d62c3, 0xdba24baa, 0x4b7109b0, 0x12a12cc2, 0xfc01864f, 0x0b69e85b, 0x33922c1f, 0xac611bc6,
1100 0x2a257155, 0x991d5fc0, 0xbfdabcb1, 0x9b73ee55, 0x5bc2b95d, 0xdef0762e, 0x6ab7c936, 0x9c4416b2,
1101 0xd60d864f, 0x03671f1f, 0x3b5da346, 0xc6f5c851, 0x5411b2d4, 0xe7c25702, 0x63474fb0, 0x7e11c854,
1102 0x52381d5f, 0x72fdfe59, 0x51599a05, 0xfb12b2d4, 0xaee4f15e, 0xd0e3f15e, 0x2aa2805f, 0xa1caf15e,
1103 0x34fe425e, 0x46e1f15e, 0xd7c71955, 0xaeeff15e, 0x47c2af55, 0x563d89b2, 0x67980fd9, 0xc9def15e,
1104 0x9cc51eb9, 0xdaa7aa6b, 0x78e6871f, 0x0d5d2cb2, 0x7aedf15e, 0x9bcaf15e, 0xe5f7f15e, 0x501c1759,
1105 0xdfbc4980, 0xa7397f2e, 0x31ea1a02, 0x3a27655e, 0xaa86f05c, 0xdcddf15e, 0x64689cb2, 0xd4bf62d4,
1106 0xf093eab2, 0x98def15e, 0xb6c5f15e, 0x81e8f15e, 0xe5d2fe59, 0xa312786d, 0x4cf9fe59, 0x8a922c1f,
1107 0x00c7fe59, 0x1ade565f, 0x9e4116b2, 0x2c36983e, 0x68f8f15e, 0x51b7eab2, 0x76c51eb9, 0x9edd4980,
1108 0x90ef565f, 0x0dd80857, 0xd513fb94, 0xf5bdeab2, 0xa95277b0, 0x2cf2f15e, 0x1897eab2, 0x924416b2,
1109 0x985c9b59, 0x30aa43d8, 0xf9c6745f, 0xaf862e5f, 0xe0ceeab2, 0xb9b3eab2, 0x6da4eab2, 0xa4fdeab2,
1110 0x0fa6c125, 0xe38bbd05, 0x5d922c1f, 0x9bd0eab2, 0x73025e02, 0xc4fd794d, 0x8435b35f, 0x2d01bc2e,
1111 0xaa2a14d4, 0xa22b07cb, 0xebda6f4f, 0xddc6514e, 0xf23feab2, 0xea1e5256, 0x6147b45e, 0x47d21e4f,
1112 0x67c41c1f, 0x53ec1a02, 0x352e786d, 0x6bec1a02, 0x78fb4abe, 0xd3014c5d, 0x9fbbeab2, 0x1fc51eb9,
1113 0x720eeab2, 0x2db5eab2, 0xe8baf65c, 0x521b459e, 0x65c4955f, 0x0e7b915f, 0xa8f37e6d, 0x6d0b465f,
1114 0xfab8ff5c, 0xf7c27e6d, 0x7345a846, 0x4fd1a7d5, 0xdfc97e6d, 0x26c27e6d, 0xa9de36b2, 0xc615344d,
1115 0x28ceb95d, 0xa52d895e, 0x18c17e6d, 0x13ec1a02, 0x0ba37125, 0x6c3d344d, 0xb3922c1f, 0x506bbeb0,
1116 0x4d04994e, 0xa1bbe56d, 0xf62c344d, 0x0847d048, 0x4bdc6451, 0xc95b9a05, 0xbcd3a7d5, 0x29b57125,
1117 0x0c4d2cb2, 0xf2b8eab2, 0xc2d5b95d, 0x0185ef59, 0x30adeab2, 0xcaf0e92e, 0x756c344d, 0xfd9e252e,
1118 0xbe5ef3bc, 0x4689344d, 0xb223895e, 0xfcebeaad, 0xb7c0e92e, 0x993c1760, 0xe1e171b0, 0xb857e75b,
1119 0xbf10002e, 0xb55b2cb2, 0xa90e2cb2, 0x13d6f15e, 0xf8be9225, 0x14ddf15e, 0x06e90305, 0x82472cb2,
1122 const char* pchTorSeed[] =
1124 "seedp4knqnoei57u.onion",
1125 "seedr3hhlepyi7fd.onion",
1126 "seed3uuomkclbiz4.onion",
1127 "seedeh7qck3ouff5.onion",
1128 "5rg3vq4jagckeckf.onion",
1129 "seedt3sraf53ajiy.onion",
1130 "seedg4qyccsg42oq.onion",
1131 "novaqrtoywpg7jly.onion",
1132 "seed3d5wolqbgrcb.onion",
1133 "seed24u5dwph3qw4.onion",
1134 "mj26ulzbs2oskgym.onion",
1135 "eqon4usunavt76m7.onion",
1136 "seedd3aldwpslzl3.onion"
1139 void DumpAddresses()
1141 int64_t nStart = GetTimeMillis();
1146 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1147 addrman.size(), GetTimeMillis() - nStart);
1150 void ThreadDumpAddress2(void* parg)
1152 printf("ThreadDumpAddress started\n");
1154 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1158 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1160 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1162 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1165 void ThreadDumpAddress(void* parg)
1167 // Make this thread recognisable as the address dumping thread
1168 RenameThread("novacoin-adrdump");
1172 ThreadDumpAddress2(parg);
1174 catch (std::exception& e) {
1175 PrintException(&e, "ThreadDumpAddress()");
1177 printf("ThreadDumpAddress exited\n");
1180 void ThreadOpenConnections(void* parg)
1182 // Make this thread recognisable as the connection opening thread
1183 RenameThread("novacoin-opencon");
1187 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1188 ThreadOpenConnections2(parg);
1189 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1191 catch (std::exception& e) {
1192 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1193 PrintException(&e, "ThreadOpenConnections()");
1195 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1196 PrintException(NULL, "ThreadOpenConnections()");
1198 printf("ThreadOpenConnections exited\n");
1201 void static ProcessOneShot()
1206 if (vOneShots.empty())
1208 strDest = vOneShots.front();
1209 vOneShots.pop_front();
1212 CSemaphoreGrant grant(*semOutbound, true);
1214 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1215 AddOneShot(strDest);
1219 void ThreadOpenConnections2(void* parg)
1221 printf("ThreadOpenConnections started\n");
1223 // Connect to specific addresses
1224 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1226 for (int64_t nLoop = 0;; nLoop++)
1229 for (string strAddr : mapMultiArgs["-connect"])
1232 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1233 for (int i = 0; i < 10 && i < nLoop; i++)
1244 // Initiate network connections
1245 int64_t nStart = GetTime();
1250 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1252 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1257 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1258 CSemaphoreGrant grant(*semOutbound);
1259 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1263 // Add seed nodes if IRC isn't working
1264 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1266 std::vector<CAddress> vAdd;
1267 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1269 // It'll only connect to one or two seed nodes because once it connects,
1270 // it'll get a pile of addresses with newer timestamps.
1271 // Seed nodes are given a random 'last seen time' of between one and two
1274 memcpy(&ip, &pnSeed[i], sizeof(ip));
1275 CAddress addr(CService(ip, GetDefaultPort()));
1276 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1277 vAdd.push_back(addr);
1279 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1282 // Add Tor nodes if we have connection with onion router
1283 if (mapArgs.count("-tor"))
1285 std::vector<CAddress> vAdd;
1286 for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1288 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1289 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1290 vAdd.push_back(addr);
1292 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1296 // Choose an address to connect to based on most recently seen
1298 CAddress addrConnect;
1300 // Only connect out to one peer per network group (/16 for IPv4).
1301 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1303 set<vector<unsigned char> > setConnected;
1306 for (CNode* pnode : vNodes) {
1307 if (!pnode->fInbound) {
1308 setConnected.insert(pnode->addr.GetGroup());
1314 int64_t nANow = GetAdjustedTime();
1319 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1320 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1322 // if we selected an invalid address, restart
1323 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1326 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1327 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1328 // already-connected network ranges, ...) before trying new addrman addresses.
1333 if (IsLimited(addr))
1336 // only consider very recently tried nodes after 30 failed attempts
1337 if (nANow - addr.nLastTry < 600 && nTries < 30)
1340 // do not allow non-default ports, unless after 50 invalid addresses selected already
1341 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1348 if (addrConnect.IsValid())
1349 OpenNetworkConnection(addrConnect, &grant);
1353 void ThreadOpenAddedConnections(void* parg)
1355 // Make this thread recognisable as the connection opening thread
1356 RenameThread("novacoin-opencon");
1360 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1361 ThreadOpenAddedConnections2(parg);
1362 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1364 catch (std::exception& e) {
1365 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1366 PrintException(&e, "ThreadOpenAddedConnections()");
1368 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1369 PrintException(NULL, "ThreadOpenAddedConnections()");
1371 printf("ThreadOpenAddedConnections exited\n");
1374 void ThreadOpenAddedConnections2(void* parg)
1376 printf("ThreadOpenAddedConnections started\n");
1379 LOCK(cs_vAddedNodes);
1380 vAddedNodes = mapMultiArgs["-addnode"];
1383 if (HaveNameProxy()) {
1385 list<string> lAddresses(0);
1387 LOCK(cs_vAddedNodes);
1388 for (string& strAddNode : vAddedNodes)
1389 lAddresses.push_back(strAddNode);
1391 for (string& strAddNode : lAddresses) {
1393 CSemaphoreGrant grant(*semOutbound);
1394 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1397 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1398 Sleep(120000); // Retry every 2 minutes
1399 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1404 for (uint32_t i = 0; true; i++)
1406 list<string> lAddresses(0);
1408 LOCK(cs_vAddedNodes);
1409 for (string& strAddNode : vAddedNodes)
1410 lAddresses.push_back(strAddNode);
1413 list<vector<CService> > lservAddressesToAdd(0);
1414 for (string& strAddNode : lAddresses)
1416 vector<CService> vservNode(0);
1417 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1419 lservAddressesToAdd.push_back(vservNode);
1421 LOCK(cs_setservAddNodeAddresses);
1422 for (CService& serv : vservNode)
1423 setservAddNodeAddresses.insert(serv);
1427 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1428 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1431 for (CNode* pnode : vNodes)
1432 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1434 for (CService& addrNode : *(it))
1435 if (pnode->addr == addrNode)
1437 it = lservAddressesToAdd.erase(it);
1438 if(it != lservAddressesToAdd.begin())
1442 if (it == lservAddressesToAdd.end())
1446 for (vector<CService>& vserv : lservAddressesToAdd)
1448 if (vserv.size() == 0)
1450 CSemaphoreGrant grant(*semOutbound);
1451 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1458 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1459 Sleep(120000); // Retry every 2 minutes
1460 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1466 // if successful, this moves the passed grant to the constructed node
1467 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1470 // Initiate outbound network connection
1475 if (IsLocal(addrConnect) ||
1476 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1477 FindNode(addrConnect.ToStringIPPort().c_str()))
1479 if (strDest && FindNode(strDest))
1482 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1483 CNode* pnode = ConnectNode(addrConnect, strDest);
1484 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1490 grantOutbound->MoveTo(pnode->grantOutbound);
1491 pnode->fNetworkNode = true;
1493 pnode->fOneShot = true;
1498 // for now, use a very simple selection metric: the node from which we received
1500 static int64_t NodeSyncScore(const CNode *pnode) {
1501 return pnode->nLastRecv;
1504 void static StartSync(const vector<CNode*> &vNodes) {
1505 CNode *pnodeNewSync = NULL;
1506 int64_t nBestScore = 0;
1508 // Iterate over all nodes
1509 for (CNode* pnode : vNodes) {
1510 // check preconditions for allowing a sync
1511 if (!pnode->fClient && !pnode->fOneShot &&
1512 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1513 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1514 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1515 // if ok, compare node's score with the best so far
1516 int64_t nScore = NodeSyncScore(pnode);
1517 if (pnodeNewSync == NULL || nScore > nBestScore) {
1518 pnodeNewSync = pnode;
1519 nBestScore = nScore;
1523 // if a new sync candidate was found, start sync!
1525 pnodeNewSync->fStartSync = true;
1526 pnodeSync = pnodeNewSync;
1530 void ThreadMessageHandler(void* parg)
1532 // Make this thread recognisable as the message handling thread
1533 RenameThread("novacoin-msghand");
1537 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1538 ThreadMessageHandler2(parg);
1539 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1541 catch (std::exception& e) {
1542 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1543 PrintException(&e, "ThreadMessageHandler()");
1545 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1546 PrintException(NULL, "ThreadMessageHandler()");
1548 printf("ThreadMessageHandler exited\n");
1551 void ThreadMessageHandler2(void* parg)
1553 printf("ThreadMessageHandler started\n");
1554 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1557 bool fHaveSyncNode = false;
1558 vector<CNode*> vNodesCopy;
1561 vNodesCopy = vNodes;
1562 for (CNode* pnode : vNodesCopy) {
1564 if (pnode == pnodeSync)
1565 fHaveSyncNode = true;
1570 StartSync(vNodesCopy);
1572 // Poll the connected nodes for messages
1573 for (CNode* pnode : vNodesCopy)
1577 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1579 if (!ProcessMessages(pnode)) {
1580 pnode->CloseSocketDisconnect();
1581 if (pnode == pnodeSync)
1582 fHaveSyncNode = false;
1591 TRY_LOCK(pnode->cs_vSend, lockSend);
1593 SendMessages(pnode);
1601 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
1604 // Wait and allow messages to bunch up.
1605 // Reduce vnThreadsRunning so StopNode has permission to exit while
1606 // we're sleeping, but we must always check fShutdown after doing this.
1607 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1609 if (fRequestShutdown)
1611 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1622 bool BindListenPort(const CService &addrBind, string& strError)
1627 // Create socket for listening for incoming connections
1629 struct sockaddr_storage sockaddr;
1631 struct sockaddr sockaddr;
1633 socklen_t len = sizeof(sockaddr);
1634 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1636 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1637 printf("%s\n", strError.c_str());
1641 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1642 if (hListenSocket == INVALID_SOCKET)
1644 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1645 printf("%s\n", strError.c_str());
1651 // Different way of disabling SIGPIPE on BSD
1652 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1654 // Allow binding if the port is still in TIME_WAIT state after
1655 // the program was closed and restarted. Not an issue on windows!
1656 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1660 // Set to non-blocking, incoming connections will also inherit this
1661 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1663 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1666 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1667 printf("%s\n", strError.c_str());
1672 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1673 // and enable it by default or not. Try to enable it, if possible.
1674 if (addrBind.IsIPv6()) {
1677 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1679 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1683 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1684 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
1689 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1691 int nErr = WSAGetLastError();
1692 if (nErr == WSAEADDRINUSE)
1693 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1695 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1696 printf("%s\n", strError.c_str());
1697 CloseSocket(hListenSocket);
1700 printf("Bound to %s\n", addrBind.ToString().c_str());
1702 // Listen for incoming connections
1703 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1705 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1706 printf("%s\n", strError.c_str());
1707 CloseSocket(hListenSocket);
1711 vhListenSocket.push_back(hListenSocket);
1713 if (addrBind.IsRoutable() && fDiscover)
1714 AddLocal(addrBind, LOCAL_BIND);
1719 void static Discover()
1725 // Get local host IP
1726 char pszHostName[1000] = "";
1727 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1729 vector<CNetAddr> vaddr;
1730 if (LookupHost(pszHostName, vaddr))
1732 for (const CNetAddr &addr : vaddr)
1734 AddLocal(addr, LOCAL_IF);
1739 // Get local host ip
1740 struct ifaddrs* myaddrs;
1741 if (getifaddrs(&myaddrs) == 0)
1743 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1745 if (ifa->ifa_addr == NULL) continue;
1746 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1747 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1748 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1749 if (ifa->ifa_addr->sa_family == AF_INET)
1751 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1752 CNetAddr addr(s4->sin_addr);
1753 if (AddLocal(addr, LOCAL_IF))
1754 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1757 else if (ifa->ifa_addr->sa_family == AF_INET6)
1759 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1760 CNetAddr addr(s6->sin6_addr);
1761 if (AddLocal(addr, LOCAL_IF))
1762 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1766 freeifaddrs(myaddrs);
1770 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1771 if (!IsLimited(NET_IPV4))
1772 NewThread(ThreadGetMyExternalIP, NULL);
1775 void StartNode(void* parg)
1777 // Make this thread recognisable as the startup thread
1778 RenameThread("novacoin-start");
1780 if (semOutbound == NULL) {
1781 // initialize semaphore
1782 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1783 semOutbound = new CSemaphore(nMaxOutbound);
1786 if (pnodeLocalHost == NULL)
1787 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1795 if (!GetBoolArg("-dnsseed", true))
1796 printf("DNS seeding disabled\n");
1798 if (!NewThread(ThreadDNSAddressSeed, NULL))
1799 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1801 // Get addresses from IRC and advertise ours
1802 if (!GetBoolArg("-irc", true))
1803 printf("IRC seeding disabled\n");
1805 if (!NewThread(ThreadIRCSeed, NULL))
1806 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1808 // Send and receive from sockets, accept connections
1809 if (!NewThread(ThreadSocketHandler, NULL))
1810 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1812 // Initiate outbound connections from -addnode
1813 if (!NewThread(ThreadOpenAddedConnections, NULL))
1814 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1816 // Initiate outbound connections
1817 if (!NewThread(ThreadOpenConnections, NULL))
1818 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1821 if (!NewThread(ThreadMessageHandler, NULL))
1822 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1824 // Dump network addresses
1825 if (!NewThread(ThreadDumpAddress, NULL))
1826 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1828 // Mine proof-of-stake blocks in the background
1829 if (!NewThread(ThreadStakeMiner, pwalletMain))
1830 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1832 // Trusted NTP server, it's localhost by default.
1833 strTrustedUpstream = GetArg("-ntp", "localhost");
1835 // Start periodical NTP sampling thread
1836 NewThread(ThreadNtpSamples, NULL);
1842 printf("StopNode()\n");
1844 nTransactionsUpdated++;
1845 int64_t nStart = GetTime();
1848 ThreadScriptCheckQuit();
1851 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1852 semOutbound->post();
1855 int nThreadsRunning = 0;
1856 for (int n = 0; n < THREAD_MAX; n++)
1857 nThreadsRunning += vnThreadsRunning[n];
1858 if (nThreadsRunning == 0)
1860 if (GetTime() - nStart > 20)
1864 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1865 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1866 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1867 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1868 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1869 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1870 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1871 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1872 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1873 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1874 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1891 for (CNode* pnode : vNodes)
1892 if (pnode->hSocket != INVALID_SOCKET)
1893 CloseSocket(pnode->hSocket);
1894 for (SOCKET hListenSocket : vhListenSocket)
1895 if (hListenSocket != INVALID_SOCKET)
1896 if (!CloseSocket(hListenSocket))
1897 printf("CloseSocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1899 // clean up some globals (to help leak detection)
1900 for (CNode *pnode : vNodes)
1902 for (CNode *pnode : vNodesDisconnected)
1905 vNodesDisconnected.clear();
1908 delete pnodeLocalHost;
1909 pnodeLocalHost = NULL;
1912 // Shutdown Windows Sockets
1917 instance_of_cnetcleanup;
1919 void RelayTransaction(const CTransaction& tx, const uint256& hash)
1921 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1924 RelayTransaction(tx, hash, ss);
1927 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
1929 CInv inv(MSG_TX, hash);
1932 // Expire old relay messages
1933 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1935 mapRelay.erase(vRelayExpiration.front().second);
1936 vRelayExpiration.pop_front();
1939 // Save original serialized message so newer versions are preserved
1940 mapRelay.insert(std::make_pair(inv, ss));
1941 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
1944 RelayInventory(inv);
1947 void CNode::RecordBytesRecv(uint64_t bytes)
1949 LOCK(cs_totalBytesRecv);
1950 nTotalBytesRecv += bytes;
1953 void CNode::RecordBytesSent(uint64_t bytes)
1955 LOCK(cs_totalBytesSent);
1956 nTotalBytesSent += bytes;
1959 uint64_t CNode::GetTotalBytesRecv()
1961 LOCK(cs_totalBytesRecv);
1962 return nTotalBytesRecv;
1965 uint64_t CNode::GetTotalBytesSent()
1967 LOCK(cs_totalBytesSent);
1968 return nTotalBytesSent;
1970 int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) {
1971 return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);