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