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_inventory, lockInv);
745 vNodesDisconnected.remove(pnode);
751 if (vNodes.size() != nPrevNodeCount)
753 nPrevNodeCount = vNodes.size();
754 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
759 // Find which sockets have data to receive
761 struct timeval timeout;
763 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
770 FD_ZERO(&fdsetError);
771 SOCKET hSocketMax = 0;
772 bool have_fds = false;
774 for (SOCKET hListenSocket : vhListenSocket) {
775 FD_SET(hListenSocket, &fdsetRecv);
776 hSocketMax = max(hSocketMax, hListenSocket);
781 for (CNode* pnode : vNodes)
783 if (pnode->hSocket == INVALID_SOCKET)
785 FD_SET(pnode->hSocket, &fdsetRecv);
786 FD_SET(pnode->hSocket, &fdsetError);
787 hSocketMax = max(hSocketMax, pnode->hSocket);
790 TRY_LOCK(pnode->cs_vSend, lockSend);
791 if (lockSend && !pnode->vSend.empty())
792 FD_SET(pnode->hSocket, &fdsetSend);
797 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
798 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
799 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
800 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
803 if (nSelect == SOCKET_ERROR)
807 int nErr = WSAGetLastError();
808 printf("socket select error %d\n", nErr);
809 for (unsigned int i = 0; i <= hSocketMax; i++)
810 FD_SET(i, &fdsetRecv);
813 FD_ZERO(&fdsetError);
814 Sleep(timeout.tv_usec/1000);
819 // Accept new connections
821 for (SOCKET hListenSocket : vhListenSocket)
822 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
825 struct sockaddr_storage sockaddr;
827 struct sockaddr sockaddr;
829 socklen_t len = sizeof(sockaddr);
830 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
834 if (hSocket != INVALID_SOCKET)
835 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
836 printf("Warning: Unknown socket family\n");
840 for (CNode* pnode : vNodes)
845 if (hSocket == INVALID_SOCKET)
847 int nErr = WSAGetLastError();
848 if (nErr != WSAEWOULDBLOCK)
849 printf("socket error accept failed: %d\n", nErr);
851 else if (nInbound >= GetArgInt("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
854 LOCK(cs_setservAddNodeAddresses);
855 if (!setservAddNodeAddresses.count(addr))
856 CloseSocket(hSocket);
859 else if (CNode::IsBanned(addr))
861 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
862 CloseSocket(hSocket);
866 printf("accepted connection %s\n", addr.ToString().c_str());
867 CNode* pnode = new CNode(hSocket, addr, "", true);
871 vNodes.push_back(pnode);
878 // Service each socket
880 vector<CNode*> vNodesCopy;
884 for (CNode* pnode : vNodesCopy)
887 for (CNode* pnode : vNodesCopy)
895 if (pnode->hSocket == INVALID_SOCKET)
897 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
899 TRY_LOCK(pnode->cs_vRecv, lockRecv);
902 CDataStream& vRecv = pnode->vRecv;
903 uint64_t nPos = vRecv.size();
905 if (nPos > ReceiveBufferSize()) {
906 if (!pnode->fDisconnect)
907 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
908 pnode->CloseSocketDisconnect();
911 // typical socket buffer is 8K-64K
912 char pchBuf[0x10000];
913 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
916 vRecv.resize(nPos + nBytes);
917 memcpy(&vRecv[nPos], pchBuf, nBytes);
918 pnode->nLastRecv = GetTime();
919 pnode->nRecvBytes += nBytes;
920 pnode->RecordBytesRecv(nBytes);
922 else if (nBytes == 0)
924 // socket closed gracefully
925 if (!pnode->fDisconnect)
926 printf("socket closed\n");
927 pnode->CloseSocketDisconnect();
932 int nErr = WSAGetLastError();
933 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
935 if (!pnode->fDisconnect)
936 printf("socket recv error %d\n", nErr);
937 pnode->CloseSocketDisconnect();
947 if (pnode->hSocket == INVALID_SOCKET)
949 if (FD_ISSET(pnode->hSocket, &fdsetSend))
951 TRY_LOCK(pnode->cs_vSend, lockSend);
954 CDataStream& vSend = pnode->vSend;
957 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
960 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
961 pnode->nLastSend = GetTime();
962 pnode->nSendBytes += nBytes;
963 pnode->RecordBytesSent(nBytes);
968 int nErr = WSAGetLastError();
969 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
971 printf("socket send error %d\n", nErr);
972 pnode->CloseSocketDisconnect();
980 // Inactivity checking
982 if (pnode->vSend.empty())
983 pnode->nLastSendEmpty = GetTime();
984 if (GetTime() - pnode->nTimeConnected > 60)
986 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
988 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
989 pnode->fDisconnect = true;
991 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
993 printf("socket not sending\n");
994 pnode->fDisconnect = true;
996 else if (GetTime() - pnode->nLastRecv > 90*60)
998 printf("socket inactivity timeout\n");
999 pnode->fDisconnect = true;
1005 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
1013 // Each pair gives a source name and a seed name.
1014 // The first name is used as information source for addrman.
1015 // The second name should resolve to a list of seed addresses.
1016 static const char *strDNSSeed[][2] = {
1017 {"node.novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro"},
1018 {"novacoin.ru", "dnsseed.novacoin.ru"},
1019 {"novacoin.ru", "testseed.novacoin.ru"},
1020 {"novaco.in", "dnsseed.novaco.in"},
1023 void ThreadDNSAddressSeed(void* parg)
1025 // Make this thread recognisable as the DNS seeding thread
1026 RenameThread("novacoin-dnsseed");
1030 vnThreadsRunning[THREAD_DNSSEED]++;
1031 ThreadDNSAddressSeed2(parg);
1032 vnThreadsRunning[THREAD_DNSSEED]--;
1034 catch (std::exception& e) {
1035 vnThreadsRunning[THREAD_DNSSEED]--;
1036 PrintException(&e, "ThreadDNSAddressSeed()");
1038 vnThreadsRunning[THREAD_DNSSEED]--;
1039 throw; // support pthread_cancel()
1041 printf("ThreadDNSAddressSeed exited\n");
1044 void ThreadDNSAddressSeed2(void* parg)
1046 printf("ThreadDNSAddressSeed started\n");
1051 printf("Loading addresses from DNS seeds (could take a while)\n");
1053 for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1054 if (HaveNameProxy()) {
1055 AddOneShot(strDNSSeed[seed_idx][1]);
1057 vector<CNetAddr> vaddr;
1058 vector<CAddress> vAdd;
1059 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
1061 for (CNetAddr& ip : vaddr)
1063 CAddress addr = CAddress(CService(ip, GetDefaultPort()));
1064 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1065 vAdd.push_back(addr);
1069 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
1074 printf("%d addresses found from DNS seeds\n", found);
1090 0x1c542868, 0x3859dd6f, 0x203c2e68, 0xf145a6bc, 0x638a545f, 0x325da346, 0x385da346, 0xfb2b8d5f,
1091 0x52568c5f, 0xa979e65b, 0x8de6485d, 0x9f79e65b, 0x048a861f, 0x3388b55f, 0x6ff0b45e, 0x17e81f5f,
1092 0x6c47bb25, 0x1ecdc852, 0x28263db9, 0x47824e5d, 0x36f1c851, 0x2bf913b2, 0x95923cb3, 0x84e63eb2,
1093 0xefdeedbf, 0x65200092, 0xf36f6805, 0x42692d05, 0x772c1955, 0xb6bf1b4e, 0x7abb5f5d, 0xdb2fa6bc,
1094 0x90e911bf, 0x82de565f, 0x694416b2, 0x0ab600bc, 0xfcecbe6d, 0x24ed9fb2, 0x1bb618c2, 0xc64765bb,
1095 0x4e3d62c3, 0xdba24baa, 0x4b7109b0, 0x12a12cc2, 0xfc01864f, 0x0b69e85b, 0x33922c1f, 0xac611bc6,
1096 0x2a257155, 0x991d5fc0, 0xbfdabcb1, 0x9b73ee55, 0x5bc2b95d, 0xdef0762e, 0x6ab7c936, 0x9c4416b2,
1097 0xd60d864f, 0x03671f1f, 0x3b5da346, 0xc6f5c851, 0x5411b2d4, 0xe7c25702, 0x63474fb0, 0x7e11c854,
1098 0x52381d5f, 0x72fdfe59, 0x51599a05, 0xfb12b2d4, 0xaee4f15e, 0xd0e3f15e, 0x2aa2805f, 0xa1caf15e,
1099 0x34fe425e, 0x46e1f15e, 0xd7c71955, 0xaeeff15e, 0x47c2af55, 0x563d89b2, 0x67980fd9, 0xc9def15e,
1100 0x9cc51eb9, 0xdaa7aa6b, 0x78e6871f, 0x0d5d2cb2, 0x7aedf15e, 0x9bcaf15e, 0xe5f7f15e, 0x501c1759,
1101 0xdfbc4980, 0xa7397f2e, 0x31ea1a02, 0x3a27655e, 0xaa86f05c, 0xdcddf15e, 0x64689cb2, 0xd4bf62d4,
1102 0xf093eab2, 0x98def15e, 0xb6c5f15e, 0x81e8f15e, 0xe5d2fe59, 0xa312786d, 0x4cf9fe59, 0x8a922c1f,
1103 0x00c7fe59, 0x1ade565f, 0x9e4116b2, 0x2c36983e, 0x68f8f15e, 0x51b7eab2, 0x76c51eb9, 0x9edd4980,
1104 0x90ef565f, 0x0dd80857, 0xd513fb94, 0xf5bdeab2, 0xa95277b0, 0x2cf2f15e, 0x1897eab2, 0x924416b2,
1105 0x985c9b59, 0x30aa43d8, 0xf9c6745f, 0xaf862e5f, 0xe0ceeab2, 0xb9b3eab2, 0x6da4eab2, 0xa4fdeab2,
1106 0x0fa6c125, 0xe38bbd05, 0x5d922c1f, 0x9bd0eab2, 0x73025e02, 0xc4fd794d, 0x8435b35f, 0x2d01bc2e,
1107 0xaa2a14d4, 0xa22b07cb, 0xebda6f4f, 0xddc6514e, 0xf23feab2, 0xea1e5256, 0x6147b45e, 0x47d21e4f,
1108 0x67c41c1f, 0x53ec1a02, 0x352e786d, 0x6bec1a02, 0x78fb4abe, 0xd3014c5d, 0x9fbbeab2, 0x1fc51eb9,
1109 0x720eeab2, 0x2db5eab2, 0xe8baf65c, 0x521b459e, 0x65c4955f, 0x0e7b915f, 0xa8f37e6d, 0x6d0b465f,
1110 0xfab8ff5c, 0xf7c27e6d, 0x7345a846, 0x4fd1a7d5, 0xdfc97e6d, 0x26c27e6d, 0xa9de36b2, 0xc615344d,
1111 0x28ceb95d, 0xa52d895e, 0x18c17e6d, 0x13ec1a02, 0x0ba37125, 0x6c3d344d, 0xb3922c1f, 0x506bbeb0,
1112 0x4d04994e, 0xa1bbe56d, 0xf62c344d, 0x0847d048, 0x4bdc6451, 0xc95b9a05, 0xbcd3a7d5, 0x29b57125,
1113 0x0c4d2cb2, 0xf2b8eab2, 0xc2d5b95d, 0x0185ef59, 0x30adeab2, 0xcaf0e92e, 0x756c344d, 0xfd9e252e,
1114 0xbe5ef3bc, 0x4689344d, 0xb223895e, 0xfcebeaad, 0xb7c0e92e, 0x993c1760, 0xe1e171b0, 0xb857e75b,
1115 0xbf10002e, 0xb55b2cb2, 0xa90e2cb2, 0x13d6f15e, 0xf8be9225, 0x14ddf15e, 0x06e90305, 0x82472cb2,
1118 const char* pchTorSeed[] =
1120 "seedp4knqnoei57u.onion",
1121 "seedr3hhlepyi7fd.onion",
1122 "seed3uuomkclbiz4.onion",
1123 "seedeh7qck3ouff5.onion",
1124 "5rg3vq4jagckeckf.onion",
1125 "seedt3sraf53ajiy.onion",
1126 "seedg4qyccsg42oq.onion",
1127 "novaqrtoywpg7jly.onion",
1128 "seed3d5wolqbgrcb.onion",
1129 "seed24u5dwph3qw4.onion",
1130 "mj26ulzbs2oskgym.onion",
1131 "eqon4usunavt76m7.onion",
1132 "seedd3aldwpslzl3.onion"
1135 void DumpAddresses()
1137 int64_t nStart = GetTimeMillis();
1142 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1143 addrman.size(), GetTimeMillis() - nStart);
1146 void ThreadDumpAddress2(void* parg)
1148 printf("ThreadDumpAddress started\n");
1150 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1154 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1156 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1158 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1161 void ThreadDumpAddress(void* parg)
1163 // Make this thread recognisable as the address dumping thread
1164 RenameThread("novacoin-adrdump");
1168 ThreadDumpAddress2(parg);
1170 catch (std::exception& e) {
1171 PrintException(&e, "ThreadDumpAddress()");
1173 printf("ThreadDumpAddress exited\n");
1176 void ThreadOpenConnections(void* parg)
1178 // Make this thread recognisable as the connection opening thread
1179 RenameThread("novacoin-opencon");
1183 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1184 ThreadOpenConnections2(parg);
1185 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1187 catch (std::exception& e) {
1188 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1189 PrintException(&e, "ThreadOpenConnections()");
1191 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1192 PrintException(NULL, "ThreadOpenConnections()");
1194 printf("ThreadOpenConnections exited\n");
1197 void static ProcessOneShot()
1202 if (vOneShots.empty())
1204 strDest = vOneShots.front();
1205 vOneShots.pop_front();
1208 CSemaphoreGrant grant(*semOutbound, true);
1210 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1211 AddOneShot(strDest);
1215 void ThreadOpenConnections2(void* parg)
1217 printf("ThreadOpenConnections started\n");
1219 // Connect to specific addresses
1220 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1222 for (int64_t nLoop = 0;; nLoop++)
1225 for (string strAddr : mapMultiArgs["-connect"])
1228 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1229 for (int i = 0; i < 10 && i < nLoop; i++)
1240 // Initiate network connections
1241 int64_t nStart = GetTime();
1246 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1248 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1253 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1254 CSemaphoreGrant grant(*semOutbound);
1255 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1259 // Add seed nodes if IRC isn't working
1260 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1262 std::vector<CAddress> vAdd;
1263 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1265 // It'll only connect to one or two seed nodes because once it connects,
1266 // it'll get a pile of addresses with newer timestamps.
1267 // Seed nodes are given a random 'last seen time' of between one and two
1270 memcpy(&ip, &pnSeed[i], sizeof(ip));
1271 CAddress addr(CService(ip, GetDefaultPort()));
1272 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1273 vAdd.push_back(addr);
1275 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1278 // Add Tor nodes if we have connection with onion router
1279 if (mapArgs.count("-tor"))
1281 std::vector<CAddress> vAdd;
1282 for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1284 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1285 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1286 vAdd.push_back(addr);
1288 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1292 // Choose an address to connect to based on most recently seen
1294 CAddress addrConnect;
1296 // Only connect out to one peer per network group (/16 for IPv4).
1297 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1299 set<vector<unsigned char> > setConnected;
1302 for (CNode* pnode : vNodes) {
1303 if (!pnode->fInbound) {
1304 setConnected.insert(pnode->addr.GetGroup());
1310 int64_t nANow = GetAdjustedTime();
1315 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1316 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1318 // if we selected an invalid address, restart
1319 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1322 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1323 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1324 // already-connected network ranges, ...) before trying new addrman addresses.
1329 if (IsLimited(addr))
1332 // only consider very recently tried nodes after 30 failed attempts
1333 if (nANow - addr.nLastTry < 600 && nTries < 30)
1336 // do not allow non-default ports, unless after 50 invalid addresses selected already
1337 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1344 if (addrConnect.IsValid())
1345 OpenNetworkConnection(addrConnect, &grant);
1349 void ThreadOpenAddedConnections(void* parg)
1351 // Make this thread recognisable as the connection opening thread
1352 RenameThread("novacoin-opencon");
1356 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1357 ThreadOpenAddedConnections2(parg);
1358 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1360 catch (std::exception& e) {
1361 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1362 PrintException(&e, "ThreadOpenAddedConnections()");
1364 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1365 PrintException(NULL, "ThreadOpenAddedConnections()");
1367 printf("ThreadOpenAddedConnections exited\n");
1370 void ThreadOpenAddedConnections2(void* parg)
1372 printf("ThreadOpenAddedConnections started\n");
1375 LOCK(cs_vAddedNodes);
1376 vAddedNodes = mapMultiArgs["-addnode"];
1379 if (HaveNameProxy()) {
1381 list<string> lAddresses(0);
1383 LOCK(cs_vAddedNodes);
1384 for (string& strAddNode : vAddedNodes)
1385 lAddresses.push_back(strAddNode);
1387 for (string& strAddNode : lAddresses) {
1389 CSemaphoreGrant grant(*semOutbound);
1390 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1393 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1394 Sleep(120000); // Retry every 2 minutes
1395 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1400 for (uint32_t i = 0; true; i++)
1402 list<string> lAddresses(0);
1404 LOCK(cs_vAddedNodes);
1405 for (string& strAddNode : vAddedNodes)
1406 lAddresses.push_back(strAddNode);
1409 list<vector<CService> > lservAddressesToAdd(0);
1410 for (string& strAddNode : lAddresses)
1412 vector<CService> vservNode(0);
1413 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1415 lservAddressesToAdd.push_back(vservNode);
1417 LOCK(cs_setservAddNodeAddresses);
1418 for (CService& serv : vservNode)
1419 setservAddNodeAddresses.insert(serv);
1423 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1424 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1427 for (CNode* pnode : vNodes)
1428 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1430 for (CService& addrNode : *(it))
1431 if (pnode->addr == addrNode)
1433 it = lservAddressesToAdd.erase(it);
1434 if(it != lservAddressesToAdd.begin())
1438 if (it == lservAddressesToAdd.end())
1442 for (vector<CService>& vserv : lservAddressesToAdd)
1444 if (vserv.size() == 0)
1446 CSemaphoreGrant grant(*semOutbound);
1447 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1454 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1455 Sleep(120000); // Retry every 2 minutes
1456 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1462 // if successful, this moves the passed grant to the constructed node
1463 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1466 // Initiate outbound network connection
1471 if (IsLocal(addrConnect) ||
1472 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1473 FindNode(addrConnect.ToStringIPPort().c_str()))
1475 if (strDest && FindNode(strDest))
1478 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1479 CNode* pnode = ConnectNode(addrConnect, strDest);
1480 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1486 grantOutbound->MoveTo(pnode->grantOutbound);
1487 pnode->fNetworkNode = true;
1489 pnode->fOneShot = true;
1494 // for now, use a very simple selection metric: the node from which we received
1496 static int64_t NodeSyncScore(const CNode *pnode) {
1497 return pnode->nLastRecv;
1500 void static StartSync(const vector<CNode*> &vNodes) {
1501 CNode *pnodeNewSync = NULL;
1502 int64_t nBestScore = 0;
1504 // Iterate over all nodes
1505 for (CNode* pnode : vNodes) {
1506 // check preconditions for allowing a sync
1507 if (!pnode->fClient && !pnode->fOneShot &&
1508 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1509 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1510 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1511 // if ok, compare node's score with the best so far
1512 int64_t nScore = NodeSyncScore(pnode);
1513 if (pnodeNewSync == NULL || nScore > nBestScore) {
1514 pnodeNewSync = pnode;
1515 nBestScore = nScore;
1519 // if a new sync candidate was found, start sync!
1521 pnodeNewSync->fStartSync = true;
1522 pnodeSync = pnodeNewSync;
1526 void ThreadMessageHandler(void* parg)
1528 // Make this thread recognisable as the message handling thread
1529 RenameThread("novacoin-msghand");
1533 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1534 ThreadMessageHandler2(parg);
1535 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1537 catch (std::exception& e) {
1538 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1539 PrintException(&e, "ThreadMessageHandler()");
1541 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1542 PrintException(NULL, "ThreadMessageHandler()");
1544 printf("ThreadMessageHandler exited\n");
1547 void ThreadMessageHandler2(void* parg)
1549 printf("ThreadMessageHandler started\n");
1550 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1553 bool fHaveSyncNode = false;
1554 vector<CNode*> vNodesCopy;
1557 vNodesCopy = vNodes;
1558 for (CNode* pnode : vNodesCopy) {
1560 if (pnode == pnodeSync)
1561 fHaveSyncNode = true;
1566 StartSync(vNodesCopy);
1568 // Poll the connected nodes for messages
1569 for (CNode* pnode : vNodesCopy)
1573 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1575 if (!ProcessMessages(pnode)) {
1576 pnode->CloseSocketDisconnect();
1577 if (pnode == pnodeSync)
1578 fHaveSyncNode = false;
1587 TRY_LOCK(pnode->cs_vSend, lockSend);
1589 SendMessages(pnode);
1597 for_each(vNodesCopy.begin(), vNodesCopy.end(), Release);
1600 // Wait and allow messages to bunch up.
1601 // Reduce vnThreadsRunning so StopNode has permission to exit while
1602 // we're sleeping, but we must always check fShutdown after doing this.
1603 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1605 if (fRequestShutdown)
1607 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1618 bool BindListenPort(const CService &addrBind, string& strError)
1623 // Create socket for listening for incoming connections
1625 struct sockaddr_storage sockaddr;
1627 struct sockaddr sockaddr;
1629 socklen_t len = sizeof(sockaddr);
1630 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1632 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1633 printf("%s\n", strError.c_str());
1637 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1638 if (hListenSocket == INVALID_SOCKET)
1640 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1641 printf("%s\n", strError.c_str());
1647 // Different way of disabling SIGPIPE on BSD
1648 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1650 // Allow binding if the port is still in TIME_WAIT state after
1651 // the program was closed and restarted. Not an issue on windows!
1652 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1656 // Set to non-blocking, incoming connections will also inherit this
1657 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1659 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1662 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1663 printf("%s\n", strError.c_str());
1668 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1669 // and enable it by default or not. Try to enable it, if possible.
1670 if (addrBind.IsIPv6()) {
1673 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1675 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1679 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1680 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
1685 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1687 int nErr = WSAGetLastError();
1688 if (nErr == WSAEADDRINUSE)
1689 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1691 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1692 printf("%s\n", strError.c_str());
1693 CloseSocket(hListenSocket);
1696 printf("Bound to %s\n", addrBind.ToString().c_str());
1698 // Listen for incoming connections
1699 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1701 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1702 printf("%s\n", strError.c_str());
1703 CloseSocket(hListenSocket);
1707 vhListenSocket.push_back(hListenSocket);
1709 if (addrBind.IsRoutable() && fDiscover)
1710 AddLocal(addrBind, LOCAL_BIND);
1715 void static Discover()
1721 // Get local host IP
1722 char pszHostName[1000] = "";
1723 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1725 vector<CNetAddr> vaddr;
1726 if (LookupHost(pszHostName, vaddr))
1728 for (const CNetAddr &addr : vaddr)
1730 AddLocal(addr, LOCAL_IF);
1735 // Get local host ip
1736 struct ifaddrs* myaddrs;
1737 if (getifaddrs(&myaddrs) == 0)
1739 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1741 if (ifa->ifa_addr == NULL) continue;
1742 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1743 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1744 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1745 if (ifa->ifa_addr->sa_family == AF_INET)
1747 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1748 CNetAddr addr(s4->sin_addr);
1749 if (AddLocal(addr, LOCAL_IF))
1750 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1753 else if (ifa->ifa_addr->sa_family == AF_INET6)
1755 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1756 CNetAddr addr(s6->sin6_addr);
1757 if (AddLocal(addr, LOCAL_IF))
1758 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1762 freeifaddrs(myaddrs);
1766 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1767 if (!IsLimited(NET_IPV4))
1768 NewThread(ThreadGetMyExternalIP, NULL);
1771 void StartNode(void* parg)
1773 // Make this thread recognisable as the startup thread
1774 RenameThread("novacoin-start");
1776 if (semOutbound == NULL) {
1777 // initialize semaphore
1778 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1779 semOutbound = new CSemaphore(nMaxOutbound);
1782 if (pnodeLocalHost == NULL)
1783 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1791 if (!GetBoolArg("-dnsseed", true))
1792 printf("DNS seeding disabled\n");
1794 if (!NewThread(ThreadDNSAddressSeed, NULL))
1795 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1797 // Get addresses from IRC and advertise ours
1798 if (!GetBoolArg("-irc", true))
1799 printf("IRC seeding disabled\n");
1801 if (!NewThread(ThreadIRCSeed, NULL))
1802 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1804 // Send and receive from sockets, accept connections
1805 if (!NewThread(ThreadSocketHandler, NULL))
1806 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1808 // Initiate outbound connections from -addnode
1809 if (!NewThread(ThreadOpenAddedConnections, NULL))
1810 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1812 // Initiate outbound connections
1813 if (!NewThread(ThreadOpenConnections, NULL))
1814 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1817 if (!NewThread(ThreadMessageHandler, NULL))
1818 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1820 // Dump network addresses
1821 if (!NewThread(ThreadDumpAddress, NULL))
1822 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1824 // Mine proof-of-stake blocks in the background
1825 if (!NewThread(ThreadStakeMiner, pwalletMain))
1826 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1828 // Trusted NTP server, it's localhost by default.
1829 strTrustedUpstream = GetArg("-ntp", "localhost");
1831 // Start periodical NTP sampling thread
1832 NewThread(ThreadNtpSamples, NULL);
1838 printf("StopNode()\n");
1840 nTransactionsUpdated++;
1841 int64_t nStart = GetTime();
1844 ThreadScriptCheckQuit();
1847 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1848 semOutbound->post();
1851 int nThreadsRunning = 0;
1852 for (int n = 0; n < THREAD_MAX; n++)
1853 nThreadsRunning += vnThreadsRunning[n];
1854 if (nThreadsRunning == 0)
1856 if (GetTime() - nStart > 20)
1860 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1861 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1862 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1863 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1864 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1865 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1866 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1867 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1868 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1869 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1870 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1887 for (CNode* pnode : vNodes)
1888 if (pnode->hSocket != INVALID_SOCKET)
1889 CloseSocket(pnode->hSocket);
1890 for (SOCKET hListenSocket : vhListenSocket)
1891 if (hListenSocket != INVALID_SOCKET)
1892 if (!CloseSocket(hListenSocket))
1893 printf("CloseSocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1895 // clean up some globals (to help leak detection)
1896 for (CNode *pnode : vNodes)
1898 for (CNode *pnode : vNodesDisconnected)
1901 vNodesDisconnected.clear();
1904 delete pnodeLocalHost;
1905 pnodeLocalHost = NULL;
1908 // Shutdown Windows Sockets
1913 instance_of_cnetcleanup;
1915 void RelayTransaction(const CTransaction& tx, const uint256& hash)
1917 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1920 RelayTransaction(tx, hash, ss);
1923 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
1925 CInv inv(MSG_TX, hash);
1928 // Expire old relay messages
1929 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1931 mapRelay.erase(vRelayExpiration.front().second);
1932 vRelayExpiration.pop_front();
1935 // Save original serialized message so newer versions are preserved
1936 mapRelay.insert(std::make_pair(inv, ss));
1937 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
1940 RelayInventory(inv);
1943 void CNode::RecordBytesRecv(uint64_t bytes)
1945 LOCK(cs_totalBytesRecv);
1946 nTotalBytesRecv += bytes;
1949 void CNode::RecordBytesSent(uint64_t bytes)
1951 LOCK(cs_totalBytesSent);
1952 nTotalBytesSent += bytes;
1955 uint64_t CNode::GetTotalBytesRecv()
1957 LOCK(cs_totalBytesRecv);
1958 return nTotalBytesRecv;
1961 uint64_t CNode::GetTotalBytesSent()
1963 LOCK(cs_totalBytesSent);
1964 return nTotalBytesSent;
1966 int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) {
1967 return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);