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