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