Merge branch '0.6.0.x' into 0.6.x
[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 = 8;
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, bool fUseGrant = true);
39
40
41
42 //
43 // Global state variables
44 //
45 bool fClient = false;
46 bool fAllowDNS = false;
47 static bool fUseUPnP = false;
48 uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
49 CAddress addrLocalHost(CService("0.0.0.0", 0), nLocalServices);
50 static CNode* pnodeLocalHost = NULL;
51 uint64 nLocalHostNonce = 0;
52 array<int, THREAD_MAX> vnThreadsRunning;
53 static SOCKET hListenSocket = INVALID_SOCKET;
54 CAddrMan addrman;
55
56 vector<CNode*> vNodes;
57 CCriticalSection cs_vNodes;
58 map<CInv, CDataStream> mapRelay;
59 deque<pair<int64, CInv> > vRelayExpiration;
60 CCriticalSection cs_mapRelay;
61 map<CInv, int64> mapAlreadyAskedFor;
62
63
64 set<CNetAddr> setservAddNodeAddresses;
65 CCriticalSection cs_setservAddNodeAddresses;
66
67 static CSemaphore *semOutbound = NULL;
68
69 unsigned short GetListenPort()
70 {
71     return (unsigned short)(GetArg("-port", GetDefaultPort()));
72 }
73
74 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
75 {
76     // Filter out duplicate requests
77     if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
78         return;
79     pindexLastGetBlocksBegin = pindexBegin;
80     hashLastGetBlocksEnd = hashEnd;
81
82     PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
83 }
84
85
86
87 bool RecvLine(SOCKET hSocket, string& strLine)
88 {
89     strLine = "";
90     loop
91     {
92         char c;
93         int nBytes = recv(hSocket, &c, 1, 0);
94         if (nBytes > 0)
95         {
96             if (c == '\n')
97                 continue;
98             if (c == '\r')
99                 return true;
100             strLine += c;
101             if (strLine.size() >= 9000)
102                 return true;
103         }
104         else if (nBytes <= 0)
105         {
106             if (fShutdown)
107                 return false;
108             if (nBytes < 0)
109             {
110                 int nErr = WSAGetLastError();
111                 if (nErr == WSAEMSGSIZE)
112                     continue;
113                 if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
114                 {
115                     Sleep(10);
116                     continue;
117                 }
118             }
119             if (!strLine.empty())
120                 return true;
121             if (nBytes == 0)
122             {
123                 // socket closed
124                 printf("socket closed\n");
125                 return false;
126             }
127             else
128             {
129                 // socket error
130                 int nErr = WSAGetLastError();
131                 printf("recv failed: %d\n", nErr);
132                 return false;
133             }
134         }
135     }
136 }
137
138
139
140 bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const char* pszKeyword, CNetAddr& ipRet)
141 {
142     SOCKET hSocket;
143     if (!ConnectSocket(addrConnect, hSocket))
144         return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
145
146     send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
147
148     string strLine;
149     while (RecvLine(hSocket, strLine))
150     {
151         if (strLine.empty()) // HTTP response is separated from headers by blank line
152         {
153             loop
154             {
155                 if (!RecvLine(hSocket, strLine))
156                 {
157                     closesocket(hSocket);
158                     return false;
159                 }
160                 if (pszKeyword == NULL)
161                     break;
162                 if (strLine.find(pszKeyword) != string::npos)
163                 {
164                     strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
165                     break;
166                 }
167             }
168             closesocket(hSocket);
169             if (strLine.find("<") != string::npos)
170                 strLine = strLine.substr(0, strLine.find("<"));
171             strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
172             while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
173                 strLine.resize(strLine.size()-1);
174             CService addr(strLine,0,true);
175             printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
176             if (!addr.IsValid() || !addr.IsRoutable())
177                 return false;
178             ipRet.SetIP(addr);
179             return true;
180         }
181     }
182     closesocket(hSocket);
183     return error("GetMyExternalIP() : connection closed");
184 }
185
186 // We now get our external IP from the IRC server first and only use this as a backup
187 bool GetMyExternalIP(CNetAddr& ipRet)
188 {
189     CService addrConnect;
190     const char* pszGet;
191     const char* pszKeyword;
192
193     if (fNoListen||fUseProxy)
194         return false;
195
196     for (int nLookup = 0; nLookup <= 1; nLookup++)
197     for (int nHost = 1; nHost <= 2; nHost++)
198     {
199         // We should be phasing out our use of sites like these.  If we need
200         // replacements, we should ask for volunteers to put this simple
201         // php file on their webserver that prints the client IP:
202         //  <?php echo $_SERVER["REMOTE_ADDR"]; ?>
203         if (nHost == 1)
204         {
205             addrConnect = CService("91.198.22.70",80); // checkip.dyndns.org
206
207             if (nLookup == 1)
208             {
209                 CService addrIP("checkip.dyndns.org", 80, true);
210                 if (addrIP.IsValid())
211                     addrConnect = addrIP;
212             }
213
214             pszGet = "GET / HTTP/1.1\r\n"
215                      "Host: checkip.dyndns.org\r\n"
216                      "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
217                      "Connection: close\r\n"
218                      "\r\n";
219
220             pszKeyword = "Address:";
221         }
222         else if (nHost == 2)
223         {
224             addrConnect = CService("74.208.43.192", 80); // www.showmyip.com
225
226             if (nLookup == 1)
227             {
228                 CService addrIP("www.showmyip.com", 80, true);
229                 if (addrIP.IsValid())
230                     addrConnect = addrIP;
231             }
232
233             pszGet = "GET /simple/ HTTP/1.1\r\n"
234                      "Host: www.showmyip.com\r\n"
235                      "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
236                      "Connection: close\r\n"
237                      "\r\n";
238
239             pszKeyword = NULL; // Returns just IP address
240         }
241
242         if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
243             return true;
244     }
245
246     return false;
247 }
248
249 void ThreadGetMyExternalIP(void* parg)
250 {
251     // Wait for IRC to get it first
252     if (GetBoolArg("-irc", false))
253     {
254         for (int i = 0; i < 2 * 60; i++)
255         {
256             Sleep(1000);
257             if (fGotExternalIP || fShutdown)
258                 return;
259         }
260     }
261
262     // Fallback in case IRC fails to get it
263     if (GetMyExternalIP(addrLocalHost))
264     {
265         printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
266         if (addrLocalHost.IsRoutable())
267         {
268             // If we already connected to a few before we had our IP, go back and addr them.
269             // setAddrKnown automatically filters any duplicate sends.
270             CAddress addr(addrLocalHost);
271             addr.nTime = GetAdjustedTime();
272             {
273                 LOCK(cs_vNodes);
274                 BOOST_FOREACH(CNode* pnode, vNodes)
275                     pnode->PushAddress(addr);
276             }
277         }
278     }
279 }
280
281
282
283
284
285 void AddressCurrentlyConnected(const CService& addr)
286 {
287     addrman.Connected(addr);
288 }
289
290
291
292
293
294
295
296 CNode* FindNode(const CNetAddr& ip)
297 {
298     {
299         LOCK(cs_vNodes);
300         BOOST_FOREACH(CNode* pnode, vNodes)
301             if ((CNetAddr)pnode->addr == ip)
302                 return (pnode);
303     }
304     return NULL;
305 }
306
307 CNode* FindNode(const CService& addr)
308 {
309     {
310         LOCK(cs_vNodes);
311         BOOST_FOREACH(CNode* pnode, vNodes)
312             if ((CService)pnode->addr == addr)
313                 return (pnode);
314     }
315     return NULL;
316 }
317
318 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
319 {
320     if ((CNetAddr)addrConnect == (CNetAddr)addrLocalHost)
321         return NULL;
322
323     // Look for an existing connection
324     CNode* pnode = FindNode((CService)addrConnect);
325     if (pnode)
326     {
327         if (nTimeout != 0)
328             pnode->AddRef(nTimeout);
329         else
330             pnode->AddRef();
331         return pnode;
332     }
333
334     /// debug print
335     printf("trying connection %s lastseen=%.1fhrs\n",
336         addrConnect.ToString().c_str(),
337         (double)(addrConnect.nTime - GetAdjustedTime())/3600.0);
338
339     addrman.Attempt(addrConnect);
340
341     // Connect
342     SOCKET hSocket;
343     if (ConnectSocket(addrConnect, hSocket))
344     {
345         /// debug print
346         printf("connected %s\n", addrConnect.ToString().c_str());
347
348         // Set to nonblocking
349 #ifdef WIN32
350         u_long nOne = 1;
351         if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
352             printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
353 #else
354         if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
355             printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
356 #endif
357
358         // Add node
359         CNode* pnode = new CNode(hSocket, addrConnect, false);
360         if (nTimeout != 0)
361             pnode->AddRef(nTimeout);
362         else
363             pnode->AddRef();
364         {
365             LOCK(cs_vNodes);
366             vNodes.push_back(pnode);
367         }
368
369         pnode->nTimeConnected = GetTime();
370         return pnode;
371     }
372     else
373     {
374         return NULL;
375     }
376 }
377
378 void CNode::CloseSocketDisconnect()
379 {
380     fDisconnect = true;
381     if (hSocket != INVALID_SOCKET)
382     {
383         if (fDebug)
384             printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
385         printf("disconnecting node %s\n", addr.ToString().c_str());
386         closesocket(hSocket);
387         hSocket = INVALID_SOCKET;
388         vRecv.clear();
389     }
390 }
391
392 void CNode::Cleanup()
393 {
394 }
395
396
397 void CNode::PushVersion()
398 {
399     /// when NTP implemented, change to just nTime = GetAdjustedTime()
400     int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
401     CAddress addrYou = (fUseProxy ? CAddress(CService("0.0.0.0",0)) : addr);
402     CAddress addrMe = (fUseProxy || !addrLocalHost.IsRoutable() ? CAddress(CService("0.0.0.0",0)) : addrLocalHost);
403     RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
404     PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
405                 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
406 }
407
408
409
410
411
412 std::map<CNetAddr, int64> CNode::setBanned;
413 CCriticalSection CNode::cs_setBanned;
414
415 void CNode::ClearBanned()
416 {
417     setBanned.clear();
418 }
419
420 bool CNode::IsBanned(CNetAddr ip)
421 {
422     bool fResult = false;
423     {
424         LOCK(cs_setBanned);
425         std::map<CNetAddr, int64>::iterator i = setBanned.find(ip);
426         if (i != setBanned.end())
427         {
428             int64 t = (*i).second;
429             if (GetTime() < t)
430                 fResult = true;
431         }
432     }
433     return fResult;
434 }
435
436 bool CNode::Misbehaving(int howmuch)
437 {
438     if (addr.IsLocal())
439     {
440         printf("Warning: local node %s misbehaving\n", addr.ToString().c_str());
441         return false;
442     }
443
444     nMisbehavior += howmuch;
445     if (nMisbehavior >= GetArg("-banscore", 100))
446     {
447         int64 banTime = GetTime()+GetArg("-bantime", 60*60*24);  // Default 24-hour ban
448         {
449             LOCK(cs_setBanned);
450             if (setBanned[addr] < banTime)
451                 setBanned[addr] = banTime;
452         }
453         CloseSocketDisconnect();
454         printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior);
455         return true;
456     }
457     return false;
458 }
459
460
461
462
463
464
465
466
467
468
469
470
471 void ThreadSocketHandler(void* parg)
472 {
473     IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
474     try
475     {
476         vnThreadsRunning[THREAD_SOCKETHANDLER]++;
477         ThreadSocketHandler2(parg);
478         vnThreadsRunning[THREAD_SOCKETHANDLER]--;
479     }
480     catch (std::exception& e) {
481         vnThreadsRunning[THREAD_SOCKETHANDLER]--;
482         PrintException(&e, "ThreadSocketHandler()");
483     } catch (...) {
484         vnThreadsRunning[THREAD_SOCKETHANDLER]--;
485         throw; // support pthread_cancel()
486     }
487     printf("ThreadSocketHandler exiting\n");
488 }
489
490 void ThreadSocketHandler2(void* parg)
491 {
492     printf("ThreadSocketHandler started\n");
493     list<CNode*> vNodesDisconnected;
494     unsigned int nPrevNodeCount = 0;
495
496     loop
497     {
498         //
499         // Disconnect nodes
500         //
501         {
502             LOCK(cs_vNodes);
503             // Disconnect unused nodes
504             vector<CNode*> vNodesCopy = vNodes;
505             BOOST_FOREACH(CNode* pnode, vNodesCopy)
506             {
507                 if (pnode->fDisconnect ||
508                     (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
509                 {
510                     // remove from vNodes
511                     vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
512
513                     if (pnode->fHasGrant)
514                         semOutbound->post();
515                     pnode->fHasGrant = false;
516
517                     // close socket and cleanup
518                     pnode->CloseSocketDisconnect();
519                     pnode->Cleanup();
520
521                     // hold in disconnected pool until all refs are released
522                     pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
523                     if (pnode->fNetworkNode || pnode->fInbound)
524                         pnode->Release();
525                     vNodesDisconnected.push_back(pnode);
526                 }
527             }
528
529             // Delete disconnected nodes
530             list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
531             BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
532             {
533                 // wait until threads are done using it
534                 if (pnode->GetRefCount() <= 0)
535                 {
536                     bool fDelete = false;
537                     {
538                         TRY_LOCK(pnode->cs_vSend, lockSend);
539                         if (lockSend)
540                         {
541                             TRY_LOCK(pnode->cs_vRecv, lockRecv);
542                             if (lockRecv)
543                             {
544                                 TRY_LOCK(pnode->cs_mapRequests, lockReq);
545                                 if (lockReq)
546                                 {
547                                     TRY_LOCK(pnode->cs_inventory, lockInv);
548                                     if (lockInv)
549                                         fDelete = true;
550                                 }
551                             }
552                         }
553                     }
554                     if (fDelete)
555                     {
556                         vNodesDisconnected.remove(pnode);
557                         delete pnode;
558                     }
559                 }
560             }
561         }
562         if (vNodes.size() != nPrevNodeCount)
563         {
564             nPrevNodeCount = vNodes.size();
565             MainFrameRepaint();
566         }
567
568
569         //
570         // Find which sockets have data to receive
571         //
572         struct timeval timeout;
573         timeout.tv_sec  = 0;
574         timeout.tv_usec = 50000; // frequency to poll pnode->vSend
575
576         fd_set fdsetRecv;
577         fd_set fdsetSend;
578         fd_set fdsetError;
579         FD_ZERO(&fdsetRecv);
580         FD_ZERO(&fdsetSend);
581         FD_ZERO(&fdsetError);
582         SOCKET hSocketMax = 0;
583
584         if(hListenSocket != INVALID_SOCKET)
585             FD_SET(hListenSocket, &fdsetRecv);
586         hSocketMax = max(hSocketMax, hListenSocket);
587         {
588             LOCK(cs_vNodes);
589             BOOST_FOREACH(CNode* pnode, vNodes)
590             {
591                 if (pnode->hSocket == INVALID_SOCKET)
592                     continue;
593                 FD_SET(pnode->hSocket, &fdsetRecv);
594                 FD_SET(pnode->hSocket, &fdsetError);
595                 hSocketMax = max(hSocketMax, pnode->hSocket);
596                 {
597                     TRY_LOCK(pnode->cs_vSend, lockSend);
598                     if (lockSend && !pnode->vSend.empty())
599                         FD_SET(pnode->hSocket, &fdsetSend);
600                 }
601             }
602         }
603
604         vnThreadsRunning[THREAD_SOCKETHANDLER]--;
605         int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
606         vnThreadsRunning[THREAD_SOCKETHANDLER]++;
607         if (fShutdown)
608             return;
609         if (nSelect == SOCKET_ERROR)
610         {
611             int nErr = WSAGetLastError();
612             if (hSocketMax != INVALID_SOCKET)
613             {
614                 printf("socket select error %d\n", nErr);
615                 for (unsigned int i = 0; i <= hSocketMax; i++)
616                     FD_SET(i, &fdsetRecv);
617             }
618             FD_ZERO(&fdsetSend);
619             FD_ZERO(&fdsetError);
620             Sleep(timeout.tv_usec/1000);
621         }
622
623
624         //
625         // Accept new connections
626         //
627         if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
628         {
629             struct sockaddr_in sockaddr;
630             socklen_t len = sizeof(sockaddr);
631             SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
632             CAddress addr;
633             int nInbound = 0;
634
635             if (hSocket != INVALID_SOCKET)
636                 addr = CAddress(sockaddr);
637
638             {
639                 LOCK(cs_vNodes);
640                 BOOST_FOREACH(CNode* pnode, vNodes)
641                     if (pnode->fInbound)
642                         nInbound++;
643             }
644
645             if (hSocket == INVALID_SOCKET)
646             {
647                 if (WSAGetLastError() != WSAEWOULDBLOCK)
648                     printf("socket error accept failed: %d\n", WSAGetLastError());
649             }
650             else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
651             {
652                 {
653                     LOCK(cs_setservAddNodeAddresses);
654                     if (!setservAddNodeAddresses.count(addr))
655                         closesocket(hSocket);
656                 }
657             }
658             else if (CNode::IsBanned(addr))
659             {
660                 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
661                 closesocket(hSocket);
662             }
663             else
664             {
665                 printf("accepted connection %s\n", addr.ToString().c_str());
666                 CNode* pnode = new CNode(hSocket, addr, true);
667                 pnode->AddRef();
668                 {
669                     LOCK(cs_vNodes);
670                     vNodes.push_back(pnode);
671                 }
672             }
673         }
674
675
676         //
677         // Service each socket
678         //
679         vector<CNode*> vNodesCopy;
680         {
681             LOCK(cs_vNodes);
682             vNodesCopy = vNodes;
683             BOOST_FOREACH(CNode* pnode, vNodesCopy)
684                 pnode->AddRef();
685         }
686         BOOST_FOREACH(CNode* pnode, vNodesCopy)
687         {
688             if (fShutdown)
689                 return;
690
691             //
692             // Receive
693             //
694             if (pnode->hSocket == INVALID_SOCKET)
695                 continue;
696             if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
697             {
698                 TRY_LOCK(pnode->cs_vRecv, lockRecv);
699                 if (lockRecv)
700                 {
701                     CDataStream& vRecv = pnode->vRecv;
702                     unsigned int nPos = vRecv.size();
703
704                     if (nPos > ReceiveBufferSize()) {
705                         if (!pnode->fDisconnect)
706                             printf("socket recv flood control disconnect (%d bytes)\n", vRecv.size());
707                         pnode->CloseSocketDisconnect();
708                     }
709                     else {
710                         // typical socket buffer is 8K-64K
711                         char pchBuf[0x10000];
712                         int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
713                         if (nBytes > 0)
714                         {
715                             vRecv.resize(nPos + nBytes);
716                             memcpy(&vRecv[nPos], pchBuf, nBytes);
717                             pnode->nLastRecv = GetTime();
718                         }
719                         else if (nBytes == 0)
720                         {
721                             // socket closed gracefully
722                             if (!pnode->fDisconnect)
723                                 printf("socket closed\n");
724                             pnode->CloseSocketDisconnect();
725                         }
726                         else if (nBytes < 0)
727                         {
728                             // error
729                             int nErr = WSAGetLastError();
730                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
731                             {
732                                 if (!pnode->fDisconnect)
733                                     printf("socket recv error %d\n", nErr);
734                                 pnode->CloseSocketDisconnect();
735                             }
736                         }
737                     }
738                 }
739             }
740
741             //
742             // Send
743             //
744             if (pnode->hSocket == INVALID_SOCKET)
745                 continue;
746             if (FD_ISSET(pnode->hSocket, &fdsetSend))
747             {
748                 TRY_LOCK(pnode->cs_vSend, lockSend);
749                 if (lockSend)
750                 {
751                     CDataStream& vSend = pnode->vSend;
752                     if (!vSend.empty())
753                     {
754                         int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
755                         if (nBytes > 0)
756                         {
757                             vSend.erase(vSend.begin(), vSend.begin() + nBytes);
758                             pnode->nLastSend = GetTime();
759                         }
760                         else if (nBytes < 0)
761                         {
762                             // error
763                             int nErr = WSAGetLastError();
764                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
765                             {
766                                 printf("socket send error %d\n", nErr);
767                                 pnode->CloseSocketDisconnect();
768                             }
769                         }
770                         if (vSend.size() > SendBufferSize()) {
771                             if (!pnode->fDisconnect)
772                                 printf("socket send flood control disconnect (%d bytes)\n", vSend.size());
773                             pnode->CloseSocketDisconnect();
774                         }
775                     }
776                 }
777             }
778
779             //
780             // Inactivity checking
781             //
782             if (pnode->vSend.empty())
783                 pnode->nLastSendEmpty = GetTime();
784             if (GetTime() - pnode->nTimeConnected > 60)
785             {
786                 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
787                 {
788                     printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
789                     pnode->fDisconnect = true;
790                 }
791                 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
792                 {
793                     printf("socket not sending\n");
794                     pnode->fDisconnect = true;
795                 }
796                 else if (GetTime() - pnode->nLastRecv > 90*60)
797                 {
798                     printf("socket inactivity timeout\n");
799                     pnode->fDisconnect = true;
800                 }
801             }
802         }
803         {
804             LOCK(cs_vNodes);
805             BOOST_FOREACH(CNode* pnode, vNodesCopy)
806                 pnode->Release();
807         }
808
809         Sleep(10);
810     }
811 }
812
813
814
815
816
817
818
819
820
821 #ifdef USE_UPNP
822 void ThreadMapPort(void* parg)
823 {
824     IMPLEMENT_RANDOMIZE_STACK(ThreadMapPort(parg));
825     try
826     {
827         vnThreadsRunning[THREAD_UPNP]++;
828         ThreadMapPort2(parg);
829         vnThreadsRunning[THREAD_UPNP]--;
830     }
831     catch (std::exception& e) {
832         vnThreadsRunning[THREAD_UPNP]--;
833         PrintException(&e, "ThreadMapPort()");
834     } catch (...) {
835         vnThreadsRunning[THREAD_UPNP]--;
836         PrintException(NULL, "ThreadMapPort()");
837     }
838     printf("ThreadMapPort exiting\n");
839 }
840
841 void ThreadMapPort2(void* parg)
842 {
843     printf("ThreadMapPort started\n");
844
845     char port[6];
846     sprintf(port, "%d", GetListenPort());
847
848     const char * multicastif = 0;
849     const char * minissdpdpath = 0;
850     struct UPNPDev * devlist = 0;
851     char lanaddr[64];
852
853 #ifndef UPNPDISCOVER_SUCCESS
854     /* miniupnpc 1.5 */
855     devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
856 #else
857     /* miniupnpc 1.6 */
858     int error = 0;
859     devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
860 #endif
861
862     struct UPNPUrls urls;
863     struct IGDdatas data;
864     int r;
865
866     r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
867     if (r == 1)
868     {
869         if (!addrLocalHost.IsRoutable())
870         {
871             char externalIPAddress[40];
872             r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
873             if(r != UPNPCOMMAND_SUCCESS)
874                 printf("UPnP: GetExternalIPAddress() returned %d\n", r);
875             else
876             {
877                 if(externalIPAddress[0])
878                 {
879                     printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
880                     CAddress addrExternalFromUPnP(CService(externalIPAddress, 0), nLocalServices);
881                     if (addrExternalFromUPnP.IsRoutable())
882                         addrLocalHost = addrExternalFromUPnP;
883                 }
884                 else
885                     printf("UPnP: GetExternalIPAddress failed.\n");
886             }
887         }
888
889         string strDesc = "Bitcoin " + FormatFullVersion();
890 #ifndef UPNPDISCOVER_SUCCESS
891         /* miniupnpc 1.5 */
892         r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
893                             port, port, lanaddr, strDesc.c_str(), "TCP", 0);
894 #else
895         /* miniupnpc 1.6 */
896         r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
897                             port, port, lanaddr, strDesc.c_str(), "TCP", 0, "0");
898 #endif
899
900         if(r!=UPNPCOMMAND_SUCCESS)
901             printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
902                 port, port, lanaddr, r, strupnperror(r));
903         else
904             printf("UPnP Port Mapping successful.\n");
905         int i = 1;
906         loop {
907             if (fShutdown || !fUseUPnP)
908             {
909                 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port, "TCP", 0);
910                 printf("UPNP_DeletePortMapping() returned : %d\n", r);
911                 freeUPNPDevlist(devlist); devlist = 0;
912                 FreeUPNPUrls(&urls);
913                 return;
914             }
915             if (i % 600 == 0) // Refresh every 20 minutes
916             {
917 #ifndef UPNPDISCOVER_SUCCESS
918                 /* miniupnpc 1.5 */
919                 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
920                                     port, port, lanaddr, strDesc.c_str(), "TCP", 0);
921 #else
922                 /* miniupnpc 1.6 */
923                 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
924                                     port, port, lanaddr, strDesc.c_str(), "TCP", 0, "0");
925 #endif
926
927                 if(r!=UPNPCOMMAND_SUCCESS)
928                     printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
929                         port, port, lanaddr, r, strupnperror(r));
930                 else
931                     printf("UPnP Port Mapping successful.\n");;
932             }
933             Sleep(2000);
934             i++;
935         }
936     } else {
937         printf("No valid UPnP IGDs found\n");
938         freeUPNPDevlist(devlist); devlist = 0;
939         if (r != 0)
940             FreeUPNPUrls(&urls);
941         loop {
942             if (fShutdown || !fUseUPnP)
943                 return;
944             Sleep(2000);
945         }
946     }
947 }
948
949 void MapPort(bool fMapPort)
950 {
951     if (fUseUPnP != fMapPort)
952     {
953         fUseUPnP = fMapPort;
954     }
955     if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1)
956     {
957         if (!CreateThread(ThreadMapPort, NULL))
958             printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
959     }
960 }
961 #else
962 void MapPort(bool /* unused fMapPort */)
963 {
964     // Intentionally left blank.
965 }
966 #endif
967
968
969
970
971
972
973
974
975
976 // DNS seeds
977 // Each pair gives a source name and a seed name.
978 // The first name is used as information source for addrman.
979 // The second name should resolve to a list of seed addresses.
980 static const char *strDNSSeed[][2] = {
981     {"xf2.org", "bitseed.xf2.org"},
982     {"bluematt.me", "dnsseed.bluematt.me"},
983     {"bitcoin.sipa.be", "seed.bitcoin.sipa.be"},
984     {"dashjr.org", "dnsseed.bitcoin.dashjr.org"},
985 };
986
987 void ThreadDNSAddressSeed(void* parg)
988 {
989     IMPLEMENT_RANDOMIZE_STACK(ThreadDNSAddressSeed(parg));
990     try
991     {
992         vnThreadsRunning[THREAD_DNSSEED]++;
993         ThreadDNSAddressSeed2(parg);
994         vnThreadsRunning[THREAD_DNSSEED]--;
995     }
996     catch (std::exception& e) {
997         vnThreadsRunning[THREAD_DNSSEED]--;
998         PrintException(&e, "ThreadDNSAddressSeed()");
999     } catch (...) {
1000         vnThreadsRunning[THREAD_DNSSEED]--;
1001         throw; // support pthread_cancel()
1002     }
1003     printf("ThreadDNSAddressSeed exiting\n");
1004 }
1005
1006 void ThreadDNSAddressSeed2(void* parg)
1007 {
1008     printf("ThreadDNSAddressSeed started\n");
1009     int found = 0;
1010
1011     if (!fTestNet)
1012     {
1013         printf("Loading addresses from DNS seeds (could take a while)\n");
1014
1015         for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1016             vector<CNetAddr> vaddr;
1017             vector<CAddress> vAdd;
1018             if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
1019             {
1020                 BOOST_FOREACH(CNetAddr& ip, vaddr)
1021                 {
1022                     int nOneDay = 24*3600;
1023                     CAddress addr = CAddress(CService(ip, GetDefaultPort()));
1024                     addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1025                     vAdd.push_back(addr);
1026                     found++;
1027                 }
1028             }
1029             addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
1030         }
1031     }
1032
1033     printf("%d addresses found from DNS seeds\n", found);
1034 }
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047 unsigned int pnSeed[] =
1048 {
1049     0x959bd347, 0xf8de42b2, 0x73bc0518, 0xea6edc50, 0x21b00a4d, 0xc725b43d, 0xd665464d, 0x1a2a770e,
1050     0x27c93946, 0x65b2fa46, 0xb80ae255, 0x66b3b446, 0xb1877a3e, 0x6ee89e3e, 0xc3175b40, 0x2a01a83c,
1051     0x95b1363a, 0xa079ad3d, 0xe6ca801f, 0x027f4f4a, 0x34f7f03a, 0xf790f04a, 0x16ca801f, 0x2f4d5e40,
1052     0x3a4d5e40, 0xc43a322e, 0xc8159753, 0x14d4724c, 0x7919a118, 0xe0bdb34e, 0x68a16b2e, 0xff64b44d,
1053     0x6099115b, 0x9b57b05b, 0x7bd1b4ad, 0xdf95944f, 0x29d2b73d, 0xafa8db79, 0xe247ba41, 0x24078348,
1054     0xf722f03c, 0x33567ebc, 0xace64ed4, 0x984d3932, 0xb5f34e55, 0x27b7024d, 0x94579247, 0x8894042e,
1055     0x9357d34c, 0x1063c24b, 0xcaa228b1, 0xa3c5a8b2, 0x5dc64857, 0xa2c23643, 0xa8369a54, 0x31203077,
1056     0x00707c5c, 0x09fc0b3a, 0x272e9e2e, 0xf80f043e, 0x9449ca3e, 0x5512c33e, 0xd106b555, 0xe8024157,
1057     0xe288ec29, 0xc79c5461, 0xafb63932, 0xdb02ab4b, 0x0e512777, 0x8a145a4c, 0xb201ff4f, 0x5e09314b,
1058     0xcd9bfbcd, 0x1c023765, 0x4394e75c, 0xa728bd4d, 0x65331552, 0xa98420b1, 0x89ecf559, 0x6e80801f,
1059     0xf404f118, 0xefd62b51, 0x05918346, 0x9b186d5f, 0xacabab46, 0xf912e255, 0xc188ea62, 0xcc55734e,
1060     0xc668064d, 0xd77a4558, 0x46201c55, 0xf17dfc80, 0xf7142f2e, 0x87bfb718, 0x8aa54fb2, 0xc451d518,
1061     0xc4ae8831, 0x8dd44d55, 0x5bbd206c, 0x64536b5d, 0x5c667e60, 0x3b064242, 0xfe963a42, 0xa28e6dc8,
1062     0xe8a9604a, 0xc989464e, 0xd124a659, 0x50065140, 0xa44dfe5e, 0x1079e655, 0x3fb986d5, 0x47895b18,
1063     0x7d3ce4ad, 0x4561ba50, 0x296eec62, 0x255b41ad, 0xaed35ec9, 0x55556f12, 0xc7d3154d, 0x3297b65d,
1064     0x8930121f, 0xabf42e4e, 0x4a29e044, 0x1212685d, 0x676c1e40, 0xce009744, 0x383a8948, 0xa2dbd0ad,
1065     0xecc2564d, 0x07dbc252, 0x887ee24b, 0x5171644c, 0x6bb798c1, 0x847f495d, 0x4cbb7145, 0x3bb81c32,
1066     0x45eb262e, 0xc8015a4e, 0x250a361b, 0xf694f946, 0xd64a183e, 0xd4f1dd59, 0x8f20ffd4, 0x51d9e55c,
1067     0x09521763, 0x5e02002e, 0x32c8074d, 0xe685762e, 0x8290b0bc, 0x762a922e, 0xfc5ee754, 0x83a24829,
1068     0x775b224d, 0x6295bb4d, 0x38ec0555, 0xbffbba50, 0xe5560260, 0x86b16a7c, 0xd372234e, 0x49a3c24b,
1069     0x2f6a171f, 0x4d75ed60, 0xae94115b, 0xcb543744, 0x63080c59, 0x3f9c724c, 0xc977ce18, 0x532efb18,
1070     0x69dc3b2e, 0x5f94d929, 0x1732bb4d, 0x9c814b4d, 0xe6b3762e, 0xc024f662, 0x8face35b, 0x6b5b044d,
1071     0x798c7b57, 0x79a6b44c, 0x067d3057, 0xf9e94e5f, 0x91cbe15b, 0x71405eb2, 0x2662234e, 0xcbcc4a6d,
1072     0xbf69d54b, 0xa79b4e55, 0xec6d3e51, 0x7c0b3c02, 0x60f83653, 0x24c1e15c, 0x1110b62e, 0x10350f59,
1073     0xa56f1d55, 0x3509e7a9, 0xeb128354, 0x14268e2e, 0x934e28bc, 0x8e32692e, 0x8331a21f, 0x3e633932,
1074     0xc812b12e, 0xc684bf2e, 0x80112d2e, 0xe0ddc96c, 0xc630ca4a, 0x5c09b3b2, 0x0b580518, 0xc8e9d54b,
1075     0xd169aa43, 0x17d0d655, 0x1d029963, 0x7ff87559, 0xcb701f1f, 0x6fa3e85d, 0xe45e9a54, 0xf05d1802,
1076     0x44d03b2e, 0x837b692e, 0xccd4354e, 0x3d6da13c, 0x3423084d, 0xf707c34a, 0x55f6db3a, 0xad26e442,
1077     0x6233a21f, 0x09e80e59, 0x8caeb54d, 0xbe870941, 0xb407d20e, 0x20b51018, 0x56fb152e, 0x460d2a4e,
1078     0xbb9a2946, 0x560eb12e, 0xed83dd29, 0xd6724f53, 0xa50aafb8, 0x451346d9, 0x88348e2e, 0x7312fead,
1079     0x8ecaf96f, 0x1bda4e5f, 0xf1671e40, 0x3c8c3e3b, 0x4716324d, 0xdde24ede, 0xf98cd17d, 0xa91d4644,
1080     0x28124eb2, 0x147d5129, 0xd022042e, 0x61733d3b, 0xad0d5e02, 0x8ce2932e, 0xe5c18502, 0x549c1e32,
1081     0x9685801f, 0x86e217ad, 0xd948214b, 0x4110f462, 0x3a2e894e, 0xbd35492e, 0x87e0d558, 0x64b8ef7d,
1082     0x7c3eb962, 0x72a84b3e, 0x7cd667c9, 0x28370a2e, 0x4bc60e7b, 0x6fc1ec60, 0x14a6983f, 0x86739a4b,
1083     0x46954e5f, 0x32e2e15c, 0x2e9326cf, 0xe5801c5e, 0x379607b2, 0x32151145, 0xf0e39744, 0xacb54c55,
1084     0xa37dfb60, 0x83b55cc9, 0x388f7ca5, 0x15034f5f, 0x3e94965b, 0x68e0ffad, 0x35280f59, 0x8fe190cf,
1085     0x7c6ba5b2, 0xa5e9db43, 0x4ee1fc60, 0xd9d94e5f, 0x04040677, 0x0ea9b35e, 0x5961f14f, 0x67fda063,
1086     0xa48a5a31, 0xc6524e55, 0x283d325e, 0x3f37515f, 0x96b94b3e, 0xacce620e, 0x6481cc5b, 0xa4a06d4b,
1087     0x9e95d2d9, 0xe40c03d5, 0xc2f4514b, 0xb79aad44, 0xf64be843, 0xb2064070, 0xfca00455, 0x429dfa4e,
1088     0x2323f173, 0xeda4185e, 0xabd5227d, 0x9efd4d58, 0xb1104758, 0x4811e955, 0xbd9ab355, 0xe921f44b,
1089     0x9f166dce, 0x09e279b2, 0xe0c9ac7b, 0x7901a5ad, 0xa145d4b0, 0x79104671, 0xec31e35a, 0x4fe0b555,
1090     0xc7d9cbad, 0xad057f55, 0xe94cc759, 0x7fe0b043, 0xe4529f2e, 0x0d4dd4b2, 0x9f11a54d, 0x031e2e4e,
1091     0xe6014f5f, 0x11d1ca6c, 0x26bd7f61, 0xeb86854f, 0x4d347b57, 0x116bbe2e, 0xdba7234e, 0x7bcbfd2e,
1092     0x174dd4b2, 0x6686762e, 0xb089ba50, 0xc6258246, 0x087e767b, 0xc4a8cb4a, 0x595dba50, 0x7f0ae502,
1093     0x7b1dbd5a, 0xa0603492, 0x57d1af4b, 0x9e21ffd4, 0x6393064d, 0x7407376e, 0xe484762e, 0x122a4e53,
1094     0x4a37aa43, 0x3888a6be, 0xee77864e, 0x039c8dd5, 0x688d89af, 0x0e988f62, 0x08218246, 0xfc2f8246,
1095     0xd1d97040, 0xd64cd4b2, 0x5ae4a6b8, 0x7d0de9bc, 0x8d304d61, 0x06c5c672, 0xa4c8bd4d, 0xe0fd373b,
1096     0x575ebe4d, 0x72d26277, 0x55570f55, 0x77b154d9, 0xe214293a, 0xfc740f4b, 0xfe3f6a57, 0xa9c55f02,
1097     0xae4054db, 0x2394d918, 0xb511b24a, 0xb8741ab2, 0x0758e65e, 0xc7b5795b, 0xb0a30a4c, 0xaf7f170c,
1098     0xf3b4762e, 0x8179576d, 0x738a1581, 0x4b95b64c, 0x9829b618, 0x1bea932e, 0x7bdeaa4b, 0xcb5e0281,
1099     0x65618f54, 0x0658474b, 0x27066acf, 0x40556d65, 0x7d204d53, 0xf28bc244, 0xdce23455, 0xadc0ff54,
1100     0x3863c948, 0xcee34e5f, 0xdeb85e02, 0x2ed17a61, 0x6a7b094d, 0x7f0cfc40, 0x59603f54, 0x3220afbc,
1101     0xb5dfd962, 0x125d21c0, 0x13f8d243, 0xacfefb4e, 0x86c2c147, 0x3d8bbd59, 0xbd02a21f, 0x2593042e,
1102     0xc6a17a7c, 0x28925861, 0xb487ed44, 0xb5f4fd6d, 0x90c28a45, 0x5a14f74d, 0x43d71b4c, 0x728ebb5d,
1103     0x885bf950, 0x08134dd0, 0x38ec046e, 0xc575684b, 0x50082d2e, 0xa2f47757, 0x270f86ae, 0xf3ff6462,
1104     0x10ed3f4e, 0x4b58d462, 0xe01ce23e, 0x8c5b092e, 0x63e52f4e, 0x22c1e85d, 0xa908f54e, 0x8591624f,
1105     0x2c0fb94e, 0xa280ba3c, 0xb6f41b4c, 0x24f9aa47, 0x27201647, 0x3a3ea6dc, 0xa14fc3be, 0x3c34bdd5,
1106     0x5b8d4f5b, 0xaadeaf4b, 0xc71cab50, 0x15697a4c, 0x9a1a734c, 0x2a037d81, 0x2590bd59, 0x48ec2741,
1107     0x53489c5b, 0x7f00314b, 0x2170d362, 0xf2e92542, 0x42c10b44, 0x98f0f118, 0x883a3456, 0x099a932e,
1108     0xea38f7bc, 0x644e9247, 0xbb61b62e, 0x30e0863d, 0x5f51be54, 0x207215c7, 0x5f306c45, 0xaa7f3932,
1109     0x98da7d45, 0x4e339b59, 0x2e411581, 0xa808f618, 0xad2c0c59, 0x54476741, 0x09e99fd1, 0x5db8f752,
1110     0xc16df8bd, 0x1dd4b44f, 0x106edf2e, 0x9e15c180, 0x2ad6b56f, 0x633a5332, 0xff33787c, 0x077cb545,
1111     0x6610be6d, 0x75aad2c4, 0x72fb4d5b, 0xe81e0f59, 0x576f6332, 0x47333373, 0x351ed783, 0x2d90fb50,
1112     0x8d5e0f6c, 0x5b27a552, 0xdb293ebb, 0xe55ef950, 0x4b133ad8, 0x75df975a, 0x7b6a8740, 0xa899464b,
1113     0xfab15161, 0x10f8b64d, 0xd055ea4d, 0xee8e146b, 0x4b14afb8, 0x4bc1c44a, 0x9b961dcc, 0xd111ff43,
1114     0xfca0b745, 0xc800e412, 0x0afad9d1, 0xf751c350, 0xf9f0cccf, 0xa290a545, 0x8ef13763, 0x7ec70d59,
1115     0x2b066acf, 0x65496c45, 0xade02c1b, 0xae6eb077, 0x92c1e65b, 0xc064e6a9, 0xc649e56d, 0x5287a243,
1116     0x36de4f5b, 0x5b1df6ad, 0x65c39a59, 0xdba805b2, 0x20067aa8, 0x6457e56d, 0x3cee26cf, 0xfd3ff26d,
1117     0x04f86d4a, 0x06b8e048, 0xa93bcd5c, 0x91135852, 0xbe90a643, 0x8fa0094d, 0x06d8215f, 0x2677094d,
1118     0xd735685c, 0x164a00c9, 0x5209ac5f, 0xa9564c5c, 0x3b504f5f, 0xcc826bd0, 0x4615042e, 0x5fe13b4a,
1119     0x8c81b86d, 0x879ab68c, 0x1de564b8, 0x434487d8, 0x2dcb1b63, 0x82ab524a, 0xb0676abb, 0xa13d9c62,
1120     0xdbb5b86d, 0x5b7f4b59, 0xaddfb44d, 0xad773532, 0x3997054c, 0x72cebd89, 0xb194544c, 0xc5b8046e,
1121     0x6e1adeb2, 0xaa5abb51, 0xefb54b44, 0x15efc54f, 0xe9f1bc4d, 0x5f401b6c, 0x97f018ad, 0xc82f9252,
1122     0x2cdc762e, 0x8e52e56d, 0x1827175e, 0x9b7d7d80, 0xb2ad6845, 0x51065140, 0x71180a18, 0x5b27006c,
1123     0x0621e255, 0x721cbe58, 0x670c0cb8, 0xf8bd715d, 0xe0bdc5d9, 0xed843501, 0x4b84554d, 0x7f1a18bc,
1124     0x53bcaf47, 0x5729d35f, 0xf0dda246, 0x22382bd0, 0x4d641fb0, 0x316afcde, 0x50a22f1f, 0x73608046,
1125     0xc461d84a, 0xb2dbe247,
1126 };
1127
1128 void DumpAddresses()
1129 {
1130     CAddrDB adb;
1131     adb.WriteAddrman(addrman);
1132 }
1133
1134 void ThreadDumpAddress2(void* parg)
1135 {
1136     vnThreadsRunning[THREAD_DUMPADDRESS]++;
1137     while (!fShutdown)
1138     {
1139         DumpAddresses();
1140         vnThreadsRunning[THREAD_DUMPADDRESS]--;
1141         Sleep(100000);
1142         vnThreadsRunning[THREAD_DUMPADDRESS]++;
1143     }
1144     vnThreadsRunning[THREAD_DUMPADDRESS]--;
1145 }
1146
1147 void ThreadDumpAddress(void* parg)
1148 {
1149     IMPLEMENT_RANDOMIZE_STACK(ThreadDumpAddress(parg));
1150     try
1151     {
1152         ThreadDumpAddress2(parg);
1153     }
1154     catch (std::exception& e) {
1155         PrintException(&e, "ThreadDumpAddress()");
1156     }
1157     printf("ThreadDumpAddress exiting\n");
1158 }
1159
1160 void ThreadOpenConnections(void* parg)
1161 {
1162     IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
1163     try
1164     {
1165         vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1166         ThreadOpenConnections2(parg);
1167         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1168     }
1169     catch (std::exception& e) {
1170         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1171         PrintException(&e, "ThreadOpenConnections()");
1172     } catch (...) {
1173         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1174         PrintException(NULL, "ThreadOpenConnections()");
1175     }
1176     printf("ThreadOpenConnections exiting\n");
1177 }
1178
1179 void ThreadOpenConnections2(void* parg)
1180 {
1181     printf("ThreadOpenConnections started\n");
1182
1183     // Connect to specific addresses
1184     if (mapArgs.count("-connect"))
1185     {
1186         for (int64 nLoop = 0;; nLoop++)
1187         {
1188             BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1189             {
1190                 CAddress addr(CService(strAddr, GetDefaultPort(), fAllowDNS));
1191                 if (addr.IsValid())
1192                     OpenNetworkConnection(addr, false);
1193                 for (int i = 0; i < 10 && i < nLoop; i++)
1194                 {
1195                     Sleep(500);
1196                     if (fShutdown)
1197                         return;
1198                 }
1199             }
1200         }
1201     }
1202
1203     // Initiate network connections
1204     int64 nStart = GetTime();
1205     loop
1206     {
1207         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1208         Sleep(500);
1209         vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1210         if (fShutdown)
1211             return;
1212
1213
1214         vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1215         semOutbound->wait();
1216         vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1217         if (fShutdown)
1218             return;
1219
1220         // Add seed nodes if IRC isn't working
1221         bool fTOR = (fUseProxy && addrProxy.GetPort() == 9050);
1222         if (addrman.size()==0 && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
1223         {
1224             std::vector<CAddress> vAdd;
1225             for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1226             {
1227                 // It'll only connect to one or two seed nodes because once it connects,
1228                 // it'll get a pile of addresses with newer timestamps.
1229                 // Seed nodes are given a random 'last seen time' of between one and two
1230                 // weeks ago.
1231                 const int64 nOneWeek = 7*24*60*60;
1232                 struct in_addr ip;
1233                 memcpy(&ip, &pnSeed[i], sizeof(ip));
1234                 CAddress addr(CService(ip, GetDefaultPort()));
1235                 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1236                 vAdd.push_back(addr);
1237             }
1238             addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1239         }
1240
1241         //
1242         // Choose an address to connect to based on most recently seen
1243         //
1244         CAddress addrConnect;
1245
1246         // Only connect to one address per a.b.?.? range.
1247         // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1248         int nOutbound = 0;
1249         set<vector<unsigned char> > setConnected;
1250         {
1251             LOCK(cs_vNodes);
1252             BOOST_FOREACH(CNode* pnode, vNodes) {
1253                 setConnected.insert(pnode->addr.GetGroup());
1254                 if (!pnode->fInbound)
1255                     nOutbound++;
1256             }
1257         }
1258
1259         int64 nANow = GetAdjustedTime();
1260
1261         int nTries = 0;
1262         loop
1263         {
1264             // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1265             CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1266
1267             // if we selected an invalid address, restart
1268             if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.GetGroup()) || addr == addrLocalHost)
1269                 break;
1270
1271             nTries++;
1272
1273             // only consider very recently tried nodes after 30 failed attempts
1274             if (nANow - addr.nLastTry < 600 && nTries < 30)
1275                 continue;
1276
1277             // do not allow non-default ports, unless after 50 invalid addresses selected already
1278             if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1279                 continue;
1280
1281             addrConnect = addr;
1282             break;
1283         }
1284
1285         if (addrConnect.IsValid())
1286             OpenNetworkConnection(addrConnect);
1287         else
1288             semOutbound->post();
1289     }
1290 }
1291
1292 void ThreadOpenAddedConnections(void* parg)
1293 {
1294     IMPLEMENT_RANDOMIZE_STACK(ThreadOpenAddedConnections(parg));
1295     try
1296     {
1297         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1298         ThreadOpenAddedConnections2(parg);
1299         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1300     }
1301     catch (std::exception& e) {
1302         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1303         PrintException(&e, "ThreadOpenAddedConnections()");
1304     } catch (...) {
1305         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1306         PrintException(NULL, "ThreadOpenAddedConnections()");
1307     }
1308     printf("ThreadOpenAddedConnections exiting\n");
1309 }
1310
1311 void ThreadOpenAddedConnections2(void* parg)
1312 {
1313     printf("ThreadOpenAddedConnections started\n");
1314
1315     if (mapArgs.count("-addnode") == 0)
1316         return;
1317
1318     vector<vector<CService> > vservAddressesToAdd(0);
1319     BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"])
1320     {
1321         vector<CService> vservNode(0);
1322         if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fAllowDNS, 0))
1323         {
1324             vservAddressesToAdd.push_back(vservNode);
1325             {
1326                 LOCK(cs_setservAddNodeAddresses);
1327                 BOOST_FOREACH(CService& serv, vservNode)
1328                     setservAddNodeAddresses.insert(serv);
1329             }
1330         }
1331     }
1332     loop
1333     {
1334         vector<vector<CService> > vservConnectAddresses = vservAddressesToAdd;
1335         // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1336         // (keeping in mind that addnode entries can have many IPs if fAllowDNS)
1337         {
1338             LOCK(cs_vNodes);
1339             BOOST_FOREACH(CNode* pnode, vNodes)
1340                 for (vector<vector<CService> >::iterator it = vservConnectAddresses.begin(); it != vservConnectAddresses.end(); it++)
1341                     BOOST_FOREACH(CService& addrNode, *(it))
1342                         if (pnode->addr == addrNode)
1343                         {
1344                             it = vservConnectAddresses.erase(it);
1345                             it--;
1346                             break;
1347                         }
1348         }
1349         BOOST_FOREACH(vector<CService>& vserv, vservConnectAddresses)
1350         {
1351             semOutbound->wait();
1352             OpenNetworkConnection(CAddress(*(vserv.begin())));
1353             Sleep(500);
1354             if (fShutdown)
1355                 return;
1356         }
1357         if (fShutdown)
1358             return;
1359         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1360         Sleep(120000); // Retry every 2 minutes
1361         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1362         if (fShutdown)
1363             return;
1364     }
1365 }
1366
1367 bool static ReleaseGrant(bool fUseGrant) {
1368     if (fUseGrant)
1369         semOutbound->post();
1370     return false;
1371 }
1372
1373 // only call this function when semOutbound has been waited for
1374 bool OpenNetworkConnection(const CAddress& addrConnect, bool fUseGrant)
1375 {
1376     //
1377     // Initiate outbound network connection
1378     //
1379     if (fShutdown)
1380         return false;
1381     if ((CNetAddr)addrConnect == (CNetAddr)addrLocalHost || !addrConnect.IsIPv4() ||
1382         FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect))
1383         return ReleaseGrant(fUseGrant);
1384
1385     vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1386     CNode* pnode = ConnectNode(addrConnect);
1387     vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1388     if (fShutdown)
1389         return false;
1390     if (!pnode)
1391         return ReleaseGrant(fUseGrant);
1392     if (pnode->fHasGrant) {
1393         // node already has connection grant, release the one that was passed to us
1394         ReleaseGrant(fUseGrant);
1395     } else {
1396         pnode->fHasGrant = fUseGrant;
1397     }
1398     pnode->fNetworkNode = true;
1399
1400     return true;
1401 }
1402
1403
1404
1405
1406
1407
1408
1409
1410 void ThreadMessageHandler(void* parg)
1411 {
1412     IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
1413     try
1414     {
1415         vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1416         ThreadMessageHandler2(parg);
1417         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1418     }
1419     catch (std::exception& e) {
1420         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1421         PrintException(&e, "ThreadMessageHandler()");
1422     } catch (...) {
1423         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1424         PrintException(NULL, "ThreadMessageHandler()");
1425     }
1426     printf("ThreadMessageHandler exiting\n");
1427 }
1428
1429 void ThreadMessageHandler2(void* parg)
1430 {
1431     printf("ThreadMessageHandler started\n");
1432     SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1433     while (!fShutdown)
1434     {
1435         vector<CNode*> vNodesCopy;
1436         {
1437             LOCK(cs_vNodes);
1438             vNodesCopy = vNodes;
1439             BOOST_FOREACH(CNode* pnode, vNodesCopy)
1440                 pnode->AddRef();
1441         }
1442
1443         // Poll the connected nodes for messages
1444         CNode* pnodeTrickle = NULL;
1445         if (!vNodesCopy.empty())
1446             pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1447         BOOST_FOREACH(CNode* pnode, vNodesCopy)
1448         {
1449             // Receive messages
1450             {
1451                 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1452                 if (lockRecv)
1453                     ProcessMessages(pnode);
1454             }
1455             if (fShutdown)
1456                 return;
1457
1458             // Send messages
1459             {
1460                 TRY_LOCK(pnode->cs_vSend, lockSend);
1461                 if (lockSend)
1462                     SendMessages(pnode, pnode == pnodeTrickle);
1463             }
1464             if (fShutdown)
1465                 return;
1466         }
1467
1468         {
1469             LOCK(cs_vNodes);
1470             BOOST_FOREACH(CNode* pnode, vNodesCopy)
1471                 pnode->Release();
1472         }
1473
1474         // Wait and allow messages to bunch up.
1475         // Reduce vnThreadsRunning so StopNode has permission to exit while
1476         // we're sleeping, but we must always check fShutdown after doing this.
1477         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1478         Sleep(100);
1479         if (fRequestShutdown)
1480             StartShutdown();
1481         vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1482         if (fShutdown)
1483             return;
1484     }
1485 }
1486
1487
1488
1489
1490
1491
1492 bool BindListenPort(string& strError)
1493 {
1494     strError = "";
1495     int nOne = 1;
1496     addrLocalHost.SetPort(GetListenPort());
1497
1498 #ifdef WIN32
1499     // Initialize Windows Sockets
1500     WSADATA wsadata;
1501     int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1502     if (ret != NO_ERROR)
1503     {
1504         strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1505         printf("%s\n", strError.c_str());
1506         return false;
1507     }
1508 #endif
1509
1510     // Create socket for listening for incoming connections
1511     hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1512     if (hListenSocket == INVALID_SOCKET)
1513     {
1514         strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1515         printf("%s\n", strError.c_str());
1516         return false;
1517     }
1518
1519 #ifdef SO_NOSIGPIPE
1520     // Different way of disabling SIGPIPE on BSD
1521     setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1522 #endif
1523
1524 #ifndef WIN32
1525     // Allow binding if the port is still in TIME_WAIT state after
1526     // the program was closed and restarted.  Not an issue on windows.
1527     setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1528 #endif
1529
1530 #ifdef WIN32
1531     // Set to nonblocking, incoming connections will also inherit this
1532     if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1533 #else
1534     if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1535 #endif
1536     {
1537         strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1538         printf("%s\n", strError.c_str());
1539         return false;
1540     }
1541
1542     // The sockaddr_in structure specifies the address family,
1543     // IP address, and port for the socket that is being bound
1544     struct sockaddr_in sockaddr;
1545     memset(&sockaddr, 0, sizeof(sockaddr));
1546     sockaddr.sin_family = AF_INET;
1547     sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
1548     sockaddr.sin_port = htons(GetListenPort());
1549     if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
1550     {
1551         int nErr = WSAGetLastError();
1552         if (nErr == WSAEADDRINUSE)
1553             strError = strprintf(_("Unable to bind to port %d on this computer.  Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
1554         else
1555             strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
1556         printf("%s\n", strError.c_str());
1557         return false;
1558     }
1559     printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
1560
1561     // Listen for incoming connections
1562     if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1563     {
1564         strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1565         printf("%s\n", strError.c_str());
1566         return false;
1567     }
1568
1569     return true;
1570 }
1571
1572 void StartNode(void* parg)
1573 {
1574     if (semOutbound == NULL) {
1575         // initialize semaphore
1576         int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
1577         semOutbound = new CSemaphore(nMaxOutbound);
1578     }
1579
1580 #ifdef USE_UPNP
1581 #if USE_UPNP
1582     fUseUPnP = GetBoolArg("-upnp", true);
1583 #else
1584     fUseUPnP = GetBoolArg("-upnp", false);
1585 #endif
1586 #endif
1587
1588     if (pnodeLocalHost == NULL)
1589         pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
1590
1591 #ifdef WIN32
1592     // Get local host ip
1593     char pszHostName[1000] = "";
1594     if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1595     {
1596         vector<CNetAddr> vaddr;
1597         if (LookupHost(pszHostName, vaddr))
1598         {
1599             BOOST_FOREACH (const CNetAddr &addr, vaddr)
1600             {
1601                 if (!addr.IsLocal())
1602                 {
1603                     addrLocalHost.SetIP(addr);
1604                     break;
1605                 }
1606             }
1607         }
1608     }
1609 #else
1610     // Get local host ip
1611     struct ifaddrs* myaddrs;
1612     if (getifaddrs(&myaddrs) == 0)
1613     {
1614         for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1615         {
1616             if (ifa->ifa_addr == NULL) continue;
1617             if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1618             if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1619             if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1620             char pszIP[100];
1621             if (ifa->ifa_addr->sa_family == AF_INET)
1622             {
1623                 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1624                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
1625                     printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
1626
1627                 // Take the first IP that isn't loopback 127.x.x.x
1628                 CAddress addr(CService(s4->sin_addr, GetListenPort()), nLocalServices);
1629                 if (addr.IsValid() && !addr.IsLocal())
1630                 {
1631                     addrLocalHost = addr;
1632                     break;
1633                 }
1634             }
1635             else if (ifa->ifa_addr->sa_family == AF_INET6)
1636             {
1637                 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1638                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
1639                     printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
1640             }
1641         }
1642         freeifaddrs(myaddrs);
1643     }
1644 #endif
1645     printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1646
1647     if (fUseProxy || mapArgs.count("-connect") || fNoListen)
1648     {
1649         // Proxies can't take incoming connections
1650         addrLocalHost.SetIP(CNetAddr("0.0.0.0"));
1651         printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1652     }
1653     else
1654     {
1655         CreateThread(ThreadGetMyExternalIP, NULL);
1656     }
1657
1658     //
1659     // Start threads
1660     //
1661
1662     if (!GetBoolArg("-dnsseed", true))
1663         printf("DNS seeding disabled\n");
1664     else
1665         if (!CreateThread(ThreadDNSAddressSeed, NULL))
1666             printf("Error: CreateThread(ThreadDNSAddressSeed) failed\n");
1667
1668     // Map ports with UPnP
1669     if (fHaveUPnP)
1670         MapPort(fUseUPnP);
1671
1672     // Get addresses from IRC and advertise ours
1673     if (!CreateThread(ThreadIRCSeed, NULL))
1674         printf("Error: CreateThread(ThreadIRCSeed) failed\n");
1675
1676     // Send and receive from sockets, accept connections
1677     if (!CreateThread(ThreadSocketHandler, NULL))
1678         printf("Error: CreateThread(ThreadSocketHandler) failed\n");
1679
1680     // Initiate outbound connections from -addnode
1681     if (!CreateThread(ThreadOpenAddedConnections, NULL))
1682         printf("Error: CreateThread(ThreadOpenAddedConnections) failed\n");
1683
1684     // Initiate outbound connections
1685     if (!CreateThread(ThreadOpenConnections, NULL))
1686         printf("Error: CreateThread(ThreadOpenConnections) failed\n");
1687
1688     // Process messages
1689     if (!CreateThread(ThreadMessageHandler, NULL))
1690         printf("Error: CreateThread(ThreadMessageHandler) failed\n");
1691
1692     // Dump network addresses
1693     if (!CreateThread(ThreadDumpAddress, NULL))
1694         printf("Error; CreateThread(ThreadDumpAddress) failed\n");
1695
1696     // Generate coins in the background
1697     GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain);
1698 }
1699
1700 bool StopNode()
1701 {
1702     printf("StopNode()\n");
1703     fShutdown = true;
1704     nTransactionsUpdated++;
1705     int64 nStart = GetTime();
1706     if (semOutbound)
1707         for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1708             semOutbound->post();
1709     do
1710     {
1711         int nThreadsRunning = 0;
1712         for (int n = 0; n < THREAD_MAX; n++)
1713             nThreadsRunning += vnThreadsRunning[n];
1714         if (nThreadsRunning == 0)
1715             break;
1716         if (GetTime() - nStart > 20)
1717             break;
1718         Sleep(20);
1719     } while(true);
1720     if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1721     if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1722     if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1723     if (vnThreadsRunning[THREAD_MINER] > 0) printf("ThreadBitcoinMiner still running\n");
1724     if (vnThreadsRunning[THREAD_RPCSERVER] > 0) printf("ThreadRPCServer still running\n");
1725     if (fHaveUPnP && vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
1726     if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1727     if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1728     if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1729     while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCSERVER] > 0)
1730         Sleep(20);
1731     Sleep(50);
1732     DumpAddresses();
1733     return true;
1734 }
1735
1736 class CNetCleanup
1737 {
1738 public:
1739     CNetCleanup()
1740     {
1741     }
1742     ~CNetCleanup()
1743     {
1744         // Close sockets
1745         BOOST_FOREACH(CNode* pnode, vNodes)
1746             if (pnode->hSocket != INVALID_SOCKET)
1747                 closesocket(pnode->hSocket);
1748         if (hListenSocket != INVALID_SOCKET)
1749             if (closesocket(hListenSocket) == SOCKET_ERROR)
1750                 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1751
1752 #ifdef WIN32
1753         // Shutdown Windows Sockets
1754         WSACleanup();
1755 #endif
1756     }
1757 }
1758 instance_of_cnetcleanup;