rpc: add getnetworkinfo
[novacoin.git] / src / net.cpp
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.
5
6 #include "irc.h"
7 #include "db.h"
8 #include "net.h"
9 #include "init.h"
10 #include "addrman.h"
11 #include "ui_interface.h"
12 #include "miner.h"
13 #include "ntp.h"
14
15 using namespace std;
16
17 static const int MAX_OUTBOUND_CONNECTIONS = 16;
18
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);
24
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.
27 #ifdef WIN32
28 #ifndef PROTECTION_LEVEL_UNRESTRICTED
29 #define PROTECTION_LEVEL_UNRESTRICTED 10
30 #endif
31 #ifndef IPV6_PROTECTION_LEVEL
32 #define IPV6_PROTECTION_LEVEL 23
33 #endif
34 #endif
35
36 //
37 // Global state variables
38 //
39 bool fClient = false;
40 bool fDiscover = true;
41 uint64_t nLocalServices = (fClient ? 0 : NODE_NETWORK);
42 CCriticalSection cs_mapLocalHost;
43 map<CNetAddr, LocalServiceInfo> mapLocalHost;
44 static bool vfReachable[NET_MAX] = {};
45 static bool vfLimited[NET_MAX] = {};
46 static CNode* pnodeLocalHost = NULL;
47 static CNode* pnodeSync = NULL;
48 CAddress addrSeenByPeer(CService("0.0.0.0", nPortZero), nLocalServices);
49 uint64_t nLocalHostNonce = 0;
50 array<int, THREAD_MAX> vnThreadsRunning;
51 static vector<SOCKET> vhListenSocket;
52 CAddrMan addrman;
53
54 vector<CNode*> vNodes;
55 CCriticalSection cs_vNodes;
56 map<CInv, CDataStream> mapRelay;
57 deque<pair<int64_t, CInv> > vRelayExpiration;
58 CCriticalSection cs_mapRelay;
59 map<CInv, int64_t> mapAlreadyAskedFor;
60
61 static deque<string> vOneShots;
62 CCriticalSection cs_vOneShots;
63
64 set<CNetAddr> setservAddNodeAddresses;
65 CCriticalSection cs_setservAddNodeAddresses;
66
67 vector<string> vAddedNodes;
68 CCriticalSection cs_vAddedNodes;
69
70 static CSemaphore *semOutbound = NULL;
71
72 void AddOneShot(string strDest)
73 {
74     LOCK(cs_vOneShots);
75     vOneShots.push_back(strDest);
76 }
77
78 uint16_t GetListenPort()
79 {
80     return static_cast<uint16_t>(GetArg("-port", GetDefaultPort()));
81 }
82
83 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
84 {
85     // Filter out duplicate requests
86     if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
87         return;
88     pindexLastGetBlocksBegin = pindexBegin;
89     hashLastGetBlocksEnd = hashEnd;
90
91     PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
92 }
93
94 // find 'best' local address for a particular peer
95 bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
96 {
97     if (fNoListen)
98         return false;
99
100     int nBestScore = -1;
101     int nBestReachability = -1;
102     {
103         LOCK(cs_mapLocalHost);
104         for (auto it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
105         {
106             int nScore = (*it).second.nScore;
107             int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
108             if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
109             {
110                 addr = CService((*it).first, (*it).second.nPort);
111                 nBestReachability = nReachability;
112                 nBestScore = nScore;
113             }
114         }
115     }
116     return nBestScore >= 0;
117 }
118
119 // get best local address for a particular peer as a CAddress
120 CAddress GetLocalAddress(const CNetAddr *paddrPeer)
121 {
122     CAddress ret(CService("0.0.0.0", nPortZero), 0);
123     CService addr;
124     if (GetLocal(addr, paddrPeer))
125     {
126         ret = CAddress(addr);
127         ret.nServices = nLocalServices;
128         ret.nTime = GetAdjustedTime();
129     }
130     return ret;
131 }
132
133 bool RecvLine(SOCKET hSocket, string& strLine)
134 {
135     strLine.clear();
136     for ( ; ; )
137     {
138         char c;
139         int nBytes = recv(hSocket, &c, 1, 0);
140         if (nBytes > 0)
141         {
142             if (c == '\n')
143                 continue;
144             if (c == '\r')
145                 return true;
146             strLine += c;
147             if (strLine.size() >= 9000)
148                 return true;
149         }
150         else if (nBytes <= 0)
151         {
152             if (fShutdown)
153                 return false;
154             if (nBytes < 0)
155             {
156                 int nErr = WSAGetLastError();
157                 if (nErr == WSAEMSGSIZE)
158                     continue;
159                 if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
160                 {
161                     Sleep(10);
162                     continue;
163                 }
164             }
165             if (!strLine.empty())
166                 return true;
167             if (nBytes == 0)
168             {
169                 // socket closed
170                 printf("socket closed\n");
171                 return false;
172             }
173             else
174             {
175                 // socket error
176                 int nErr = WSAGetLastError();
177                 printf("recv failed: %s\n", NetworkErrorString(nErr).c_str());
178                 return false;
179             }
180         }
181     }
182 }
183
184 // used when scores of local addresses may have changed
185 // pushes better local address to peers
186 void static AdvertizeLocal()
187 {
188     LOCK(cs_vNodes);
189     for(CNode* pnode :  vNodes)
190     {
191         if (pnode->fSuccessfullyConnected)
192         {
193             auto addrLocal = GetLocalAddress(&pnode->addr);
194             if (addrLocal.IsRoutable() && (CService)addrLocal != pnode->addrLocal)
195             {
196                 pnode->PushAddress(addrLocal);
197                 pnode->addrLocal = addrLocal;
198             }
199         }
200     }
201 }
202
203 void SetReachable(enum Network net, bool fFlag)
204 {
205     LOCK(cs_mapLocalHost);
206     vfReachable[net] = fFlag;
207     if (net == NET_IPV6 && fFlag)
208         vfReachable[NET_IPV4] = true;
209 }
210
211 int GetnScore(const CService& addr)
212 {
213     LOCK(cs_mapLocalHost);
214     if (mapLocalHost.count(addr) == LOCAL_NONE)
215         return 0;
216     return mapLocalHost[addr].nScore;
217 }
218
219
220 // Is our peer's addrLocal potentially useful as an external IP source?
221 bool IsPeerAddrLocalGood(CNode *pnode)
222 {
223     return fDiscover && pnode->addr.IsRoutable() && pnode->addrLocal.IsRoutable() &&
224            !IsLimited(pnode->addrLocal.GetNetwork());
225 }
226
227 // pushes our own address to a peer
228 void AdvertiseLocal(CNode *pnode)
229 {
230     if (!fNoListen && pnode->fSuccessfullyConnected)
231     {
232         auto addrLocal = GetLocalAddress(&pnode->addr);
233         // If discovery is enabled, sometimes give our peer the address it
234         // tells us that it sees us as in case it has a better idea of our
235         // address than we do.
236         if (IsPeerAddrLocalGood(pnode) && (!addrLocal.IsRoutable() ||
237              GetRand((GetnScore(addrLocal) > LOCAL_MANUAL) ? 8:2) == 0))
238         {
239             addrLocal.SetIP(pnode->addrLocal);
240         }
241         if (addrLocal.IsRoutable())
242         {
243             printf("AdvertiseLocal: advertising address %s\n", addrLocal.ToString().c_str());
244             pnode->PushAddress(addrLocal);
245         }
246     }
247 }
248
249 // learn a new local address
250 bool AddLocal(const CService& addr, int nScore)
251 {
252     if (!addr.IsRoutable())
253         return false;
254
255     if (!fDiscover && nScore < LOCAL_MANUAL)
256         return false;
257
258     if (IsLimited(addr))
259         return false;
260
261     printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
262
263     {
264         LOCK(cs_mapLocalHost);
265         bool fAlready = mapLocalHost.count(addr) > 0;
266         LocalServiceInfo &info = mapLocalHost[addr];
267         if (!fAlready || nScore >= info.nScore) {
268             info.nScore = nScore + (fAlready ? 1 : 0);
269             info.nPort = addr.GetPort();
270         }
271         SetReachable(addr.GetNetwork());
272     }
273
274     AdvertizeLocal();
275
276     return true;
277 }
278
279 bool AddLocal(const CNetAddr &addr, int nScore)
280 {
281     return AddLocal(CService(addr, GetListenPort()), nScore);
282 }
283
284 /** Make a particular network entirely off-limits (no automatic connects to it) */
285 void SetLimited(enum Network net, bool fLimited)
286 {
287     if (net == NET_UNROUTABLE)
288         return;
289     LOCK(cs_mapLocalHost);
290     vfLimited[net] = fLimited;
291 }
292
293 bool IsLimited(enum Network net)
294 {
295     LOCK(cs_mapLocalHost);
296     return vfLimited[net];
297 }
298
299 bool IsLimited(const CNetAddr &addr)
300 {
301     return IsLimited(addr.GetNetwork());
302 }
303
304 /** vote for a local address */
305 bool SeenLocal(const CService& addr)
306 {
307     {
308         LOCK(cs_mapLocalHost);
309         if (mapLocalHost.count(addr) == 0)
310             return false;
311         mapLocalHost[addr].nScore++;
312     }
313
314     AdvertizeLocal();
315
316     return true;
317 }
318
319 /** check whether a given address is potentially local */
320 bool IsLocal(const CService& addr)
321 {
322     LOCK(cs_mapLocalHost);
323     return mapLocalHost.count(addr) > 0;
324 }
325
326 /** check whether a given address is in a network we can probably connect to */
327 bool IsReachable(const CNetAddr& addr)
328 {
329     LOCK(cs_mapLocalHost);
330     enum Network net = addr.GetNetwork();
331     return vfReachable[net] && !vfLimited[net];
332 }
333
334 extern int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv);
335
336 // We now get our external IP from the IRC server first and only use this as a backup
337 bool GetMyExternalIP(CNetAddr& ipRet)
338 {
339     struct sockaddr_in mapped = {};
340     auto rnd = GetRand(numeric_limits<uint64_t>::max());
341     const char *srv;
342     int rc = GetExternalIPbySTUN(rnd, &mapped, &srv);
343     if(rc >= 0) {
344         ipRet = CNetAddr(mapped.sin_addr);
345         if (fDebugNet) {
346             printf("GetExternalIPbySTUN(%" PRIu64 ") returned %s in attempt %d; Server=%s\n", rnd, ipRet.ToStringIP().c_str(), rc, srv);
347         }
348         return true;
349     }
350     return false;
351 }
352
353 void ThreadGetMyExternalIP(void* parg)
354 {
355     // Make this thread recognisable as the external IP detection thread
356     RenameThread("novacoin-ext-ip");
357
358     CNetAddr addrLocalHost;
359     if (GetMyExternalIP(addrLocalHost))
360     {
361         printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
362         AddLocal(addrLocalHost, LOCAL_HTTP);
363     }
364 }
365
366 void AddressCurrentlyConnected(const CService& addr)
367 {
368     addrman.Connected(addr);
369 }
370
371
372
373
374 uint64_t CNode::nTotalBytesRecv = 0;
375 uint64_t CNode::nTotalBytesSent = 0;
376 CCriticalSection CNode::cs_totalBytesRecv;
377 CCriticalSection CNode::cs_totalBytesSent;
378
379 CNode* FindNode(const CNetAddr& ip)
380 {
381     LOCK(cs_vNodes);
382     for(CNode* pnode :  vNodes)
383         if ((CNetAddr)pnode->addr == ip)
384             return (pnode);
385     return NULL;
386 }
387
388 CNode* FindNode(string addrName)
389 {
390     LOCK(cs_vNodes);
391     for(CNode* pnode :  vNodes)
392         if (pnode->addrName == addrName)
393             return (pnode);
394     return NULL;
395 }
396
397 CNode* FindNode(const CService& addr)
398 {
399     LOCK(cs_vNodes);
400     for(CNode* pnode :  vNodes)
401         if ((CService)pnode->addr == addr)
402             return (pnode);
403     return NULL;
404 }
405
406 CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64_t nTimeout)
407 {
408     if (pszDest == NULL) {
409         if (IsLocal(addrConnect))
410             return NULL;
411
412         // Look for an existing connection
413         CNode* pnode = FindNode((CService)addrConnect);
414         if (pnode)
415         {
416             if (nTimeout != 0)
417                 pnode->AddRef(nTimeout);
418             else
419                 pnode->AddRef();
420             return pnode;
421         }
422     }
423
424
425     /// debug print
426     printf("trying connection %s lastseen=%.1fhrs\n",
427         pszDest ? pszDest : addrConnect.ToString().c_str(),
428         pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
429
430     // Connect
431     SOCKET hSocket;
432     if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
433     {
434         addrman.Attempt(addrConnect);
435
436         /// debug print
437         printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
438
439         // Set to non-blocking
440 #ifdef WIN32
441         u_long nOne = 1;
442         if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
443             printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %s\n", NetworkErrorString(WSAGetLastError()).c_str());
444 #else
445         if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
446             printf("ConnectSocket() : fcntl non-blocking setting failed, error %s\n", NetworkErrorString(errno).c_str());
447 #endif
448
449         // Add node
450         CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
451         if (nTimeout != 0)
452             pnode->AddRef(nTimeout);
453         else
454             pnode->AddRef();
455
456         {
457             LOCK(cs_vNodes);
458             vNodes.push_back(pnode);
459         }
460
461         pnode->nTimeConnected = GetTime();
462         return pnode;
463     }
464     else
465     {
466         return NULL;
467     }
468 }
469
470 CNode::CNode(SOCKET hSocketIn, CAddress addrIn, string addrNameIn, bool fInboundIn) : vSend(SER_NETWORK, MIN_PROTO_VERSION), vRecv(SER_NETWORK, MIN_PROTO_VERSION)
471 {
472     nServices = 0;
473     hSocket = hSocketIn;
474     nLastSend = 0;
475     nLastRecv = 0;
476     nSendBytes = 0;
477     nRecvBytes = 0;
478     nLastSendEmpty = GetTime();
479     nTimeConnected = GetTime();
480     nHeaderStart = -1;
481     nMessageStart = numeric_limits<uint32_t>::max();
482     addr = addrIn;
483     addrName = addrNameIn.empty() ? addr.ToStringIPPort() : addrNameIn;
484     nVersion = 0;
485     strSubVer.clear();
486     fOneShot = false;
487     fClient = false; // set by version message
488     fInbound = fInboundIn;
489     fNetworkNode = false;
490     fSuccessfullyConnected = false;
491     fDisconnect = false;
492     nRefCount = 0;
493     nReleaseTime = 0;
494     hashContinue = 0;
495     pindexLastGetBlocksBegin = 0;
496     hashLastGetBlocksEnd = 0;
497     nStartingHeight = -1;
498     nNextLocalAddrSend = 0;
499     nNextAddrSend = 0;
500     nNextInvSend = 0;
501     fStartSync = false;
502     fGetAddr = false;
503     nMisbehavior = 0;
504     hashCheckpointKnown = 0;
505     setInventoryKnown.max_size((size_t)SendBufferSize() / 1000);
506
507     // Be shy and don't send version until we hear
508     if (hSocket != INVALID_SOCKET && !fInbound)
509         PushVersion();
510 }
511
512 CNode::~CNode()
513 {
514     if (hSocket != INVALID_SOCKET)
515     {
516         CloseSocket(hSocket);
517     }
518 }
519
520 int CNode::GetRefCount()
521 {
522     return max(nRefCount, 0) + (GetTime() < nReleaseTime ? 1 : 0);
523 }
524
525 CNode* CNode::AddRef(int64_t nTimeout)
526 {
527     if (nTimeout != 0)
528         nReleaseTime = max(nReleaseTime, GetTime() + nTimeout);
529     else
530         nRefCount++;
531     return this;
532 }
533
534 void CNode::Release()
535 {
536     nRefCount--;
537 }
538
539 void CNode::AddAddressKnown(const CAddress& addr)
540 {
541     setAddrKnown.insert(addr);
542 }
543
544 void CNode::PushAddress(const CAddress& addr)
545 {
546     // Known checking here is only to save space from duplicates.
547     // SendMessages will filter it again for knowns that were added
548     // after addresses were pushed.
549     if (addr.IsValid() && !setAddrKnown.count(addr))
550         vAddrToSend.push_back(addr);
551 }
552
553 void CNode::AddInventoryKnown(const CInv& inv)
554 {
555     {
556         LOCK(cs_inventory);
557         setInventoryKnown.insert(inv);
558     }
559 }
560
561 void CNode::PushInventory(const CInv& inv)
562 {
563     {
564         LOCK(cs_inventory);
565         if (!setInventoryKnown.count(inv))
566             vInventoryToSend.push_back(inv);
567     }
568 }
569
570 void CNode::AskFor(const CInv& inv)
571 {
572     // We're using mapAskFor as a priority queue,
573     // the key is the earliest time the request can be sent
574     int64_t& nRequestTime = mapAlreadyAskedFor[inv];
575     if (fDebugNet)
576         printf("askfor %s   %" PRId64 " (%s)\n", inv.ToString().c_str(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str());
577
578     // Make sure not to reuse time indexes to keep things in the same order
579     int64_t nNow = (GetTime() - 1) * 1000000;
580     static int64_t nLastTime;
581     ++nLastTime;
582     nNow = max(nNow, nLastTime);
583     nLastTime = nNow;
584
585     // Each retry is 2 minutes after the last
586     nRequestTime = max(nRequestTime + 2 * 60 * 1000000, nNow);
587     mapAskFor.insert({ nRequestTime, inv });
588 }
589
590 void CNode::BeginMessage(const char* pszCommand)
591 {
592     ENTER_CRITICAL_SECTION(cs_vSend);
593     if (nHeaderStart != -1)
594         AbortMessage();
595     nHeaderStart = (int32_t)vSend.size();
596     vSend << CMessageHeader(pszCommand, 0);
597     nMessageStart = (uint32_t)vSend.size();
598     if (fDebug)
599         printf("sending: %s ", pszCommand);
600 }
601
602 void CNode::AbortMessage()
603 {
604     if (nHeaderStart < 0)
605         return;
606     vSend.resize(nHeaderStart);
607     nHeaderStart = -1;
608     nMessageStart = numeric_limits<uint32_t>::max();
609     LEAVE_CRITICAL_SECTION(cs_vSend);
610
611     if (fDebug)
612         printf("(aborted)\n");
613 }
614
615 void CNode::EndMessage()
616 {
617     if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
618     {
619         printf("dropmessages DROPPING SEND MESSAGE\n");
620         AbortMessage();
621         return;
622     }
623
624     if (nHeaderStart < 0)
625         return;
626
627     // Set the size
628     uint32_t nSize = (uint32_t) vSend.size() - nMessageStart;
629     memcpy((char*)&vSend[nHeaderStart] + CMessageHeader::MESSAGE_SIZE_OFFSET, &nSize, sizeof(nSize));
630
631     // Set the checksum
632     auto hash = Hash(vSend.begin() + nMessageStart, vSend.end());
633     uint32_t nChecksum = 0;
634     memcpy(&nChecksum, &hash, sizeof(nChecksum));
635     assert(nMessageStart - nHeaderStart >= CMessageHeader::CHECKSUM_OFFSET + sizeof(nChecksum));
636     memcpy((char*)&vSend[nHeaderStart] + CMessageHeader::CHECKSUM_OFFSET, &nChecksum, sizeof(nChecksum));
637
638     if (fDebug) {
639         printf("(%d bytes)\n", nSize);
640     }
641
642     nHeaderStart = -1;
643     nMessageStart = numeric_limits<uint32_t>::max();
644     LEAVE_CRITICAL_SECTION(cs_vSend);
645 }
646
647 void CNode::EndMessageAbortIfEmpty()
648 {
649     if (nHeaderStart < 0)
650         return;
651     int nSize = (int) vSend.size() - nMessageStart;
652     if (nSize > 0)
653         EndMessage();
654     else
655         AbortMessage();
656 }
657
658 void CNode::CloseSocketDisconnect()
659 {
660     fDisconnect = true;
661     if (hSocket != INVALID_SOCKET)
662     {
663         printf("disconnecting node %s\n", addrName.c_str());
664         CloseSocket(hSocket);
665         vRecv.clear();
666     }
667
668     // in case this fails, we'll empty the recv buffer when the CNode is deleted
669     TRY_LOCK(cs_vRecv, lockRecv);
670     if (lockRecv)
671         vRecv.clear();
672
673     // if this was the sync node, we'll need a new one
674     if (this == pnodeSync)
675         pnodeSync = NULL;
676 }
677
678 void CNode::Cleanup()
679 {
680 }
681
682
683 void CNode::PushVersion()
684 {
685     auto nTime = GetAdjustedTime();
686     CAddress addrYou, addrMe;
687
688     bool fHidden = false;
689     if (addr.IsTor()) {
690         if (mapArgs.count("-torname")) {
691             // Our hidden service address
692             CService addrTorName(mapArgs["-torname"], GetListenPort());
693
694             if (addrTorName.IsValid()) {
695                 addrYou = addr;
696                 addrMe = CAddress(addrTorName);
697                 fHidden = true;
698             }
699         }
700     }
701
702     if (!fHidden) {
703         addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", nPortZero)));
704         addrMe = GetLocalAddress(&addr);
705     }
706
707     RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
708     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());
709     PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
710                 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, vector<string>()), nBestHeight);
711 }
712
713
714
715
716
717 map<CNetAddr, int64_t> CNode::setBanned;
718 CCriticalSection CNode::cs_setBanned;
719
720 void CNode::ClearBanned()
721 {
722     setBanned.clear();
723 }
724
725 bool CNode::IsBanned(const CNetAddr& ip)
726 {
727     bool fResult = false;
728     {
729         LOCK(cs_setBanned);
730         auto i = setBanned.find(ip);
731         if (i != setBanned.end())
732         {
733             auto t = (*i).second;
734             if (GetTime() < t)
735                 fResult = true;
736         }
737     }
738     return fResult;
739 }
740
741 bool CNode::Misbehaving(int howmuch)
742 {
743     if (addr.IsLocal())
744     {
745         printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
746         return false;
747     }
748
749     nMisbehavior += howmuch;
750     if (nMisbehavior >= GetArgInt("-banscore", 100))
751     {
752         auto banTime = GetTime()+GetArg("-bantime", nOneDay);  // Default 24-hour ban
753         printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
754         {
755             LOCK(cs_setBanned);
756             if (setBanned[addr] < banTime)
757                 setBanned[addr] = banTime;
758         }
759         CloseSocketDisconnect();
760         return true;
761     } else
762         printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
763     return false;
764 }
765
766 #undef X
767 #define X(name) stats.name = name
768 void CNode::copyStats(CNodeStats &stats)
769 {
770     X(nServices);
771     X(nLastSend);
772     X(nLastRecv);
773     X(nTimeConnected);
774     X(addrName);
775     X(nVersion);
776     X(strSubVer);
777     X(fInbound);
778     X(nReleaseTime);
779     X(nStartingHeight);
780     X(nMisbehavior);
781     X(nSendBytes);
782     X(nRecvBytes);
783     stats.fSyncNode = (this == pnodeSync);
784 }
785 #undef X
786
787
788 void ThreadSocketHandler(void* parg)
789 {
790     // Make this thread recognisable as the networking thread
791     RenameThread("novacoin-net");
792
793     try
794     {
795         vnThreadsRunning[THREAD_SOCKETHANDLER]++;
796         ThreadSocketHandler2(parg);
797         vnThreadsRunning[THREAD_SOCKETHANDLER]--;
798     }
799     catch (exception& e) {
800         vnThreadsRunning[THREAD_SOCKETHANDLER]--;
801         PrintException(&e, "ThreadSocketHandler()");
802     } catch (...) {
803         vnThreadsRunning[THREAD_SOCKETHANDLER]--;
804         throw; // support pthread_cancel()
805     }
806     printf("ThreadSocketHandler exited\n");
807 }
808
809 static list<CNode*> vNodesDisconnected;
810
811 void ThreadSocketHandler2(void* parg)
812 {
813     printf("ThreadSocketHandler started\n");
814     size_t nPrevNodeCount = 0;
815     for ( ; ; )
816     {
817         //
818         // Disconnect nodes
819         //
820         {
821             LOCK(cs_vNodes);
822             // Disconnect unused nodes
823             vector<CNode*> vNodesCopy = vNodes;
824             for(CNode* pnode :  vNodesCopy)
825             {
826                 if (pnode->fDisconnect ||
827                     (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
828                 {
829                     // remove from vNodes
830                     vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
831
832                     // release outbound grant (if any)
833                     pnode->grantOutbound.Release();
834
835                     // close socket and cleanup
836                     pnode->CloseSocketDisconnect();
837                     pnode->Cleanup();
838
839                     // hold in disconnected pool until all refs are released
840                     pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
841                     if (pnode->fNetworkNode || pnode->fInbound)
842                         pnode->Release();
843                     vNodesDisconnected.push_back(pnode);
844                 }
845             }
846
847             // Delete disconnected nodes
848             list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
849             for(CNode* pnode :  vNodesDisconnectedCopy)
850             {
851                 // wait until threads are done using it
852                 if (pnode->GetRefCount() <= 0)
853                 {
854                     bool fDelete = false;
855                     {
856                         TRY_LOCK(pnode->cs_vSend, lockSend);
857                         if (lockSend)
858                         {
859                             TRY_LOCK(pnode->cs_vRecv, lockRecv);
860                             if (lockRecv)
861                             {
862                                 TRY_LOCK(pnode->cs_mapRequests, lockReq);
863                                 if (lockReq)
864                                 {
865                                     TRY_LOCK(pnode->cs_inventory, lockInv);
866                                     if (lockInv)
867                                         fDelete = true;
868                                 }
869                             }
870                         }
871                     }
872                     if (fDelete)
873                     {
874                         vNodesDisconnected.remove(pnode);
875                         delete pnode;
876                     }
877                 }
878             }
879         }
880         if (vNodes.size() != nPrevNodeCount)
881         {
882             nPrevNodeCount = vNodes.size();
883             uiInterface.NotifyNumConnectionsChanged(vNodes.size());
884         }
885
886
887         //
888         // Find which sockets have data to receive
889         //
890         struct timeval timeout;
891         timeout.tv_sec  = 0;
892         timeout.tv_usec = 50000; // frequency to poll pnode->vSend
893
894         fd_set fdsetRecv;
895         fd_set fdsetSend;
896         fd_set fdsetError;
897         FD_ZERO(&fdsetRecv);
898         FD_ZERO(&fdsetSend);
899         FD_ZERO(&fdsetError);
900         SOCKET hSocketMax = 0;
901         bool have_fds = false;
902
903         for(SOCKET hListenSocket :  vhListenSocket) {
904             FD_SET(hListenSocket, &fdsetRecv);
905             hSocketMax = max(hSocketMax, hListenSocket);
906             have_fds = true;
907         }
908         {
909             LOCK(cs_vNodes);
910             for(CNode* pnode :  vNodes)
911             {
912                 if (pnode->hSocket == INVALID_SOCKET)
913                     continue;
914                 FD_SET(pnode->hSocket, &fdsetRecv);
915                 FD_SET(pnode->hSocket, &fdsetError);
916                 hSocketMax = max(hSocketMax, pnode->hSocket);
917                 have_fds = true;
918                 {
919                     TRY_LOCK(pnode->cs_vSend, lockSend);
920                     if (lockSend && !pnode->vSend.empty())
921                         FD_SET(pnode->hSocket, &fdsetSend);
922                 }
923             }
924         }
925
926         vnThreadsRunning[THREAD_SOCKETHANDLER]--;
927         int nSelect = select(have_fds ? hSocketMax + 1 : 0,
928                              &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
929         vnThreadsRunning[THREAD_SOCKETHANDLER]++;
930         if (fShutdown)
931             return;
932         if (nSelect == SOCKET_ERROR)
933         {
934             if (have_fds)
935             {
936                 int nErr = WSAGetLastError();
937                 printf("socket select error %s\n", NetworkErrorString(nErr).c_str());
938                 for (unsigned int i = 0; i <= hSocketMax; i++)
939                     FD_SET(i, &fdsetRecv);
940             }
941             FD_ZERO(&fdsetSend);
942             FD_ZERO(&fdsetError);
943             Sleep(timeout.tv_usec/1000);
944         }
945
946
947         //
948         // Accept new connections
949         //
950         for(SOCKET hListenSocket :  vhListenSocket)
951         if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
952         {
953             struct sockaddr_storage sockaddr;
954             socklen_t len = sizeof(sockaddr);
955             SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
956             CAddress addr;
957             int nInbound = 0;
958
959             if (hSocket != INVALID_SOCKET)
960                 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
961                     printf("Warning: Unknown socket family\n");
962
963             {
964                 LOCK(cs_vNodes);
965                 for(CNode* pnode :  vNodes)
966                     if (pnode->fInbound)
967                         nInbound++;
968             }
969
970             if (hSocket == INVALID_SOCKET)
971             {
972                 int nErr = WSAGetLastError();
973                 if (nErr != WSAEWOULDBLOCK)
974                     printf("socket error accept failed: %s\n", NetworkErrorString(nErr).c_str());
975             }
976             else if (nInbound >= GetArgInt("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
977             {
978                 printf("connection from %s dropped (overall limit)\n", addr.ToString().c_str());
979                 CloseSocket(hSocket);
980             }
981             else if (CNode::IsBanned(addr))
982             {
983                 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
984                 CloseSocket(hSocket);
985             }
986             else
987             {
988                 printf("accepted connection %s\n", addr.ToString().c_str());
989                 CNode* pnode = new CNode(hSocket, addr, "", true);
990                 pnode->AddRef();
991                 {
992                     LOCK(cs_vNodes);
993                     vNodes.push_back(pnode);
994                 }
995             }
996         }
997
998
999         //
1000         // Service each socket
1001         //
1002         vector<CNode*> vNodesCopy;
1003         {
1004             LOCK(cs_vNodes);
1005             vNodesCopy = vNodes;
1006             for(CNode* pnode :  vNodesCopy)
1007                 pnode->AddRef();
1008         }
1009         for(CNode* pnode :  vNodesCopy)
1010         {
1011             if (fShutdown)
1012                 return;
1013
1014             //
1015             // Receive
1016             //
1017             if (pnode->hSocket == INVALID_SOCKET)
1018                 continue;
1019             if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
1020             {
1021                 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1022                 if (lockRecv)
1023                 {
1024                     CDataStream& vRecv = pnode->vRecv;
1025                     uint64_t nPos = vRecv.size();
1026
1027                     if (nPos > ReceiveBufferSize()) {
1028                         if (!pnode->fDisconnect)
1029                             printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
1030                         pnode->CloseSocketDisconnect();
1031                     }
1032                     else {
1033                         // typical socket buffer is 8K-64K
1034                         char pchBuf[0x10000];
1035                         int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
1036                         if (nBytes > 0)
1037                         {
1038                             vRecv.resize(nPos + nBytes);
1039                             memcpy(&vRecv[nPos], pchBuf, nBytes);
1040                             pnode->nLastRecv = GetTime();
1041                             pnode->nRecvBytes += nBytes;
1042                             pnode->RecordBytesRecv(nBytes);
1043                         }
1044                         else if (nBytes == 0)
1045                         {
1046                             // socket closed gracefully
1047                             if (!pnode->fDisconnect)
1048                                 printf("socket closed\n");
1049                             pnode->CloseSocketDisconnect();
1050                         }
1051                         else if (nBytes < 0)
1052                         {
1053                             // error
1054                             int nErr = WSAGetLastError();
1055                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
1056                             {
1057                                 if (!pnode->fDisconnect)
1058                                     printf("socket recv error %s\n", NetworkErrorString(nErr).c_str());
1059                                 pnode->CloseSocketDisconnect();
1060                             }
1061                         }
1062                     }
1063                 }
1064             }
1065
1066             //
1067             // Send
1068             //
1069             if (pnode->hSocket == INVALID_SOCKET)
1070                 continue;
1071             if (FD_ISSET(pnode->hSocket, &fdsetSend))
1072             {
1073                 TRY_LOCK(pnode->cs_vSend, lockSend);
1074                 if (lockSend)
1075                 {
1076                     CDataStream& vSend = pnode->vSend;
1077                     if (!vSend.empty())
1078                     {
1079                         int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
1080                         if (nBytes > 0)
1081                         {
1082                             vSend.erase(vSend.begin(), vSend.begin() + nBytes);
1083                             pnode->nLastSend = GetTime();
1084                             pnode->nSendBytes += nBytes;
1085                             pnode->RecordBytesSent(nBytes);
1086                         }
1087                         else if (nBytes < 0)
1088                         {
1089                             // error
1090                             int nErr = WSAGetLastError();
1091                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
1092                             {
1093                                 printf("socket send error %s\n", NetworkErrorString(nErr).c_str());
1094                                 pnode->CloseSocketDisconnect();
1095                             }
1096                         }
1097                     }
1098                 }
1099             }
1100
1101             //
1102             // Inactivity checking
1103             //
1104             if (pnode->vSend.empty())
1105                 pnode->nLastSendEmpty = GetTime();
1106             if (GetTime() - pnode->nTimeConnected > 60)
1107             {
1108                 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
1109                 {
1110                     printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
1111                     pnode->fDisconnect = true;
1112                 }
1113                 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
1114                 {
1115                     printf("socket not sending\n");
1116                     pnode->fDisconnect = true;
1117                 }
1118                 else if (GetTime() - pnode->nLastRecv > 90*60)
1119                 {
1120                     printf("socket inactivity timeout\n");
1121                     pnode->fDisconnect = true;
1122                 }
1123             }
1124         }
1125         {
1126             LOCK(cs_vNodes);
1127             for(CNode* pnode :  vNodesCopy)
1128                 pnode->Release();
1129         }
1130
1131         Sleep(10);
1132     }
1133 }
1134
1135 void ThreadDNSAddressSeed(void* parg)
1136 {
1137     // Make this thread recognisable as the DNS seeding thread
1138     RenameThread("novacoin-dnsseed");
1139
1140     try
1141     {
1142         vnThreadsRunning[THREAD_DNSSEED]++;
1143         ThreadDNSAddressSeed2(parg);
1144         vnThreadsRunning[THREAD_DNSSEED]--;
1145     }
1146     catch (exception& e) {
1147         vnThreadsRunning[THREAD_DNSSEED]--;
1148         PrintException(&e, "ThreadDNSAddressSeed()");
1149     } catch (...) {
1150         vnThreadsRunning[THREAD_DNSSEED]--;
1151         throw; // support pthread_cancel()
1152     }
1153     printf("ThreadDNSAddressSeed exited\n");
1154 }
1155
1156 void ThreadDNSAddressSeed2(void* parg)
1157 {
1158     printf("ThreadDNSAddressSeed started\n");
1159     int found = 0;
1160
1161     if (!fTestNet)
1162     {
1163         // DNS seeds
1164         // Each pair gives a source name and a seed name.
1165         // The first name is used as information source for addrman.
1166         // The second name should resolve to a list of seed addresses.
1167         static const vector<pair <string, string> > vstrDNSSeed = {
1168             { "node.novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro" },
1169             { "novacoin.ru", "dnsseed.novacoin.ru" },
1170             { "novacoin.ru", "testseed.novacoin.ru" },
1171             { "novaco.in", "dnsseed.novaco.in" },
1172         };
1173         printf("Loading addresses from DNS seeds (could take a while)\n");
1174
1175         for (unsigned int seed_idx = 0; seed_idx < vstrDNSSeed.size(); seed_idx++) {
1176             if (HaveNameProxy()) {
1177                 AddOneShot(vstrDNSSeed[seed_idx].second);
1178             } else {
1179                 vector<CNetAddr> vaddr;
1180                 vector<CAddress> vAdd;
1181                 if (LookupHost(vstrDNSSeed[seed_idx].second, vaddr))
1182                 {
1183                     for(CNetAddr& ip :  vaddr)
1184                     {
1185                         auto addr = CAddress(CService(ip, GetDefaultPort()));
1186                         addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1187                         vAdd.push_back(addr);
1188                         found++;
1189                     }
1190                 }
1191                 addrman.Add(vAdd, CNetAddr(vstrDNSSeed[seed_idx].first, true));
1192             }
1193         }
1194     }
1195
1196     printf("%d addresses found from DNS seeds\n", found);
1197 }
1198
1199 void DumpAddresses()
1200 {
1201     auto nStart = GetTimeMillis();
1202
1203     CAddrDB adb;
1204     adb.Write(addrman);
1205
1206     printf("Flushed %d addresses to peers.dat  %" PRId64 "ms\n",
1207            addrman.size(), GetTimeMillis() - nStart);
1208 }
1209
1210 void ThreadDumpAddress2(void* parg)
1211 {
1212     printf("ThreadDumpAddress started\n");
1213
1214     vnThreadsRunning[THREAD_DUMPADDRESS]++;
1215     while (!fShutdown)
1216     {
1217         DumpAddresses();
1218         vnThreadsRunning[THREAD_DUMPADDRESS]--;
1219         Sleep(600000);
1220         vnThreadsRunning[THREAD_DUMPADDRESS]++;
1221     }
1222     vnThreadsRunning[THREAD_DUMPADDRESS]--;
1223 }
1224
1225 void ThreadDumpAddress(void* parg)
1226 {
1227     // Make this thread recognisable as the address dumping thread
1228     RenameThread("novacoin-adrdump");
1229
1230     try
1231     {
1232         ThreadDumpAddress2(parg);
1233     }
1234     catch (exception& e) {
1235         PrintException(&e, "ThreadDumpAddress()");
1236     }
1237     printf("ThreadDumpAddress exited\n");
1238 }
1239
1240 void ThreadOpenConnections(void* parg)
1241 {
1242     // Make this thread recognisable as the connection opening thread
1243     RenameThread("novacoin-opencon");
1244
1245     try
1246     {
1247         vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1248         ThreadOpenConnections2(parg);
1249         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1250     }
1251     catch (exception& e) {
1252         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1253         PrintException(&e, "ThreadOpenConnections()");
1254     } catch (...) {
1255         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1256         PrintException(NULL, "ThreadOpenConnections()");
1257     }
1258     printf("ThreadOpenConnections exited\n");
1259 }
1260
1261 void static ProcessOneShot()
1262 {
1263     string strDest;
1264     {
1265         LOCK(cs_vOneShots);
1266         if (vOneShots.empty())
1267             return;
1268         strDest = vOneShots.front();
1269         vOneShots.pop_front();
1270     }
1271     CAddress addr;
1272     CSemaphoreGrant grant(*semOutbound, true);
1273     if (grant) {
1274         if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1275             AddOneShot(strDest);
1276     }
1277 }
1278
1279 void ThreadOpenConnections2(void* parg)
1280 {
1281     printf("ThreadOpenConnections started\n");
1282
1283     // Connect to specific addresses
1284     if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1285     {
1286         for (int64_t nLoop = 0;; nLoop++)
1287         {
1288             ProcessOneShot();
1289             for(string strAddr :  mapMultiArgs["-connect"])
1290             {
1291                 CAddress addr;
1292                 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1293                 for (int i = 0; i < 10 && i < nLoop; i++)
1294                 {
1295                     Sleep(500);
1296                     if (fShutdown)
1297                         return;
1298                 }
1299             }
1300             Sleep(500);
1301         }
1302     }
1303
1304     // Initiate network connections
1305     auto nStart = GetTime();
1306     for ( ; ; )
1307     {
1308         ProcessOneShot();
1309
1310         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1311         Sleep(500);
1312         vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1313         if (fShutdown)
1314             return;
1315
1316
1317         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1318         CSemaphoreGrant grant(*semOutbound);
1319         vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1320         if (fShutdown)
1321             return;
1322
1323         // Add seed nodes if IRC isn't working
1324         if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1325         {
1326             vector<uint32_t> vnSeed =
1327             {
1328                 0x1c542868, 0x3859dd6f, 0x203c2e68, 0xf145a6bc, 0x638a545f, 0x325da346, 0x385da346, 0xfb2b8d5f,
1329                 0x52568c5f, 0xa979e65b, 0x8de6485d, 0x9f79e65b, 0x048a861f, 0x3388b55f, 0x6ff0b45e, 0x17e81f5f,
1330                 0x6c47bb25, 0x1ecdc852, 0x28263db9, 0x47824e5d, 0x36f1c851, 0x2bf913b2, 0x95923cb3, 0x84e63eb2,
1331                 0xefdeedbf, 0x65200092, 0xf36f6805, 0x42692d05, 0x772c1955, 0xb6bf1b4e, 0x7abb5f5d, 0xdb2fa6bc,
1332                 0x90e911bf, 0x82de565f, 0x694416b2, 0x0ab600bc, 0xfcecbe6d, 0x24ed9fb2, 0x1bb618c2, 0xc64765bb,
1333                 0x4e3d62c3, 0xdba24baa, 0x4b7109b0, 0x12a12cc2, 0xfc01864f, 0x0b69e85b, 0x33922c1f, 0xac611bc6,
1334                 0x2a257155, 0x991d5fc0, 0xbfdabcb1, 0x9b73ee55, 0x5bc2b95d, 0xdef0762e, 0x6ab7c936, 0x9c4416b2,
1335                 0xd60d864f, 0x03671f1f, 0x3b5da346, 0xc6f5c851, 0x5411b2d4, 0xe7c25702, 0x63474fb0, 0x7e11c854,
1336                 0x52381d5f, 0x72fdfe59, 0x51599a05, 0xfb12b2d4, 0xaee4f15e, 0xd0e3f15e, 0x2aa2805f, 0xa1caf15e,
1337                 0x34fe425e, 0x46e1f15e, 0xd7c71955, 0xaeeff15e, 0x47c2af55, 0x563d89b2, 0x67980fd9, 0xc9def15e,
1338                 0x9cc51eb9, 0xdaa7aa6b, 0x78e6871f, 0x0d5d2cb2, 0x7aedf15e, 0x9bcaf15e, 0xe5f7f15e, 0x501c1759,
1339                 0xdfbc4980, 0xa7397f2e, 0x31ea1a02, 0x3a27655e, 0xaa86f05c, 0xdcddf15e, 0x64689cb2, 0xd4bf62d4,
1340                 0xf093eab2, 0x98def15e, 0xb6c5f15e, 0x81e8f15e, 0xe5d2fe59, 0xa312786d, 0x4cf9fe59, 0x8a922c1f,
1341                 0x00c7fe59, 0x1ade565f, 0x9e4116b2, 0x2c36983e, 0x68f8f15e, 0x51b7eab2, 0x76c51eb9, 0x9edd4980,
1342                 0x90ef565f, 0x0dd80857, 0xd513fb94, 0xf5bdeab2, 0xa95277b0, 0x2cf2f15e, 0x1897eab2, 0x924416b2,
1343                 0x985c9b59, 0x30aa43d8, 0xf9c6745f, 0xaf862e5f, 0xe0ceeab2, 0xb9b3eab2, 0x6da4eab2, 0xa4fdeab2,
1344                 0x0fa6c125, 0xe38bbd05, 0x5d922c1f, 0x9bd0eab2, 0x73025e02, 0xc4fd794d, 0x8435b35f, 0x2d01bc2e,
1345                 0xaa2a14d4, 0xa22b07cb, 0xebda6f4f, 0xddc6514e, 0xf23feab2, 0xea1e5256, 0x6147b45e, 0x47d21e4f,
1346                 0x67c41c1f, 0x53ec1a02, 0x352e786d, 0x6bec1a02, 0x78fb4abe, 0xd3014c5d, 0x9fbbeab2, 0x1fc51eb9,
1347                 0x720eeab2, 0x2db5eab2, 0xe8baf65c, 0x521b459e, 0x65c4955f, 0x0e7b915f, 0xa8f37e6d, 0x6d0b465f,
1348                 0xfab8ff5c, 0xf7c27e6d, 0x7345a846, 0x4fd1a7d5, 0xdfc97e6d, 0x26c27e6d, 0xa9de36b2, 0xc615344d,
1349                 0x28ceb95d, 0xa52d895e, 0x18c17e6d, 0x13ec1a02, 0x0ba37125, 0x6c3d344d, 0xb3922c1f, 0x506bbeb0,
1350                 0x4d04994e, 0xa1bbe56d, 0xf62c344d, 0x0847d048, 0x4bdc6451, 0xc95b9a05, 0xbcd3a7d5, 0x29b57125,
1351                 0x0c4d2cb2, 0xf2b8eab2, 0xc2d5b95d, 0x0185ef59, 0x30adeab2, 0xcaf0e92e, 0x756c344d, 0xfd9e252e,
1352                 0xbe5ef3bc, 0x4689344d, 0xb223895e, 0xfcebeaad, 0xb7c0e92e, 0x993c1760, 0xe1e171b0, 0xb857e75b,
1353                 0xbf10002e, 0xb55b2cb2, 0xa90e2cb2, 0x13d6f15e, 0xf8be9225, 0x14ddf15e, 0x06e90305, 0x82472cb2,
1354             };
1355             vector<CAddress> vAdd;
1356             for (unsigned int i = 0; i < vnSeed.size(); i++)
1357             {
1358                 // It'll only connect to one or two seed nodes because once it connects,
1359                 // it'll get a pile of addresses with newer timestamps.
1360                 // Seed nodes are given a random 'last seen time' of between one and two
1361                 // weeks ago.
1362                 struct in_addr ip;
1363                 memcpy(&ip, &vnSeed[i], sizeof(ip));
1364                 CAddress addr(CService(ip, GetDefaultPort()));
1365                 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1366                 vAdd.push_back(addr);
1367             }
1368             addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1369         }
1370
1371         // Add Tor nodes if we have connection with onion router
1372         if (mapArgs.count("-tor"))
1373         {
1374             const vector<string> vstrTorSeed =
1375             {
1376                 "seedp4knqnoei57u.onion",
1377                 "seedr3hhlepyi7fd.onion",
1378                 "seed3uuomkclbiz4.onion",
1379                 "seedeh7qck3ouff5.onion",
1380                 "5rg3vq4jagckeckf.onion",
1381                 "seedt3sraf53ajiy.onion",
1382                 "seedg4qyccsg42oq.onion",
1383                 "novaqrtoywpg7jly.onion",
1384                 "seed3d5wolqbgrcb.onion",
1385                 "seed24u5dwph3qw4.onion",
1386                 "mj26ulzbs2oskgym.onion",
1387                 "eqon4usunavt76m7.onion",
1388                 "seedd3aldwpslzl3.onion"
1389             };
1390             vector<CAddress> vAdd;
1391             for (unsigned int i = 0; i < vstrTorSeed.size(); i++)
1392             {
1393                 CAddress addr(CService(vstrTorSeed[i], GetDefaultPort()));
1394                 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1395                 vAdd.push_back(addr);
1396             }
1397             addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1398         }
1399
1400         //
1401         // Choose an address to connect to based on most recently seen
1402         //
1403         CAddress addrConnect;
1404
1405         // Only connect out to one peer per network group (/16 for IPv4).
1406         // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1407         int nOutbound = 0;
1408         set<vector<unsigned char> > setConnected;
1409         {
1410             LOCK(cs_vNodes);
1411             for(CNode* pnode :  vNodes) {
1412                 if (!pnode->fInbound) {
1413                     setConnected.insert(pnode->addr.GetGroup());
1414                     nOutbound++;
1415                 }
1416             }
1417         }
1418
1419         auto nANow = GetAdjustedTime();
1420
1421         int nTries = 0;
1422         for ( ; ; )
1423         {
1424             // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1425             auto addr = addrman.Select(10 + min(nOutbound,8)*10);
1426
1427             // if we selected an invalid address, restart
1428             if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1429                 break;
1430
1431             // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1432             // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1433             // already-connected network ranges, ...) before trying new addrman addresses.
1434             nTries++;
1435             if (nTries > 100)
1436                 break;
1437
1438             if (IsLimited(addr))
1439                 continue;
1440
1441             // only consider very recently tried nodes after 30 failed attempts
1442             if (nANow - addr.nLastTry < 600 && nTries < 30)
1443                 continue;
1444
1445             // do not allow non-default ports, unless after 50 invalid addresses selected already
1446             if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1447                 continue;
1448
1449             addrConnect = addr;
1450             break;
1451         }
1452
1453         if (addrConnect.IsValid())
1454             OpenNetworkConnection(addrConnect, &grant);
1455     }
1456 }
1457
1458 void ThreadOpenAddedConnections(void* parg)
1459 {
1460     // Make this thread recognisable as the connection opening thread
1461     RenameThread("novacoin-opencon");
1462
1463     try
1464     {
1465         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1466         ThreadOpenAddedConnections2(parg);
1467         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1468     }
1469     catch (exception& e) {
1470         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1471         PrintException(&e, "ThreadOpenAddedConnections()");
1472     } catch (...) {
1473         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1474         PrintException(NULL, "ThreadOpenAddedConnections()");
1475     }
1476     printf("ThreadOpenAddedConnections exited\n");
1477 }
1478
1479 void ThreadOpenAddedConnections2(void* parg)
1480 {
1481     printf("ThreadOpenAddedConnections started\n");
1482
1483     {
1484         LOCK(cs_vAddedNodes);
1485         vAddedNodes = mapMultiArgs["-addnode"];
1486     }
1487
1488     if (HaveNameProxy()) {
1489         while(!fShutdown) {
1490             list<string> lAddresses(0);
1491             {
1492                 LOCK(cs_vAddedNodes);
1493                 for(string& strAddNode :  vAddedNodes)
1494                     lAddresses.push_back(strAddNode);
1495             }
1496             for(string& strAddNode :  lAddresses) {
1497                 CAddress addr;
1498                 CSemaphoreGrant grant(*semOutbound);
1499                 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1500                 Sleep(500);
1501             }
1502             vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1503             Sleep(120000); // Retry every 2 minutes
1504             vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1505         }
1506         return;
1507     }
1508
1509     for (uint32_t i = 0; true; i++)
1510     {
1511         list<string> lAddresses(0);
1512         {
1513             LOCK(cs_vAddedNodes);
1514             for(string& strAddNode :  vAddedNodes)
1515                 lAddresses.push_back(strAddNode);
1516         }
1517
1518         list<vector<CService> > lservAddressesToAdd(0);
1519         for(string& strAddNode :  lAddresses)
1520         {
1521             vector<CService> vservNode(0);
1522             if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1523             {
1524                 lservAddressesToAdd.push_back(vservNode);
1525                 {
1526                     LOCK(cs_setservAddNodeAddresses);
1527                     for(CService& serv :  vservNode)
1528                         setservAddNodeAddresses.insert(serv);
1529                 }
1530             }
1531         }
1532         // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1533         // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1534         {
1535             LOCK(cs_vNodes);
1536             for(CNode* pnode :  vNodes)
1537                 for (auto it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1538                 {
1539                     for(CService& addrNode :  *(it))
1540                         if (pnode->addr == addrNode)
1541                         {
1542                             it = lservAddressesToAdd.erase(it);
1543                             if(it != lservAddressesToAdd.begin())
1544                                 it--;
1545                             break;
1546                         }
1547                     if (it == lservAddressesToAdd.end())
1548                         break;
1549                 }
1550         }
1551         for(vector<CService>& vserv :  lservAddressesToAdd)
1552         {
1553             if (vserv.size() == 0)
1554                 continue;
1555             CSemaphoreGrant grant(*semOutbound);
1556             OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1557             Sleep(500);
1558             if (fShutdown)
1559                 return;
1560         }
1561         if (fShutdown)
1562             return;
1563         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1564         Sleep(120000); // Retry every 2 minutes
1565         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1566         if (fShutdown)
1567             return;
1568     }
1569 }
1570
1571 // if successful, this moves the passed grant to the constructed node
1572 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1573 {
1574     //
1575     // Initiate outbound network connection
1576     //
1577     if (fShutdown)
1578         return false;
1579     if (!strDest)
1580         if (IsLocal(addrConnect) ||
1581             FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1582             FindNode(addrConnect.ToStringIPPort().c_str()))
1583             return false;
1584     if (strDest && FindNode(strDest))
1585         return false;
1586
1587     vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1588     CNode* pnode = ConnectNode(addrConnect, strDest);
1589     vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1590     if (fShutdown)
1591         return false;
1592     if (!pnode)
1593         return false;
1594     if (grantOutbound)
1595         grantOutbound->MoveTo(pnode->grantOutbound);
1596     pnode->fNetworkNode = true;
1597     if (fOneShot)
1598         pnode->fOneShot = true;
1599
1600     return true;
1601 }
1602
1603 // for now, use a very simple selection metric: the node from which we received
1604 // most recently
1605 static int64_t NodeSyncScore(const CNode *pnode) {
1606     return pnode->nLastRecv;
1607 }
1608
1609 void static StartSync(const vector<CNode*> &vNodes) {
1610     CNode *pnodeNewSync = NULL;
1611     int64_t nBestScore = 0;
1612
1613     // Iterate over all nodes
1614     for(CNode* pnode :  vNodes) {
1615         // check preconditions for allowing a sync
1616         if (!pnode->fClient && !pnode->fOneShot &&
1617             !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1618             (pnode->nStartingHeight > (nBestHeight - 144)) &&
1619             (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1620             // if ok, compare node's score with the best so far
1621             int64_t nScore = NodeSyncScore(pnode);
1622             if (pnodeNewSync == NULL || nScore > nBestScore) {
1623                 pnodeNewSync = pnode;
1624                 nBestScore = nScore;
1625             }
1626         }
1627     }
1628     // if a new sync candidate was found, start sync!
1629     if (pnodeNewSync) {
1630         pnodeNewSync->fStartSync = true;
1631         pnodeSync = pnodeNewSync;
1632     }
1633 }
1634
1635 void ThreadMessageHandler(void* parg)
1636 {
1637     // Make this thread recognisable as the message handling thread
1638     RenameThread("novacoin-msghand");
1639
1640     try
1641     {
1642         vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1643         ThreadMessageHandler2(parg);
1644         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1645     }
1646     catch (exception& e) {
1647         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1648         PrintException(&e, "ThreadMessageHandler()");
1649     } catch (...) {
1650         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1651         PrintException(NULL, "ThreadMessageHandler()");
1652     }
1653     printf("ThreadMessageHandler exited\n");
1654 }
1655
1656 void ThreadMessageHandler2(void* parg)
1657 {
1658     printf("ThreadMessageHandler started\n");
1659     SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1660     while (!fShutdown)
1661     {
1662         bool fHaveSyncNode = false;
1663         vector<CNode*> vNodesCopy;
1664         {
1665             LOCK(cs_vNodes);
1666             vNodesCopy = vNodes;
1667             for(CNode* pnode :  vNodesCopy) {
1668                 pnode->AddRef();
1669                 if (pnode == pnodeSync)
1670                     fHaveSyncNode = true;
1671             }
1672         }
1673
1674         if (!fHaveSyncNode)
1675             StartSync(vNodesCopy);
1676
1677         // Poll the connected nodes for messages
1678         for(CNode* pnode :  vNodesCopy)
1679         {
1680             // Receive messages
1681             {
1682                 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1683                 if (lockRecv)
1684                     ProcessMessages(pnode);
1685             }
1686             if (fShutdown)
1687                 return;
1688
1689             // Send messages
1690             {
1691                 TRY_LOCK(pnode->cs_vSend, lockSend);
1692                 if (lockSend)
1693                     SendMessages(pnode);
1694             }
1695             if (fShutdown)
1696                 return;
1697         }
1698
1699         {
1700             LOCK(cs_vNodes);
1701             for(CNode* pnode :  vNodesCopy)
1702                 pnode->Release();
1703         }
1704
1705         // Wait and allow messages to bunch up.
1706         // Reduce vnThreadsRunning so StopNode has permission to exit while
1707         // we're sleeping, but we must always check fShutdown after doing this.
1708         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1709         Sleep(100);
1710         if (fRequestShutdown)
1711             StartShutdown();
1712         vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1713         if (fShutdown)
1714             return;
1715     }
1716 }
1717
1718
1719
1720
1721
1722
1723 bool BindListenPort(const CService &addrBind, string& strError)
1724 {
1725     strError.clear();
1726     int nOne = 1;
1727
1728     // Create socket for listening for incoming connections
1729     struct sockaddr_storage sockaddr;
1730     socklen_t len = sizeof(sockaddr);
1731     if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1732     {
1733         strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1734         printf("%s\n", strError.c_str());
1735         return false;
1736     }
1737
1738     SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1739     if (hListenSocket == INVALID_SOCKET)
1740     {
1741         strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %s)", NetworkErrorString(WSAGetLastError()).c_str());
1742         printf("%s\n", strError.c_str());
1743         return false;
1744     }
1745
1746 #ifndef WIN32
1747 #ifdef SO_NOSIGPIPE
1748     // Different way of disabling SIGPIPE on BSD
1749     if (setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int)) == SOCKET_ERROR)
1750     {
1751         printf("WARNING: setsockopt failed\n");
1752         //TODO: work around problem - may be add CloseSocket and return false?
1753     }
1754 #endif
1755     // Allow binding if the port is still in TIME_WAIT state after
1756     // the program was closed and restarted. Not an issue on windows!
1757     if (setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int)) == SOCKET_ERROR)
1758     {
1759         printf("WARNING: setsockopt failed\n");
1760         //TODO: work around problem - may be add CloseSocket and return false?
1761     }
1762 #endif
1763
1764 #ifdef WIN32
1765     // Set to non-blocking, incoming connections will also inherit this
1766     if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1767 #else
1768     if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1769 #endif
1770     {
1771         strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %s)", NetworkErrorString(WSAGetLastError()).c_str());
1772         printf("%s\n", strError.c_str());
1773         CloseSocket(hListenSocket);
1774         return false;
1775     }
1776
1777     // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1778     // and enable it by default or not. Try to enable it, if possible.
1779     if (addrBind.IsIPv6()) {
1780 #ifdef IPV6_V6ONLY
1781 #ifdef WIN32
1782     if (setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int)) == SOCKET_ERROR)
1783     {
1784         printf("WARNING: setsockopt failed\n");
1785         //TODO: work around problem - may be add CloseSocket and return false?
1786     }
1787 #else
1788     if (setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int)) == SOCKET_ERROR)
1789     {
1790         printf("WARNING: setsockopt failed\n");
1791         //TODO: work around problem - may be add CloseSocket and return false?
1792     }
1793 #endif
1794 #endif
1795 #ifdef WIN32
1796     int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1797     if (setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int)) == SOCKET_ERROR)
1798     {
1799         printf("WARNING: setsockopt failed\n");
1800         //TODO: work around problem - may be add CloseSocket and return false?
1801     }
1802 #endif
1803     }
1804
1805     if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1806     {
1807         int nErr = WSAGetLastError();
1808         if (nErr == WSAEADDRINUSE)
1809             strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1810         else
1811             strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToString().c_str(), NetworkErrorString(nErr).c_str());
1812         printf("%s\n", strError.c_str());
1813         CloseSocket(hListenSocket);
1814         return false;
1815     }
1816     printf("Bound to %s\n", addrBind.ToString().c_str());
1817
1818     // Listen for incoming connections
1819     if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1820     {
1821         strError = strprintf("Error: Listening for incoming connections failed (listen returned error %s)", NetworkErrorString(WSAGetLastError()).c_str());
1822         printf("%s\n", strError.c_str());
1823         CloseSocket(hListenSocket);
1824         return false;
1825     }
1826
1827     vhListenSocket.push_back(hListenSocket);
1828
1829     if (addrBind.IsRoutable() && fDiscover)
1830         AddLocal(addrBind, LOCAL_BIND);
1831
1832     return true;
1833 }
1834
1835 void static Discover()
1836 {
1837     if (!fDiscover)
1838         return;
1839
1840 #ifdef WIN32
1841     // Get local host IP
1842     char pszHostName[1000] = "";
1843     if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1844     {
1845         vector<CNetAddr> vaddr;
1846         if (LookupHost(pszHostName, vaddr))
1847         {
1848             for(const auto &addr : vaddr)
1849             {
1850                 AddLocal(addr, LOCAL_IF);
1851             }
1852         }
1853     }
1854 #else
1855     // Get local host ip
1856     struct ifaddrs* myaddrs;
1857     if (getifaddrs(&myaddrs) == 0)
1858     {
1859         for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1860         {
1861             if (ifa->ifa_addr == NULL) continue;
1862             if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1863             if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1864             if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1865             if (ifa->ifa_addr->sa_family == AF_INET)
1866             {
1867                 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1868                 CNetAddr addr(s4->sin_addr);
1869                 if (AddLocal(addr, LOCAL_IF))
1870                     printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1871             }
1872             else if (ifa->ifa_addr->sa_family == AF_INET6)
1873             {
1874                 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1875                 CNetAddr addr(s6->sin6_addr);
1876                 if (AddLocal(addr, LOCAL_IF))
1877                     printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1878             }
1879         }
1880         freeifaddrs(myaddrs);
1881     }
1882 #endif
1883
1884     // Don't use external IPv4 discovery, when -onlynet="IPv6"
1885     if (!IsLimited(NET_IPV4))
1886         NewThread(ThreadGetMyExternalIP, NULL);
1887 }
1888
1889 void StartNode(void* parg)
1890 {
1891     // Make this thread recognisable as the startup thread
1892     RenameThread("novacoin-start");
1893
1894     if (semOutbound == NULL) {
1895         // initialize semaphore
1896         int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1897         semOutbound = new CSemaphore(nMaxOutbound);
1898     }
1899
1900     if (pnodeLocalHost == NULL)
1901         pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1902
1903     Discover();
1904
1905     //
1906     // Start threads
1907     //
1908
1909     if (!GetBoolArg("-dnsseed", true))
1910         printf("DNS seeding disabled\n");
1911     else
1912         if (!NewThread(ThreadDNSAddressSeed, NULL))
1913             printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1914
1915     // Get addresses from IRC and advertise ours
1916     if (!GetBoolArg("-irc", true))
1917         printf("IRC seeding disabled\n");
1918     else
1919         if (!NewThread(ThreadIRCSeed, NULL))
1920             printf("Error: NewThread(ThreadIRCSeed) failed\n");
1921
1922     // Send and receive from sockets, accept connections
1923     if (!NewThread(ThreadSocketHandler, NULL))
1924         printf("Error: NewThread(ThreadSocketHandler) failed\n");
1925
1926     // Initiate outbound connections from -addnode
1927     if (!NewThread(ThreadOpenAddedConnections, NULL))
1928         printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1929
1930     // Initiate outbound connections
1931     if (!NewThread(ThreadOpenConnections, NULL))
1932         printf("Error: NewThread(ThreadOpenConnections) failed\n");
1933
1934     // Process messages
1935     if (!NewThread(ThreadMessageHandler, NULL))
1936         printf("Error: NewThread(ThreadMessageHandler) failed\n");
1937
1938     // Dump network addresses
1939     if (!NewThread(ThreadDumpAddress, NULL))
1940         printf("Error; NewThread(ThreadDumpAddress) failed\n");
1941
1942     // Mine proof-of-stake blocks in the background
1943     if (!NewThread(ThreadStakeMiner, pwalletMain))
1944         printf("Error: NewThread(ThreadStakeMiner) failed\n");
1945
1946     // Trusted NTP server, it's localhost by default.
1947     strTrustedUpstream = GetArg("-ntp", "localhost");
1948
1949     // Start periodical NTP sampling thread
1950     NewThread(ThreadNtpSamples, NULL);
1951
1952 }
1953
1954 bool StopNode()
1955 {
1956     printf("StopNode()\n");
1957     fShutdown = true;
1958     nTransactionsUpdated++;
1959     auto nStart = GetTime();
1960     {
1961         LOCK(cs_main);
1962         ThreadScriptCheckQuit();
1963     }
1964     if (semOutbound)
1965         for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1966             semOutbound->post();
1967     for ( ; ; )
1968     {
1969         int nThreadsRunning = 0;
1970         for (int n = 0; n < THREAD_MAX; n++)
1971             nThreadsRunning += vnThreadsRunning[n];
1972         if (nThreadsRunning == 0)
1973             break;
1974         if (GetTime() - nStart > 20)
1975             break;
1976         Sleep(20);
1977     };
1978     if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1979     if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1980     if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1981     if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1982     if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1983     if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1984     if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1985     if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1986     if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1987     if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1988     while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1989         Sleep(20);
1990     Sleep(50);
1991     DumpAddresses();
1992
1993     return true;
1994 }
1995
1996 class CNetCleanup
1997 {
1998 public:
1999     CNetCleanup()
2000     {
2001     }
2002     ~CNetCleanup()
2003     {
2004         // Close sockets
2005         for(CNode* pnode :  vNodes)
2006             if (pnode->hSocket != INVALID_SOCKET)
2007                 CloseSocket(pnode->hSocket);
2008         for(SOCKET hListenSocket :  vhListenSocket)
2009             if (hListenSocket != INVALID_SOCKET)
2010                 if (!CloseSocket(hListenSocket))
2011                     printf("CloseSocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError()).c_str());
2012
2013         // clean up some globals (to help leak detection)
2014         for(CNode *pnode :  vNodes)
2015             delete pnode;
2016         for(CNode *pnode :  vNodesDisconnected)
2017             delete pnode;
2018         vNodes.clear();
2019         vNodesDisconnected.clear();
2020         delete semOutbound;
2021         semOutbound = NULL;
2022         delete pnodeLocalHost;
2023         pnodeLocalHost = NULL;
2024
2025 #ifdef WIN32
2026         // Shutdown Windows Sockets
2027         WSACleanup();
2028 #endif
2029     }
2030 }
2031 instance_of_cnetcleanup;
2032
2033 inline void RelayInventory(const CInv& inv)
2034 {
2035     // Put on lists to offer to the other nodes
2036     {
2037         LOCK(cs_vNodes);
2038         for(CNode* pnode :  vNodes)
2039             pnode->PushInventory(inv);
2040     }
2041 }
2042
2043 void RelayTransaction(const CTransaction& tx, const uint256& hash)
2044 {
2045     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2046     ss.reserve(10000);
2047     ss << tx;
2048     RelayTransaction(tx, hash, ss);
2049 }
2050
2051 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
2052 {
2053     CInv inv(MSG_TX, hash);
2054     {
2055         LOCK(cs_mapRelay);
2056         // Expire old relay messages
2057         while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
2058         {
2059             mapRelay.erase(vRelayExpiration.front().second);
2060             vRelayExpiration.pop_front();
2061         }
2062
2063         // Save original serialized message so newer versions are preserved
2064         mapRelay.insert({inv, ss});
2065         vRelayExpiration.push_back({GetTime() + 15 * 60, inv});
2066     }
2067
2068     RelayInventory(inv);
2069 }
2070
2071 void CNode::RecordBytesRecv(uint64_t bytes)
2072 {
2073     LOCK(cs_totalBytesRecv);
2074     nTotalBytesRecv += bytes;
2075 }
2076
2077 void CNode::RecordBytesSent(uint64_t bytes)
2078 {
2079     LOCK(cs_totalBytesSent);
2080     nTotalBytesSent += bytes;
2081 }
2082
2083 uint64_t CNode::GetTotalBytesRecv()
2084 {
2085     LOCK(cs_totalBytesRecv);
2086     return nTotalBytesRecv;
2087 }
2088
2089 uint64_t CNode::GetTotalBytesSent()
2090 {
2091     LOCK(cs_totalBytesSent);
2092     return nTotalBytesSent;
2093 }
2094
2095 int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) {
2096     return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);
2097 }