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