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