Remove novacoin.su seed.
[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.ru", "dnsseed.novacoin.ru"},
1102     {"novacoin.ru", "testseed.novacoin.ru"},
1103     {"novaco.in", "dnsseed.novaco.in"},
1104 };
1105
1106 void ThreadDNSAddressSeed(void* parg)
1107 {
1108     // Make this thread recognisable as the DNS seeding thread
1109     RenameThread("novacoin-dnsseed");
1110
1111     try
1112     {
1113         vnThreadsRunning[THREAD_DNSSEED]++;
1114         ThreadDNSAddressSeed2(parg);
1115         vnThreadsRunning[THREAD_DNSSEED]--;
1116     }
1117     catch (std::exception& e) {
1118         vnThreadsRunning[THREAD_DNSSEED]--;
1119         PrintException(&e, "ThreadDNSAddressSeed()");
1120     } catch (...) {
1121         vnThreadsRunning[THREAD_DNSSEED]--;
1122         throw; // support pthread_cancel()
1123     }
1124     printf("ThreadDNSAddressSeed exited\n");
1125 }
1126
1127 void ThreadDNSAddressSeed2(void* parg)
1128 {
1129     printf("ThreadDNSAddressSeed started\n");
1130     int found = 0;
1131
1132     if (!fTestNet)
1133     {
1134         printf("Loading addresses from DNS seeds (could take a while)\n");
1135
1136         for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1137             if (HaveNameProxy()) {
1138                 AddOneShot(strDNSSeed[seed_idx][1]);
1139             } else {
1140                 vector<CNetAddr> vaddr;
1141                 vector<CAddress> vAdd;
1142                 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
1143                 {
1144                     BOOST_FOREACH(CNetAddr& ip, vaddr)
1145                     {
1146                         int nOneDay = 24*3600;
1147                         CAddress addr = CAddress(CService(ip, GetDefaultPort()));
1148                         addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1149                         vAdd.push_back(addr);
1150                         found++;
1151                     }
1152                 }
1153                 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
1154             }
1155         }
1156     }
1157
1158     printf("%d addresses found from DNS seeds\n", found);
1159 }
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172 uint32_t pnSeed[] =
1173 {
1174     0xa52bf0da, 0x30aa43d8, 0x614488d5, 0x517b6fd5, 0xd4bf62d4, 0xb7d638d4, 0xbc12bcd1, 0xa2501bc6,
1175     0xfde617c6, 0x3337b1c6, 0x1dcd71c3, 0x2c1544c1, 0xe05f6ac1, 0x852f63c0, 0x3e2363c0, 0x15f563c0,
1176     0x430d63c0, 0x50d6a9c0, 0xf0a679c0, 0xefdeedbf, 0x7aaee8bc, 0x3a3dbbbc, 0xef218abc, 0x0bef78bc,
1177     0x8baa3eb2, 0x2bf913b2, 0x24ed9fb2, 0xb42289b2, 0x718a09b0, 0xe9433eb0, 0x559425b0, 0xc97e1fb0,
1178     0x18e1d4b0, 0x8f6cc1b0, 0xac3838ae, 0x86c0ffad, 0x6b0272a7, 0xa463f8a2, 0x6f17f3a2, 0xb3d6f3a2,
1179     0x9cd8f997, 0xd513fb94, 0x39e64880, 0x3859dd6f, 0x0b08fe6d, 0xe601fe6d, 0xeb44a26d, 0xfe53186c,
1180     0x203c2e68, 0x1c542868, 0x0caa8368, 0xb8748368, 0xccca4762, 0xc637555f, 0x638a545f, 0x59b2205f,
1181     0x52568c5f, 0xba568c5f, 0x8a568c5f, 0x31b0f45e, 0x54a0f45e, 0x37d6f15e, 0xc520175e, 0x7620175e,
1182     0xc310175e, 0x8e33b45e, 0x7abb5f5d, 0xd3014c5d, 0xa1e1485d, 0x9947645d, 0xfab8ff5c, 0xa979e65b,
1183     0xa879e65b, 0x9f79e65b, 0x9fa3d25b, 0x112a925b, 0x7b92905b, 0x60647a5b, 0x1e389d5a, 0x851afa59,
1184     0x0185ef59, 0x26549b59, 0x1c9efe57, 0xc54c1256, 0x1ad51955, 0x19d21955, 0x73c41955, 0x3f74ee55,
1185     0x633eea55, 0x6883d655, 0xfb72c655, 0x5360a653, 0x17c1ea52, 0xc661c852, 0x1ecdc852, 0x006a9752,
1186     0xf72d9252, 0x82650551, 0x36f1c851, 0x33f1c851, 0xd5c1864f, 0xb6bf1b4e, 0x96da184e, 0x40d0234d,
1187     0x9a96ab4c, 0x8fc2a84c, 0xb5dbd048, 0xf4644447, 0x2d51af47, 0xa9625445, 0x83f05243, 0x89672941,
1188     0x3a8bad3e, 0xf0a05436, 0x6ab7c936, 0x49971d32, 0xadd4482e, 0xcffd212e, 0x6730bc2e, 0x839aa12e,
1189     0x68d9692e, 0xc7183b25, 0x6c47bb25, 0x2490bb25, 0xad651c1f, 0x048a861f, 0x6937811f, 0x064b2d05,
1190     0x4d226805,
1191 };
1192
1193 const char* pchTorSeed[] = 
1194 {
1195     "seedp4knqnoei57u.onion",
1196     "seedr3hhlepyi7fd.onion",
1197     "seed3uuomkclbiz4.onion",
1198     "seedeh7qck3ouff5.onion",
1199     "5rg3vq4jagckeckf.onion",
1200     "seedt3sraf53ajiy.onion",
1201     "seedg4qyccsg42oq.onion",
1202     "novaqrtoywpg7jly.onion",
1203     "seed3d5wolqbgrcb.onion",
1204     "seed24u5dwph3qw4.onion",
1205     "mj26ulzbs2oskgym.onion",
1206     "eqon4usunavt76m7.onion",
1207 };
1208
1209 void DumpAddresses()
1210 {
1211     int64_t nStart = GetTimeMillis();
1212
1213     CAddrDB adb;
1214     adb.Write(addrman);
1215
1216     printf("Flushed %d addresses to peers.dat  %" PRId64 "ms\n",
1217            addrman.size(), GetTimeMillis() - nStart);
1218 }
1219
1220 void ThreadDumpAddress2(void* parg)
1221 {
1222     vnThreadsRunning[THREAD_DUMPADDRESS]++;
1223     while (!fShutdown)
1224     {
1225         DumpAddresses();
1226         vnThreadsRunning[THREAD_DUMPADDRESS]--;
1227         Sleep(600000);
1228         vnThreadsRunning[THREAD_DUMPADDRESS]++;
1229     }
1230     vnThreadsRunning[THREAD_DUMPADDRESS]--;
1231 }
1232
1233 void ThreadDumpAddress(void* parg)
1234 {
1235     // Make this thread recognisable as the address dumping thread
1236     RenameThread("novacoin-adrdump");
1237
1238     try
1239     {
1240         ThreadDumpAddress2(parg);
1241     }
1242     catch (std::exception& e) {
1243         PrintException(&e, "ThreadDumpAddress()");
1244     }
1245     printf("ThreadDumpAddress exited\n");
1246 }
1247
1248 void ThreadOpenConnections(void* parg)
1249 {
1250     // Make this thread recognisable as the connection opening thread
1251     RenameThread("novacoin-opencon");
1252
1253     try
1254     {
1255         vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1256         ThreadOpenConnections2(parg);
1257         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1258     }
1259     catch (std::exception& e) {
1260         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1261         PrintException(&e, "ThreadOpenConnections()");
1262     } catch (...) {
1263         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1264         PrintException(NULL, "ThreadOpenConnections()");
1265     }
1266     printf("ThreadOpenConnections exited\n");
1267 }
1268
1269 void static ProcessOneShot()
1270 {
1271     string strDest;
1272     {
1273         LOCK(cs_vOneShots);
1274         if (vOneShots.empty())
1275             return;
1276         strDest = vOneShots.front();
1277         vOneShots.pop_front();
1278     }
1279     CAddress addr;
1280     CSemaphoreGrant grant(*semOutbound, true);
1281     if (grant) {
1282         if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1283             AddOneShot(strDest);
1284     }
1285 }
1286
1287 // ppcoin: stake minter thread
1288 void static ThreadStakeMinter(void* parg)
1289 {
1290     printf("ThreadStakeMinter started\n");
1291     CWallet* pwallet = (CWallet*)parg;
1292     try
1293     {
1294         vnThreadsRunning[THREAD_MINTER]++;
1295         StakeMiner(pwallet);
1296         vnThreadsRunning[THREAD_MINTER]--;
1297     }
1298     catch (std::exception& e) {
1299         vnThreadsRunning[THREAD_MINTER]--;
1300         PrintException(&e, "ThreadStakeMinter()");
1301     } catch (...) {
1302         vnThreadsRunning[THREAD_MINTER]--;
1303         PrintException(NULL, "ThreadStakeMinter()");
1304     }
1305     printf("ThreadStakeMinter exiting, %d threads remaining\n", vnThreadsRunning[THREAD_MINTER]);
1306 }
1307
1308 void ThreadOpenConnections2(void* parg)
1309 {
1310     printf("ThreadOpenConnections started\n");
1311
1312     // Connect to specific addresses
1313     if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1314     {
1315         for (int64_t nLoop = 0;; nLoop++)
1316         {
1317             ProcessOneShot();
1318             BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1319             {
1320                 CAddress addr;
1321                 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1322                 for (int i = 0; i < 10 && i < nLoop; i++)
1323                 {
1324                     Sleep(500);
1325                     if (fShutdown)
1326                         return;
1327                 }
1328             }
1329             Sleep(500);
1330         }
1331     }
1332
1333     // Initiate network connections
1334     int64_t nStart = GetTime();
1335     while (true)
1336     {
1337         ProcessOneShot();
1338
1339         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1340         Sleep(500);
1341         vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1342         if (fShutdown)
1343             return;
1344
1345
1346         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1347         CSemaphoreGrant grant(*semOutbound);
1348         vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1349         if (fShutdown)
1350             return;
1351
1352         // Add seed nodes if IRC isn't working
1353         if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1354         {
1355             std::vector<CAddress> vAdd;
1356             for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1357             {
1358                 // It'll only connect to one or two seed nodes because once it connects,
1359                 // it'll get a pile of addresses with newer timestamps.
1360                 // Seed nodes are given a random 'last seen time' of between one and two
1361                 // weeks ago.
1362                 const int64_t nOneWeek = 7*24*60*60;
1363                 struct in_addr ip;
1364                 memcpy(&ip, &pnSeed[i], sizeof(ip));
1365                 CAddress addr(CService(ip, GetDefaultPort()));
1366                 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1367                 vAdd.push_back(addr);
1368             }
1369             addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1370         }
1371
1372         // Add Tor nodes if we have connection with onion router
1373         if (mapArgs.count("-tor"))
1374         {
1375             std::vector<CAddress> vAdd;
1376             for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1377             {
1378                 const int64_t nOneWeek = 7*24*60*60;
1379                 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1380                 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1381                 vAdd.push_back(addr);
1382             }
1383             addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1384         }
1385
1386         //
1387         // Choose an address to connect to based on most recently seen
1388         //
1389         CAddress addrConnect;
1390
1391         // Only connect out to one peer per network group (/16 for IPv4).
1392         // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1393         int nOutbound = 0;
1394         set<vector<unsigned char> > setConnected;
1395         {
1396             LOCK(cs_vNodes);
1397             BOOST_FOREACH(CNode* pnode, vNodes) {
1398                 if (!pnode->fInbound) {
1399                     setConnected.insert(pnode->addr.GetGroup());
1400                     nOutbound++;
1401                 }
1402             }
1403         }
1404
1405         int64_t nANow = GetAdjustedTime();
1406
1407         int nTries = 0;
1408         while (true)
1409         {
1410             // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1411             CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1412
1413             // if we selected an invalid address, restart
1414             if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1415                 break;
1416
1417             // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1418             // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1419             // already-connected network ranges, ...) before trying new addrman addresses.
1420             nTries++;
1421             if (nTries > 100)
1422                 break;
1423
1424             if (IsLimited(addr))
1425                 continue;
1426
1427             // only consider very recently tried nodes after 30 failed attempts
1428             if (nANow - addr.nLastTry < 600 && nTries < 30)
1429                 continue;
1430
1431             // do not allow non-default ports, unless after 50 invalid addresses selected already
1432             if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1433                 continue;
1434
1435             addrConnect = addr;
1436             break;
1437         }
1438
1439         if (addrConnect.IsValid())
1440             OpenNetworkConnection(addrConnect, &grant);
1441     }
1442 }
1443
1444 void ThreadOpenAddedConnections(void* parg)
1445 {
1446     // Make this thread recognisable as the connection opening thread
1447     RenameThread("novacoin-opencon");
1448
1449     try
1450     {
1451         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1452         ThreadOpenAddedConnections2(parg);
1453         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1454     }
1455     catch (std::exception& e) {
1456         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1457         PrintException(&e, "ThreadOpenAddedConnections()");
1458     } catch (...) {
1459         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1460         PrintException(NULL, "ThreadOpenAddedConnections()");
1461     }
1462     printf("ThreadOpenAddedConnections exited\n");
1463 }
1464
1465 void ThreadOpenAddedConnections2(void* parg)
1466 {
1467     printf("ThreadOpenAddedConnections started\n");
1468
1469     {
1470         LOCK(cs_vAddedNodes);
1471         vAddedNodes = mapMultiArgs["-addnode"];
1472     }
1473
1474     if (HaveNameProxy()) {
1475         while(!fShutdown) {
1476             list<string> lAddresses(0);
1477             {
1478                 LOCK(cs_vAddedNodes);
1479                 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1480                     lAddresses.push_back(strAddNode);
1481             }
1482             BOOST_FOREACH(string& strAddNode, lAddresses) {
1483                 CAddress addr;
1484                 CSemaphoreGrant grant(*semOutbound);
1485                 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1486                 Sleep(500);
1487             }
1488             vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1489             Sleep(120000); // Retry every 2 minutes
1490             vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1491         }
1492         return;
1493     }
1494
1495     for (uint32_t i = 0; true; i++)
1496     {
1497         list<string> lAddresses(0);
1498         {
1499             LOCK(cs_vAddedNodes);
1500             BOOST_FOREACH(string& strAddNode, vAddedNodes)
1501                 lAddresses.push_back(strAddNode);
1502         }
1503
1504         list<vector<CService> > lservAddressesToAdd(0);
1505         BOOST_FOREACH(string& strAddNode, lAddresses)
1506         {
1507             vector<CService> vservNode(0);
1508             if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1509             {
1510                 lservAddressesToAdd.push_back(vservNode);
1511                 {
1512                     LOCK(cs_setservAddNodeAddresses);
1513                     BOOST_FOREACH(CService& serv, vservNode)
1514                         setservAddNodeAddresses.insert(serv);
1515                 }
1516             }
1517         }
1518         // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1519         // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1520         {
1521             LOCK(cs_vNodes);
1522             BOOST_FOREACH(CNode* pnode, vNodes)
1523                 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1524                 {
1525                     BOOST_FOREACH(CService& addrNode, *(it))
1526                         if (pnode->addr == addrNode)
1527                         {
1528                             it = lservAddressesToAdd.erase(it);
1529                             if(it != lservAddressesToAdd.begin())
1530                                 it--;
1531                             break;
1532                         }
1533                     if (it == lservAddressesToAdd.end())
1534                         break;
1535                 }
1536         }
1537         BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
1538         {
1539             if (vserv.size() == 0)
1540                 continue;
1541             CSemaphoreGrant grant(*semOutbound);
1542             OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1543             Sleep(500);
1544             if (fShutdown)
1545                 return;
1546         }
1547         if (fShutdown)
1548             return;
1549         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1550         Sleep(120000); // Retry every 2 minutes
1551         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1552         if (fShutdown)
1553             return;
1554     }
1555 }
1556
1557 // if successful, this moves the passed grant to the constructed node
1558 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1559 {
1560     //
1561     // Initiate outbound network connection
1562     //
1563     if (fShutdown)
1564         return false;
1565     if (!strDest)
1566         if (IsLocal(addrConnect) ||
1567             FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1568             FindNode(addrConnect.ToStringIPPort().c_str()))
1569             return false;
1570     if (strDest && FindNode(strDest))
1571         return false;
1572
1573     vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1574     CNode* pnode = ConnectNode(addrConnect, strDest);
1575     vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1576     if (fShutdown)
1577         return false;
1578     if (!pnode)
1579         return false;
1580     if (grantOutbound)
1581         grantOutbound->MoveTo(pnode->grantOutbound);
1582     pnode->fNetworkNode = true;
1583     if (fOneShot)
1584         pnode->fOneShot = true;
1585
1586     return true;
1587 }
1588
1589 // for now, use a very simple selection metric: the node from which we received
1590 // most recently
1591 double static NodeSyncScore(const CNode *pnode) {
1592     return -pnode->nLastRecv;
1593 }
1594
1595 void static StartSync(const vector<CNode*> &vNodes) {
1596     CNode *pnodeNewSync = NULL;
1597     double dBestScore = 0;
1598
1599     // Iterate over all nodes
1600     BOOST_FOREACH(CNode* pnode, vNodes) {
1601         // check preconditions for allowing a sync
1602         if (!pnode->fClient && !pnode->fOneShot &&
1603             !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1604             (pnode->nStartingHeight > (nBestHeight - 144)) &&
1605             (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1606             // if ok, compare node's score with the best so far
1607             double dScore = NodeSyncScore(pnode);
1608             if (pnodeNewSync == NULL || dScore > dBestScore) {
1609                 pnodeNewSync = pnode;
1610                 dBestScore = dScore;
1611             }
1612         }
1613     }
1614     // if a new sync candidate was found, start sync!
1615     if (pnodeNewSync) {
1616         pnodeNewSync->fStartSync = true;
1617         pnodeSync = pnodeNewSync;
1618     }
1619 }
1620
1621 void ThreadMessageHandler(void* parg)
1622 {
1623     // Make this thread recognisable as the message handling thread
1624     RenameThread("novacoin-msghand");
1625
1626     try
1627     {
1628         vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1629         ThreadMessageHandler2(parg);
1630         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1631     }
1632     catch (std::exception& e) {
1633         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1634         PrintException(&e, "ThreadMessageHandler()");
1635     } catch (...) {
1636         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1637         PrintException(NULL, "ThreadMessageHandler()");
1638     }
1639     printf("ThreadMessageHandler exited\n");
1640 }
1641
1642 void ThreadMessageHandler2(void* parg)
1643 {
1644     printf("ThreadMessageHandler started\n");
1645     SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1646     while (!fShutdown)
1647     {
1648         bool fHaveSyncNode = false;
1649         vector<CNode*> vNodesCopy;
1650         {
1651             LOCK(cs_vNodes);
1652             vNodesCopy = vNodes;
1653             BOOST_FOREACH(CNode* pnode, vNodesCopy) {
1654                 pnode->AddRef();
1655                 if (pnode == pnodeSync)
1656                     fHaveSyncNode = true;
1657             }
1658         }
1659
1660         if (!fHaveSyncNode)
1661             StartSync(vNodesCopy);
1662
1663         // Poll the connected nodes for messages
1664         CNode* pnodeTrickle = NULL;
1665         if (!vNodesCopy.empty())
1666             pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1667         BOOST_FOREACH(CNode* pnode, vNodesCopy)
1668         {
1669             // Receive messages
1670             {
1671                 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1672                 if (lockRecv)
1673                     ProcessMessages(pnode);
1674             }
1675             if (fShutdown)
1676                 return;
1677
1678             // Send messages
1679             {
1680                 TRY_LOCK(pnode->cs_vSend, lockSend);
1681                 if (lockSend)
1682                     SendMessages(pnode, pnode == pnodeTrickle);
1683             }
1684             if (fShutdown)
1685                 return;
1686         }
1687
1688         {
1689             LOCK(cs_vNodes);
1690             BOOST_FOREACH(CNode* pnode, vNodesCopy)
1691                 pnode->Release();
1692         }
1693
1694         // Wait and allow messages to bunch up.
1695         // Reduce vnThreadsRunning so StopNode has permission to exit while
1696         // we're sleeping, but we must always check fShutdown after doing this.
1697         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1698         Sleep(100);
1699         if (fRequestShutdown)
1700             StartShutdown();
1701         vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1702         if (fShutdown)
1703             return;
1704     }
1705 }
1706
1707
1708
1709
1710
1711
1712 bool BindListenPort(const CService &addrBind, string& strError)
1713 {
1714     strError = "";
1715     int nOne = 1;
1716
1717 #ifdef WIN32
1718     // Initialize Windows Sockets
1719     WSADATA wsadata;
1720     int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1721     if (ret != NO_ERROR)
1722     {
1723         strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1724         printf("%s\n", strError.c_str());
1725         return false;
1726     }
1727 #endif
1728
1729     // Create socket for listening for incoming connections
1730 #ifdef USE_IPV6
1731     struct sockaddr_storage sockaddr;
1732 #else
1733     struct sockaddr sockaddr;
1734 #endif
1735     socklen_t len = sizeof(sockaddr);
1736     if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1737     {
1738         strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1739         printf("%s\n", strError.c_str());
1740         return false;
1741     }
1742
1743     SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1744     if (hListenSocket == INVALID_SOCKET)
1745     {
1746         strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1747         printf("%s\n", strError.c_str());
1748         return false;
1749     }
1750
1751 #ifdef SO_NOSIGPIPE
1752     // Different way of disabling SIGPIPE on BSD
1753     setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1754 #endif
1755
1756 #ifndef WIN32
1757     // Allow binding if the port is still in TIME_WAIT state after
1758     // the program was closed and restarted.  Not an issue on windows.
1759     setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1760 #endif
1761
1762
1763 #ifdef WIN32
1764     // Set to non-blocking, incoming connections will also inherit this
1765     if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1766 #else
1767     if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1768 #endif
1769     {
1770         strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1771         printf("%s\n", strError.c_str());
1772         return false;
1773     }
1774
1775 #ifdef USE_IPV6
1776     // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1777     // and enable it by default or not. Try to enable it, if possible.
1778     if (addrBind.IsIPv6()) {
1779 #ifdef IPV6_V6ONLY
1780 #ifdef WIN32
1781         setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1782 #else
1783         setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1784 #endif
1785 #endif
1786 #ifdef WIN32
1787         int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */;
1788         int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */;
1789         // this call is allowed to fail
1790         setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int));
1791 #endif
1792     }
1793 #endif
1794
1795     if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1796     {
1797         int nErr = WSAGetLastError();
1798         if (nErr == WSAEADDRINUSE)
1799             strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1800         else
1801             strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1802         printf("%s\n", strError.c_str());
1803         return false;
1804     }
1805     printf("Bound to %s\n", addrBind.ToString().c_str());
1806
1807     // Listen for incoming connections
1808     if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1809     {
1810         strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1811         printf("%s\n", strError.c_str());
1812         return false;
1813     }
1814
1815     vhListenSocket.push_back(hListenSocket);
1816
1817     if (addrBind.IsRoutable() && fDiscover)
1818         AddLocal(addrBind, LOCAL_BIND);
1819
1820     return true;
1821 }
1822
1823 void static Discover()
1824 {
1825     if (!fDiscover)
1826         return;
1827
1828 #ifdef WIN32
1829     // Get local host IP
1830     char pszHostName[1000] = "";
1831     if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1832     {
1833         vector<CNetAddr> vaddr;
1834         if (LookupHost(pszHostName, vaddr))
1835         {
1836             BOOST_FOREACH (const CNetAddr &addr, vaddr)
1837             {
1838                 AddLocal(addr, LOCAL_IF);
1839             }
1840         }
1841     }
1842 #else
1843     // Get local host ip
1844     struct ifaddrs* myaddrs;
1845     if (getifaddrs(&myaddrs) == 0)
1846     {
1847         for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1848         {
1849             if (ifa->ifa_addr == NULL) continue;
1850             if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1851             if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1852             if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1853             if (ifa->ifa_addr->sa_family == AF_INET)
1854             {
1855                 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1856                 CNetAddr addr(s4->sin_addr);
1857                 if (AddLocal(addr, LOCAL_IF))
1858                     printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1859             }
1860 #ifdef USE_IPV6
1861             else if (ifa->ifa_addr->sa_family == AF_INET6)
1862             {
1863                 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1864                 CNetAddr addr(s6->sin6_addr);
1865                 if (AddLocal(addr, LOCAL_IF))
1866                     printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1867             }
1868 #endif
1869         }
1870         freeifaddrs(myaddrs);
1871     }
1872 #endif
1873
1874     // Don't use external IPv4 discovery, when -onlynet="IPv6"
1875     if (!IsLimited(NET_IPV4))
1876         NewThread(ThreadGetMyExternalIP, NULL);
1877 }
1878
1879 void StartNode(void* parg)
1880 {
1881     // Make this thread recognisable as the startup thread
1882     RenameThread("novacoin-start");
1883
1884     if (semOutbound == NULL) {
1885         // initialize semaphore
1886         int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
1887         semOutbound = new CSemaphore(nMaxOutbound);
1888     }
1889
1890     if (pnodeLocalHost == NULL)
1891         pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
1892
1893     Discover();
1894
1895     //
1896     // Start threads
1897     //
1898
1899     if (!GetBoolArg("-dnsseed", true))
1900         printf("DNS seeding disabled\n");
1901     else
1902         if (!NewThread(ThreadDNSAddressSeed, NULL))
1903             printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1904
1905     // Map ports with UPnP
1906     if (!fUseUPnP)
1907         printf("UPNP port mapping is disabled\n");
1908     else
1909         MapPort();
1910
1911     // Get addresses from IRC and advertise ours
1912     if (!GetBoolArg("-irc", true))
1913         printf("IRC seeding disabled\n");
1914     else
1915         if (!NewThread(ThreadIRCSeed, NULL))
1916             printf("Error: NewThread(ThreadIRCSeed) failed\n");
1917
1918     // Send and receive from sockets, accept connections
1919     if (!NewThread(ThreadSocketHandler, NULL))
1920         printf("Error: NewThread(ThreadSocketHandler) failed\n");
1921
1922     // Initiate outbound connections from -addnode
1923     if (!NewThread(ThreadOpenAddedConnections, NULL))
1924         printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1925
1926     // Initiate outbound connections
1927     if (!NewThread(ThreadOpenConnections, NULL))
1928         printf("Error: NewThread(ThreadOpenConnections) failed\n");
1929
1930     // Process messages
1931     if (!NewThread(ThreadMessageHandler, NULL))
1932         printf("Error: NewThread(ThreadMessageHandler) failed\n");
1933
1934     // Dump network addresses
1935     if (!NewThread(ThreadDumpAddress, NULL))
1936         printf("Error; NewThread(ThreadDumpAddress) failed\n");
1937
1938     // ppcoin: mint proof-of-stake blocks in the background
1939     if (!NewThread(ThreadStakeMinter, pwalletMain))
1940         printf("Error: NewThread(ThreadStakeMinter) failed\n");
1941 }
1942
1943 bool StopNode()
1944 {
1945     printf("StopNode()\n");
1946     fShutdown = true;
1947     nTransactionsUpdated++;
1948     int64_t nStart = GetTime();
1949     {
1950         LOCK(cs_main);
1951         ThreadScriptCheckQuit();
1952     }
1953     if (semOutbound)
1954         for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1955             semOutbound->post();
1956     do
1957     {
1958         int nThreadsRunning = 0;
1959         for (int n = 0; n < THREAD_MAX; n++)
1960             nThreadsRunning += vnThreadsRunning[n];
1961         if (nThreadsRunning == 0)
1962             break;
1963         if (GetTime() - nStart > 20)
1964             break;
1965         Sleep(20);
1966     } while(true);
1967     if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1968     if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1969     if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1970     if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1971     if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1972 #ifdef USE_UPNP
1973     if (vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
1974 #endif
1975     if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1976     if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1977     if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1978     if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1979     if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1980     while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1981         Sleep(20);
1982     Sleep(50);
1983     DumpAddresses();
1984     return true;
1985 }
1986
1987 class CNetCleanup
1988 {
1989 public:
1990     CNetCleanup()
1991     {
1992     }
1993     ~CNetCleanup()
1994     {
1995         // Close sockets
1996         BOOST_FOREACH(CNode* pnode, vNodes)
1997             if (pnode->hSocket != INVALID_SOCKET)
1998                 closesocket(pnode->hSocket);
1999         BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
2000             if (hListenSocket != INVALID_SOCKET)
2001                 if (closesocket(hListenSocket) == SOCKET_ERROR)
2002                     printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
2003
2004 #ifdef WIN32
2005         // Shutdown Windows Sockets
2006         WSACleanup();
2007 #endif
2008     }
2009 }
2010 instance_of_cnetcleanup;
2011
2012 void RelayTransaction(const CTransaction& tx, const uint256& hash)
2013 {
2014     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2015     ss.reserve(10000);
2016     ss << tx;
2017     RelayTransaction(tx, hash, ss);
2018 }
2019
2020 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
2021 {
2022     CInv inv(MSG_TX, hash);
2023     {
2024         LOCK(cs_mapRelay);
2025         // Expire old relay messages
2026         while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
2027         {
2028             mapRelay.erase(vRelayExpiration.front().second);
2029             vRelayExpiration.pop_front();
2030         }
2031
2032         // Save original serialized message so newer versions are preserved
2033         mapRelay.insert(std::make_pair(inv, ss));
2034         vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
2035     }
2036
2037     RelayInventory(inv);
2038 }
2039
2040 void CNode::RecordBytesRecv(uint64_t bytes)
2041 {
2042     LOCK(cs_totalBytesRecv);
2043     nTotalBytesRecv += bytes;
2044 }
2045
2046 void CNode::RecordBytesSent(uint64_t bytes)
2047 {
2048     LOCK(cs_totalBytesSent);
2049     nTotalBytesSent += bytes;
2050 }
2051
2052 uint64_t CNode::GetTotalBytesRecv()
2053 {
2054     LOCK(cs_totalBytesRecv);
2055     return nTotalBytesRecv;
2056 }
2057
2058 uint64_t CNode::GetTotalBytesSent()
2059 {
2060     LOCK(cs_totalBytesSent);
2061     return nTotalBytesSent;
2062 }