Give hard-coded seed nodes a random last-seen time, to randomize order they're tried.
[novacoin.git] / src / net.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2011 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
13 #ifdef __WXMSW__
14 #include <string.h>
15 #endif
16
17 #ifdef USE_UPNP
18 #include <miniupnpc/miniwget.h>
19 #include <miniupnpc/miniupnpc.h>
20 #include <miniupnpc/upnpcommands.h>
21 #include <miniupnpc/upnperrors.h>
22 #endif
23
24 using namespace std;
25 using namespace boost;
26
27 static const int MAX_OUTBOUND_CONNECTIONS = 8;
28
29 void ThreadMessageHandler2(void* parg);
30 void ThreadSocketHandler2(void* parg);
31 void ThreadOpenConnections2(void* parg);
32 #ifdef USE_UPNP
33 void ThreadMapPort2(void* parg);
34 #endif
35 bool OpenNetworkConnection(const CAddress& addrConnect);
36
37
38
39
40
41 //
42 // Global state variables
43 //
44 bool fClient = false;
45 bool fAllowDNS = false;
46 uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
47 CAddress addrLocalHost("0.0.0.0", 0, false, nLocalServices);
48 static CNode* pnodeLocalHost = NULL;
49 uint64 nLocalHostNonce = 0;
50 array<int, 10> vnThreadsRunning;
51 static SOCKET hListenSocket = INVALID_SOCKET;
52
53 vector<CNode*> vNodes;
54 CCriticalSection cs_vNodes;
55 map<vector<unsigned char>, CAddress> mapAddresses;
56 CCriticalSection cs_mapAddresses;
57 map<CInv, CDataStream> mapRelay;
58 deque<pair<int64, CInv> > vRelayExpiration;
59 CCriticalSection cs_mapRelay;
60 map<CInv, int64> mapAlreadyAskedFor;
61
62 // Settings
63 int fUseProxy = false;
64 int nConnectTimeout = 5000;
65 CAddress addrProxy("127.0.0.1",9050);
66
67
68
69
70 unsigned short GetListenPort()
71 {
72     return (unsigned short)(GetArg("-port", GetDefaultPort()));
73 }
74
75 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
76 {
77     // Filter out duplicate requests
78     if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
79         return;
80     pindexLastGetBlocksBegin = pindexBegin;
81     hashLastGetBlocksEnd = hashEnd;
82
83     PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
84 }
85
86
87
88
89
90 bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout)
91 {
92     hSocketRet = INVALID_SOCKET;
93
94     SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
95     if (hSocket == INVALID_SOCKET)
96         return false;
97 #ifdef SO_NOSIGPIPE
98     int set = 1;
99     setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
100 #endif
101
102     bool fProxy = (fUseProxy && addrConnect.IsRoutable());
103     struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
104
105 #ifdef __WXMSW__
106     u_long fNonblock = 1;
107     if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
108 #else
109     int fFlags = fcntl(hSocket, F_GETFL, 0);
110     if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
111 #endif
112     {
113         closesocket(hSocket);
114         return false;
115     }
116
117
118     if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
119     {
120         // WSAEINVAL is here because some legacy version of winsock uses it
121         if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
122         {
123             struct timeval timeout;
124             timeout.tv_sec  = nTimeout / 1000;
125             timeout.tv_usec = (nTimeout % 1000) * 1000;
126
127             fd_set fdset;
128             FD_ZERO(&fdset);
129             FD_SET(hSocket, &fdset);
130             int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
131             if (nRet == 0)
132             {
133                 printf("connection timeout\n");
134                 closesocket(hSocket);
135                 return false;
136             }
137             if (nRet == SOCKET_ERROR)
138             {
139                 printf("select() for connection failed: %i\n",WSAGetLastError());
140                 closesocket(hSocket);
141                 return false;
142             }
143             socklen_t nRetSize = sizeof(nRet);
144 #ifdef __WXMSW__
145             if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
146 #else
147             if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
148 #endif
149             {
150                 printf("getsockopt() for connection failed: %i\n",WSAGetLastError());
151                 closesocket(hSocket);
152                 return false;
153             }
154             if (nRet != 0)
155             {
156                 printf("connect() failed after select(): %s\n",strerror(nRet));
157                 closesocket(hSocket);
158                 return false;
159             }
160         }
161 #ifdef __WXMSW__
162         else if (WSAGetLastError() != WSAEISCONN)
163 #else
164         else
165 #endif
166         {
167             printf("connect() failed: %i\n",WSAGetLastError());
168             closesocket(hSocket);
169             return false;
170         }
171     }
172
173     /*
174     this isn't even strictly necessary
175     CNode::ConnectNode immediately turns the socket back to non-blocking
176     but we'll turn it back to blocking just in case
177     */
178 #ifdef __WXMSW__
179     fNonblock = 0;
180     if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
181 #else
182     fFlags = fcntl(hSocket, F_GETFL, 0);
183     if (fcntl(hSocket, F_SETFL, fFlags & !O_NONBLOCK) == SOCKET_ERROR)
184 #endif
185     {
186         closesocket(hSocket);
187         return false;
188     }
189
190     if (fProxy)
191     {
192         printf("proxy connecting %s\n", addrConnect.ToString().c_str());
193         char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
194         memcpy(pszSocks4IP + 2, &addrConnect.port, 2);
195         memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);
196         char* pszSocks4 = pszSocks4IP;
197         int nSize = sizeof(pszSocks4IP);
198
199         int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
200         if (ret != nSize)
201         {
202             closesocket(hSocket);
203             return error("Error sending to proxy");
204         }
205         char pchRet[8];
206         if (recv(hSocket, pchRet, 8, 0) != 8)
207         {
208             closesocket(hSocket);
209             return error("Error reading proxy response");
210         }
211         if (pchRet[1] != 0x5a)
212         {
213             closesocket(hSocket);
214             if (pchRet[1] != 0x5b)
215                 printf("ERROR: Proxy returned error %d\n", pchRet[1]);
216             return false;
217         }
218         printf("proxy connected %s\n", addrConnect.ToString().c_str());
219     }
220
221     hSocketRet = hSocket;
222     return true;
223 }
224
225 // portDefault is in host order
226 bool Lookup(const char *pszName, vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup, int portDefault, bool fAllowPort)
227 {
228     vaddr.clear();
229     if (pszName[0] == 0)
230         return false;
231     int port = portDefault;
232     char psz[256];
233     char *pszHost = psz;
234     strlcpy(psz, pszName, sizeof(psz));
235     if (fAllowPort)
236     {
237         char* pszColon = strrchr(psz+1,':');
238         char *pszPortEnd = NULL;
239         int portParsed = pszColon ? strtoul(pszColon+1, &pszPortEnd, 10) : 0;
240         if (pszColon && pszPortEnd && pszPortEnd[0] == 0)
241         {
242             if (psz[0] == '[' && pszColon[-1] == ']')
243             {
244                 // Future: enable IPv6 colon-notation inside []
245                 pszHost = psz+1;
246                 pszColon[-1] = 0;
247             }
248             else
249                 pszColon[0] = 0;
250             port = portParsed;
251             if (port < 0 || port > USHRT_MAX)
252                 port = USHRT_MAX;
253         }
254     }
255
256     unsigned int addrIP = inet_addr(pszHost);
257     if (addrIP != INADDR_NONE)
258     {
259         // valid IP address passed
260         vaddr.push_back(CAddress(addrIP, port, nServices));
261         return true;
262     }
263
264     if (!fAllowLookup)
265         return false;
266
267     struct hostent* phostent = gethostbyname(pszHost);
268     if (!phostent)
269         return false;
270
271     if (phostent->h_addrtype != AF_INET)
272         return false;
273
274     char** ppAddr = phostent->h_addr_list;
275     while (*ppAddr != NULL && vaddr.size() != nMaxSolutions)
276     {
277         CAddress addr(((struct in_addr*)ppAddr[0])->s_addr, port, nServices);
278         if (addr.IsValid())
279             vaddr.push_back(addr);
280         ppAddr++;
281     }
282
283     return (vaddr.size() > 0);
284 }
285
286 // portDefault is in host order
287 bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup, int portDefault, bool fAllowPort)
288 {
289     vector<CAddress> vaddr;
290     bool fRet = Lookup(pszName, vaddr, nServices, 1, fAllowLookup, portDefault, fAllowPort);
291     if (fRet)
292         addr = vaddr[0];
293     return fRet;
294 }
295
296 bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const char* pszKeyword, unsigned int& ipRet)
297 {
298     SOCKET hSocket;
299     if (!ConnectSocket(addrConnect, hSocket))
300         return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
301
302     send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
303
304     string strLine;
305     while (RecvLine(hSocket, strLine))
306     {
307         if (strLine.empty()) // HTTP response is separated from headers by blank line
308         {
309             loop
310             {
311                 if (!RecvLine(hSocket, strLine))
312                 {
313                     closesocket(hSocket);
314                     return false;
315                 }
316                 if (pszKeyword == NULL)
317                     break;
318                 if (strLine.find(pszKeyword) != -1)
319                 {
320                     strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
321                     break;
322                 }
323             }
324             closesocket(hSocket);
325             if (strLine.find("<") != -1)
326                 strLine = strLine.substr(0, strLine.find("<"));
327             strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
328             while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
329                 strLine.resize(strLine.size()-1);
330             CAddress addr(strLine,0,true);
331             printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
332             if (addr.ip == 0 || addr.ip == INADDR_NONE || !addr.IsRoutable())
333                 return false;
334             ipRet = addr.ip;
335             return true;
336         }
337     }
338     closesocket(hSocket);
339     return error("GetMyExternalIP() : connection closed");
340 }
341
342 // We now get our external IP from the IRC server first and only use this as a backup
343 bool GetMyExternalIP(unsigned int& ipRet)
344 {
345     CAddress addrConnect;
346     const char* pszGet;
347     const char* pszKeyword;
348
349     if (fUseProxy)
350         return false;
351
352     for (int nLookup = 0; nLookup <= 1; nLookup++)
353     for (int nHost = 1; nHost <= 2; nHost++)
354     {
355         // We should be phasing out our use of sites like these.  If we need
356         // replacements, we should ask for volunteers to put this simple
357         // php file on their webserver that prints the client IP:
358         //  <?php echo $_SERVER["REMOTE_ADDR"]; ?>
359         if (nHost == 1)
360         {
361             addrConnect = CAddress("91.198.22.70",80); // checkip.dyndns.org
362
363             if (nLookup == 1)
364             {
365                 CAddress addrIP("checkip.dyndns.org", 80, true);
366                 if (addrIP.IsValid())
367                     addrConnect = addrIP;
368             }
369
370             pszGet = "GET / HTTP/1.1\r\n"
371                      "Host: checkip.dyndns.org\r\n"
372                      "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
373                      "Connection: close\r\n"
374                      "\r\n";
375
376             pszKeyword = "Address:";
377         }
378         else if (nHost == 2)
379         {
380             addrConnect = CAddress("74.208.43.192", 80); // www.showmyip.com
381
382             if (nLookup == 1)
383             {
384                 CAddress addrIP("www.showmyip.com", 80, true);
385                 if (addrIP.IsValid())
386                     addrConnect = addrIP;
387             }
388
389             pszGet = "GET /simple/ HTTP/1.1\r\n"
390                      "Host: www.showmyip.com\r\n"
391                      "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
392                      "Connection: close\r\n"
393                      "\r\n";
394
395             pszKeyword = NULL; // Returns just IP address
396         }
397
398         if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
399             return true;
400     }
401
402     return false;
403 }
404
405 void ThreadGetMyExternalIP(void* parg)
406 {
407     // Wait for IRC to get it first
408     if (!GetBoolArg("-noirc"))
409     {
410         for (int i = 0; i < 2 * 60; i++)
411         {
412             Sleep(1000);
413             if (fGotExternalIP || fShutdown)
414                 return;
415         }
416     }
417
418     // Fallback in case IRC fails to get it
419     if (GetMyExternalIP(addrLocalHost.ip))
420     {
421         printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
422         if (addrLocalHost.IsRoutable())
423         {
424             // If we already connected to a few before we had our IP, go back and addr them.
425             // setAddrKnown automatically filters any duplicate sends.
426             CAddress addr(addrLocalHost);
427             addr.nTime = GetAdjustedTime();
428             CRITICAL_BLOCK(cs_vNodes)
429                 BOOST_FOREACH(CNode* pnode, vNodes)
430                     pnode->PushAddress(addr);
431         }
432     }
433 }
434
435
436
437
438
439 bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB)
440 {
441     if (!addr.IsRoutable())
442         return false;
443     if (addr.ip == addrLocalHost.ip)
444         return false;
445     addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty);
446     CRITICAL_BLOCK(cs_mapAddresses)
447     {
448         map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
449         if (it == mapAddresses.end())
450         {
451             // New address
452             printf("AddAddress(%s)\n", addr.ToString().c_str());
453             mapAddresses.insert(make_pair(addr.GetKey(), addr));
454             if (pAddrDB)
455                 pAddrDB->WriteAddress(addr);
456             else
457                 CAddrDB().WriteAddress(addr);
458             return true;
459         }
460         else
461         {
462             bool fUpdated = false;
463             CAddress& addrFound = (*it).second;
464             if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
465             {
466                 // Services have been added
467                 addrFound.nServices |= addr.nServices;
468                 fUpdated = true;
469             }
470             bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
471             int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
472             if (addrFound.nTime < addr.nTime - nUpdateInterval)
473             {
474                 // Periodically update most recently seen time
475                 addrFound.nTime = addr.nTime;
476                 fUpdated = true;
477             }
478             if (fUpdated)
479             {
480                 if (pAddrDB)
481                     pAddrDB->WriteAddress(addrFound);
482                 else
483                     CAddrDB().WriteAddress(addrFound);
484             }
485         }
486     }
487     return false;
488 }
489
490 void AddressCurrentlyConnected(const CAddress& addr)
491 {
492     CRITICAL_BLOCK(cs_mapAddresses)
493     {
494         // Only if it's been published already
495         map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
496         if (it != mapAddresses.end())
497         {
498             CAddress& addrFound = (*it).second;
499             int64 nUpdateInterval = 20 * 60;
500             if (addrFound.nTime < GetAdjustedTime() - nUpdateInterval)
501             {
502                 // Periodically update most recently seen time
503                 addrFound.nTime = GetAdjustedTime();
504                 CAddrDB addrdb;
505                 addrdb.WriteAddress(addrFound);
506             }
507         }
508     }
509 }
510
511
512
513
514
515 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
516 {
517     // If the dialog might get closed before the reply comes back,
518     // call this in the destructor so it doesn't get called after it's deleted.
519     CRITICAL_BLOCK(cs_vNodes)
520     {
521         BOOST_FOREACH(CNode* pnode, vNodes)
522         {
523             CRITICAL_BLOCK(pnode->cs_mapRequests)
524             {
525                 for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
526                 {
527                     CRequestTracker& tracker = (*mi).second;
528                     if (tracker.fn == fn && tracker.param1 == param1)
529                         pnode->mapRequests.erase(mi++);
530                     else
531                         mi++;
532                 }
533             }
534         }
535     }
536 }
537
538
539
540
541
542
543
544 //
545 // Subscription methods for the broadcast and subscription system.
546 // Channel numbers are message numbers, i.e. MSG_TABLE and MSG_PRODUCT.
547 //
548 // The subscription system uses a meet-in-the-middle strategy.
549 // With 100,000 nodes, if senders broadcast to 1000 random nodes and receivers
550 // subscribe to 1000 random nodes, 99.995% (1 - 0.99^1000) of messages will get through.
551 //
552
553 bool AnySubscribed(unsigned int nChannel)
554 {
555     if (pnodeLocalHost->IsSubscribed(nChannel))
556         return true;
557     CRITICAL_BLOCK(cs_vNodes)
558         BOOST_FOREACH(CNode* pnode, vNodes)
559             if (pnode->IsSubscribed(nChannel))
560                 return true;
561     return false;
562 }
563
564 bool CNode::IsSubscribed(unsigned int nChannel)
565 {
566     if (nChannel >= vfSubscribe.size())
567         return false;
568     return vfSubscribe[nChannel];
569 }
570
571 void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
572 {
573     if (nChannel >= vfSubscribe.size())
574         return;
575
576     if (!AnySubscribed(nChannel))
577     {
578         // Relay subscribe
579         CRITICAL_BLOCK(cs_vNodes)
580             BOOST_FOREACH(CNode* pnode, vNodes)
581                 if (pnode != this)
582                     pnode->PushMessage("subscribe", nChannel, nHops);
583     }
584
585     vfSubscribe[nChannel] = true;
586 }
587
588 void CNode::CancelSubscribe(unsigned int nChannel)
589 {
590     if (nChannel >= vfSubscribe.size())
591         return;
592
593     // Prevent from relaying cancel if wasn't subscribed
594     if (!vfSubscribe[nChannel])
595         return;
596     vfSubscribe[nChannel] = false;
597
598     if (!AnySubscribed(nChannel))
599     {
600         // Relay subscription cancel
601         CRITICAL_BLOCK(cs_vNodes)
602             BOOST_FOREACH(CNode* pnode, vNodes)
603                 if (pnode != this)
604                     pnode->PushMessage("sub-cancel", nChannel);
605     }
606 }
607
608
609
610
611
612
613
614
615
616 CNode* FindNode(unsigned int ip)
617 {
618     CRITICAL_BLOCK(cs_vNodes)
619     {
620         BOOST_FOREACH(CNode* pnode, vNodes)
621             if (pnode->addr.ip == ip)
622                 return (pnode);
623     }
624     return NULL;
625 }
626
627 CNode* FindNode(CAddress addr)
628 {
629     CRITICAL_BLOCK(cs_vNodes)
630     {
631         BOOST_FOREACH(CNode* pnode, vNodes)
632             if (pnode->addr == addr)
633                 return (pnode);
634     }
635     return NULL;
636 }
637
638 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
639 {
640     if (addrConnect.ip == addrLocalHost.ip)
641         return NULL;
642
643     // Look for an existing connection
644     CNode* pnode = FindNode(addrConnect.ip);
645     if (pnode)
646     {
647         if (nTimeout != 0)
648             pnode->AddRef(nTimeout);
649         else
650             pnode->AddRef();
651         return pnode;
652     }
653
654     /// debug print
655     printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",
656         addrConnect.ToString().c_str(),
657         (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
658         (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
659
660     CRITICAL_BLOCK(cs_mapAddresses)
661         mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
662
663     // Connect
664     SOCKET hSocket;
665     if (ConnectSocket(addrConnect, hSocket))
666     {
667         /// debug print
668         printf("connected %s\n", addrConnect.ToString().c_str());
669
670         // Set to nonblocking
671 #ifdef __WXMSW__
672         u_long nOne = 1;
673         if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
674             printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
675 #else
676         if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
677             printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
678 #endif
679
680         // Add node
681         CNode* pnode = new CNode(hSocket, addrConnect, false);
682         if (nTimeout != 0)
683             pnode->AddRef(nTimeout);
684         else
685             pnode->AddRef();
686         CRITICAL_BLOCK(cs_vNodes)
687             vNodes.push_back(pnode);
688
689         pnode->nTimeConnected = GetTime();
690         return pnode;
691     }
692     else
693     {
694         return NULL;
695     }
696 }
697
698 void CNode::CloseSocketDisconnect()
699 {
700     fDisconnect = true;
701     if (hSocket != INVALID_SOCKET)
702     {
703         if (fDebug)
704             printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
705         printf("disconnecting node %s\n", addr.ToString().c_str());
706         closesocket(hSocket);
707         hSocket = INVALID_SOCKET;
708     }
709 }
710
711 void CNode::Cleanup()
712 {
713     // All of a nodes broadcasts and subscriptions are automatically torn down
714     // when it goes down, so a node has to stay up to keep its broadcast going.
715
716     // Cancel subscriptions
717     for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
718         if (vfSubscribe[nChannel])
719             CancelSubscribe(nChannel);
720 }
721
722
723
724
725
726
727
728
729
730
731
732
733
734 void ThreadSocketHandler(void* parg)
735 {
736     IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
737     try
738     {
739         vnThreadsRunning[0]++;
740         ThreadSocketHandler2(parg);
741         vnThreadsRunning[0]--;
742     }
743     catch (std::exception& e) {
744         vnThreadsRunning[0]--;
745         PrintException(&e, "ThreadSocketHandler()");
746     } catch (...) {
747         vnThreadsRunning[0]--;
748         throw; // support pthread_cancel()
749     }
750     printf("ThreadSocketHandler exiting\n");
751 }
752
753 void ThreadSocketHandler2(void* parg)
754 {
755     printf("ThreadSocketHandler started\n");
756     list<CNode*> vNodesDisconnected;
757     int nPrevNodeCount = 0;
758
759     loop
760     {
761         //
762         // Disconnect nodes
763         //
764         CRITICAL_BLOCK(cs_vNodes)
765         {
766             // Disconnect unused nodes
767             vector<CNode*> vNodesCopy = vNodes;
768             BOOST_FOREACH(CNode* pnode, vNodesCopy)
769             {
770                 if (pnode->fDisconnect ||
771                     (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
772                 {
773                     // remove from vNodes
774                     vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
775
776                     // close socket and cleanup
777                     pnode->CloseSocketDisconnect();
778                     pnode->Cleanup();
779
780                     // hold in disconnected pool until all refs are released
781                     pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
782                     if (pnode->fNetworkNode || pnode->fInbound)
783                         pnode->Release();
784                     vNodesDisconnected.push_back(pnode);
785                 }
786             }
787
788             // Delete disconnected nodes
789             list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
790             BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
791             {
792                 // wait until threads are done using it
793                 if (pnode->GetRefCount() <= 0)
794                 {
795                     bool fDelete = false;
796                     TRY_CRITICAL_BLOCK(pnode->cs_vSend)
797                      TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
798                       TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
799                        TRY_CRITICAL_BLOCK(pnode->cs_inventory)
800                         fDelete = true;
801                     if (fDelete)
802                     {
803                         vNodesDisconnected.remove(pnode);
804                         delete pnode;
805                     }
806                 }
807             }
808         }
809         if (vNodes.size() != nPrevNodeCount)
810         {
811             nPrevNodeCount = vNodes.size();
812             MainFrameRepaint();
813         }
814
815
816         //
817         // Find which sockets have data to receive
818         //
819         struct timeval timeout;
820         timeout.tv_sec  = 0;
821         timeout.tv_usec = 50000; // frequency to poll pnode->vSend
822
823         fd_set fdsetRecv;
824         fd_set fdsetSend;
825         fd_set fdsetError;
826         FD_ZERO(&fdsetRecv);
827         FD_ZERO(&fdsetSend);
828         FD_ZERO(&fdsetError);
829         SOCKET hSocketMax = 0;
830
831         if(hListenSocket != INVALID_SOCKET)
832             FD_SET(hListenSocket, &fdsetRecv);
833         hSocketMax = max(hSocketMax, hListenSocket);
834         CRITICAL_BLOCK(cs_vNodes)
835         {
836             BOOST_FOREACH(CNode* pnode, vNodes)
837             {
838                 if (pnode->hSocket == INVALID_SOCKET)
839                     continue;
840                 FD_SET(pnode->hSocket, &fdsetRecv);
841                 FD_SET(pnode->hSocket, &fdsetError);
842                 hSocketMax = max(hSocketMax, pnode->hSocket);
843                 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
844                     if (!pnode->vSend.empty())
845                         FD_SET(pnode->hSocket, &fdsetSend);
846             }
847         }
848
849         vnThreadsRunning[0]--;
850         int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
851         vnThreadsRunning[0]++;
852         if (fShutdown)
853             return;
854         if (nSelect == SOCKET_ERROR)
855         {
856             int nErr = WSAGetLastError();
857             if (hSocketMax > -1)
858             {
859                 printf("socket select error %d\n", nErr);
860                 for (int i = 0; i <= hSocketMax; i++)
861                     FD_SET(i, &fdsetRecv);
862             }
863             FD_ZERO(&fdsetSend);
864             FD_ZERO(&fdsetError);
865             Sleep(timeout.tv_usec/1000);
866         }
867
868
869         //
870         // Accept new connections
871         //
872         if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
873         {
874             struct sockaddr_in sockaddr;
875             socklen_t len = sizeof(sockaddr);
876             SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
877             CAddress addr(sockaddr);
878             int nInbound = 0;
879
880             CRITICAL_BLOCK(cs_vNodes)
881                 BOOST_FOREACH(CNode* pnode, vNodes)
882                 if (pnode->fInbound)
883                     nInbound++;
884             if (hSocket == INVALID_SOCKET)
885             {
886                 if (WSAGetLastError() != WSAEWOULDBLOCK)
887                     printf("socket error accept failed: %d\n", WSAGetLastError());
888             }
889             else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
890             {
891                 closesocket(hSocket);
892             }
893             else
894             {
895                 printf("accepted connection %s\n", addr.ToString().c_str());
896                 CNode* pnode = new CNode(hSocket, addr, true);
897                 pnode->AddRef();
898                 CRITICAL_BLOCK(cs_vNodes)
899                     vNodes.push_back(pnode);
900             }
901         }
902
903
904         //
905         // Service each socket
906         //
907         vector<CNode*> vNodesCopy;
908         CRITICAL_BLOCK(cs_vNodes)
909         {
910             vNodesCopy = vNodes;
911             BOOST_FOREACH(CNode* pnode, vNodesCopy)
912                 pnode->AddRef();
913         }
914         BOOST_FOREACH(CNode* pnode, vNodesCopy)
915         {
916             if (fShutdown)
917                 return;
918
919             //
920             // Receive
921             //
922             if (pnode->hSocket == INVALID_SOCKET)
923                 continue;
924             if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
925             {
926                 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
927                 {
928                     CDataStream& vRecv = pnode->vRecv;
929                     unsigned int nPos = vRecv.size();
930
931                     if (nPos > ReceiveBufferSize()) {
932                         if (!pnode->fDisconnect)
933                             printf("socket recv flood control disconnect (%d bytes)\n", vRecv.size());
934                         pnode->CloseSocketDisconnect();
935                     }
936                     else {
937                         // typical socket buffer is 8K-64K
938                         char pchBuf[0x10000];
939                         int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
940                         if (nBytes > 0)
941                         {
942                             vRecv.resize(nPos + nBytes);
943                             memcpy(&vRecv[nPos], pchBuf, nBytes);
944                             pnode->nLastRecv = GetTime();
945                         }
946                         else if (nBytes == 0)
947                         {
948                             // socket closed gracefully
949                             if (!pnode->fDisconnect)
950                                 printf("socket closed\n");
951                             pnode->CloseSocketDisconnect();
952                         }
953                         else if (nBytes < 0)
954                         {
955                             // error
956                             int nErr = WSAGetLastError();
957                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
958                             {
959                                 if (!pnode->fDisconnect)
960                                     printf("socket recv error %d\n", nErr);
961                                 pnode->CloseSocketDisconnect();
962                             }
963                         }
964                     }
965                 }
966             }
967
968             //
969             // Send
970             //
971             if (pnode->hSocket == INVALID_SOCKET)
972                 continue;
973             if (FD_ISSET(pnode->hSocket, &fdsetSend))
974             {
975                 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
976                 {
977                     CDataStream& vSend = pnode->vSend;
978                     if (!vSend.empty())
979                     {
980                         int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
981                         if (nBytes > 0)
982                         {
983                             vSend.erase(vSend.begin(), vSend.begin() + nBytes);
984                             pnode->nLastSend = GetTime();
985                         }
986                         else if (nBytes < 0)
987                         {
988                             // error
989                             int nErr = WSAGetLastError();
990                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
991                             {
992                                 printf("socket send error %d\n", nErr);
993                                 pnode->CloseSocketDisconnect();
994                             }
995                         }
996                         if (vSend.size() > SendBufferSize()) {
997                             if (!pnode->fDisconnect)
998                                 printf("socket send flood control disconnect (%d bytes)\n", vSend.size());
999                             pnode->CloseSocketDisconnect();
1000                         }
1001                     }
1002                 }
1003             }
1004
1005             //
1006             // Inactivity checking
1007             //
1008             if (pnode->vSend.empty())
1009                 pnode->nLastSendEmpty = GetTime();
1010             if (GetTime() - pnode->nTimeConnected > 60)
1011             {
1012                 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
1013                 {
1014                     printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
1015                     pnode->fDisconnect = true;
1016                 }
1017                 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
1018                 {
1019                     printf("socket not sending\n");
1020                     pnode->fDisconnect = true;
1021                 }
1022                 else if (GetTime() - pnode->nLastRecv > 90*60)
1023                 {
1024                     printf("socket inactivity timeout\n");
1025                     pnode->fDisconnect = true;
1026                 }
1027             }
1028         }
1029         CRITICAL_BLOCK(cs_vNodes)
1030         {
1031             BOOST_FOREACH(CNode* pnode, vNodesCopy)
1032                 pnode->Release();
1033         }
1034
1035         Sleep(10);
1036     }
1037 }
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047 #ifdef USE_UPNP
1048 void ThreadMapPort(void* parg)
1049 {
1050     IMPLEMENT_RANDOMIZE_STACK(ThreadMapPort(parg));
1051     try
1052     {
1053         vnThreadsRunning[5]++;
1054         ThreadMapPort2(parg);
1055         vnThreadsRunning[5]--;
1056     }
1057     catch (std::exception& e) {
1058         vnThreadsRunning[5]--;
1059         PrintException(&e, "ThreadMapPort()");
1060     } catch (...) {
1061         vnThreadsRunning[5]--;
1062         PrintException(NULL, "ThreadMapPort()");
1063     }
1064     printf("ThreadMapPort exiting\n");
1065 }
1066
1067 void ThreadMapPort2(void* parg)
1068 {
1069     printf("ThreadMapPort started\n");
1070
1071     char port[6];
1072     sprintf(port, "%d", GetListenPort());
1073
1074     const char * rootdescurl = 0;
1075     const char * multicastif = 0;
1076     const char * minissdpdpath = 0;
1077     int error = 0;
1078     struct UPNPDev * devlist = 0;
1079     char lanaddr[64];
1080
1081     devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
1082
1083     struct UPNPUrls urls;
1084     struct IGDdatas data;
1085     int r;
1086
1087     r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
1088     if (r == 1)
1089     {
1090         char intClient[16];
1091         char intPort[6];
1092         string strDesc = "Bitcoin " + FormatFullVersion();
1093         r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1094                                 port, port, lanaddr, strDesc.c_str(), "TCP", 0, "0");
1095
1096         if(r!=UPNPCOMMAND_SUCCESS)
1097             printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1098                 port, port, lanaddr, r, strupnperror(r));
1099         else
1100             printf("UPnP Port Mapping successful.\n");
1101         loop {
1102             if (fShutdown || !fUseUPnP)
1103             {
1104                 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port, "TCP", 0);
1105                 printf("UPNP_DeletePortMapping() returned : %d\n", r);
1106                 freeUPNPDevlist(devlist); devlist = 0;
1107                 FreeUPNPUrls(&urls);
1108                 return;
1109             }
1110             Sleep(2000);
1111         }
1112     } else {
1113         printf("No valid UPnP IGDs found\n");
1114         freeUPNPDevlist(devlist); devlist = 0;
1115         if (r != 0)
1116             FreeUPNPUrls(&urls);
1117         loop {
1118             if (fShutdown || !fUseUPnP)
1119                 return;
1120             Sleep(2000);
1121         }
1122     }
1123 }
1124
1125 void MapPort(bool fMapPort)
1126 {
1127     if (fUseUPnP != fMapPort)
1128     {
1129         fUseUPnP = fMapPort;
1130         WriteSetting("fUseUPnP", fUseUPnP);
1131     }
1132     if (fUseUPnP && vnThreadsRunning[5] < 1)
1133     {
1134         if (!CreateThread(ThreadMapPort, NULL))
1135             printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
1136     }
1137 }
1138 #else
1139 void MapPort(bool /* unused fMapPort */)
1140 {
1141     // Intentionally left blank.
1142 }
1143 #endif
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154 static const char *strDNSSeed[] = {
1155     "bitseed.xf2.org",
1156     "bitseed.bitcoin.org.uk",
1157     "dnsseed.bluematt.me",
1158 };
1159
1160 void DNSAddressSeed()
1161 {
1162     int found = 0;
1163
1164     if (!fTestNet)
1165     {
1166         printf("Loading addresses from DNS seeds (could take a while)\n");
1167         CAddrDB addrDB;
1168         addrDB.TxnBegin();
1169
1170         for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1171             vector<CAddress> vaddr;
1172             if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, -1, true))
1173             {
1174                 BOOST_FOREACH (CAddress& addr, vaddr)
1175                 {
1176                     if (addr.GetByte(3) != 127)
1177                     {
1178                         addr.nTime = 0;
1179                         AddAddress(addr, 0, &addrDB);
1180                         found++;
1181                     }
1182                 }
1183             }
1184         }
1185
1186         addrDB.TxnCommit();  // Save addresses (it's ok if this fails)
1187     }
1188
1189     printf("%d addresses found from DNS seeds\n", found);
1190 }
1191
1192
1193
1194 unsigned int pnSeed[] =
1195 {
1196     0x6884ac63, 0x3ffecead, 0x2919b953, 0x0942fe50, 0x7a1d922e, 0xcdd6734a, 0x953a5bb6, 0x2c46922e,
1197     0xe2a5f143, 0xaa39103a, 0xa06afa5c, 0x135ffd59, 0xe8e82863, 0xf61ef029, 0xf75f042e, 0x2b363532,
1198     0x29b2df42, 0x16b1f64e, 0xd46e281b, 0x5280bf58, 0x60372229, 0x1be58e4f, 0xa8496f45, 0x1fb1a057,
1199     0x756b3844, 0x3bb79445, 0x0b375518, 0xcccb0102, 0xb682bf2e, 0x46431c02, 0x3a81073a, 0xa3771f1f,
1200     0x213a121f, 0x85dc2c1b, 0x56b4323b, 0xb34e8945, 0x3c40b33d, 0xfa276418, 0x1f818d29, 0xebe1e344,
1201     0xf6160a18, 0xf4fa384a, 0x34b09558, 0xb882b543, 0xe3ce2253, 0x6abf56d8, 0xe91b1155, 0x688ee6ad,
1202     0x2efc6058, 0x4792cd47, 0x0c32f757, 0x4c813a46, 0x8c93644a, 0x37507444, 0x813ad218, 0xdac06d4a,
1203     0xe4c63e4b, 0x21a1ea3c, 0x8d88556f, 0x30e9173a, 0x041f681b, 0xdc77ba50, 0xc0072753, 0xceddd44f,
1204     0x052d1743, 0xe3c77a4a, 0x13981c3a, 0x5685d918, 0x3c0e4e70, 0x3e56fb54, 0xb676ae0c, 0xac93c859,
1205     0x22279f43, 0x975a4542, 0xe527f071, 0xea162f2e, 0x3c65a32e, 0x5be5713b, 0x961ec418, 0xb202922e,
1206     0x5ef7be50, 0xce49f53e, 0x05803b47, 0x8463b055, 0x78576153, 0x3ec2ae3a, 0x4bbd7118, 0xafcee043,
1207     0x56a3e8ba, 0x6174de4d, 0x8d01ba4b, 0xc9af564e, 0xdbc9c547, 0xa627474d, 0xdada9244, 0xd3b3083a,
1208     0x523e071f, 0xd6b96f18, 0xbd527c46, 0xdf2bbb4d, 0xd37b4a4b, 0x3a6a2158, 0xc064b055, 0x18a8e055,
1209     0xec4dae3b, 0x0540416c, 0x475b4fbe, 0x064803b2, 0x48e9f062, 0x2898524b, 0xd315ff43, 0xf786d247,
1210     0xc7ea2f3e, 0xc087f043, 0xc163354b, 0x8250284d, 0xed300029, 0xbf36e05c, 0x8eb3ae4c, 0xe7aa623e,
1211     0x7ced0274, 0xdd362c1b, 0x362b995a, 0xca26b629, 0x3fc41618, 0xb97b364e, 0xa05b8729, 0x0f5e3c43,
1212     0xdf942618, 0x6aeb9b5b, 0xbf04762e, 0xfaaeb118, 0x87579958, 0x76520044, 0xc2660c5b, 0x628b201b,
1213     0xf193932e, 0x1c0ad045, 0xff908346, 0x8da9d4da, 0xed201c1f, 0xa47a2b1b, 0x330007d4, 0x8ba1ed47,
1214     0xb2f02d44, 0x7db62c1b, 0x781c454b, 0xc0300029, 0xb7062a45, 0x88b52e3a, 0x78dd6b63, 0x1cb9b718,
1215     0x5d358e47, 0x59912c3b, 0x79607544, 0x5197f759, 0xc023be48, 0xd1013743, 0x0f354057, 0x8e3aac3b,
1216     0x4114693e, 0x22316318, 0xe27dda50, 0x878eac3b, 0x4948a21f, 0x5db7f24c, 0x8ccb6157, 0x26a5de18,
1217     0x0a11bd43, 0x27bb1e41, 0x60a7a951, 0x3e16b35e, 0x07888b53, 0x5648a853, 0x0149fe50, 0xd070a34f,
1218     0x6454c96d, 0xd6e54758, 0xa96dc152, 0x65447861, 0xf6bdf95e, 0x10400202, 0x2c29d483, 0x18174732,
1219     0x1d840618, 0x12e61818, 0x089d3f3c, 0x917e931f, 0xd1b0c90e, 0x25bd3c42, 0xeb05775b, 0x7d550c59,
1220     0x6cfacb01, 0xe4224444, 0xa41dd943, 0x0f5aa643, 0x5e33731b, 0x81036d50, 0x6f46a0d1, 0x7731be43,
1221     0x14840e18, 0xf1e8d059, 0x661d2b1f, 0x40a3201b, 0x9407b843, 0xedf0254d, 0x7bd1a5bc, 0x073dbe51,
1222     0xe864a97b, 0x2efd947b, 0xb9ca0e45, 0x4e2113ad, 0xcc305731, 0xd39ca63c, 0x733df918, 0xda172b1f,
1223     0xaa03b34d, 0x7230fd4d, 0xf1ce6e3a, 0x2e9fab43, 0xa4010750, 0xa928bd18, 0x6809be42, 0xb19de348,
1224     0xff956270, 0x0d795f51, 0xd2dec247, 0x6df5774b, 0xbac11f79, 0xdfb05c75, 0x887683d8, 0xa1e83632,
1225     0x2c0f7671, 0x28bcb65d, 0xac2a7545, 0x3eebfc60, 0x304ad7c4, 0xa215a462, 0xc86f0f58, 0xcfb92ebe,
1226     0x5e23ed82, 0xf506184b, 0xec0f19b7, 0x060c59ad, 0x86ee3174, 0x85380774, 0xa199a562, 0x02b507ae,
1227     0x33eb2163, 0xf2112b1f, 0xb702ba50, 0x131b9618, 0x90ccd04a, 0x08f3273b, 0xecb61718, 0x64b8b44d,
1228     0x182bf4dc, 0xc7b68286, 0x6e318d5f, 0xfdb03654, 0xb3272e54, 0xe014ad4b, 0x274e4a31, 0x7806375c,
1229     0xbc34a748, 0x1b5ad94a, 0x6b54d10e, 0x73e2ae6e, 0x5529d483, 0x8455a76d, 0x99c13f47, 0x1d811741,
1230     0xa9782a78, 0x0b00464d, 0x7266ea50, 0x532dab46, 0x33e1413e, 0x780d0c18, 0x0fb0854e, 0x03370155,
1231     0x2693042e, 0xfa3d824a, 0x2bb1681b, 0x37ea2a18, 0x7fb8414b, 0x32e0713b, 0xacf38d3f, 0xa282716f,
1232     0xb1a09d7b, 0xa04b764b, 0x83c94d18, 0x05ee4c6d, 0x0e795f51, 0x46984352, 0xf80fc247, 0x3fccb946,
1233     0xd7ae244b, 0x0a8e0a4c, 0x57b141bc, 0x3647bed1, 0x1431b052, 0x803a8bbb, 0xfc69056b, 0xf5991862,
1234     0x14963b2e, 0xd35d5dda, 0xc6c73574, 0xc8f1405b, 0x0ca4224d, 0xecd36071, 0xa9461754, 0xe7a0ed72,
1235     0x559e8346, 0x1c9beec1, 0xc786ea4a, 0x9561b44d, 0x9788074d, 0x1a69934f, 0x23c5614c, 0x07c79d4b,
1236     0xc7ee52db, 0xc72df351, 0xcb135e44, 0xa0988346, 0xc211fc4c, 0x87dec34b, 0x1381074d, 0x04a65cb7,
1237     0x4409083a, 0x4a407a4c, 0x92b8d37d, 0xacf50b4d, 0xa58aa5bc, 0x448f801f, 0x9c83762e, 0x6fd5734a,
1238     0xfe2d454b, 0x84144c55, 0x05190e4c, 0xb2151448, 0x63867a3e, 0x16099018, 0x9c010d3c, 0x962d8f3d,
1239     0xd51ee453, 0x9d86801f, 0x68e87b47, 0x6bf7bb73, 0x5fc7910e, 0x10d90118, 0x3db04442, 0x729d3e4b,
1240     0xc397d842, 0x57bb15ad, 0x72f31f4e, 0xc9380043, 0x2bb24e18, 0xd9b8ab50, 0xb786801f, 0xf4dc4847,
1241     0x85f4bb51, 0x4435995b, 0x5ba07e40, 0x2c57392e, 0x3628124b, 0x9839b64b, 0x6fe8b24d, 0xaddce847,
1242     0x75260e45, 0x0c572a43, 0xfea21902, 0xb9f9742e, 0x5a70d443, 0x8fc5910e, 0x868d4744, 0x56245e02,
1243     0xd7eb5f02, 0x35c12c1b, 0x4373034b, 0x8786554c, 0xa6facf18, 0x4b11a31f, 0x3570664e, 0x5a64bc42,
1244     0x0b03983f, 0x8f457e4c, 0x0fd874c3, 0xb6cf31b2, 0x2bbc2d4e, 0x146ca5b2, 0x9d00b150, 0x048a4153,
1245     0xca4dcd43, 0xc1607cca, 0x8234cf57, 0x9c7daead, 0x3dc07658, 0xea5c6e4c, 0xf1a0084e, 0x16d2ee53,
1246     0x1b849418, 0xfe913a47, 0x1e988f62, 0x208b644c, 0xc55ee980, 0xbdbce747, 0xf59a384e, 0x0f56091b,
1247     0x7417b745, 0x0c37344e, 0x2c62ab47, 0xf8533a4d, 0x8030084d, 0x76b93c4b, 0xda6ea0ad, 0x3c54f618,
1248     0x63b0de1f, 0x7370d858, 0x1a70bb4c, 0xdda63b2e, 0x60b2ba50, 0x1ba7d048, 0xbe1b2c1b, 0xabea5747,
1249     0x29ad2e4d, 0xe8cd7642, 0x66c80e18, 0x138bf34a, 0xc6145e44, 0x2586794c, 0x07bc5478, 0x0da0b14d,
1250     0x8f95354e, 0x9eb11c62, 0xa1545e46, 0x2e7a2602, 0x408c9c3d, 0x59065d55, 0xf51d1a4c, 0x3bbc6a4e,
1251     0xc71b2a2e, 0xcdaaa545, 0x17d659d0, 0x5202e7ad, 0xf1b68445, 0x93375961, 0xbd88a043, 0x066ad655,
1252     0x890f6318, 0x7b7dca47, 0x99bdd662, 0x3bb4fc53, 0x1231efdc, 0xc0a99444, 0x96bbea47, 0x61ed8748,
1253     0x27dfa73b, 0x8d4d1754, 0x3460042e, 0x551f0c4c, 0x8d0e0718, 0x162ddc53, 0x53231718, 0x1ecd65d0,
1254     0x944d28bc, 0x3b79d058, 0xaff97fbc, 0x4860006c, 0xc101c90e, 0xace41743, 0xa5975d4c, 0x5cc2703e,
1255     0xb55a4450, 0x02d18840, 0xee2765ae, 0xd6012fd5, 0x24c94d7d, 0x8c6eec47, 0x7520ba5d, 0x9e15e460,
1256     0x8510b04c, 0x75ec3847, 0x1dfa6661, 0xe172b3ad, 0x5744c90e, 0x52a0a152, 0x8d6fad18, 0x67b74b6d,
1257     0x93a089b2, 0x0f3ac5d5, 0xe5de1855, 0x43d25747, 0x4bad804a, 0x55b408d8, 0x60a36441, 0xf553e860,
1258     0xdb2fa2c8, 0x03152b32, 0xdd27a7d5, 0x3116a8b8, 0x0a1d708c, 0xeee2f13c, 0x6acf436f, 0xce6eb4ca,
1259     0x101cd3d9, 0x1c48a6b8, 0xe57d6f44, 0x93dcf562,
1260 };
1261
1262
1263
1264 void ThreadOpenConnections(void* parg)
1265 {
1266     IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
1267     try
1268     {
1269         vnThreadsRunning[1]++;
1270         ThreadOpenConnections2(parg);
1271         vnThreadsRunning[1]--;
1272     }
1273     catch (std::exception& e) {
1274         vnThreadsRunning[1]--;
1275         PrintException(&e, "ThreadOpenConnections()");
1276     } catch (...) {
1277         vnThreadsRunning[1]--;
1278         PrintException(NULL, "ThreadOpenConnections()");
1279     }
1280     printf("ThreadOpenConnections exiting\n");
1281 }
1282
1283 void ThreadOpenConnections2(void* parg)
1284 {
1285     printf("ThreadOpenConnections started\n");
1286
1287     // Connect to specific addresses
1288     if (mapArgs.count("-connect"))
1289     {
1290         for (int64 nLoop = 0;; nLoop++)
1291         {
1292             BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1293             {
1294                 CAddress addr(strAddr, fAllowDNS);
1295                 if (addr.IsValid())
1296                     OpenNetworkConnection(addr);
1297                 for (int i = 0; i < 10 && i < nLoop; i++)
1298                 {
1299                     Sleep(500);
1300                     if (fShutdown)
1301                         return;
1302                 }
1303             }
1304         }
1305     }
1306
1307     // Connect to manually added nodes first
1308     if (mapArgs.count("-addnode"))
1309     {
1310         BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
1311         {
1312             CAddress addr(strAddr, fAllowDNS);
1313             if (addr.IsValid())
1314             {
1315                 OpenNetworkConnection(addr);
1316                 Sleep(500);
1317                 if (fShutdown)
1318                     return;
1319             }
1320         }
1321     }
1322
1323     // Initiate network connections
1324     int64 nStart = GetTime();
1325     loop
1326     {
1327         // Limit outbound connections
1328         vnThreadsRunning[1]--;
1329         Sleep(500);
1330         loop
1331         {
1332             int nOutbound = 0;
1333             CRITICAL_BLOCK(cs_vNodes)
1334                 BOOST_FOREACH(CNode* pnode, vNodes)
1335                     if (!pnode->fInbound)
1336                         nOutbound++;
1337             int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
1338             nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
1339             if (nOutbound < nMaxOutboundConnections)
1340                 break;
1341             Sleep(2000);
1342             if (fShutdown)
1343                 return;
1344         }
1345         vnThreadsRunning[1]++;
1346         if (fShutdown)
1347             return;
1348
1349         CRITICAL_BLOCK(cs_mapAddresses)
1350         {
1351             // Add seed nodes if IRC isn't working
1352             static bool fSeedUsed;
1353             bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
1354             if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
1355             {
1356                 for (int i = 0; i < ARRAYLEN(pnSeed); i++)
1357                 {
1358                     // It'll only connect to one or two seed nodes because once it connects,
1359                     // it'll get a pile of addresses with newer timestamps.
1360                     // Seed nodes are given a random 'last seen time' of between one and two
1361                     // weeks ago.
1362                     const int64 nOneWeek = 7*24*60*60;
1363                     CAddress addr;
1364                     addr.ip = pnSeed[i];
1365                     addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1366                     AddAddress(addr);
1367                 }
1368                 fSeedUsed = true;
1369             }
1370
1371             if (fSeedUsed && mapAddresses.size() > ARRAYLEN(pnSeed) + 100)
1372             {
1373                 // Disconnect seed nodes
1374                 set<unsigned int> setSeed(pnSeed, pnSeed + ARRAYLEN(pnSeed));
1375                 static int64 nSeedDisconnected;
1376                 if (nSeedDisconnected == 0)
1377                 {
1378                     nSeedDisconnected = GetTime();
1379                     CRITICAL_BLOCK(cs_vNodes)
1380                         BOOST_FOREACH(CNode* pnode, vNodes)
1381                             if (setSeed.count(pnode->addr.ip))
1382                                 pnode->fDisconnect = true;
1383                 }
1384
1385                 // Keep setting timestamps to 0 so they won't reconnect
1386                 if (GetTime() - nSeedDisconnected < 60 * 60)
1387                 {
1388                     BOOST_FOREACH(PAIRTYPE(const vector<unsigned char>, CAddress)& item, mapAddresses)
1389                     {
1390                         if (setSeed.count(item.second.ip) && item.second.nTime != 0)
1391                         {
1392                             item.second.nTime = 0;
1393                             CAddrDB().WriteAddress(item.second);
1394                         }
1395                     }
1396                 }
1397             }
1398         }
1399
1400
1401         //
1402         // Choose an address to connect to based on most recently seen
1403         //
1404         CAddress addrConnect;
1405         int64 nBest = INT64_MIN;
1406
1407         // Only connect to one address per a.b.?.? range.
1408         // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1409         set<unsigned int> setConnected;
1410         CRITICAL_BLOCK(cs_vNodes)
1411             BOOST_FOREACH(CNode* pnode, vNodes)
1412                 setConnected.insert(pnode->addr.ip & 0x0000ffff);
1413
1414         CRITICAL_BLOCK(cs_mapAddresses)
1415         {
1416             BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
1417             {
1418                 const CAddress& addr = item.second;
1419                 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
1420                     continue;
1421                 int64 nSinceLastSeen = GetAdjustedTime() - addr.nTime;
1422                 int64 nSinceLastTry = GetAdjustedTime() - addr.nLastTry;
1423
1424                 // Randomize the order in a deterministic way, putting the standard port first
1425                 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
1426                 if (addr.port != htons(GetDefaultPort()))
1427                     nRandomizer += 2 * 60 * 60;
1428
1429                 // Last seen  Base retry frequency
1430                 //   <1 hour   10 min
1431                 //    1 hour    1 hour
1432                 //    4 hours   2 hours
1433                 //   24 hours   5 hours
1434                 //   48 hours   7 hours
1435                 //    7 days   13 hours
1436                 //   30 days   27 hours
1437                 //   90 days   46 hours
1438                 //  365 days   93 hours
1439                 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
1440
1441                 // Fast reconnect for one hour after last seen
1442                 if (nSinceLastSeen < 60 * 60)
1443                     nDelay = 10 * 60;
1444
1445                 // Limit retry frequency
1446                 if (nSinceLastTry < nDelay)
1447                     continue;
1448
1449                 // If we have IRC, we'll be notified when they first come online,
1450                 // and again every 24 hours by the refresh broadcast.
1451                 if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)
1452                     continue;
1453
1454                 // Only try the old stuff if we don't have enough connections
1455                 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
1456                     continue;
1457
1458                 // If multiple addresses are ready, prioritize by time since
1459                 // last seen and time since last tried.
1460                 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
1461                 if (nScore > nBest)
1462                 {
1463                     nBest = nScore;
1464                     addrConnect = addr;
1465                 }
1466             }
1467         }
1468
1469         if (addrConnect.IsValid())
1470             OpenNetworkConnection(addrConnect);
1471     }
1472 }
1473
1474 bool OpenNetworkConnection(const CAddress& addrConnect)
1475 {
1476     //
1477     // Initiate outbound network connection
1478     //
1479     if (fShutdown)
1480         return false;
1481     if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
1482         return false;
1483
1484     vnThreadsRunning[1]--;
1485     CNode* pnode = ConnectNode(addrConnect);
1486     vnThreadsRunning[1]++;
1487     if (fShutdown)
1488         return false;
1489     if (!pnode)
1490         return false;
1491     pnode->fNetworkNode = true;
1492
1493     return true;
1494 }
1495
1496
1497
1498
1499
1500
1501
1502
1503 void ThreadMessageHandler(void* parg)
1504 {
1505     IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
1506     try
1507     {
1508         vnThreadsRunning[2]++;
1509         ThreadMessageHandler2(parg);
1510         vnThreadsRunning[2]--;
1511     }
1512     catch (std::exception& e) {
1513         vnThreadsRunning[2]--;
1514         PrintException(&e, "ThreadMessageHandler()");
1515     } catch (...) {
1516         vnThreadsRunning[2]--;
1517         PrintException(NULL, "ThreadMessageHandler()");
1518     }
1519     printf("ThreadMessageHandler exiting\n");
1520 }
1521
1522 void ThreadMessageHandler2(void* parg)
1523 {
1524     printf("ThreadMessageHandler started\n");
1525     SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1526     while (!fShutdown)
1527     {
1528         vector<CNode*> vNodesCopy;
1529         CRITICAL_BLOCK(cs_vNodes)
1530         {
1531             vNodesCopy = vNodes;
1532             BOOST_FOREACH(CNode* pnode, vNodesCopy)
1533                 pnode->AddRef();
1534         }
1535
1536         // Poll the connected nodes for messages
1537         CNode* pnodeTrickle = NULL;
1538         if (!vNodesCopy.empty())
1539             pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1540         BOOST_FOREACH(CNode* pnode, vNodesCopy)
1541         {
1542             // Receive messages
1543             TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
1544                 ProcessMessages(pnode);
1545             if (fShutdown)
1546                 return;
1547
1548             // Send messages
1549             TRY_CRITICAL_BLOCK(pnode->cs_vSend)
1550                 SendMessages(pnode, pnode == pnodeTrickle);
1551             if (fShutdown)
1552                 return;
1553         }
1554
1555         CRITICAL_BLOCK(cs_vNodes)
1556         {
1557             BOOST_FOREACH(CNode* pnode, vNodesCopy)
1558                 pnode->Release();
1559         }
1560
1561         // Wait and allow messages to bunch up.
1562         // Reduce vnThreadsRunning so StopNode has permission to exit while
1563         // we're sleeping, but we must always check fShutdown after doing this.
1564         vnThreadsRunning[2]--;
1565         Sleep(100);
1566         if (fRequestShutdown)
1567             Shutdown(NULL);
1568         vnThreadsRunning[2]++;
1569         if (fShutdown)
1570             return;
1571     }
1572 }
1573
1574
1575
1576
1577
1578
1579 bool BindListenPort(string& strError)
1580 {
1581     strError = "";
1582     int nOne = 1;
1583     addrLocalHost.port = htons(GetListenPort());
1584
1585 #ifdef __WXMSW__
1586     // Initialize Windows Sockets
1587     WSADATA wsadata;
1588     int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1589     if (ret != NO_ERROR)
1590     {
1591         strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1592         printf("%s\n", strError.c_str());
1593         return false;
1594     }
1595 #endif
1596
1597     // Create socket for listening for incoming connections
1598     hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1599     if (hListenSocket == INVALID_SOCKET)
1600     {
1601         strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1602         printf("%s\n", strError.c_str());
1603         return false;
1604     }
1605
1606 #ifdef SO_NOSIGPIPE
1607     // Different way of disabling SIGPIPE on BSD
1608     setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1609 #endif
1610
1611 #ifndef __WXMSW__
1612     // Allow binding if the port is still in TIME_WAIT state after
1613     // the program was closed and restarted.  Not an issue on windows.
1614     setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1615 #endif
1616
1617 #ifdef __WXMSW__
1618     // Set to nonblocking, incoming connections will also inherit this
1619     if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1620 #else
1621     if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1622 #endif
1623     {
1624         strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1625         printf("%s\n", strError.c_str());
1626         return false;
1627     }
1628
1629     // The sockaddr_in structure specifies the address family,
1630     // IP address, and port for the socket that is being bound
1631     struct sockaddr_in sockaddr;
1632     memset(&sockaddr, 0, sizeof(sockaddr));
1633     sockaddr.sin_family = AF_INET;
1634     sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
1635     sockaddr.sin_port = htons(GetListenPort());
1636     if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
1637     {
1638         int nErr = WSAGetLastError();
1639         if (nErr == WSAEADDRINUSE)
1640             strError = strprintf(_("Unable to bind to port %d on this computer.  Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
1641         else
1642             strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
1643         printf("%s\n", strError.c_str());
1644         return false;
1645     }
1646     printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
1647
1648     // Listen for incoming connections
1649     if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1650     {
1651         strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1652         printf("%s\n", strError.c_str());
1653         return false;
1654     }
1655
1656     return true;
1657 }
1658
1659 void StartNode(void* parg)
1660 {
1661     if (pnodeLocalHost == NULL)
1662         pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, false, nLocalServices));
1663
1664 #ifdef __WXMSW__
1665     // Get local host ip
1666     char pszHostName[1000] = "";
1667     if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1668     {
1669         vector<CAddress> vaddr;
1670         if (Lookup(pszHostName, vaddr, nLocalServices, -1, true))
1671             BOOST_FOREACH (const CAddress &addr, vaddr)
1672                 if (addr.GetByte(3) != 127)
1673                 {
1674                     addrLocalHost = addr;
1675                     break;
1676                 }
1677     }
1678 #else
1679     // Get local host ip
1680     struct ifaddrs* myaddrs;
1681     if (getifaddrs(&myaddrs) == 0)
1682     {
1683         for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1684         {
1685             if (ifa->ifa_addr == NULL) continue;
1686             if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1687             if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1688             if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1689             char pszIP[100];
1690             if (ifa->ifa_addr->sa_family == AF_INET)
1691             {
1692                 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1693                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
1694                     printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
1695
1696                 // Take the first IP that isn't loopback 127.x.x.x
1697                 CAddress addr(*(unsigned int*)&s4->sin_addr, GetListenPort(), nLocalServices);
1698                 if (addr.IsValid() && addr.GetByte(3) != 127)
1699                 {
1700                     addrLocalHost = addr;
1701                     break;
1702                 }
1703             }
1704             else if (ifa->ifa_addr->sa_family == AF_INET6)
1705             {
1706                 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1707                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
1708                     printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
1709             }
1710         }
1711         freeifaddrs(myaddrs);
1712     }
1713 #endif
1714     printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1715
1716     if (fUseProxy || mapArgs.count("-connect") || fNoListen)
1717     {
1718         // Proxies can't take incoming connections
1719         addrLocalHost.ip = CAddress("0.0.0.0").ip;
1720         printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1721     }
1722     else
1723     {
1724         CreateThread(ThreadGetMyExternalIP, NULL);
1725     }
1726
1727     //
1728     // Start threads
1729     //
1730
1731     // Map ports with UPnP
1732     if (fHaveUPnP)
1733         MapPort(fUseUPnP);
1734
1735     // Get addresses from IRC and advertise ours
1736     if (!CreateThread(ThreadIRCSeed, NULL))
1737         printf("Error: CreateThread(ThreadIRCSeed) failed\n");
1738
1739     // Send and receive from sockets, accept connections
1740     CreateThread(ThreadSocketHandler, NULL, true);
1741
1742     // Initiate outbound connections
1743     if (!CreateThread(ThreadOpenConnections, NULL))
1744         printf("Error: CreateThread(ThreadOpenConnections) failed\n");
1745
1746     // Process messages
1747     if (!CreateThread(ThreadMessageHandler, NULL))
1748         printf("Error: CreateThread(ThreadMessageHandler) failed\n");
1749
1750     // Generate coins in the background
1751     GenerateBitcoins(fGenerateBitcoins, pwalletMain);
1752 }
1753
1754 bool StopNode()
1755 {
1756     printf("StopNode()\n");
1757     fShutdown = true;
1758     nTransactionsUpdated++;
1759     int64 nStart = GetTime();
1760     while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0
1761 #ifdef USE_UPNP
1762         || vnThreadsRunning[5] > 0
1763 #endif
1764     )
1765     {
1766         if (GetTime() - nStart > 20)
1767             break;
1768         Sleep(20);
1769     }
1770     if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
1771     if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
1772     if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
1773     if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
1774     if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
1775     if (fHaveUPnP && vnThreadsRunning[5] > 0) printf("ThreadMapPort still running\n");
1776     while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
1777         Sleep(20);
1778     Sleep(50);
1779
1780     return true;
1781 }
1782
1783 class CNetCleanup
1784 {
1785 public:
1786     CNetCleanup()
1787     {
1788     }
1789     ~CNetCleanup()
1790     {
1791         // Close sockets
1792         BOOST_FOREACH(CNode* pnode, vNodes)
1793             if (pnode->hSocket != INVALID_SOCKET)
1794                 closesocket(pnode->hSocket);
1795         if (hListenSocket != INVALID_SOCKET)
1796             if (closesocket(hListenSocket) == SOCKET_ERROR)
1797                 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1798
1799 #ifdef __WXMSW__
1800         // Shutdown Windows Sockets
1801         WSACleanup();
1802 #endif
1803     }
1804 }
1805 instance_of_cnetcleanup;