Improve Tor support
[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 "strlcpy.h"
11 #include "addrman.h"
12 #include "ui_interface.h"
13
14 #ifdef WIN32
15 #include <string.h>
16 #endif
17
18 #ifdef USE_UPNP
19 #include <miniupnpc/miniwget.h>
20 #include <miniupnpc/miniupnpc.h>
21 #include <miniupnpc/upnpcommands.h>
22 #include <miniupnpc/upnperrors.h>
23 #endif
24
25 using namespace std;
26 using namespace boost;
27
28 static const int MAX_OUTBOUND_CONNECTIONS = 16;
29
30 void ThreadMessageHandler2(void* parg);
31 void ThreadSocketHandler2(void* parg);
32 void ThreadOpenConnections2(void* parg);
33 void ThreadOpenAddedConnections2(void* parg);
34 #ifdef USE_UPNP
35 void ThreadMapPort2(void* parg);
36 #endif
37 void ThreadDNSAddressSeed2(void* parg);
38
39 struct LocalServiceInfo {
40     int nScore;
41     int nPort;
42 };
43
44 //
45 // Global state variables
46 //
47 bool fClient = false;
48 bool fDiscover = true;
49 bool fUseUPnP = false;
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", 0), nLocalServices);
58 uint64_t nLocalHostNonce = 0;
59 boost::array<int, THREAD_MAX> vnThreadsRunning;
60 static std::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<std::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 unsigned short GetListenPort()
88 {
89     return (unsigned short)(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 (map<CNetAddr, LocalServiceInfo>::iterator 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",0),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 = "";
145     while (true)
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     BOOST_FOREACH(CNode* pnode, vNodes)
199     {
200         if (pnode->fSuccessfullyConnected)
201         {
202             CAddress addrLocal = GetLocalAddress(&pnode->addr);
203             if (addrLocal.IsRoutable() && (CService)addrLocal != (CService)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 // learn a new local address
221 bool AddLocal(const CService& addr, int nScore)
222 {
223     if (!addr.IsRoutable())
224         return false;
225
226     if (!fDiscover && nScore < LOCAL_MANUAL)
227         return false;
228
229     if (IsLimited(addr))
230         return false;
231
232     printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
233
234     {
235         LOCK(cs_mapLocalHost);
236         bool fAlready = mapLocalHost.count(addr) > 0;
237         LocalServiceInfo &info = mapLocalHost[addr];
238         if (!fAlready || nScore >= info.nScore) {
239             info.nScore = nScore + (fAlready ? 1 : 0);
240             info.nPort = addr.GetPort();
241         }
242         SetReachable(addr.GetNetwork());
243     }
244
245     AdvertizeLocal();
246
247     return true;
248 }
249
250 bool AddLocal(const CNetAddr &addr, int nScore)
251 {
252     return AddLocal(CService(addr, GetListenPort()), nScore);
253 }
254
255 /** Make a particular network entirely off-limits (no automatic connects to it) */
256 void SetLimited(enum Network net, bool fLimited)
257 {
258     if (net == NET_UNROUTABLE)
259         return;
260     LOCK(cs_mapLocalHost);
261     vfLimited[net] = fLimited;
262 }
263
264 bool IsLimited(enum Network net)
265 {
266     LOCK(cs_mapLocalHost);
267     return vfLimited[net];
268 }
269
270 bool IsLimited(const CNetAddr &addr)
271 {
272     return IsLimited(addr.GetNetwork());
273 }
274
275 /** vote for a local address */
276 bool SeenLocal(const CService& addr)
277 {
278     {
279         LOCK(cs_mapLocalHost);
280         if (mapLocalHost.count(addr) == 0)
281             return false;
282         mapLocalHost[addr].nScore++;
283     }
284
285     AdvertizeLocal();
286
287     return true;
288 }
289
290 /** check whether a given address is potentially local */
291 bool IsLocal(const CService& addr)
292 {
293     LOCK(cs_mapLocalHost);
294     return mapLocalHost.count(addr) > 0;
295 }
296
297 /** check whether a given address is in a network we can probably connect to */
298 bool IsReachable(const CNetAddr& addr)
299 {
300     LOCK(cs_mapLocalHost);
301     enum Network net = addr.GetNetwork();
302     return vfReachable[net] && !vfLimited[net];
303 }
304
305 extern int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv);
306
307 // We now get our external IP from the IRC server first and only use this as a backup
308 bool GetMyExternalIP(CNetAddr& ipRet)
309 {
310     struct sockaddr_in mapped;
311     uint64_t rnd = GetRand(~0LL);
312     const char *srv;
313     int rc = GetExternalIPbySTUN(rnd, &mapped, &srv);
314     if(rc >= 0) {
315         ipRet = CNetAddr(mapped.sin_addr);
316         printf("GetExternalIPbySTUN(%" PRIu64 ") returned %s in attempt %d; Server=%s\n", rnd, ipRet.ToStringIP().c_str(), rc, srv);
317         return true;
318     }
319     return false;
320 }
321
322 void ThreadGetMyExternalIP(void* parg)
323 {
324     // Make this thread recognisable as the external IP detection thread
325     RenameThread("novacoin-ext-ip");
326
327     CNetAddr addrLocalHost;
328     if (GetMyExternalIP(addrLocalHost))
329     {
330         printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
331         AddLocal(addrLocalHost, LOCAL_HTTP);
332     }
333 }
334
335
336
337
338
339 void AddressCurrentlyConnected(const CService& addr)
340 {
341     addrman.Connected(addr);
342 }
343
344
345
346
347 uint64_t CNode::nTotalBytesRecv = 0;
348 uint64_t CNode::nTotalBytesSent = 0;
349 CCriticalSection CNode::cs_totalBytesRecv;
350 CCriticalSection CNode::cs_totalBytesSent;
351
352 CNode* FindNode(const CNetAddr& ip)
353 {
354     LOCK(cs_vNodes);
355     BOOST_FOREACH(CNode* pnode, vNodes)
356         if ((CNetAddr)pnode->addr == ip)
357             return (pnode);
358     return NULL;
359 }
360
361 CNode* FindNode(std::string addrName)
362 {
363     LOCK(cs_vNodes);
364     BOOST_FOREACH(CNode* pnode, vNodes)
365         if (pnode->addrName == addrName)
366             return (pnode);
367     return NULL;
368 }
369
370 CNode* FindNode(const CService& addr)
371 {
372     LOCK(cs_vNodes);
373     BOOST_FOREACH(CNode* pnode, vNodes)
374         if ((CService)pnode->addr == addr)
375             return (pnode);
376     return NULL;
377 }
378
379 CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64_t nTimeout)
380 {
381     if (pszDest == NULL) {
382         if (IsLocal(addrConnect))
383             return NULL;
384
385         // Look for an existing connection
386         CNode* pnode = FindNode((CService)addrConnect);
387         if (pnode)
388         {
389             if (nTimeout != 0)
390                 pnode->AddRef(nTimeout);
391             else
392                 pnode->AddRef();
393             return pnode;
394         }
395     }
396
397
398     /// debug print
399     printf("trying connection %s lastseen=%.1fhrs\n",
400         pszDest ? pszDest : addrConnect.ToString().c_str(),
401         pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
402
403     // Connect
404     SOCKET hSocket;
405     if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
406     {
407         addrman.Attempt(addrConnect);
408
409         /// debug print
410         printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
411
412         // Set to non-blocking
413 #ifdef WIN32
414         u_long nOne = 1;
415         if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
416             printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
417 #else
418         if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
419             printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
420 #endif
421
422         // Add node
423         CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
424         if (nTimeout != 0)
425             pnode->AddRef(nTimeout);
426         else
427             pnode->AddRef();
428
429         {
430             LOCK(cs_vNodes);
431             vNodes.push_back(pnode);
432         }
433
434         pnode->nTimeConnected = GetTime();
435         return pnode;
436     }
437     else
438     {
439         return NULL;
440     }
441 }
442
443 void CNode::CloseSocketDisconnect()
444 {
445     fDisconnect = true;
446     if (hSocket != INVALID_SOCKET)
447     {
448         printf("disconnecting node %s\n", addrName.c_str());
449         closesocket(hSocket);
450         hSocket = INVALID_SOCKET;
451         vRecv.clear();
452     }
453
454     // in case this fails, we'll empty the recv buffer when the CNode is deleted
455     TRY_LOCK(cs_vRecv, lockRecv);
456     if (lockRecv)
457         vRecv.clear();
458
459     // if this was the sync node, we'll need a new one
460     if (this == pnodeSync)
461         pnodeSync = NULL;
462 }
463
464 void CNode::Cleanup()
465 {
466 }
467
468
469 void CNode::PushVersion()
470 {
471     /// when NTP implemented, change to just nTime = GetAdjustedTime()
472     int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime());
473     CAddress addrYou, addrMe;
474
475     bool fHidden = false;
476     if (addr.IsTor()) {
477         if (mapArgs.count("-torname")) {
478             // Our hidden service address
479             CService addrTorName(mapArgs["-torname"], GetListenPort());
480
481             if (addrTorName.IsValid()) {
482                 addrYou = addr;
483                 addrMe = CAddress(addrTorName);
484                 fHidden = true;
485             }
486         }
487     }
488
489     if (!fHidden) {
490         addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
491         addrMe = GetLocalAddress(&addr);
492     }
493
494     RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
495     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());
496     PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
497                 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
498 }
499
500
501
502
503
504 std::map<CNetAddr, int64_t> CNode::setBanned;
505 CCriticalSection CNode::cs_setBanned;
506
507 void CNode::ClearBanned()
508 {
509     setBanned.clear();
510 }
511
512 bool CNode::IsBanned(CNetAddr ip)
513 {
514     bool fResult = false;
515     {
516         LOCK(cs_setBanned);
517         std::map<CNetAddr, int64_t>::iterator i = setBanned.find(ip);
518         if (i != setBanned.end())
519         {
520             int64_t t = (*i).second;
521             if (GetTime() < t)
522                 fResult = true;
523         }
524     }
525     return fResult;
526 }
527
528 bool CNode::Misbehaving(int howmuch)
529 {
530     if (addr.IsLocal())
531     {
532         printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
533         return false;
534     }
535
536     nMisbehavior += howmuch;
537     if (nMisbehavior >= GetArg("-banscore", 100))
538     {
539         int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24);  // Default 24-hour ban
540         printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
541         {
542             LOCK(cs_setBanned);
543             if (setBanned[addr] < banTime)
544                 setBanned[addr] = banTime;
545         }
546         CloseSocketDisconnect();
547         return true;
548     } else
549         printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
550     return false;
551 }
552
553 #undef X
554 #define X(name) stats.name = name
555 void CNode::copyStats(CNodeStats &stats)
556 {
557     X(nServices);
558     X(nLastSend);
559     X(nLastRecv);
560     X(nTimeConnected);
561     X(addrName);
562     X(nVersion);
563     X(strSubVer);
564     X(fInbound);
565     X(nReleaseTime);
566     X(nStartingHeight);
567     X(nMisbehavior);
568     X(nSendBytes);
569     X(nRecvBytes);
570     stats.fSyncNode = (this == pnodeSync);
571 }
572 #undef X
573
574
575
576
577
578
579
580
581
582
583 void ThreadSocketHandler(void* parg)
584 {
585     // Make this thread recognisable as the networking thread
586     RenameThread("novacoin-net");
587
588     try
589     {
590         vnThreadsRunning[THREAD_SOCKETHANDLER]++;
591         ThreadSocketHandler2(parg);
592         vnThreadsRunning[THREAD_SOCKETHANDLER]--;
593     }
594     catch (std::exception& e) {
595         vnThreadsRunning[THREAD_SOCKETHANDLER]--;
596         PrintException(&e, "ThreadSocketHandler()");
597     } catch (...) {
598         vnThreadsRunning[THREAD_SOCKETHANDLER]--;
599         throw; // support pthread_cancel()
600     }
601     printf("ThreadSocketHandler exited\n");
602 }
603
604 void ThreadSocketHandler2(void* parg)
605 {
606     printf("ThreadSocketHandler started\n");
607     list<CNode*> vNodesDisconnected;
608     unsigned int nPrevNodeCount = 0;
609
610     while (true)
611     {
612         //
613         // Disconnect nodes
614         //
615         {
616             LOCK(cs_vNodes);
617             // Disconnect unused nodes
618             vector<CNode*> vNodesCopy = vNodes;
619             BOOST_FOREACH(CNode* pnode, vNodesCopy)
620             {
621                 if (pnode->fDisconnect ||
622                     (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
623                 {
624                     // remove from vNodes
625                     vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
626
627                     // release outbound grant (if any)
628                     pnode->grantOutbound.Release();
629
630                     // close socket and cleanup
631                     pnode->CloseSocketDisconnect();
632                     pnode->Cleanup();
633
634                     // hold in disconnected pool until all refs are released
635                     pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
636                     if (pnode->fNetworkNode || pnode->fInbound)
637                         pnode->Release();
638                     vNodesDisconnected.push_back(pnode);
639                 }
640             }
641
642             // Delete disconnected nodes
643             list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
644             BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
645             {
646                 // wait until threads are done using it
647                 if (pnode->GetRefCount() <= 0)
648                 {
649                     bool fDelete = false;
650                     {
651                         TRY_LOCK(pnode->cs_vSend, lockSend);
652                         if (lockSend)
653                         {
654                             TRY_LOCK(pnode->cs_vRecv, lockRecv);
655                             if (lockRecv)
656                             {
657                                 TRY_LOCK(pnode->cs_mapRequests, lockReq);
658                                 if (lockReq)
659                                 {
660                                     TRY_LOCK(pnode->cs_inventory, lockInv);
661                                     if (lockInv)
662                                         fDelete = true;
663                                 }
664                             }
665                         }
666                     }
667                     if (fDelete)
668                     {
669                         vNodesDisconnected.remove(pnode);
670                         delete pnode;
671                     }
672                 }
673             }
674         }
675         if (vNodes.size() != nPrevNodeCount)
676         {
677             nPrevNodeCount = vNodes.size();
678             uiInterface.NotifyNumConnectionsChanged(vNodes.size());
679         }
680
681
682         //
683         // Find which sockets have data to receive
684         //
685         struct timeval timeout;
686         timeout.tv_sec  = 0;
687         timeout.tv_usec = 50000; // frequency to poll pnode->vSend
688
689         fd_set fdsetRecv;
690         fd_set fdsetSend;
691         fd_set fdsetError;
692         FD_ZERO(&fdsetRecv);
693         FD_ZERO(&fdsetSend);
694         FD_ZERO(&fdsetError);
695         SOCKET hSocketMax = 0;
696         bool have_fds = false;
697
698         BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) {
699             FD_SET(hListenSocket, &fdsetRecv);
700             hSocketMax = max(hSocketMax, hListenSocket);
701             have_fds = true;
702         }
703         {
704             LOCK(cs_vNodes);
705             BOOST_FOREACH(CNode* pnode, vNodes)
706             {
707                 if (pnode->hSocket == INVALID_SOCKET)
708                     continue;
709                 FD_SET(pnode->hSocket, &fdsetRecv);
710                 FD_SET(pnode->hSocket, &fdsetError);
711                 hSocketMax = max(hSocketMax, pnode->hSocket);
712                 have_fds = true;
713                 {
714                     TRY_LOCK(pnode->cs_vSend, lockSend);
715                     if (lockSend && !pnode->vSend.empty())
716                         FD_SET(pnode->hSocket, &fdsetSend);
717                 }
718             }
719         }
720
721         vnThreadsRunning[THREAD_SOCKETHANDLER]--;
722         int nSelect = select(have_fds ? hSocketMax + 1 : 0,
723                              &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
724         vnThreadsRunning[THREAD_SOCKETHANDLER]++;
725         if (fShutdown)
726             return;
727         if (nSelect == SOCKET_ERROR)
728         {
729             if (have_fds)
730             {
731                 int nErr = WSAGetLastError();
732                 printf("socket select error %d\n", nErr);
733                 for (unsigned int i = 0; i <= hSocketMax; i++)
734                     FD_SET(i, &fdsetRecv);
735             }
736             FD_ZERO(&fdsetSend);
737             FD_ZERO(&fdsetError);
738             Sleep(timeout.tv_usec/1000);
739         }
740
741
742         //
743         // Accept new connections
744         //
745         BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
746         if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
747         {
748 #ifdef USE_IPV6
749             struct sockaddr_storage sockaddr;
750 #else
751             struct sockaddr sockaddr;
752 #endif
753             socklen_t len = sizeof(sockaddr);
754             SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
755             CAddress addr;
756             int nInbound = 0;
757
758             if (hSocket != INVALID_SOCKET)
759                 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
760                     printf("Warning: Unknown socket family\n");
761
762             {
763                 LOCK(cs_vNodes);
764                 BOOST_FOREACH(CNode* pnode, vNodes)
765                     if (pnode->fInbound)
766                         nInbound++;
767             }
768
769             if (hSocket == INVALID_SOCKET)
770             {
771                 int nErr = WSAGetLastError();
772                 if (nErr != WSAEWOULDBLOCK)
773                     printf("socket error accept failed: %d\n", nErr);
774             }
775             else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
776             {
777                 {
778                     LOCK(cs_setservAddNodeAddresses);
779                     if (!setservAddNodeAddresses.count(addr))
780                         closesocket(hSocket);
781                 }
782             }
783             else if (CNode::IsBanned(addr))
784             {
785                 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
786                 closesocket(hSocket);
787             }
788             else
789             {
790                 printf("accepted connection %s\n", addr.ToString().c_str());
791                 CNode* pnode = new CNode(hSocket, addr, "", true);
792                 pnode->AddRef();
793                 {
794                     LOCK(cs_vNodes);
795                     vNodes.push_back(pnode);
796                 }
797             }
798         }
799
800
801         //
802         // Service each socket
803         //
804         vector<CNode*> vNodesCopy;
805         {
806             LOCK(cs_vNodes);
807             vNodesCopy = vNodes;
808             BOOST_FOREACH(CNode* pnode, vNodesCopy)
809                 pnode->AddRef();
810         }
811         BOOST_FOREACH(CNode* pnode, vNodesCopy)
812         {
813             if (fShutdown)
814                 return;
815
816             //
817             // Receive
818             //
819             if (pnode->hSocket == INVALID_SOCKET)
820                 continue;
821             if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
822             {
823                 TRY_LOCK(pnode->cs_vRecv, lockRecv);
824                 if (lockRecv)
825                 {
826                     CDataStream& vRecv = pnode->vRecv;
827                     uint64_t nPos = vRecv.size();
828
829                     if (nPos > ReceiveBufferSize()) {
830                         if (!pnode->fDisconnect)
831                             printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
832                         pnode->CloseSocketDisconnect();
833                     }
834                     else {
835                         // typical socket buffer is 8K-64K
836                         char pchBuf[0x10000];
837                         int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
838                         if (nBytes > 0)
839                         {
840                             vRecv.resize(nPos + nBytes);
841                             memcpy(&vRecv[nPos], pchBuf, nBytes);
842                             pnode->nLastRecv = GetTime();
843                             pnode->nRecvBytes += nBytes;
844                             pnode->RecordBytesRecv(nBytes);
845                         }
846                         else if (nBytes == 0)
847                         {
848                             // socket closed gracefully
849                             if (!pnode->fDisconnect)
850                                 printf("socket closed\n");
851                             pnode->CloseSocketDisconnect();
852                         }
853                         else if (nBytes < 0)
854                         {
855                             // error
856                             int nErr = WSAGetLastError();
857                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
858                             {
859                                 if (!pnode->fDisconnect)
860                                     printf("socket recv error %d\n", nErr);
861                                 pnode->CloseSocketDisconnect();
862                             }
863                         }
864                     }
865                 }
866             }
867
868             //
869             // Send
870             //
871             if (pnode->hSocket == INVALID_SOCKET)
872                 continue;
873             if (FD_ISSET(pnode->hSocket, &fdsetSend))
874             {
875                 TRY_LOCK(pnode->cs_vSend, lockSend);
876                 if (lockSend)
877                 {
878                     CDataStream& vSend = pnode->vSend;
879                     if (!vSend.empty())
880                     {
881                         int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
882                         if (nBytes > 0)
883                         {
884                             vSend.erase(vSend.begin(), vSend.begin() + nBytes);
885                             pnode->nLastSend = GetTime();
886                             pnode->nSendBytes += nBytes;
887                             pnode->RecordBytesSent(nBytes);
888                         }
889                         else if (nBytes < 0)
890                         {
891                             // error
892                             int nErr = WSAGetLastError();
893                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
894                             {
895                                 printf("socket send error %d\n", nErr);
896                                 pnode->CloseSocketDisconnect();
897                             }
898                         }
899                     }
900                 }
901             }
902
903             //
904             // Inactivity checking
905             //
906             if (pnode->vSend.empty())
907                 pnode->nLastSendEmpty = GetTime();
908             if (GetTime() - pnode->nTimeConnected > 60)
909             {
910                 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
911                 {
912                     printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
913                     pnode->fDisconnect = true;
914                 }
915                 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
916                 {
917                     printf("socket not sending\n");
918                     pnode->fDisconnect = true;
919                 }
920                 else if (GetTime() - pnode->nLastRecv > 90*60)
921                 {
922                     printf("socket inactivity timeout\n");
923                     pnode->fDisconnect = true;
924                 }
925             }
926         }
927         {
928             LOCK(cs_vNodes);
929             BOOST_FOREACH(CNode* pnode, vNodesCopy)
930                 pnode->Release();
931         }
932
933         Sleep(10);
934     }
935 }
936
937
938
939
940
941
942
943
944
945 #ifdef USE_UPNP
946 void ThreadMapPort(void* parg)
947 {
948     // Make this thread recognisable as the UPnP thread
949     RenameThread("novacoin-UPnP");
950
951     try
952     {
953         vnThreadsRunning[THREAD_UPNP]++;
954         ThreadMapPort2(parg);
955         vnThreadsRunning[THREAD_UPNP]--;
956     }
957     catch (std::exception& e) {
958         vnThreadsRunning[THREAD_UPNP]--;
959         PrintException(&e, "ThreadMapPort()");
960     } catch (...) {
961         vnThreadsRunning[THREAD_UPNP]--;
962         PrintException(NULL, "ThreadMapPort()");
963     }
964     printf("ThreadMapPort exited\n");
965 }
966
967 void ThreadMapPort2(void* parg)
968 {
969     printf("ThreadMapPort started\n");
970
971     std::string port = strprintf("%u", GetListenPort());
972     const char * multicastif = 0;
973     const char * minissdpdpath = 0;
974     struct UPNPDev * devlist = 0;
975     char lanaddr[64];
976
977 #ifndef UPNPDISCOVER_SUCCESS
978     /* miniupnpc 1.5 */
979     devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
980 #else
981     /* miniupnpc 1.6 */
982     int error = 0;
983     devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
984 #endif
985
986     struct UPNPUrls urls;
987     struct IGDdatas data;
988     int r;
989
990     r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
991     if (r == 1)
992     {
993         if (fDiscover) {
994             char externalIPAddress[40];
995             r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
996             if(r != UPNPCOMMAND_SUCCESS)
997                 printf("UPnP: GetExternalIPAddress() returned %d\n", r);
998             else
999             {
1000                 if(externalIPAddress[0])
1001                 {
1002                     printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
1003                     AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
1004                 }
1005                 else
1006                     printf("UPnP: GetExternalIPAddress failed.\n");
1007             }
1008         }
1009
1010         string strDesc = "NovaCoin " + FormatFullVersion();
1011 #ifndef UPNPDISCOVER_SUCCESS
1012         /* miniupnpc 1.5 */
1013         r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1014                             port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
1015 #else
1016         /* miniupnpc 1.6 */
1017         r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1018                             port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
1019 #endif
1020
1021         if(r!=UPNPCOMMAND_SUCCESS)
1022             printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1023                 port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
1024         else
1025             printf("UPnP Port Mapping successful.\n");
1026         int i = 1;
1027         while (true)
1028         {
1029             if (fShutdown || !fUseUPnP)
1030             {
1031                 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
1032                 printf("UPNP_DeletePortMapping() returned : %d\n", r);
1033                 freeUPNPDevlist(devlist); devlist = 0;
1034                 FreeUPNPUrls(&urls);
1035                 return;
1036             }
1037             if (i % 600 == 0) // Refresh every 20 minutes
1038             {
1039 #ifndef UPNPDISCOVER_SUCCESS
1040                 /* miniupnpc 1.5 */
1041                 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1042                                     port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
1043 #else
1044                 /* miniupnpc 1.6 */
1045                 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1046                                     port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
1047 #endif
1048
1049                 if(r!=UPNPCOMMAND_SUCCESS)
1050                     printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1051                         port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
1052                 else
1053                     printf("UPnP Port Mapping successful.\n");;
1054             }
1055             Sleep(2000);
1056             i++;
1057         }
1058     } else {
1059         printf("No valid UPnP IGDs found\n");
1060         freeUPNPDevlist(devlist); devlist = 0;
1061         if (r != 0)
1062             FreeUPNPUrls(&urls);
1063         while (true)
1064         {
1065             if (fShutdown || !fUseUPnP)
1066                 return;
1067             Sleep(2000);
1068         }
1069     }
1070 }
1071
1072 void MapPort()
1073 {
1074     if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1)
1075     {
1076         if (!NewThread(ThreadMapPort, NULL))
1077             printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
1078     }
1079 }
1080 #else
1081 void MapPort()
1082 {
1083     // Intentionally left blank.
1084 }
1085 #endif
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095 // DNS seeds
1096 // Each pair gives a source name and a seed name.
1097 // The first name is used as information source for addrman.
1098 // The second name should resolve to a list of seed addresses.
1099 static const char *strDNSSeed[][2] = {
1100     {"novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro"},
1101     {"novacoin.su", "dnsseed.novacoin.su"},
1102     {"novacoin.ru", "dnsseed.novacoin.ru"},
1103     {"novacoin.ru", "testseed.novacoin.ru"},
1104     {"novaco.in", "dnsseed.novaco.in"},
1105 };
1106
1107 void ThreadDNSAddressSeed(void* parg)
1108 {
1109     // Make this thread recognisable as the DNS seeding thread
1110     RenameThread("novacoin-dnsseed");
1111
1112     try
1113     {
1114         vnThreadsRunning[THREAD_DNSSEED]++;
1115         ThreadDNSAddressSeed2(parg);
1116         vnThreadsRunning[THREAD_DNSSEED]--;
1117     }
1118     catch (std::exception& e) {
1119         vnThreadsRunning[THREAD_DNSSEED]--;
1120         PrintException(&e, "ThreadDNSAddressSeed()");
1121     } catch (...) {
1122         vnThreadsRunning[THREAD_DNSSEED]--;
1123         throw; // support pthread_cancel()
1124     }
1125     printf("ThreadDNSAddressSeed exited\n");
1126 }
1127
1128 void ThreadDNSAddressSeed2(void* parg)
1129 {
1130     printf("ThreadDNSAddressSeed started\n");
1131     int found = 0;
1132
1133     if (!fTestNet)
1134     {
1135         printf("Loading addresses from DNS seeds (could take a while)\n");
1136
1137         for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1138             if (HaveNameProxy()) {
1139                 AddOneShot(strDNSSeed[seed_idx][1]);
1140             } else {
1141                 vector<CNetAddr> vaddr;
1142                 vector<CAddress> vAdd;
1143                 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
1144                 {
1145                     BOOST_FOREACH(CNetAddr& ip, vaddr)
1146                     {
1147                         int nOneDay = 24*3600;
1148                         CAddress addr = CAddress(CService(ip, GetDefaultPort()));
1149                         addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1150                         vAdd.push_back(addr);
1151                         found++;
1152                     }
1153                 }
1154                 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
1155             }
1156         }
1157     }
1158
1159     printf("%d addresses found from DNS seeds\n", found);
1160 }
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173 uint32_t pnSeed[] =
1174 {
1175     0xa52bf0da, 0x30aa43d8, 0x614488d5, 0x517b6fd5, 0xd4bf62d4, 0xb7d638d4, 0xbc12bcd1, 0xa2501bc6,
1176     0xfde617c6, 0x3337b1c6, 0x1dcd71c3, 0x2c1544c1, 0xe05f6ac1, 0x852f63c0, 0x3e2363c0, 0x15f563c0,
1177     0x430d63c0, 0x50d6a9c0, 0xf0a679c0, 0xefdeedbf, 0x7aaee8bc, 0x3a3dbbbc, 0xef218abc, 0x0bef78bc,
1178     0x8baa3eb2, 0x2bf913b2, 0x24ed9fb2, 0xb42289b2, 0x718a09b0, 0xe9433eb0, 0x559425b0, 0xc97e1fb0,
1179     0x18e1d4b0, 0x8f6cc1b0, 0xac3838ae, 0x86c0ffad, 0x6b0272a7, 0xa463f8a2, 0x6f17f3a2, 0xb3d6f3a2,
1180     0x9cd8f997, 0xd513fb94, 0x39e64880, 0x3859dd6f, 0x0b08fe6d, 0xe601fe6d, 0xeb44a26d, 0xfe53186c,
1181     0x203c2e68, 0x1c542868, 0x0caa8368, 0xb8748368, 0xccca4762, 0xc637555f, 0x638a545f, 0x59b2205f,
1182     0x52568c5f, 0xba568c5f, 0x8a568c5f, 0x31b0f45e, 0x54a0f45e, 0x37d6f15e, 0xc520175e, 0x7620175e,
1183     0xc310175e, 0x8e33b45e, 0x7abb5f5d, 0xd3014c5d, 0xa1e1485d, 0x9947645d, 0xfab8ff5c, 0xa979e65b,
1184     0xa879e65b, 0x9f79e65b, 0x9fa3d25b, 0x112a925b, 0x7b92905b, 0x60647a5b, 0x1e389d5a, 0x851afa59,
1185     0x0185ef59, 0x26549b59, 0x1c9efe57, 0xc54c1256, 0x1ad51955, 0x19d21955, 0x73c41955, 0x3f74ee55,
1186     0x633eea55, 0x6883d655, 0xfb72c655, 0x5360a653, 0x17c1ea52, 0xc661c852, 0x1ecdc852, 0x006a9752,
1187     0xf72d9252, 0x82650551, 0x36f1c851, 0x33f1c851, 0xd5c1864f, 0xb6bf1b4e, 0x96da184e, 0x40d0234d,
1188     0x9a96ab4c, 0x8fc2a84c, 0xb5dbd048, 0xf4644447, 0x2d51af47, 0xa9625445, 0x83f05243, 0x89672941,
1189     0x3a8bad3e, 0xf0a05436, 0x6ab7c936, 0x49971d32, 0xadd4482e, 0xcffd212e, 0x6730bc2e, 0x839aa12e,
1190     0x68d9692e, 0xc7183b25, 0x6c47bb25, 0x2490bb25, 0xad651c1f, 0x048a861f, 0x6937811f, 0x064b2d05,
1191     0x4d226805,
1192 };
1193
1194 const char* pchTorSeed[] = 
1195 {
1196     "seedp4knqnoei57u.onion",
1197     "seedr3hhlepyi7fd.onion",
1198     "seed3uuomkclbiz4.onion",
1199     "seedeh7qck3ouff5.onion",
1200     "5rg3vq4jagckeckf.onion",
1201     "seedt3sraf53ajiy.onion",
1202     "seedg4qyccsg42oq.onion",
1203     "novaqrtoywpg7jly.onion",
1204     "seed3d5wolqbgrcb.onion",
1205     "seed24u5dwph3qw4.onion",
1206     "mj26ulzbs2oskgym.onion",
1207     "eqon4usunavt76m7.onion",
1208 };
1209
1210 void DumpAddresses()
1211 {
1212     int64_t nStart = GetTimeMillis();
1213
1214     CAddrDB adb;
1215     adb.Write(addrman);
1216
1217     printf("Flushed %d addresses to peers.dat  %" PRId64 "ms\n",
1218            addrman.size(), GetTimeMillis() - nStart);
1219 }
1220
1221 void ThreadDumpAddress2(void* parg)
1222 {
1223     vnThreadsRunning[THREAD_DUMPADDRESS]++;
1224     while (!fShutdown)
1225     {
1226         DumpAddresses();
1227         vnThreadsRunning[THREAD_DUMPADDRESS]--;
1228         Sleep(600000);
1229         vnThreadsRunning[THREAD_DUMPADDRESS]++;
1230     }
1231     vnThreadsRunning[THREAD_DUMPADDRESS]--;
1232 }
1233
1234 void ThreadDumpAddress(void* parg)
1235 {
1236     // Make this thread recognisable as the address dumping thread
1237     RenameThread("novacoin-adrdump");
1238
1239     try
1240     {
1241         ThreadDumpAddress2(parg);
1242     }
1243     catch (std::exception& e) {
1244         PrintException(&e, "ThreadDumpAddress()");
1245     }
1246     printf("ThreadDumpAddress exited\n");
1247 }
1248
1249 void ThreadOpenConnections(void* parg)
1250 {
1251     // Make this thread recognisable as the connection opening thread
1252     RenameThread("novacoin-opencon");
1253
1254     try
1255     {
1256         vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1257         ThreadOpenConnections2(parg);
1258         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1259     }
1260     catch (std::exception& e) {
1261         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1262         PrintException(&e, "ThreadOpenConnections()");
1263     } catch (...) {
1264         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1265         PrintException(NULL, "ThreadOpenConnections()");
1266     }
1267     printf("ThreadOpenConnections exited\n");
1268 }
1269
1270 void static ProcessOneShot()
1271 {
1272     string strDest;
1273     {
1274         LOCK(cs_vOneShots);
1275         if (vOneShots.empty())
1276             return;
1277         strDest = vOneShots.front();
1278         vOneShots.pop_front();
1279     }
1280     CAddress addr;
1281     CSemaphoreGrant grant(*semOutbound, true);
1282     if (grant) {
1283         if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1284             AddOneShot(strDest);
1285     }
1286 }
1287
1288 // ppcoin: stake minter thread
1289 void static ThreadStakeMinter(void* parg)
1290 {
1291     printf("ThreadStakeMinter started\n");
1292     CWallet* pwallet = (CWallet*)parg;
1293     try
1294     {
1295         vnThreadsRunning[THREAD_MINTER]++;
1296         StakeMiner(pwallet);
1297         vnThreadsRunning[THREAD_MINTER]--;
1298     }
1299     catch (std::exception& e) {
1300         vnThreadsRunning[THREAD_MINTER]--;
1301         PrintException(&e, "ThreadStakeMinter()");
1302     } catch (...) {
1303         vnThreadsRunning[THREAD_MINTER]--;
1304         PrintException(NULL, "ThreadStakeMinter()");
1305     }
1306     printf("ThreadStakeMinter exiting, %d threads remaining\n", vnThreadsRunning[THREAD_MINTER]);
1307 }
1308
1309 void ThreadOpenConnections2(void* parg)
1310 {
1311     printf("ThreadOpenConnections started\n");
1312
1313     // Connect to specific addresses
1314     if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1315     {
1316         for (int64_t nLoop = 0;; nLoop++)
1317         {
1318             ProcessOneShot();
1319             BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1320             {
1321                 CAddress addr;
1322                 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1323                 for (int i = 0; i < 10 && i < nLoop; i++)
1324                 {
1325                     Sleep(500);
1326                     if (fShutdown)
1327                         return;
1328                 }
1329             }
1330             Sleep(500);
1331         }
1332     }
1333
1334     // Initiate network connections
1335     int64_t nStart = GetTime();
1336     while (true)
1337     {
1338         ProcessOneShot();
1339
1340         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1341         Sleep(500);
1342         vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1343         if (fShutdown)
1344             return;
1345
1346
1347         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1348         CSemaphoreGrant grant(*semOutbound);
1349         vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1350         if (fShutdown)
1351             return;
1352
1353         // Add seed nodes if IRC isn't working
1354         if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1355         {
1356             std::vector<CAddress> vAdd;
1357             for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1358             {
1359                 // It'll only connect to one or two seed nodes because once it connects,
1360                 // it'll get a pile of addresses with newer timestamps.
1361                 // Seed nodes are given a random 'last seen time' of between one and two
1362                 // weeks ago.
1363                 const int64_t nOneWeek = 7*24*60*60;
1364                 struct in_addr ip;
1365                 memcpy(&ip, &pnSeed[i], sizeof(ip));
1366                 CAddress addr(CService(ip, GetDefaultPort()));
1367                 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1368                 vAdd.push_back(addr);
1369             }
1370             addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1371         }
1372
1373         // Add Tor nodes if we have connection with onion router
1374         if (mapArgs.count("-tor"))
1375         {
1376             std::vector<CAddress> vAdd;
1377             for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1378             {
1379                 const int64_t nOneWeek = 7*24*60*60;
1380                 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1381                 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1382                 vAdd.push_back(addr);
1383             }
1384             addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1385         }
1386
1387         //
1388         // Choose an address to connect to based on most recently seen
1389         //
1390         CAddress addrConnect;
1391
1392         // Only connect out to one peer per network group (/16 for IPv4).
1393         // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1394         int nOutbound = 0;
1395         set<vector<unsigned char> > setConnected;
1396         {
1397             LOCK(cs_vNodes);
1398             BOOST_FOREACH(CNode* pnode, vNodes) {
1399                 if (!pnode->fInbound) {
1400                     setConnected.insert(pnode->addr.GetGroup());
1401                     nOutbound++;
1402                 }
1403             }
1404         }
1405
1406         int64_t nANow = GetAdjustedTime();
1407
1408         int nTries = 0;
1409         while (true)
1410         {
1411             // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1412             CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1413
1414             // if we selected an invalid address, restart
1415             if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1416                 break;
1417
1418             // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1419             // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1420             // already-connected network ranges, ...) before trying new addrman addresses.
1421             nTries++;
1422             if (nTries > 100)
1423                 break;
1424
1425             if (IsLimited(addr))
1426                 continue;
1427
1428             // only consider very recently tried nodes after 30 failed attempts
1429             if (nANow - addr.nLastTry < 600 && nTries < 30)
1430                 continue;
1431
1432             // do not allow non-default ports, unless after 50 invalid addresses selected already
1433             if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1434                 continue;
1435
1436             addrConnect = addr;
1437             break;
1438         }
1439
1440         if (addrConnect.IsValid())
1441             OpenNetworkConnection(addrConnect, &grant);
1442     }
1443 }
1444
1445 void ThreadOpenAddedConnections(void* parg)
1446 {
1447     // Make this thread recognisable as the connection opening thread
1448     RenameThread("novacoin-opencon");
1449
1450     try
1451     {
1452         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1453         ThreadOpenAddedConnections2(parg);
1454         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1455     }
1456     catch (std::exception& e) {
1457         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1458         PrintException(&e, "ThreadOpenAddedConnections()");
1459     } catch (...) {
1460         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1461         PrintException(NULL, "ThreadOpenAddedConnections()");
1462     }
1463     printf("ThreadOpenAddedConnections exited\n");
1464 }
1465
1466 void ThreadOpenAddedConnections2(void* parg)
1467 {
1468     printf("ThreadOpenAddedConnections started\n");
1469
1470     {
1471         LOCK(cs_vAddedNodes);
1472         vAddedNodes = mapMultiArgs["-addnode"];
1473     }
1474
1475     if (HaveNameProxy()) {
1476         while(!fShutdown) {
1477             list<string> lAddresses(0);
1478             {
1479                 LOCK(cs_vAddedNodes);
1480                 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1481                     lAddresses.push_back(strAddNode);
1482             }
1483             BOOST_FOREACH(string& strAddNode, lAddresses) {
1484                 CAddress addr;
1485                 CSemaphoreGrant grant(*semOutbound);
1486                 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1487                 Sleep(500);
1488             }
1489             vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1490             Sleep(120000); // Retry every 2 minutes
1491             vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1492         }
1493         return;
1494     }
1495
1496     for (uint32_t i = 0; true; i++)
1497     {
1498         list<string> lAddresses(0);
1499         {
1500             LOCK(cs_vAddedNodes);
1501             BOOST_FOREACH(string& strAddNode, vAddedNodes)
1502                 lAddresses.push_back(strAddNode);
1503         }
1504
1505         list<vector<CService> > lservAddressesToAdd(0);
1506         BOOST_FOREACH(string& strAddNode, lAddresses)
1507         {
1508             vector<CService> vservNode(0);
1509             if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1510             {
1511                 lservAddressesToAdd.push_back(vservNode);
1512                 {
1513                     LOCK(cs_setservAddNodeAddresses);
1514                     BOOST_FOREACH(CService& serv, vservNode)
1515                         setservAddNodeAddresses.insert(serv);
1516                 }
1517             }
1518         }
1519         // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1520         // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1521         {
1522             LOCK(cs_vNodes);
1523             BOOST_FOREACH(CNode* pnode, vNodes)
1524                 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1525                 {
1526                     BOOST_FOREACH(CService& addrNode, *(it))
1527                         if (pnode->addr == addrNode)
1528                         {
1529                             it = lservAddressesToAdd.erase(it);
1530                             if(it != lservAddressesToAdd.begin())
1531                                 it--;
1532                             break;
1533                         }
1534                     if (it == lservAddressesToAdd.end())
1535                         break;
1536                 }
1537         }
1538         BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
1539         {
1540             if (vserv.size() == 0)
1541                 continue;
1542             CSemaphoreGrant grant(*semOutbound);
1543             OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1544             Sleep(500);
1545             if (fShutdown)
1546                 return;
1547         }
1548         if (fShutdown)
1549             return;
1550         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1551         Sleep(120000); // Retry every 2 minutes
1552         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1553         if (fShutdown)
1554             return;
1555     }
1556 }
1557
1558 // if successful, this moves the passed grant to the constructed node
1559 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1560 {
1561     //
1562     // Initiate outbound network connection
1563     //
1564     if (fShutdown)
1565         return false;
1566     if (!strDest)
1567         if (IsLocal(addrConnect) ||
1568             FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1569             FindNode(addrConnect.ToStringIPPort().c_str()))
1570             return false;
1571     if (strDest && FindNode(strDest))
1572         return false;
1573
1574     vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1575     CNode* pnode = ConnectNode(addrConnect, strDest);
1576     vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1577     if (fShutdown)
1578         return false;
1579     if (!pnode)
1580         return false;
1581     if (grantOutbound)
1582         grantOutbound->MoveTo(pnode->grantOutbound);
1583     pnode->fNetworkNode = true;
1584     if (fOneShot)
1585         pnode->fOneShot = true;
1586
1587     return true;
1588 }
1589
1590 // for now, use a very simple selection metric: the node from which we received
1591 // most recently
1592 double static NodeSyncScore(const CNode *pnode) {
1593     return -pnode->nLastRecv;
1594 }
1595
1596 void static StartSync(const vector<CNode*> &vNodes) {
1597     CNode *pnodeNewSync = NULL;
1598     double dBestScore = 0;
1599
1600     // Iterate over all nodes
1601     BOOST_FOREACH(CNode* pnode, vNodes) {
1602         // check preconditions for allowing a sync
1603         if (!pnode->fClient && !pnode->fOneShot &&
1604             !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1605             (pnode->nStartingHeight > (nBestHeight - 144)) &&
1606             (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1607             // if ok, compare node's score with the best so far
1608             double dScore = NodeSyncScore(pnode);
1609             if (pnodeNewSync == NULL || dScore > dBestScore) {
1610                 pnodeNewSync = pnode;
1611                 dBestScore = dScore;
1612             }
1613         }
1614     }
1615     // if a new sync candidate was found, start sync!
1616     if (pnodeNewSync) {
1617         pnodeNewSync->fStartSync = true;
1618         pnodeSync = pnodeNewSync;
1619     }
1620 }
1621
1622 void ThreadMessageHandler(void* parg)
1623 {
1624     // Make this thread recognisable as the message handling thread
1625     RenameThread("novacoin-msghand");
1626
1627     try
1628     {
1629         vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1630         ThreadMessageHandler2(parg);
1631         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1632     }
1633     catch (std::exception& e) {
1634         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1635         PrintException(&e, "ThreadMessageHandler()");
1636     } catch (...) {
1637         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1638         PrintException(NULL, "ThreadMessageHandler()");
1639     }
1640     printf("ThreadMessageHandler exited\n");
1641 }
1642
1643 void ThreadMessageHandler2(void* parg)
1644 {
1645     printf("ThreadMessageHandler started\n");
1646     SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1647     while (!fShutdown)
1648     {
1649         bool fHaveSyncNode = false;
1650         vector<CNode*> vNodesCopy;
1651         {
1652             LOCK(cs_vNodes);
1653             vNodesCopy = vNodes;
1654             BOOST_FOREACH(CNode* pnode, vNodesCopy) {
1655                 pnode->AddRef();
1656                 if (pnode == pnodeSync)
1657                     fHaveSyncNode = true;
1658             }
1659         }
1660
1661         if (!fHaveSyncNode)
1662             StartSync(vNodesCopy);
1663
1664         // Poll the connected nodes for messages
1665         CNode* pnodeTrickle = NULL;
1666         if (!vNodesCopy.empty())
1667             pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1668         BOOST_FOREACH(CNode* pnode, vNodesCopy)
1669         {
1670             // Receive messages
1671             {
1672                 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1673                 if (lockRecv)
1674                     ProcessMessages(pnode);
1675             }
1676             if (fShutdown)
1677                 return;
1678
1679             // Send messages
1680             {
1681                 TRY_LOCK(pnode->cs_vSend, lockSend);
1682                 if (lockSend)
1683                     SendMessages(pnode, pnode == pnodeTrickle);
1684             }
1685             if (fShutdown)
1686                 return;
1687         }
1688
1689         {
1690             LOCK(cs_vNodes);
1691             BOOST_FOREACH(CNode* pnode, vNodesCopy)
1692                 pnode->Release();
1693         }
1694
1695         // Wait and allow messages to bunch up.
1696         // Reduce vnThreadsRunning so StopNode has permission to exit while
1697         // we're sleeping, but we must always check fShutdown after doing this.
1698         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1699         Sleep(100);
1700         if (fRequestShutdown)
1701             StartShutdown();
1702         vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1703         if (fShutdown)
1704             return;
1705     }
1706 }
1707
1708
1709
1710
1711
1712
1713 bool BindListenPort(const CService &addrBind, string& strError)
1714 {
1715     strError = "";
1716     int nOne = 1;
1717
1718 #ifdef WIN32
1719     // Initialize Windows Sockets
1720     WSADATA wsadata;
1721     int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1722     if (ret != NO_ERROR)
1723     {
1724         strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1725         printf("%s\n", strError.c_str());
1726         return false;
1727     }
1728 #endif
1729
1730     // Create socket for listening for incoming connections
1731 #ifdef USE_IPV6
1732     struct sockaddr_storage sockaddr;
1733 #else
1734     struct sockaddr sockaddr;
1735 #endif
1736     socklen_t len = sizeof(sockaddr);
1737     if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1738     {
1739         strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1740         printf("%s\n", strError.c_str());
1741         return false;
1742     }
1743
1744     SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1745     if (hListenSocket == INVALID_SOCKET)
1746     {
1747         strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1748         printf("%s\n", strError.c_str());
1749         return false;
1750     }
1751
1752 #ifdef SO_NOSIGPIPE
1753     // Different way of disabling SIGPIPE on BSD
1754     setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1755 #endif
1756
1757 #ifndef WIN32
1758     // Allow binding if the port is still in TIME_WAIT state after
1759     // the program was closed and restarted.  Not an issue on windows.
1760     setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1761 #endif
1762
1763
1764 #ifdef WIN32
1765     // Set to non-blocking, incoming connections will also inherit this
1766     if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1767 #else
1768     if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1769 #endif
1770     {
1771         strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1772         printf("%s\n", strError.c_str());
1773         return false;
1774     }
1775
1776 #ifdef USE_IPV6
1777     // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1778     // and enable it by default or not. Try to enable it, if possible.
1779     if (addrBind.IsIPv6()) {
1780 #ifdef IPV6_V6ONLY
1781 #ifdef WIN32
1782         setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1783 #else
1784         setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1785 #endif
1786 #endif
1787 #ifdef WIN32
1788         int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */;
1789         int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */;
1790         // this call is allowed to fail
1791         setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int));
1792 #endif
1793     }
1794 #endif
1795
1796     if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1797     {
1798         int nErr = WSAGetLastError();
1799         if (nErr == WSAEADDRINUSE)
1800             strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1801         else
1802             strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1803         printf("%s\n", strError.c_str());
1804         return false;
1805     }
1806     printf("Bound to %s\n", addrBind.ToString().c_str());
1807
1808     // Listen for incoming connections
1809     if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1810     {
1811         strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1812         printf("%s\n", strError.c_str());
1813         return false;
1814     }
1815
1816     vhListenSocket.push_back(hListenSocket);
1817
1818     if (addrBind.IsRoutable() && fDiscover)
1819         AddLocal(addrBind, LOCAL_BIND);
1820
1821     return true;
1822 }
1823
1824 void static Discover()
1825 {
1826     if (!fDiscover)
1827         return;
1828
1829 #ifdef WIN32
1830     // Get local host IP
1831     char pszHostName[1000] = "";
1832     if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1833     {
1834         vector<CNetAddr> vaddr;
1835         if (LookupHost(pszHostName, vaddr))
1836         {
1837             BOOST_FOREACH (const CNetAddr &addr, vaddr)
1838             {
1839                 AddLocal(addr, LOCAL_IF);
1840             }
1841         }
1842     }
1843 #else
1844     // Get local host ip
1845     struct ifaddrs* myaddrs;
1846     if (getifaddrs(&myaddrs) == 0)
1847     {
1848         for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1849         {
1850             if (ifa->ifa_addr == NULL) continue;
1851             if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1852             if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1853             if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1854             if (ifa->ifa_addr->sa_family == AF_INET)
1855             {
1856                 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1857                 CNetAddr addr(s4->sin_addr);
1858                 if (AddLocal(addr, LOCAL_IF))
1859                     printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1860             }
1861 #ifdef USE_IPV6
1862             else if (ifa->ifa_addr->sa_family == AF_INET6)
1863             {
1864                 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1865                 CNetAddr addr(s6->sin6_addr);
1866                 if (AddLocal(addr, LOCAL_IF))
1867                     printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1868             }
1869 #endif
1870         }
1871         freeifaddrs(myaddrs);
1872     }
1873 #endif
1874
1875     // Don't use external IPv4 discovery, when -onlynet="IPv6"
1876     if (!IsLimited(NET_IPV4))
1877         NewThread(ThreadGetMyExternalIP, NULL);
1878 }
1879
1880 void StartNode(void* parg)
1881 {
1882     // Make this thread recognisable as the startup thread
1883     RenameThread("novacoin-start");
1884
1885     if (semOutbound == NULL) {
1886         // initialize semaphore
1887         int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
1888         semOutbound = new CSemaphore(nMaxOutbound);
1889     }
1890
1891     if (pnodeLocalHost == NULL)
1892         pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
1893
1894     Discover();
1895
1896     //
1897     // Start threads
1898     //
1899
1900     if (!GetBoolArg("-dnsseed", true))
1901         printf("DNS seeding disabled\n");
1902     else
1903         if (!NewThread(ThreadDNSAddressSeed, NULL))
1904             printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1905
1906     // Map ports with UPnP
1907     if (!fUseUPnP)
1908         printf("UPNP port mapping is disabled\n");
1909     else
1910         MapPort();
1911
1912     // Get addresses from IRC and advertise ours
1913     if (!GetBoolArg("-irc", true))
1914         printf("IRC seeding disabled\n");
1915     else
1916         if (!NewThread(ThreadIRCSeed, NULL))
1917             printf("Error: NewThread(ThreadIRCSeed) failed\n");
1918
1919     // Send and receive from sockets, accept connections
1920     if (!NewThread(ThreadSocketHandler, NULL))
1921         printf("Error: NewThread(ThreadSocketHandler) failed\n");
1922
1923     // Initiate outbound connections from -addnode
1924     if (!NewThread(ThreadOpenAddedConnections, NULL))
1925         printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1926
1927     // Initiate outbound connections
1928     if (!NewThread(ThreadOpenConnections, NULL))
1929         printf("Error: NewThread(ThreadOpenConnections) failed\n");
1930
1931     // Process messages
1932     if (!NewThread(ThreadMessageHandler, NULL))
1933         printf("Error: NewThread(ThreadMessageHandler) failed\n");
1934
1935     // Dump network addresses
1936     if (!NewThread(ThreadDumpAddress, NULL))
1937         printf("Error; NewThread(ThreadDumpAddress) failed\n");
1938
1939     // ppcoin: mint proof-of-stake blocks in the background
1940     if (!NewThread(ThreadStakeMinter, pwalletMain))
1941         printf("Error: NewThread(ThreadStakeMinter) failed\n");
1942 }
1943
1944 bool StopNode()
1945 {
1946     printf("StopNode()\n");
1947     fShutdown = true;
1948     nTransactionsUpdated++;
1949     int64_t nStart = GetTime();
1950     {
1951         LOCK(cs_main);
1952         ThreadScriptCheckQuit();
1953     }
1954     if (semOutbound)
1955         for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1956             semOutbound->post();
1957     do
1958     {
1959         int nThreadsRunning = 0;
1960         for (int n = 0; n < THREAD_MAX; n++)
1961             nThreadsRunning += vnThreadsRunning[n];
1962         if (nThreadsRunning == 0)
1963             break;
1964         if (GetTime() - nStart > 20)
1965             break;
1966         Sleep(20);
1967     } while(true);
1968     if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1969     if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1970     if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1971     if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1972     if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1973 #ifdef USE_UPNP
1974     if (vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
1975 #endif
1976     if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1977     if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1978     if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1979     if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1980     if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1981     while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1982         Sleep(20);
1983     Sleep(50);
1984     DumpAddresses();
1985     return true;
1986 }
1987
1988 class CNetCleanup
1989 {
1990 public:
1991     CNetCleanup()
1992     {
1993     }
1994     ~CNetCleanup()
1995     {
1996         // Close sockets
1997         BOOST_FOREACH(CNode* pnode, vNodes)
1998             if (pnode->hSocket != INVALID_SOCKET)
1999                 closesocket(pnode->hSocket);
2000         BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
2001             if (hListenSocket != INVALID_SOCKET)
2002                 if (closesocket(hListenSocket) == SOCKET_ERROR)
2003                     printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
2004
2005 #ifdef WIN32
2006         // Shutdown Windows Sockets
2007         WSACleanup();
2008 #endif
2009     }
2010 }
2011 instance_of_cnetcleanup;
2012
2013 void RelayTransaction(const CTransaction& tx, const uint256& hash)
2014 {
2015     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2016     ss.reserve(10000);
2017     ss << tx;
2018     RelayTransaction(tx, hash, ss);
2019 }
2020
2021 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
2022 {
2023     CInv inv(MSG_TX, hash);
2024     {
2025         LOCK(cs_mapRelay);
2026         // Expire old relay messages
2027         while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
2028         {
2029             mapRelay.erase(vRelayExpiration.front().second);
2030             vRelayExpiration.pop_front();
2031         }
2032
2033         // Save original serialized message so newer versions are preserved
2034         mapRelay.insert(std::make_pair(inv, ss));
2035         vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
2036     }
2037
2038     RelayInventory(inv);
2039 }
2040
2041 void CNode::RecordBytesRecv(uint64_t bytes)
2042 {
2043     LOCK(cs_totalBytesRecv);
2044     nTotalBytesRecv += bytes;
2045 }
2046
2047 void CNode::RecordBytesSent(uint64_t bytes)
2048 {
2049     LOCK(cs_totalBytesSent);
2050     nTotalBytesSent += bytes;
2051 }
2052
2053 uint64_t CNode::GetTotalBytesRecv()
2054 {
2055     LOCK(cs_totalBytesRecv);
2056     return nTotalBytesRecv;
2057 }
2058
2059 uint64_t CNode::GetTotalBytesSent()
2060 {
2061     LOCK(cs_totalBytesSent);
2062     return nTotalBytesSent;
2063 }