added a subset of Crypto++ 5.6.0 with 48% faster ASM SHA-256, combined speedup 2...
[novacoin.git] / net.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
4
5 #include "headers.h"
6
7 void ThreadMessageHandler2(void* parg);
8 void ThreadSocketHandler2(void* parg);
9 void ThreadOpenConnections2(void* parg);
10 bool OpenNetworkConnection(const CAddress& addrConnect);
11
12
13
14
15
16 //
17 // Global state variables
18 //
19 bool fClient = false;
20 uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
21 CAddress addrLocalHost(0, DEFAULT_PORT, nLocalServices);
22 CNode* pnodeLocalHost = NULL;
23 uint64 nLocalHostNonce = 0;
24 array<int, 10> vnThreadsRunning;
25 SOCKET hListenSocket = INVALID_SOCKET;
26 int64 nThreadSocketHandlerHeartbeat = INT64_MAX;
27
28 vector<CNode*> vNodes;
29 CCriticalSection cs_vNodes;
30 map<vector<unsigned char>, CAddress> mapAddresses;
31 CCriticalSection cs_mapAddresses;
32 map<CInv, CDataStream> mapRelay;
33 deque<pair<int64, CInv> > vRelayExpiration;
34 CCriticalSection cs_mapRelay;
35 map<CInv, int64> mapAlreadyAskedFor;
36
37 // Settings
38 int fUseProxy = false;
39 CAddress addrProxy("127.0.0.1:9050");
40
41
42
43
44
45 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
46 {
47     // Filter out duplicate requests
48     if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
49         return;
50     pindexLastGetBlocksBegin = pindexBegin;
51     hashLastGetBlocksEnd = hashEnd;
52
53     PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
54 }
55
56
57
58
59
60 bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
61 {
62     hSocketRet = INVALID_SOCKET;
63
64     SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
65     if (hSocket == INVALID_SOCKET)
66         return false;
67 #if defined(__BSD__) || defined(__WXMAC_OSX__)
68     int set = 1;
69     setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
70 #endif
71
72     bool fRoutable = !(addrConnect.GetByte(3) == 10 || (addrConnect.GetByte(3) == 192 && addrConnect.GetByte(2) == 168));
73     bool fProxy = (fUseProxy && fRoutable);
74     struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
75
76     if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
77     {
78         closesocket(hSocket);
79         return false;
80     }
81
82     if (fProxy)
83     {
84         printf("proxy connecting %s\n", addrConnect.ToStringLog().c_str());
85         char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
86         memcpy(pszSocks4IP + 2, &addrConnect.port, 2);
87         memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);
88         char* pszSocks4 = pszSocks4IP;
89         int nSize = sizeof(pszSocks4IP);
90
91         int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
92         if (ret != nSize)
93         {
94             closesocket(hSocket);
95             return error("Error sending to proxy");
96         }
97         char pchRet[8];
98         if (recv(hSocket, pchRet, 8, 0) != 8)
99         {
100             closesocket(hSocket);
101             return error("Error reading proxy response");
102         }
103         if (pchRet[1] != 0x5a)
104         {
105             closesocket(hSocket);
106             if (pchRet[1] != 0x5b)
107                 printf("ERROR: Proxy returned error %d\n", pchRet[1]);
108             return false;
109         }
110         printf("proxy connected %s\n", addrConnect.ToStringLog().c_str());
111     }
112
113     hSocketRet = hSocket;
114     return true;
115 }
116
117
118
119 bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const char* pszKeyword, unsigned int& ipRet)
120 {
121     SOCKET hSocket;
122     if (!ConnectSocket(addrConnect, hSocket))
123         return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
124
125     send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
126
127     string strLine;
128     while (RecvLine(hSocket, strLine))
129     {
130         if (strLine.empty())
131         {
132             loop
133             {
134                 if (!RecvLine(hSocket, strLine))
135                 {
136                     closesocket(hSocket);
137                     return false;
138                 }
139                 if (strLine.find(pszKeyword) != -1)
140                 {
141                     strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
142                     break;
143                 }
144             }
145             closesocket(hSocket);
146             if (strLine.find("<"))
147                 strLine = strLine.substr(0, strLine.find("<"));
148             strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
149             while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
150                 strLine.resize(strLine.size()-1);
151             CAddress addr(strLine.c_str());
152             printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
153             if (addr.ip == 0 || addr.ip == INADDR_NONE || !addr.IsRoutable())
154                 return false;
155             ipRet = addr.ip;
156             return true;
157         }
158     }
159     closesocket(hSocket);
160     return error("GetMyExternalIP() : connection closed");
161 }
162
163
164 bool GetMyExternalIP(unsigned int& ipRet)
165 {
166     CAddress addrConnect;
167     const char* pszGet;
168     const char* pszKeyword;
169
170     if (fUseProxy)
171         return false;
172
173     for (int nLookup = 0; nLookup <= 1; nLookup++)
174     for (int nHost = 1; nHost <= 2; nHost++)
175     {
176         if (nHost == 1)
177         {
178             addrConnect = CAddress("70.86.96.218:80"); // www.ipaddressworld.com
179
180             if (nLookup == 1)
181             {
182                 struct hostent* phostent = gethostbyname("www.ipaddressworld.com");
183                 if (phostent && phostent->h_addr_list && phostent->h_addr_list[0])
184                     addrConnect = CAddress(*(u_long*)phostent->h_addr_list[0], htons(80));
185             }
186
187             pszGet = "GET /ip.php HTTP/1.1\r\n"
188                      "Host: www.ipaddressworld.com\r\n"
189                      "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
190                      "Connection: close\r\n"
191                      "\r\n";
192
193             pszKeyword = "IP:";
194         }
195         else if (nHost == 2)
196         {
197             addrConnect = CAddress("208.78.68.70:80"); // checkip.dyndns.org
198
199             if (nLookup == 1)
200             {
201                 struct hostent* phostent = gethostbyname("checkip.dyndns.org");
202                 if (phostent && phostent->h_addr_list && phostent->h_addr_list[0])
203                     addrConnect = CAddress(*(u_long*)phostent->h_addr_list[0], htons(80));
204             }
205
206             pszGet = "GET / HTTP/1.1\r\n"
207                      "Host: checkip.dyndns.org\r\n"
208                      "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
209                      "Connection: close\r\n"
210                      "\r\n";
211
212             pszKeyword = "Address:";
213         }
214
215         if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
216             return true;
217     }
218
219     return false;
220 }
221
222
223
224
225
226 bool AddAddress(CAddress addr)
227 {
228     if (!addr.IsRoutable())
229         return false;
230     if (addr.ip == addrLocalHost.ip)
231         return false;
232     CRITICAL_BLOCK(cs_mapAddresses)
233     {
234         map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
235         if (it == mapAddresses.end())
236         {
237             // New address
238             printf("AddAddress(%s)\n", addr.ToStringLog().c_str());
239             mapAddresses.insert(make_pair(addr.GetKey(), addr));
240             CAddrDB().WriteAddress(addr);
241             return true;
242         }
243         else
244         {
245             bool fUpdated = false;
246             CAddress& addrFound = (*it).second;
247             if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
248             {
249                 // Services have been added
250                 addrFound.nServices |= addr.nServices;
251                 fUpdated = true;
252             }
253             bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
254             int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
255             if (addrFound.nTime < addr.nTime - nUpdateInterval)
256             {
257                 // Periodically update most recently seen time
258                 addrFound.nTime = addr.nTime;
259                 fUpdated = true;
260             }
261             if (fUpdated)
262                 CAddrDB().WriteAddress(addrFound);
263         }
264     }
265     return false;
266 }
267
268 void AddressCurrentlyConnected(const CAddress& addr)
269 {
270     CRITICAL_BLOCK(cs_mapAddresses)
271     {
272         // Only if it's been published already
273         map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
274         if (it != mapAddresses.end())
275         {
276             CAddress& addrFound = (*it).second;
277             int64 nUpdateInterval = 20 * 60;
278             if (addrFound.nTime < GetAdjustedTime() - nUpdateInterval)
279             {
280                 // Periodically update most recently seen time
281                 addrFound.nTime = GetAdjustedTime();
282                 CAddrDB addrdb;
283                 addrdb.WriteAddress(addrFound);
284             }
285         }
286     }
287 }
288
289
290
291
292
293 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
294 {
295     // If the dialog might get closed before the reply comes back,
296     // call this in the destructor so it doesn't get called after it's deleted.
297     CRITICAL_BLOCK(cs_vNodes)
298     {
299         foreach(CNode* pnode, vNodes)
300         {
301             CRITICAL_BLOCK(pnode->cs_mapRequests)
302             {
303                 for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
304                 {
305                     CRequestTracker& tracker = (*mi).second;
306                     if (tracker.fn == fn && tracker.param1 == param1)
307                         pnode->mapRequests.erase(mi++);
308                     else
309                         mi++;
310                 }
311             }
312         }
313     }
314 }
315
316
317
318
319
320
321
322 //
323 // Subscription methods for the broadcast and subscription system.
324 // Channel numbers are message numbers, i.e. MSG_TABLE and MSG_PRODUCT.
325 //
326 // The subscription system uses a meet-in-the-middle strategy.
327 // With 100,000 nodes, if senders broadcast to 1000 random nodes and receivers
328 // subscribe to 1000 random nodes, 99.995% (1 - 0.99^1000) of messages will get through.
329 //
330
331 bool AnySubscribed(unsigned int nChannel)
332 {
333     if (pnodeLocalHost->IsSubscribed(nChannel))
334         return true;
335     CRITICAL_BLOCK(cs_vNodes)
336         foreach(CNode* pnode, vNodes)
337             if (pnode->IsSubscribed(nChannel))
338                 return true;
339     return false;
340 }
341
342 bool CNode::IsSubscribed(unsigned int nChannel)
343 {
344     if (nChannel >= vfSubscribe.size())
345         return false;
346     return vfSubscribe[nChannel];
347 }
348
349 void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
350 {
351     if (nChannel >= vfSubscribe.size())
352         return;
353
354     if (!AnySubscribed(nChannel))
355     {
356         // Relay subscribe
357         CRITICAL_BLOCK(cs_vNodes)
358             foreach(CNode* pnode, vNodes)
359                 if (pnode != this)
360                     pnode->PushMessage("subscribe", nChannel, nHops);
361     }
362
363     vfSubscribe[nChannel] = true;
364 }
365
366 void CNode::CancelSubscribe(unsigned int nChannel)
367 {
368     if (nChannel >= vfSubscribe.size())
369         return;
370
371     // Prevent from relaying cancel if wasn't subscribed
372     if (!vfSubscribe[nChannel])
373         return;
374     vfSubscribe[nChannel] = false;
375
376     if (!AnySubscribed(nChannel))
377     {
378         // Relay subscription cancel
379         CRITICAL_BLOCK(cs_vNodes)
380             foreach(CNode* pnode, vNodes)
381                 if (pnode != this)
382                     pnode->PushMessage("sub-cancel", nChannel);
383     }
384 }
385
386
387
388
389
390
391
392
393
394 CNode* FindNode(unsigned int ip)
395 {
396     CRITICAL_BLOCK(cs_vNodes)
397     {
398         foreach(CNode* pnode, vNodes)
399             if (pnode->addr.ip == ip)
400                 return (pnode);
401     }
402     return NULL;
403 }
404
405 CNode* FindNode(CAddress addr)
406 {
407     CRITICAL_BLOCK(cs_vNodes)
408     {
409         foreach(CNode* pnode, vNodes)
410             if (pnode->addr == addr)
411                 return (pnode);
412     }
413     return NULL;
414 }
415
416 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
417 {
418     if (addrConnect.ip == addrLocalHost.ip)
419         return NULL;
420
421     // Look for an existing connection
422     CNode* pnode = FindNode(addrConnect.ip);
423     if (pnode)
424     {
425         if (nTimeout != 0)
426             pnode->AddRef(nTimeout);
427         else
428             pnode->AddRef();
429         return pnode;
430     }
431
432     /// debug print
433     printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",
434         addrConnect.ToStringLog().c_str(),
435         (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
436         (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
437
438     CRITICAL_BLOCK(cs_mapAddresses)
439         mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
440
441     // Connect
442     SOCKET hSocket;
443     if (ConnectSocket(addrConnect, hSocket))
444     {
445         /// debug print
446         printf("connected %s\n", addrConnect.ToStringLog().c_str());
447
448         // Set to nonblocking
449 #ifdef __WXMSW__
450         u_long nOne = 1;
451         if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
452             printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
453 #else
454         if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
455             printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
456 #endif
457
458         // Add node
459         CNode* pnode = new CNode(hSocket, addrConnect, false);
460         if (nTimeout != 0)
461             pnode->AddRef(nTimeout);
462         else
463             pnode->AddRef();
464         CRITICAL_BLOCK(cs_vNodes)
465             vNodes.push_back(pnode);
466
467         pnode->nTimeConnected = GetTime();
468         return pnode;
469     }
470     else
471     {
472         return NULL;
473     }
474 }
475
476 void CNode::CloseSocketDisconnect()
477 {
478     fDisconnect = true;
479     if (hSocket != INVALID_SOCKET)
480     {
481         if (fDebug)
482             printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
483         printf("disconnecting node %s\n", addr.ToStringLog().c_str());
484         closesocket(hSocket);
485         hSocket = INVALID_SOCKET;
486     }
487 }
488
489 void CNode::Cleanup()
490 {
491     // All of a nodes broadcasts and subscriptions are automatically torn down
492     // when it goes down, so a node has to stay up to keep its broadcast going.
493
494     // Cancel subscriptions
495     for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
496         if (vfSubscribe[nChannel])
497             CancelSubscribe(nChannel);
498 }
499
500
501
502
503
504
505
506
507
508
509
510
511
512 void ThreadSocketHandler(void* parg)
513 {
514     IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
515     try
516     {
517         vnThreadsRunning[0]++;
518         ThreadSocketHandler2(parg);
519         vnThreadsRunning[0]--;
520     }
521     catch (std::exception& e) {
522         vnThreadsRunning[0]--;
523         PrintException(&e, "ThreadSocketHandler()");
524     } catch (...) {
525         vnThreadsRunning[0]--;
526         throw; // support pthread_cancel()
527     }
528     printf("ThreadSocketHandler exiting\n");
529 }
530
531 void ThreadSocketHandler2(void* parg)
532 {
533     printf("ThreadSocketHandler started\n");
534     list<CNode*> vNodesDisconnected;
535     int nPrevNodeCount = 0;
536
537     loop
538     {
539         //
540         // Disconnect nodes
541         //
542         CRITICAL_BLOCK(cs_vNodes)
543         {
544             // Disconnect unused nodes
545             vector<CNode*> vNodesCopy = vNodes;
546             foreach(CNode* pnode, vNodesCopy)
547             {
548                 if (pnode->fDisconnect ||
549                     (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
550                 {
551                     // remove from vNodes
552                     vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
553
554                     // close socket and cleanup
555                     pnode->CloseSocketDisconnect();
556                     pnode->Cleanup();
557
558                     // hold in disconnected pool until all refs are released
559                     pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
560                     if (pnode->fNetworkNode || pnode->fInbound)
561                         pnode->Release();
562                     vNodesDisconnected.push_back(pnode);
563                 }
564             }
565
566             // Delete disconnected nodes
567             list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
568             foreach(CNode* pnode, vNodesDisconnectedCopy)
569             {
570                 // wait until threads are done using it
571                 if (pnode->GetRefCount() <= 0)
572                 {
573                     bool fDelete = false;
574                     TRY_CRITICAL_BLOCK(pnode->cs_vSend)
575                      TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
576                       TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
577                        TRY_CRITICAL_BLOCK(pnode->cs_inventory)
578                         fDelete = true;
579                     if (fDelete)
580                     {
581                         vNodesDisconnected.remove(pnode);
582                         delete pnode;
583                     }
584                 }
585             }
586         }
587         if (vNodes.size() != nPrevNodeCount)
588         {
589             nPrevNodeCount = vNodes.size();
590             MainFrameRepaint();
591         }
592
593
594         //
595         // Find which sockets have data to receive
596         //
597         struct timeval timeout;
598         timeout.tv_sec  = 0;
599         timeout.tv_usec = 50000; // frequency to poll pnode->vSend
600
601         fd_set fdsetRecv;
602         fd_set fdsetSend;
603         fd_set fdsetError;
604         FD_ZERO(&fdsetRecv);
605         FD_ZERO(&fdsetSend);
606         FD_ZERO(&fdsetError);
607         SOCKET hSocketMax = 0;
608         FD_SET(hListenSocket, &fdsetRecv);
609         hSocketMax = max(hSocketMax, hListenSocket);
610         CRITICAL_BLOCK(cs_vNodes)
611         {
612             foreach(CNode* pnode, vNodes)
613             {
614                 if (pnode->hSocket == INVALID_SOCKET || pnode->hSocket < 0)
615                     continue;
616                 FD_SET(pnode->hSocket, &fdsetRecv);
617                 FD_SET(pnode->hSocket, &fdsetError);
618                 hSocketMax = max(hSocketMax, pnode->hSocket);
619                 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
620                     if (!pnode->vSend.empty())
621                         FD_SET(pnode->hSocket, &fdsetSend);
622             }
623         }
624
625         vnThreadsRunning[0]--;
626         int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
627         vnThreadsRunning[0]++;
628         if (fShutdown)
629             return;
630         if (nSelect == SOCKET_ERROR)
631         {
632             int nErr = WSAGetLastError();
633             printf("socket select error %d\n", nErr);
634             for (int i = 0; i <= hSocketMax; i++)
635                 FD_SET(i, &fdsetRecv);
636             FD_ZERO(&fdsetSend);
637             FD_ZERO(&fdsetError);
638             Sleep(timeout.tv_usec/1000);
639         }
640
641
642         //
643         // Accept new connections
644         //
645         if (FD_ISSET(hListenSocket, &fdsetRecv))
646         {
647             struct sockaddr_in sockaddr;
648             socklen_t len = sizeof(sockaddr);
649             SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
650             CAddress addr(sockaddr);
651             if (hSocket == INVALID_SOCKET)
652             {
653                 if (WSAGetLastError() != WSAEWOULDBLOCK)
654                     printf("socket error accept failed: %d\n", WSAGetLastError());
655             }
656             else
657             {
658                 printf("accepted connection %s\n", addr.ToStringLog().c_str());
659                 CNode* pnode = new CNode(hSocket, addr, true);
660                 pnode->AddRef();
661                 CRITICAL_BLOCK(cs_vNodes)
662                     vNodes.push_back(pnode);
663             }
664         }
665
666
667         //
668         // Service each socket
669         //
670         vector<CNode*> vNodesCopy;
671         CRITICAL_BLOCK(cs_vNodes)
672         {
673             vNodesCopy = vNodes;
674             foreach(CNode* pnode, vNodesCopy)
675                 pnode->AddRef();
676         }
677         foreach(CNode* pnode, vNodesCopy)
678         {
679             if (fShutdown)
680                 return;
681
682             //
683             // Receive
684             //
685             if (pnode->hSocket == INVALID_SOCKET)
686                 continue;
687             if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
688             {
689                 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
690                 {
691                     CDataStream& vRecv = pnode->vRecv;
692                     unsigned int nPos = vRecv.size();
693
694                     // typical socket buffer is 8K-64K
695                     char pchBuf[0x10000];
696                     int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
697                     if (nBytes > 0)
698                     {
699                         vRecv.resize(nPos + nBytes);
700                         memcpy(&vRecv[nPos], pchBuf, nBytes);
701                         pnode->nLastRecv = GetTime();
702                     }
703                     else if (nBytes == 0)
704                     {
705                         // socket closed gracefully
706                         if (!pnode->fDisconnect)
707                             printf("socket closed\n");
708                         pnode->CloseSocketDisconnect();
709                     }
710                     else if (nBytes < 0)
711                     {
712                         // error
713                         int nErr = WSAGetLastError();
714                         if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
715                         {
716                             if (!pnode->fDisconnect)
717                                 printf("socket recv error %d\n", nErr);
718                             pnode->CloseSocketDisconnect();
719                         }
720                     }
721                 }
722             }
723
724             //
725             // Send
726             //
727             if (pnode->hSocket == INVALID_SOCKET)
728                 continue;
729             if (FD_ISSET(pnode->hSocket, &fdsetSend))
730             {
731                 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
732                 {
733                     CDataStream& vSend = pnode->vSend;
734                     if (!vSend.empty())
735                     {
736                         int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
737                         if (nBytes > 0)
738                         {
739                             vSend.erase(vSend.begin(), vSend.begin() + nBytes);
740                             pnode->nLastSend = GetTime();
741                         }
742                         else if (nBytes < 0)
743                         {
744                             // error
745                             int nErr = WSAGetLastError();
746                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
747                             {
748                                 printf("socket send error %d\n", nErr);
749                                 pnode->CloseSocketDisconnect();
750                             }
751                         }
752                     }
753                 }
754             }
755
756             //
757             // Inactivity checking
758             //
759             if (pnode->vSend.empty())
760                 pnode->nLastSendEmpty = GetTime();
761             if (GetTime() - pnode->nTimeConnected > 60)
762             {
763                 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
764                 {
765                     printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
766                     pnode->fDisconnect = true;
767                 }
768                 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
769                 {
770                     printf("socket not sending\n");
771                     pnode->fDisconnect = true;
772                 }
773                 else if (GetTime() - pnode->nLastRecv > 90*60)
774                 {
775                     printf("socket inactivity timeout\n");
776                     pnode->fDisconnect = true;
777                 }
778             }
779         }
780         CRITICAL_BLOCK(cs_vNodes)
781         {
782             foreach(CNode* pnode, vNodesCopy)
783                 pnode->Release();
784         }
785
786         nThreadSocketHandlerHeartbeat = GetTime();
787         Sleep(10);
788     }
789 }
790
791
792
793
794
795
796
797
798
799
800
801
802
803 unsigned int pnSeed[] =
804 {
805     0x35218252, 0x9c9c9618, 0xda6bacad, 0xb9aca862, 0x97c235c6,
806     0x146f9562, 0xb67b9e4b, 0x87cf4bc0, 0xb83945d0, 0x984333ad,
807     0xbbeec555, 0x6f0eb440, 0xe0005318, 0x7797e460, 0xddc60fcc,
808     0xb3bbd24a, 0x1ac85746, 0x641846a6, 0x85ee1155, 0xbb2e7a4c,
809     0x9cb8514b, 0xfc342648, 0x62958fae, 0xd0a8c87a, 0xa800795b,
810     0xda8c814e, 0x256a0c80, 0x3f23ec63, 0xd565df43, 0x997d9044,
811     0xaa121448, 0xbed8688e, 0x59d09a5e, 0xb2931243, 0x3730ba18,
812     0xdd3462d0, 0x4e4d1448, 0x171df645, 0x84ee1155,
813     0x248ac445, 0x0e634444, 0x0ded1b63, 0x30c01e60,
814     0xa2b9a094, 0x29e4fd43, 0x9ce61b4c, 0xdae09744,
815 };
816
817
818
819 void ThreadOpenConnections(void* parg)
820 {
821     IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
822     try
823     {
824         vnThreadsRunning[1]++;
825         ThreadOpenConnections2(parg);
826         vnThreadsRunning[1]--;
827     }
828     catch (std::exception& e) {
829         vnThreadsRunning[1]--;
830         PrintException(&e, "ThreadOpenConnections()");
831     } catch (...) {
832         vnThreadsRunning[1]--;
833         PrintException(NULL, "ThreadOpenConnections()");
834     }
835     printf("ThreadOpenConnections exiting\n");
836 }
837
838 void ThreadOpenConnections2(void* parg)
839 {
840     printf("ThreadOpenConnections started\n");
841
842     // Connect to specific addresses
843     if (mapArgs.count("-connect"))
844     {
845         for (int64 nLoop = 0;; nLoop++)
846         {
847             foreach(string strAddr, mapMultiArgs["-connect"])
848             {
849                 CAddress addr(strAddr, NODE_NETWORK);
850                 if (addr.IsValid())
851                     OpenNetworkConnection(addr);
852                 for (int i = 0; i < 10 && i < nLoop; i++)
853                 {
854                     Sleep(500);
855                     if (fShutdown)
856                         return;
857                 }
858             }
859         }
860     }
861
862     // Connect to manually added nodes first
863     if (mapArgs.count("-addnode"))
864     {
865         foreach(string strAddr, mapMultiArgs["-addnode"])
866         {
867             CAddress addr(strAddr, NODE_NETWORK);
868             if (addr.IsValid())
869             {
870                 OpenNetworkConnection(addr);
871                 Sleep(500);
872                 if (fShutdown)
873                     return;
874             }
875         }
876     }
877
878     // Initiate network connections
879     int64 nStart = GetTime();
880     loop
881     {
882         // Wait
883         vnThreadsRunning[1]--;
884         Sleep(500);
885         const int nMaxConnections = 8;
886         while (vNodes.size() >= nMaxConnections)
887         {
888             Sleep(2000);
889             if (fShutdown)
890                 return;
891         }
892         vnThreadsRunning[1]++;
893         if (fShutdown)
894             return;
895
896         CRITICAL_BLOCK(cs_mapAddresses)
897         {
898             // Add seed nodes if IRC isn't working
899             static bool fSeedUsed;
900             bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
901             if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR))
902             {
903                 for (int i = 0; i < ARRAYLEN(pnSeed); i++)
904                 {
905                     // It'll only connect to one or two seed nodes because once it connects,
906                     // it'll get a pile of addresses with newer timestamps.
907                     CAddress addr;
908                     addr.ip = pnSeed[i];
909                     addr.nTime = 0;
910                     AddAddress(addr);
911                 }
912                 fSeedUsed = true;
913             }
914
915             if (fSeedUsed && mapAddresses.size() > ARRAYLEN(pnSeed) + 100)
916             {
917                 // Disconnect seed nodes
918                 set<unsigned int> setSeed(pnSeed, pnSeed + ARRAYLEN(pnSeed));
919                 static int64 nSeedDisconnected;
920                 if (nSeedDisconnected == 0)
921                 {
922                     nSeedDisconnected = GetTime();
923                     CRITICAL_BLOCK(cs_vNodes)
924                         foreach(CNode* pnode, vNodes)
925                             if (setSeed.count(pnode->addr.ip))
926                                 pnode->fDisconnect = true;
927                 }
928
929                 // Keep setting timestamps to 0 so they won't reconnect
930                 if (GetTime() - nSeedDisconnected < 60 * 60)
931                 {
932                     foreach(PAIRTYPE(const vector<unsigned char>, CAddress)& item, mapAddresses)
933                     {
934                         if (setSeed.count(item.second.ip))
935                         {
936                             item.second.nTime = 0;
937                             CAddrDB().WriteAddress(item.second);
938                         }
939                     }
940                 }
941             }
942         }
943
944
945         //
946         // Choose an address to connect to based on most recently seen
947         //
948         CAddress addrConnect;
949         int64 nBest = INT64_MIN;
950
951         // Do this here so we don't have to critsect vNodes inside mapAddresses critsect
952         set<unsigned int> setConnected;
953         CRITICAL_BLOCK(cs_vNodes)
954             foreach(CNode* pnode, vNodes)
955                 setConnected.insert(pnode->addr.ip);
956
957         CRITICAL_BLOCK(cs_mapAddresses)
958         {
959             foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
960             {
961                 const CAddress& addr = item.second;
962                 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip))
963                     continue;
964                 int64 nSinceLastSeen = GetAdjustedTime() - addr.nTime;
965                 int64 nSinceLastTry = GetAdjustedTime() - addr.nLastTry;
966
967                 // Randomize the order in a deterministic way, putting the standard port first
968                 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
969                 if (addr.port != DEFAULT_PORT)
970                     nRandomizer += 2 * 60 * 60;
971
972                 // Last seen  Base retry frequency
973                 //   <1 hour   10 min
974                 //    1 hour    1 hour
975                 //    4 hours   2 hours
976                 //   24 hours   5 hours
977                 //   48 hours   7 hours
978                 //    7 days   13 hours
979                 //   30 days   27 hours
980                 //   90 days   46 hours
981                 //  365 days   93 hours
982                 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
983
984                 // Fast reconnect for one hour after last seen
985                 if (nSinceLastSeen < 60 * 60)
986                     nDelay = 10 * 60;
987
988                 // Limit retry frequency
989                 if (nSinceLastTry < nDelay)
990                     continue;
991
992                 // If we have IRC, we'll be notified when they first come online,
993                 // and again every 24 hours by the refresh broadcast.
994                 if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)
995                     continue;
996
997                 // Only try the old stuff if we don't have enough connections
998                 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
999                     continue;
1000
1001                 // If multiple addresses are ready, prioritize by time since
1002                 // last seen and time since last tried.
1003                 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
1004                 if (nScore > nBest)
1005                 {
1006                     nBest = nScore;
1007                     addrConnect = addr;
1008                 }
1009             }
1010         }
1011
1012         if (addrConnect.IsValid())
1013             OpenNetworkConnection(addrConnect);
1014     }
1015 }
1016
1017 bool OpenNetworkConnection(const CAddress& addrConnect)
1018 {
1019     //
1020     // Initiate outbound network connection
1021     //
1022     if (fShutdown)
1023         return false;
1024     if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
1025         return false;
1026
1027     vnThreadsRunning[1]--;
1028     CNode* pnode = ConnectNode(addrConnect);
1029     vnThreadsRunning[1]++;
1030     if (fShutdown)
1031         return false;
1032     if (!pnode)
1033         return false;
1034     pnode->fNetworkNode = true;
1035
1036     if (addrLocalHost.IsRoutable() && !fUseProxy)
1037     {
1038         // Advertise our address
1039         vector<CAddress> vAddr;
1040         vAddr.push_back(addrLocalHost);
1041         pnode->PushMessage("addr", vAddr);
1042     }
1043
1044     // Get as many addresses as we can
1045     pnode->PushMessage("getaddr");
1046     pnode->fGetAddr = true; // don't relay the results of the getaddr
1047
1048     ////// should the one on the receiving end do this too?
1049     // Subscribe our local subscription list
1050     const unsigned int nHops = 0;
1051     for (unsigned int nChannel = 0; nChannel < pnodeLocalHost->vfSubscribe.size(); nChannel++)
1052         if (pnodeLocalHost->vfSubscribe[nChannel])
1053             pnode->PushMessage("subscribe", nChannel, nHops);
1054
1055     return true;
1056 }
1057
1058
1059
1060
1061
1062
1063
1064
1065 void ThreadMessageHandler(void* parg)
1066 {
1067     IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
1068     try
1069     {
1070         vnThreadsRunning[2]++;
1071         ThreadMessageHandler2(parg);
1072         vnThreadsRunning[2]--;
1073     }
1074     catch (std::exception& e) {
1075         vnThreadsRunning[2]--;
1076         PrintException(&e, "ThreadMessageHandler()");
1077     } catch (...) {
1078         vnThreadsRunning[2]--;
1079         PrintException(NULL, "ThreadMessageHandler()");
1080     }
1081     printf("ThreadMessageHandler exiting\n");
1082 }
1083
1084 void ThreadMessageHandler2(void* parg)
1085 {
1086     printf("ThreadMessageHandler started\n");
1087     SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1088     while (!fShutdown)
1089     {
1090         vector<CNode*> vNodesCopy;
1091         CRITICAL_BLOCK(cs_vNodes)
1092         {
1093             vNodesCopy = vNodes;
1094             foreach(CNode* pnode, vNodesCopy)
1095                 pnode->AddRef();
1096         }
1097
1098         // Poll the connected nodes for messages
1099         CNode* pnodeTrickle = NULL;
1100         if (!vNodesCopy.empty())
1101             pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1102         foreach(CNode* pnode, vNodesCopy)
1103         {
1104             // Receive messages
1105             TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
1106                 ProcessMessages(pnode);
1107             if (fShutdown)
1108                 return;
1109
1110             // Send messages
1111             TRY_CRITICAL_BLOCK(pnode->cs_vSend)
1112                 SendMessages(pnode, pnode == pnodeTrickle);
1113             if (fShutdown)
1114                 return;
1115         }
1116
1117         CRITICAL_BLOCK(cs_vNodes)
1118         {
1119             foreach(CNode* pnode, vNodesCopy)
1120                 pnode->Release();
1121         }
1122
1123         // Wait and allow messages to bunch up
1124         vnThreadsRunning[2]--;
1125         Sleep(100);
1126         vnThreadsRunning[2]++;
1127         if (fShutdown)
1128             return;
1129     }
1130 }
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140 bool BindListenPort(string& strError)
1141 {
1142     strError = "";
1143     int nOne = 1;
1144
1145 #ifdef __WXMSW__
1146     // Initialize Windows Sockets
1147     WSADATA wsadata;
1148     int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1149     if (ret != NO_ERROR)
1150     {
1151         strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1152         printf("%s\n", strError.c_str());
1153         return false;
1154     }
1155 #endif
1156
1157     // Create socket for listening for incoming connections
1158     hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1159     if (hListenSocket == INVALID_SOCKET)
1160     {
1161         strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1162         printf("%s\n", strError.c_str());
1163         return false;
1164     }
1165
1166 #if defined(__BSD__) || defined(__WXMAC_OSX__)
1167     // Different way of disabling SIGPIPE on BSD
1168     setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1169 #endif
1170
1171 #ifndef __WXMSW__
1172     // Allow binding if the port is still in TIME_WAIT state after
1173     // the program was closed and restarted.  Not an issue on windows.
1174     setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1175 #endif
1176
1177 #ifdef __WXMSW__
1178     // Set to nonblocking, incoming connections will also inherit this
1179     if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1180 #else
1181     if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1182 #endif
1183     {
1184         strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1185         printf("%s\n", strError.c_str());
1186         return false;
1187     }
1188
1189     // The sockaddr_in structure specifies the address family,
1190     // IP address, and port for the socket that is being bound
1191     struct sockaddr_in sockaddr;
1192     memset(&sockaddr, 0, sizeof(sockaddr));
1193     sockaddr.sin_family = AF_INET;
1194     sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
1195     sockaddr.sin_port = DEFAULT_PORT;
1196     if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
1197     {
1198         int nErr = WSAGetLastError();
1199         if (nErr == WSAEADDRINUSE)
1200             strError = strprintf("Unable to bind to port %d on this computer.  Bitcoin is probably already running.", ntohs(sockaddr.sin_port));
1201         else
1202             strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
1203         printf("%s\n", strError.c_str());
1204         return false;
1205     }
1206     printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
1207
1208     // Listen for incoming connections
1209     if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1210     {
1211         strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1212         printf("%s\n", strError.c_str());
1213         return false;
1214     }
1215
1216     return true;
1217 }
1218
1219 void StartNode(void* parg)
1220 {
1221     if (pnodeLocalHost == NULL)
1222         pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices));
1223
1224 #ifdef __WXMSW__
1225     // Get local host ip
1226     char pszHostName[1000] = "";
1227     if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1228     {
1229         struct hostent* phostent = gethostbyname(pszHostName);
1230         if (phostent)
1231         {
1232             // Take the first IP that isn't loopback 127.x.x.x
1233             for (int i = 0; phostent->h_addr_list[i] != NULL; i++)
1234                 printf("host ip %d: %s\n", i, CAddress(*(unsigned int*)phostent->h_addr_list[i]).ToStringIP().c_str());
1235             for (int i = 0; phostent->h_addr_list[i] != NULL; i++)
1236             {
1237                 CAddress addr(*(unsigned int*)phostent->h_addr_list[i], DEFAULT_PORT, nLocalServices);
1238                 if (addr.IsValid() && addr.GetByte(3) != 127)
1239                 {
1240                     addrLocalHost = addr;
1241                     break;
1242                 }
1243             }
1244         }
1245     }
1246 #else
1247     // Get local host ip
1248     struct ifaddrs* myaddrs;
1249     if (getifaddrs(&myaddrs) == 0)
1250     {
1251         for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1252         {
1253             if (ifa->ifa_addr == NULL) continue;
1254             if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1255             if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1256             if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1257             char pszIP[100];
1258             if (ifa->ifa_addr->sa_family == AF_INET)
1259             {
1260                 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1261                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
1262                     printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
1263
1264                 // Take the first IP that isn't loopback 127.x.x.x
1265                 CAddress addr(*(unsigned int*)&s4->sin_addr, DEFAULT_PORT, nLocalServices);
1266                 if (addr.IsValid() && addr.GetByte(3) != 127)
1267                 {
1268                     addrLocalHost = addr;
1269                     break;
1270                 }
1271             }
1272             else if (ifa->ifa_addr->sa_family == AF_INET6)
1273             {
1274                 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1275                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
1276                     printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
1277             }
1278         }
1279         freeifaddrs(myaddrs);
1280     }
1281 #endif
1282     printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1283
1284     // Get our external IP address for incoming connections
1285     if (fUseProxy)
1286     {
1287         // Proxies can't take incoming connections
1288         addrLocalHost.ip = CAddress("0.0.0.0").ip;
1289         printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1290     }
1291     else
1292     {
1293         if (addrIncoming.IsValid())
1294             addrLocalHost.ip = addrIncoming.ip;
1295
1296         if (GetMyExternalIP(addrLocalHost.ip))
1297         {
1298             addrIncoming = addrLocalHost;
1299             CWalletDB().WriteSetting("addrIncoming", addrIncoming);
1300             printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1301         }
1302     }
1303
1304     //
1305     // Start threads
1306     //
1307
1308     // Get addresses from IRC and advertise ours
1309     if (!CreateThread(ThreadIRCSeed, NULL))
1310         printf("Error: CreateThread(ThreadIRCSeed) failed\n");
1311
1312     // Send and receive from sockets, accept connections
1313     pthread_t hThreadSocketHandler = CreateThread(ThreadSocketHandler, NULL, true);
1314
1315     // Initiate outbound connections
1316     if (!CreateThread(ThreadOpenConnections, NULL))
1317         printf("Error: CreateThread(ThreadOpenConnections) failed\n");
1318
1319     // Process messages
1320     if (!CreateThread(ThreadMessageHandler, NULL))
1321         printf("Error: CreateThread(ThreadMessageHandler) failed\n");
1322
1323     // Generate coins in the background
1324     GenerateBitcoins(fGenerateBitcoins);
1325
1326     //
1327     // Thread monitoring
1328     // Not really needed anymore, the cause of the hanging was fixed
1329     //
1330     loop
1331     {
1332         Sleep(1000);
1333         if (fShutdown)
1334             return;
1335         if (GetTime() - nThreadSocketHandlerHeartbeat > 15 * 60)
1336         {
1337             // First see if closing sockets will free it
1338             printf("*** ThreadSocketHandler is stopped ***\n");
1339             CRITICAL_BLOCK(cs_vNodes)
1340             {
1341                 foreach(CNode* pnode, vNodes)
1342                 {
1343                     bool fGot = false;
1344                     TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
1345                         TRY_CRITICAL_BLOCK(pnode->cs_vSend)
1346                             fGot = true;
1347                     if (!fGot)
1348                     {
1349                         printf("*** closing socket\n");
1350                         pnode->CloseSocketDisconnect();
1351                     }
1352                 }
1353             }
1354             Sleep(10000);
1355             if (fShutdown)
1356                 return;
1357             if (GetTime() - nThreadSocketHandlerHeartbeat < 60)
1358                 continue;
1359
1360             // Hopefully it never comes to this.
1361             // We know it'll always be hung in the recv or send call.
1362             // cs_vRecv or cs_vSend may be left permanently unreleased,
1363             // but we always only use TRY_CRITICAL_SECTION on them.
1364             printf("*** Restarting ThreadSocketHandler ***\n");
1365             TerminateThread(hThreadSocketHandler, 0);
1366             #ifdef __WXMSW__
1367             CloseHandle(hThreadSocketHandler);
1368             #endif
1369             vnThreadsRunning[0] = 0;
1370
1371             // Restart
1372             hThreadSocketHandler = CreateThread(ThreadSocketHandler, NULL, true);
1373             nThreadSocketHandlerHeartbeat = GetTime();
1374         }
1375     }
1376 }
1377
1378 bool StopNode()
1379 {
1380     printf("StopNode()\n");
1381     fShutdown = true;
1382     nTransactionsUpdated++;
1383     int64 nStart = GetTime();
1384     while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0)
1385     {
1386         if (GetTime() - nStart > 20)
1387             break;
1388         Sleep(20);
1389     }
1390     if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
1391     if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
1392     if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
1393     if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
1394     if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
1395     while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
1396         Sleep(20);
1397     Sleep(50);
1398
1399     return true;
1400 }
1401
1402 class CNetCleanup
1403 {
1404 public:
1405     CNetCleanup()
1406     {
1407     }
1408     ~CNetCleanup()
1409     {
1410         // Close sockets
1411         foreach(CNode* pnode, vNodes)
1412             if (pnode->hSocket != INVALID_SOCKET)
1413                 closesocket(pnode->hSocket);
1414         if (hListenSocket != INVALID_SOCKET)
1415             if (closesocket(hListenSocket) == SOCKET_ERROR)
1416                 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1417
1418 #ifdef __WXMSW__
1419         // Shutdown Windows Sockets
1420         WSACleanup();
1421 #endif
1422     }
1423 }
1424 instance_of_cnetcleanup;