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