fix compiler warning "suggest explicit braces to avoid ambiguous "else"
[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 "irc.h"
7 #include "db.h"
8 #include "net.h"
9 #include "init.h"
10 #include "strlcpy.h"
11 #include "addrman.h"
12 #include "ui_interface.h"
13
14 #ifdef WIN32
15 #include <string.h>
16 #endif
17
18 #ifdef USE_UPNP
19 #include <miniupnpc/miniwget.h>
20 #include <miniupnpc/miniupnpc.h>
21 #include <miniupnpc/upnpcommands.h>
22 #include <miniupnpc/upnperrors.h>
23 #endif
24
25 using namespace std;
26 using namespace boost;
27
28 static const int MAX_OUTBOUND_CONNECTIONS = 8;
29
30 void ThreadMessageHandler2(void* parg);
31 void ThreadSocketHandler2(void* parg);
32 void ThreadOpenConnections2(void* parg);
33 void ThreadOpenAddedConnections2(void* parg);
34 #ifdef USE_UPNP
35 void ThreadMapPort2(void* parg);
36 #endif
37 void ThreadDNSAddressSeed2(void* parg);
38 bool OpenNetworkConnection(const CAddress& addrConnect);
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) != string::npos)
166                 {
167                     strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
168                     break;
169                 }
170             }
171             closesocket(hSocket);
172             if (strLine.find("<") != string::npos)
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     unsigned 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 (unsigned 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 (unsigned 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         // Add seed nodes if IRC isn't working
1237         bool fTOR = (fUseProxy && addrProxy.GetPort() == 9050);
1238         if (addrman.size()==0 && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
1239         {
1240             std::vector<CAddress> vAdd;
1241             for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1242             {
1243                 // It'll only connect to one or two seed nodes because once it connects,
1244                 // it'll get a pile of addresses with newer timestamps.
1245                 // Seed nodes are given a random 'last seen time' of between one and two
1246                 // weeks ago.
1247                 const int64 nOneWeek = 7*24*60*60;
1248                 struct in_addr ip;
1249                 memcpy(&ip, &pnSeed[i], sizeof(ip));
1250                 CAddress addr(CService(ip, GetDefaultPort()));
1251                 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1252                 vAdd.push_back(addr);
1253             }
1254             addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1255         }
1256
1257         //
1258         // Choose an address to connect to based on most recently seen
1259         //
1260         CAddress addrConnect;
1261
1262         // Only connect to one address per a.b.?.? range.
1263         // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1264         set<vector<unsigned char> > setConnected;
1265         {
1266             LOCK(cs_vNodes);
1267             BOOST_FOREACH(CNode* pnode, vNodes)
1268                 setConnected.insert(pnode->addr.GetGroup());
1269         }
1270
1271         int64 nANow = GetAdjustedTime();
1272
1273         int nTries = 0;
1274         loop
1275         {
1276             // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1277             CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1278
1279             // if we selected an invalid address, restart
1280             if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.GetGroup()) || addr == addrLocalHost)
1281                 break;
1282
1283             nTries++;
1284
1285             // only consider very recently tried nodes after 30 failed attempts
1286             if (nANow - addr.nLastTry < 600 && nTries < 30)
1287                 continue;
1288
1289             // do not allow non-default ports, unless after 50 invalid addresses selected already
1290             if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1291                 continue;
1292
1293             addrConnect = addr;
1294             break;
1295         }
1296
1297         if (addrConnect.IsValid())
1298             OpenNetworkConnection(addrConnect);
1299     }
1300 }
1301
1302 void ThreadOpenAddedConnections(void* parg)
1303 {
1304     IMPLEMENT_RANDOMIZE_STACK(ThreadOpenAddedConnections(parg));
1305     try
1306     {
1307         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1308         ThreadOpenAddedConnections2(parg);
1309         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1310     }
1311     catch (std::exception& e) {
1312         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1313         PrintException(&e, "ThreadOpenAddedConnections()");
1314     } catch (...) {
1315         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1316         PrintException(NULL, "ThreadOpenAddedConnections()");
1317     }
1318     printf("ThreadOpenAddedConnections exiting\n");
1319 }
1320
1321 void ThreadOpenAddedConnections2(void* parg)
1322 {
1323     printf("ThreadOpenAddedConnections started\n");
1324
1325     if (mapArgs.count("-addnode") == 0)
1326         return;
1327
1328     vector<vector<CService> > vservAddressesToAdd(0);
1329     BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"])
1330     {
1331         vector<CService> vservNode(0);
1332         if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fAllowDNS, 0))
1333         {
1334             vservAddressesToAdd.push_back(vservNode);
1335             {
1336                 LOCK(cs_setservAddNodeAddresses);
1337                 BOOST_FOREACH(CService& serv, vservNode)
1338                     setservAddNodeAddresses.insert(serv);
1339             }
1340         }
1341     }
1342     loop
1343     {
1344         vector<vector<CService> > vservConnectAddresses = vservAddressesToAdd;
1345         // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1346         // (keeping in mind that addnode entries can have many IPs if fAllowDNS)
1347         {
1348             LOCK(cs_vNodes);
1349             BOOST_FOREACH(CNode* pnode, vNodes)
1350                 for (vector<vector<CService> >::iterator it = vservConnectAddresses.begin(); it != vservConnectAddresses.end(); it++)
1351                     BOOST_FOREACH(CService& addrNode, *(it))
1352                         if (pnode->addr == addrNode)
1353                         {
1354                             it = vservConnectAddresses.erase(it);
1355                             it--;
1356                             break;
1357                         }
1358         }
1359         BOOST_FOREACH(vector<CService>& vserv, vservConnectAddresses)
1360         {
1361             OpenNetworkConnection(CAddress(*(vserv.begin())));
1362             Sleep(500);
1363             if (fShutdown)
1364                 return;
1365         }
1366         if (fShutdown)
1367             return;
1368         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1369         Sleep(120000); // Retry every 2 minutes
1370         vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1371         if (fShutdown)
1372             return;
1373     }
1374 }
1375
1376 bool OpenNetworkConnection(const CAddress& addrConnect)
1377 {
1378     //
1379     // Initiate outbound network connection
1380     //
1381     if (fShutdown)
1382         return false;
1383     if ((CNetAddr)addrConnect == (CNetAddr)addrLocalHost || !addrConnect.IsIPv4() ||
1384         FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect))
1385         return false;
1386
1387     vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1388     CNode* pnode = ConnectNode(addrConnect);
1389     vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1390     if (fShutdown)
1391         return false;
1392     if (!pnode)
1393         return false;
1394     pnode->fNetworkNode = true;
1395
1396     return true;
1397 }
1398
1399
1400
1401
1402
1403
1404
1405
1406 void ThreadMessageHandler(void* parg)
1407 {
1408     IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
1409     try
1410     {
1411         vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1412         ThreadMessageHandler2(parg);
1413         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1414     }
1415     catch (std::exception& e) {
1416         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1417         PrintException(&e, "ThreadMessageHandler()");
1418     } catch (...) {
1419         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1420         PrintException(NULL, "ThreadMessageHandler()");
1421     }
1422     printf("ThreadMessageHandler exiting\n");
1423 }
1424
1425 void ThreadMessageHandler2(void* parg)
1426 {
1427     printf("ThreadMessageHandler started\n");
1428     SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1429     while (!fShutdown)
1430     {
1431         vector<CNode*> vNodesCopy;
1432         {
1433             LOCK(cs_vNodes);
1434             vNodesCopy = vNodes;
1435             BOOST_FOREACH(CNode* pnode, vNodesCopy)
1436                 pnode->AddRef();
1437         }
1438
1439         // Poll the connected nodes for messages
1440         CNode* pnodeTrickle = NULL;
1441         if (!vNodesCopy.empty())
1442             pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1443         BOOST_FOREACH(CNode* pnode, vNodesCopy)
1444         {
1445             // Receive messages
1446             {
1447                 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1448                 if (lockRecv)
1449                     ProcessMessages(pnode);
1450             }
1451             if (fShutdown)
1452                 return;
1453
1454             // Send messages
1455             {
1456                 TRY_LOCK(pnode->cs_vSend, lockSend);
1457                 if (lockSend)
1458                     SendMessages(pnode, pnode == pnodeTrickle);
1459             }
1460             if (fShutdown)
1461                 return;
1462         }
1463
1464         {
1465             LOCK(cs_vNodes);
1466             BOOST_FOREACH(CNode* pnode, vNodesCopy)
1467                 pnode->Release();
1468         }
1469
1470         // Wait and allow messages to bunch up.
1471         // Reduce vnThreadsRunning so StopNode has permission to exit while
1472         // we're sleeping, but we must always check fShutdown after doing this.
1473         vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1474         Sleep(100);
1475         if (fRequestShutdown)
1476             Shutdown(NULL);
1477         vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1478         if (fShutdown)
1479             return;
1480     }
1481 }
1482
1483
1484
1485
1486
1487
1488 bool BindListenPort(string& strError)
1489 {
1490     strError = "";
1491     int nOne = 1;
1492     addrLocalHost.SetPort(GetListenPort());
1493
1494 #ifdef WIN32
1495     // Initialize Windows Sockets
1496     WSADATA wsadata;
1497     int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1498     if (ret != NO_ERROR)
1499     {
1500         strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1501         printf("%s\n", strError.c_str());
1502         return false;
1503     }
1504 #endif
1505
1506     // Create socket for listening for incoming connections
1507     hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1508     if (hListenSocket == INVALID_SOCKET)
1509     {
1510         strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1511         printf("%s\n", strError.c_str());
1512         return false;
1513     }
1514
1515 #ifdef SO_NOSIGPIPE
1516     // Different way of disabling SIGPIPE on BSD
1517     setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1518 #endif
1519
1520 #ifndef WIN32
1521     // Allow binding if the port is still in TIME_WAIT state after
1522     // the program was closed and restarted.  Not an issue on windows.
1523     setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1524 #endif
1525
1526 #ifdef WIN32
1527     // Set to nonblocking, incoming connections will also inherit this
1528     if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1529 #else
1530     if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1531 #endif
1532     {
1533         strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1534         printf("%s\n", strError.c_str());
1535         return false;
1536     }
1537
1538     // The sockaddr_in structure specifies the address family,
1539     // IP address, and port for the socket that is being bound
1540     struct sockaddr_in sockaddr;
1541     memset(&sockaddr, 0, sizeof(sockaddr));
1542     sockaddr.sin_family = AF_INET;
1543     sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
1544     sockaddr.sin_port = htons(GetListenPort());
1545     if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
1546     {
1547         int nErr = WSAGetLastError();
1548         if (nErr == WSAEADDRINUSE)
1549             strError = strprintf(_("Unable to bind to port %d on this computer.  Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
1550         else
1551             strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
1552         printf("%s\n", strError.c_str());
1553         return false;
1554     }
1555     printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
1556
1557     // Listen for incoming connections
1558     if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1559     {
1560         strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1561         printf("%s\n", strError.c_str());
1562         return false;
1563     }
1564
1565     return true;
1566 }
1567
1568 void StartNode(void* parg)
1569 {
1570 #ifdef USE_UPNP
1571 #if USE_UPNP
1572     fUseUPnP = GetBoolArg("-upnp", true);
1573 #else
1574     fUseUPnP = GetBoolArg("-upnp", false);
1575 #endif
1576 #endif
1577
1578     if (pnodeLocalHost == NULL)
1579         pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
1580
1581 #ifdef WIN32
1582     // Get local host ip
1583     char pszHostName[1000] = "";
1584     if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1585     {
1586         vector<CNetAddr> vaddr;
1587         if (LookupHost(pszHostName, vaddr))
1588         {
1589             BOOST_FOREACH (const CNetAddr &addr, vaddr)
1590             {
1591                 if (!addr.IsLocal())
1592                 {
1593                     addrLocalHost.SetIP(addr);
1594                     break;
1595                 }
1596             }
1597         }
1598     }
1599 #else
1600     // Get local host ip
1601     struct ifaddrs* myaddrs;
1602     if (getifaddrs(&myaddrs) == 0)
1603     {
1604         for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1605         {
1606             if (ifa->ifa_addr == NULL) continue;
1607             if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1608             if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1609             if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1610             char pszIP[100];
1611             if (ifa->ifa_addr->sa_family == AF_INET)
1612             {
1613                 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1614                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
1615                     printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
1616
1617                 // Take the first IP that isn't loopback 127.x.x.x
1618                 CAddress addr(CService(s4->sin_addr, GetListenPort()), nLocalServices);
1619                 if (addr.IsValid() && !addr.IsLocal())
1620                 {
1621                     addrLocalHost = addr;
1622                     break;
1623                 }
1624             }
1625             else if (ifa->ifa_addr->sa_family == AF_INET6)
1626             {
1627                 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1628                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
1629                     printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
1630             }
1631         }
1632         freeifaddrs(myaddrs);
1633     }
1634 #endif
1635     printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1636
1637     if (fUseProxy || mapArgs.count("-connect") || fNoListen)
1638     {
1639         // Proxies can't take incoming connections
1640         addrLocalHost.SetIP(CNetAddr("0.0.0.0"));
1641         printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1642     }
1643     else
1644     {
1645         CreateThread(ThreadGetMyExternalIP, NULL);
1646     }
1647
1648     //
1649     // Start threads
1650     //
1651
1652     if (!GetBoolArg("-dnsseed", true))
1653         printf("DNS seeding disabled\n");
1654     else
1655         if (!CreateThread(ThreadDNSAddressSeed, NULL))
1656             printf("Error: CreateThread(ThreadDNSAddressSeed) failed\n");
1657
1658     // Map ports with UPnP
1659     if (fHaveUPnP)
1660         MapPort(fUseUPnP);
1661
1662     // Get addresses from IRC and advertise ours
1663     if (!CreateThread(ThreadIRCSeed, NULL))
1664         printf("Error: CreateThread(ThreadIRCSeed) failed\n");
1665
1666     // Send and receive from sockets, accept connections
1667     if (!CreateThread(ThreadSocketHandler, NULL))
1668         printf("Error: CreateThread(ThreadSocketHandler) failed\n");
1669
1670     // Initiate outbound connections from -addnode
1671     if (!CreateThread(ThreadOpenAddedConnections, NULL))
1672         printf("Error: CreateThread(ThreadOpenAddedConnections) failed\n");
1673
1674     // Initiate outbound connections
1675     if (!CreateThread(ThreadOpenConnections, NULL))
1676         printf("Error: CreateThread(ThreadOpenConnections) failed\n");
1677
1678     // Process messages
1679     if (!CreateThread(ThreadMessageHandler, NULL))
1680         printf("Error: CreateThread(ThreadMessageHandler) failed\n");
1681
1682     // Dump network addresses
1683     if (!CreateThread(ThreadDumpAddress, NULL))
1684         printf("Error; CreateThread(ThreadDumpAddress) failed\n");
1685
1686     // Generate coins in the background
1687     GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain);
1688 }
1689
1690 bool StopNode()
1691 {
1692     printf("StopNode()\n");
1693     fShutdown = true;
1694     nTransactionsUpdated++;
1695     int64 nStart = GetTime();
1696     NOTIFY_ALL(condOutbound);
1697     do
1698     {
1699         int nThreadsRunning = 0;
1700         for (int n = 0; n < THREAD_MAX; n++)
1701             nThreadsRunning += vnThreadsRunning[n];
1702         if (nThreadsRunning == 0)
1703             break;
1704         if (GetTime() - nStart > 20)
1705             break;
1706         Sleep(20);
1707     } while(true);
1708     if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1709     if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1710     if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1711     if (vnThreadsRunning[THREAD_MINER] > 0) printf("ThreadBitcoinMiner still running\n");
1712     if (vnThreadsRunning[THREAD_RPCSERVER] > 0) printf("ThreadRPCServer still running\n");
1713     if (fHaveUPnP && vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
1714     if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1715     if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1716     if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1717     while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCSERVER] > 0)
1718         Sleep(20);
1719     Sleep(50);
1720     DumpAddresses();
1721     return true;
1722 }
1723
1724 class CNetCleanup
1725 {
1726 public:
1727     CNetCleanup()
1728     {
1729     }
1730     ~CNetCleanup()
1731     {
1732         // Close sockets
1733         BOOST_FOREACH(CNode* pnode, vNodes)
1734             if (pnode->hSocket != INVALID_SOCKET)
1735                 closesocket(pnode->hSocket);
1736         if (hListenSocket != INVALID_SOCKET)
1737             if (closesocket(hListenSocket) == SOCKET_ERROR)
1738                 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1739
1740 #ifdef WIN32
1741         // Shutdown Windows Sockets
1742         WSACleanup();
1743 #endif
1744     }
1745 }
1746 instance_of_cnetcleanup;