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