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