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