Bugfix: avoid sub-cent change (lost in fees) whenever possible
[bitcoin.git] / net.cpp
blobb022dad9efdb2eb3a86ce18fa2f9f4e33fdf1d78
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.
5 #include "headers.h"
7 static const int MAX_OUTBOUND_CONNECTIONS = 8;
9 void ThreadMessageHandler2(void* parg);
10 void ThreadSocketHandler2(void* parg);
11 void ThreadOpenConnections2(void* parg);
12 bool OpenNetworkConnection(const CAddress& addrConnect);
19 // Global state variables
21 bool fClient = false;
22 uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
23 CAddress addrLocalHost(0, 0, nLocalServices);
24 CNode* pnodeLocalHost = NULL;
25 uint64 nLocalHostNonce = 0;
26 array<int, 10> vnThreadsRunning;
27 SOCKET hListenSocket = INVALID_SOCKET;
29 vector<CNode*> vNodes;
30 CCriticalSection cs_vNodes;
31 map<vector<unsigned char>, CAddress> mapAddresses;
32 CCriticalSection cs_mapAddresses;
33 map<CInv, CDataStream> mapRelay;
34 deque<pair<int64, CInv> > vRelayExpiration;
35 CCriticalSection cs_mapRelay;
36 map<CInv, int64> mapAlreadyAskedFor;
38 // Settings
39 int fUseProxy = false;
40 CAddress addrProxy("127.0.0.1:9050");
46 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
48 // Filter out duplicate requests
49 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
50 return;
51 pindexLastGetBlocksBegin = pindexBegin;
52 hashLastGetBlocksEnd = hashEnd;
54 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
61 bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
63 hSocketRet = INVALID_SOCKET;
65 SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
66 if (hSocket == INVALID_SOCKET)
67 return false;
68 #ifdef BSD
69 int set = 1;
70 setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
71 #endif
73 bool fRoutable = !(addrConnect.GetByte(3) == 10 || (addrConnect.GetByte(3) == 192 && addrConnect.GetByte(2) == 168));
74 bool fProxy = (fUseProxy && fRoutable);
75 struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
77 if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
79 closesocket(hSocket);
80 return false;
83 if (fProxy)
85 printf("proxy connecting %s\n", addrConnect.ToStringLog().c_str());
86 char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
87 memcpy(pszSocks4IP + 2, &addrConnect.port, 2);
88 memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);
89 char* pszSocks4 = pszSocks4IP;
90 int nSize = sizeof(pszSocks4IP);
92 int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
93 if (ret != nSize)
95 closesocket(hSocket);
96 return error("Error sending to proxy");
98 char pchRet[8];
99 if (recv(hSocket, pchRet, 8, 0) != 8)
101 closesocket(hSocket);
102 return error("Error reading proxy response");
104 if (pchRet[1] != 0x5a)
106 closesocket(hSocket);
107 if (pchRet[1] != 0x5b)
108 printf("ERROR: Proxy returned error %d\n", pchRet[1]);
109 return false;
111 printf("proxy connected %s\n", addrConnect.ToStringLog().c_str());
114 hSocketRet = hSocket;
115 return true;
120 bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const char* pszKeyword, unsigned int& ipRet)
122 SOCKET hSocket;
123 if (!ConnectSocket(addrConnect, hSocket))
124 return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
126 send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
128 string strLine;
129 while (RecvLine(hSocket, strLine))
131 if (strLine.empty()) // HTTP response is separated from headers by blank line
133 loop
135 if (!RecvLine(hSocket, strLine))
137 closesocket(hSocket);
138 return false;
140 if (pszKeyword == NULL)
141 break;
142 if (strLine.find(pszKeyword) != -1)
144 strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
145 break;
148 closesocket(hSocket);
149 if (strLine.find("<") != -1)
150 strLine = strLine.substr(0, strLine.find("<"));
151 strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
152 while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
153 strLine.resize(strLine.size()-1);
154 CAddress addr(strLine.c_str());
155 printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
156 if (addr.ip == 0 || addr.ip == INADDR_NONE || !addr.IsRoutable())
157 return false;
158 ipRet = addr.ip;
159 return true;
162 closesocket(hSocket);
163 return error("GetMyExternalIP() : connection closed");
166 // We now get our external IP from the IRC server first and only use this as a backup
167 bool GetMyExternalIP(unsigned int& ipRet)
169 CAddress addrConnect;
170 const char* pszGet;
171 const char* pszKeyword;
173 if (fUseProxy)
174 return false;
176 for (int nLookup = 0; nLookup <= 1; nLookup++)
177 for (int nHost = 1; nHost <= 2; nHost++)
179 // We should be phasing out our use of sites like these. If we need
180 // replacements, we should ask for volunteers to put this simple
181 // php file on their webserver that prints the client IP:
182 // <?php echo $_SERVER["REMOTE_ADDR"]; ?>
183 if (nHost == 1)
185 addrConnect = CAddress("91.198.22.70:80"); // checkip.dyndns.org
187 if (nLookup == 1)
189 struct hostent* phostent = gethostbyname("checkip.dyndns.org");
190 if (phostent && phostent->h_addr_list && phostent->h_addr_list[0])
191 addrConnect = CAddress(*(u_long*)phostent->h_addr_list[0], htons(80));
194 pszGet = "GET / HTTP/1.1\r\n"
195 "Host: checkip.dyndns.org\r\n"
196 "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
197 "Connection: close\r\n"
198 "\r\n";
200 pszKeyword = "Address:";
202 else if (nHost == 2)
204 addrConnect = CAddress("74.208.43.192:80"); // www.showmyip.com
206 if (nLookup == 1)
208 struct hostent* phostent = gethostbyname("www.showmyip.com");
209 if (phostent && phostent->h_addr_list && phostent->h_addr_list[0])
210 addrConnect = CAddress(*(u_long*)phostent->h_addr_list[0], htons(80));
213 pszGet = "GET /simple/ HTTP/1.1\r\n"
214 "Host: www.showmyip.com\r\n"
215 "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
216 "Connection: close\r\n"
217 "\r\n";
219 pszKeyword = NULL; // Returns just IP address
222 if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
223 return true;
226 return false;
229 void ThreadGetMyExternalIP(void* parg)
231 // Wait for IRC to get it first
232 if (!GetBoolArg("-noirc"))
234 for (int i = 0; i < 2 * 60; i++)
236 Sleep(1000);
237 if (fGotExternalIP || fShutdown)
238 return;
242 // Fallback in case IRC fails to get it
243 if (GetMyExternalIP(addrLocalHost.ip))
245 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
246 if (addrLocalHost.IsRoutable())
248 // If we already connected to a few before we had our IP, go back and addr them.
249 // setAddrKnown automatically filters any duplicate sends.
250 CAddress addr(addrLocalHost);
251 addr.nTime = GetAdjustedTime();
252 CRITICAL_BLOCK(cs_vNodes)
253 foreach(CNode* pnode, vNodes)
254 pnode->PushAddress(addr);
263 bool AddAddress(CAddress addr, int64 nTimePenalty)
265 if (!addr.IsRoutable())
266 return false;
267 if (addr.ip == addrLocalHost.ip)
268 return false;
269 addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty);
270 CRITICAL_BLOCK(cs_mapAddresses)
272 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
273 if (it == mapAddresses.end())
275 // New address
276 printf("AddAddress(%s)\n", addr.ToStringLog().c_str());
277 mapAddresses.insert(make_pair(addr.GetKey(), addr));
278 CAddrDB().WriteAddress(addr);
279 return true;
281 else
283 bool fUpdated = false;
284 CAddress& addrFound = (*it).second;
285 if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
287 // Services have been added
288 addrFound.nServices |= addr.nServices;
289 fUpdated = true;
291 bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
292 int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
293 if (addrFound.nTime < addr.nTime - nUpdateInterval)
295 // Periodically update most recently seen time
296 addrFound.nTime = addr.nTime;
297 fUpdated = true;
299 if (fUpdated)
300 CAddrDB().WriteAddress(addrFound);
303 return false;
306 void AddressCurrentlyConnected(const CAddress& addr)
308 CRITICAL_BLOCK(cs_mapAddresses)
310 // Only if it's been published already
311 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
312 if (it != mapAddresses.end())
314 CAddress& addrFound = (*it).second;
315 int64 nUpdateInterval = 20 * 60;
316 if (addrFound.nTime < GetAdjustedTime() - nUpdateInterval)
318 // Periodically update most recently seen time
319 addrFound.nTime = GetAdjustedTime();
320 CAddrDB addrdb;
321 addrdb.WriteAddress(addrFound);
331 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
333 // If the dialog might get closed before the reply comes back,
334 // call this in the destructor so it doesn't get called after it's deleted.
335 CRITICAL_BLOCK(cs_vNodes)
337 foreach(CNode* pnode, vNodes)
339 CRITICAL_BLOCK(pnode->cs_mapRequests)
341 for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
343 CRequestTracker& tracker = (*mi).second;
344 if (tracker.fn == fn && tracker.param1 == param1)
345 pnode->mapRequests.erase(mi++);
346 else
347 mi++;
361 // Subscription methods for the broadcast and subscription system.
362 // Channel numbers are message numbers, i.e. MSG_TABLE and MSG_PRODUCT.
364 // The subscription system uses a meet-in-the-middle strategy.
365 // With 100,000 nodes, if senders broadcast to 1000 random nodes and receivers
366 // subscribe to 1000 random nodes, 99.995% (1 - 0.99^1000) of messages will get through.
369 bool AnySubscribed(unsigned int nChannel)
371 if (pnodeLocalHost->IsSubscribed(nChannel))
372 return true;
373 CRITICAL_BLOCK(cs_vNodes)
374 foreach(CNode* pnode, vNodes)
375 if (pnode->IsSubscribed(nChannel))
376 return true;
377 return false;
380 bool CNode::IsSubscribed(unsigned int nChannel)
382 if (nChannel >= vfSubscribe.size())
383 return false;
384 return vfSubscribe[nChannel];
387 void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
389 if (nChannel >= vfSubscribe.size())
390 return;
392 if (!AnySubscribed(nChannel))
394 // Relay subscribe
395 CRITICAL_BLOCK(cs_vNodes)
396 foreach(CNode* pnode, vNodes)
397 if (pnode != this)
398 pnode->PushMessage("subscribe", nChannel, nHops);
401 vfSubscribe[nChannel] = true;
404 void CNode::CancelSubscribe(unsigned int nChannel)
406 if (nChannel >= vfSubscribe.size())
407 return;
409 // Prevent from relaying cancel if wasn't subscribed
410 if (!vfSubscribe[nChannel])
411 return;
412 vfSubscribe[nChannel] = false;
414 if (!AnySubscribed(nChannel))
416 // Relay subscription cancel
417 CRITICAL_BLOCK(cs_vNodes)
418 foreach(CNode* pnode, vNodes)
419 if (pnode != this)
420 pnode->PushMessage("sub-cancel", nChannel);
432 CNode* FindNode(unsigned int ip)
434 CRITICAL_BLOCK(cs_vNodes)
436 foreach(CNode* pnode, vNodes)
437 if (pnode->addr.ip == ip)
438 return (pnode);
440 return NULL;
443 CNode* FindNode(CAddress addr)
445 CRITICAL_BLOCK(cs_vNodes)
447 foreach(CNode* pnode, vNodes)
448 if (pnode->addr == addr)
449 return (pnode);
451 return NULL;
454 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
456 if (addrConnect.ip == addrLocalHost.ip)
457 return NULL;
459 // Look for an existing connection
460 CNode* pnode = FindNode(addrConnect.ip);
461 if (pnode)
463 if (nTimeout != 0)
464 pnode->AddRef(nTimeout);
465 else
466 pnode->AddRef();
467 return pnode;
470 /// debug print
471 printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",
472 addrConnect.ToStringLog().c_str(),
473 (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
474 (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
476 CRITICAL_BLOCK(cs_mapAddresses)
477 mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
479 // Connect
480 SOCKET hSocket;
481 if (ConnectSocket(addrConnect, hSocket))
483 /// debug print
484 printf("connected %s\n", addrConnect.ToStringLog().c_str());
486 // Set to nonblocking
487 #ifdef __WXMSW__
488 u_long nOne = 1;
489 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
490 printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
491 #else
492 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
493 printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
494 #endif
496 // Add node
497 CNode* pnode = new CNode(hSocket, addrConnect, false);
498 if (nTimeout != 0)
499 pnode->AddRef(nTimeout);
500 else
501 pnode->AddRef();
502 CRITICAL_BLOCK(cs_vNodes)
503 vNodes.push_back(pnode);
505 pnode->nTimeConnected = GetTime();
506 return pnode;
508 else
510 return NULL;
514 void CNode::CloseSocketDisconnect()
516 fDisconnect = true;
517 if (hSocket != INVALID_SOCKET)
519 if (fDebug)
520 printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
521 printf("disconnecting node %s\n", addr.ToStringLog().c_str());
522 closesocket(hSocket);
523 hSocket = INVALID_SOCKET;
527 void CNode::Cleanup()
529 // All of a nodes broadcasts and subscriptions are automatically torn down
530 // when it goes down, so a node has to stay up to keep its broadcast going.
532 // Cancel subscriptions
533 for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
534 if (vfSubscribe[nChannel])
535 CancelSubscribe(nChannel);
550 void ThreadSocketHandler(void* parg)
552 IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
555 vnThreadsRunning[0]++;
556 ThreadSocketHandler2(parg);
557 vnThreadsRunning[0]--;
559 catch (std::exception& e) {
560 vnThreadsRunning[0]--;
561 PrintException(&e, "ThreadSocketHandler()");
562 } catch (...) {
563 vnThreadsRunning[0]--;
564 throw; // support pthread_cancel()
566 printf("ThreadSocketHandler exiting\n");
569 void ThreadSocketHandler2(void* parg)
571 printf("ThreadSocketHandler started\n");
572 list<CNode*> vNodesDisconnected;
573 int nPrevNodeCount = 0;
575 loop
578 // Disconnect nodes
580 CRITICAL_BLOCK(cs_vNodes)
582 // Disconnect unused nodes
583 vector<CNode*> vNodesCopy = vNodes;
584 foreach(CNode* pnode, vNodesCopy)
586 if (pnode->fDisconnect ||
587 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
589 // remove from vNodes
590 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
592 // close socket and cleanup
593 pnode->CloseSocketDisconnect();
594 pnode->Cleanup();
596 // hold in disconnected pool until all refs are released
597 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
598 if (pnode->fNetworkNode || pnode->fInbound)
599 pnode->Release();
600 vNodesDisconnected.push_back(pnode);
604 // Delete disconnected nodes
605 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
606 foreach(CNode* pnode, vNodesDisconnectedCopy)
608 // wait until threads are done using it
609 if (pnode->GetRefCount() <= 0)
611 bool fDelete = false;
612 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
613 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
614 TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
615 TRY_CRITICAL_BLOCK(pnode->cs_inventory)
616 fDelete = true;
617 if (fDelete)
619 vNodesDisconnected.remove(pnode);
620 delete pnode;
625 if (vNodes.size() != nPrevNodeCount)
627 nPrevNodeCount = vNodes.size();
628 MainFrameRepaint();
633 // Find which sockets have data to receive
635 struct timeval timeout;
636 timeout.tv_sec = 0;
637 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
639 fd_set fdsetRecv;
640 fd_set fdsetSend;
641 fd_set fdsetError;
642 FD_ZERO(&fdsetRecv);
643 FD_ZERO(&fdsetSend);
644 FD_ZERO(&fdsetError);
645 SOCKET hSocketMax = 0;
647 if(hListenSocket != INVALID_SOCKET)
648 FD_SET(hListenSocket, &fdsetRecv);
649 hSocketMax = max(hSocketMax, hListenSocket);
650 CRITICAL_BLOCK(cs_vNodes)
652 foreach(CNode* pnode, vNodes)
654 if (pnode->hSocket == INVALID_SOCKET || pnode->hSocket < 0)
655 continue;
656 FD_SET(pnode->hSocket, &fdsetRecv);
657 FD_SET(pnode->hSocket, &fdsetError);
658 hSocketMax = max(hSocketMax, pnode->hSocket);
659 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
660 if (!pnode->vSend.empty())
661 FD_SET(pnode->hSocket, &fdsetSend);
665 vnThreadsRunning[0]--;
666 int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
667 vnThreadsRunning[0]++;
668 if (fShutdown)
669 return;
670 if (nSelect == SOCKET_ERROR)
672 int nErr = WSAGetLastError();
673 printf("socket select error %d\n", nErr);
674 for (int i = 0; i <= hSocketMax; i++)
675 FD_SET(i, &fdsetRecv);
676 FD_ZERO(&fdsetSend);
677 FD_ZERO(&fdsetError);
678 Sleep(timeout.tv_usec/1000);
683 // Accept new connections
685 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
687 struct sockaddr_in sockaddr;
688 socklen_t len = sizeof(sockaddr);
689 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
690 CAddress addr(sockaddr);
691 bool fLimitConnections = false;
692 int nInbound = 0;
694 if (mapArgs.count("-maxconnections"))
695 fLimitConnections = true;
697 if (fLimitConnections)
699 CRITICAL_BLOCK(cs_vNodes)
700 foreach(CNode* pnode, vNodes)
701 if (pnode->fInbound)
702 nInbound++;
704 if (hSocket == INVALID_SOCKET)
706 if (WSAGetLastError() != WSAEWOULDBLOCK)
707 printf("socket error accept failed: %d\n", WSAGetLastError());
709 else if (fLimitConnections && nInbound >= atoi(mapArgs["-maxconnections"]) - MAX_OUTBOUND_CONNECTIONS)
711 closesocket(hSocket);
713 else
715 printf("accepted connection %s\n", addr.ToStringLog().c_str());
716 CNode* pnode = new CNode(hSocket, addr, true);
717 pnode->AddRef();
718 CRITICAL_BLOCK(cs_vNodes)
719 vNodes.push_back(pnode);
725 // Service each socket
727 vector<CNode*> vNodesCopy;
728 CRITICAL_BLOCK(cs_vNodes)
730 vNodesCopy = vNodes;
731 foreach(CNode* pnode, vNodesCopy)
732 pnode->AddRef();
734 foreach(CNode* pnode, vNodesCopy)
736 if (fShutdown)
737 return;
740 // Receive
742 if (pnode->hSocket == INVALID_SOCKET)
743 continue;
744 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
746 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
748 CDataStream& vRecv = pnode->vRecv;
749 unsigned int nPos = vRecv.size();
751 // typical socket buffer is 8K-64K
752 char pchBuf[0x10000];
753 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
754 if (nBytes > 0)
756 vRecv.resize(nPos + nBytes);
757 memcpy(&vRecv[nPos], pchBuf, nBytes);
758 pnode->nLastRecv = GetTime();
760 else if (nBytes == 0)
762 // socket closed gracefully
763 if (!pnode->fDisconnect)
764 printf("socket closed\n");
765 pnode->CloseSocketDisconnect();
767 else if (nBytes < 0)
769 // error
770 int nErr = WSAGetLastError();
771 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
773 if (!pnode->fDisconnect)
774 printf("socket recv error %d\n", nErr);
775 pnode->CloseSocketDisconnect();
782 // Send
784 if (pnode->hSocket == INVALID_SOCKET)
785 continue;
786 if (FD_ISSET(pnode->hSocket, &fdsetSend))
788 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
790 CDataStream& vSend = pnode->vSend;
791 if (!vSend.empty())
793 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
794 if (nBytes > 0)
796 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
797 pnode->nLastSend = GetTime();
799 else if (nBytes < 0)
801 // error
802 int nErr = WSAGetLastError();
803 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
805 printf("socket send error %d\n", nErr);
806 pnode->CloseSocketDisconnect();
814 // Inactivity checking
816 if (pnode->vSend.empty())
817 pnode->nLastSendEmpty = GetTime();
818 if (GetTime() - pnode->nTimeConnected > 60)
820 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
822 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
823 pnode->fDisconnect = true;
825 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
827 printf("socket not sending\n");
828 pnode->fDisconnect = true;
830 else if (GetTime() - pnode->nLastRecv > 90*60)
832 printf("socket inactivity timeout\n");
833 pnode->fDisconnect = true;
837 CRITICAL_BLOCK(cs_vNodes)
839 foreach(CNode* pnode, vNodesCopy)
840 pnode->Release();
843 Sleep(10);
859 unsigned int pnSeed[] =
861 // 2010/06
862 0x35218252, 0x9c9c9618, 0xda6bacad, 0xb9aca862, 0x97c235c6,
863 0x146f9562, 0xb67b9e4b, 0x87cf4bc0, 0xb83945d0, 0x984333ad,
864 0xbbeec555, 0x6f0eb440, 0xe0005318, 0x7797e460, 0xddc60fcc,
865 0xb3bbd24a, 0x1ac85746, 0x641846a6, 0x85ee1155, 0xbb2e7a4c,
866 0x9cb8514b, 0xfc342648, 0x62958fae, 0xd0a8c87a, 0xa800795b,
867 0xda8c814e, 0x256a0c80, 0x3f23ec63, 0xd565df43, 0x997d9044,
868 0xaa121448, 0xbed8688e, 0x59d09a5e, 0xb2931243, 0x3730ba18,
869 0xdd3462d0, 0x4e4d1448, 0x171df645, 0x84ee1155,
870 0x248ac445, 0x0e634444, 0x0ded1b63, 0x30c01e60,
871 0xa2b9a094, 0x29e4fd43, 0x9ce61b4c, 0xdae09744,
873 // 2010/08
874 0x5ae6bf43, 0x460be257, 0x7245c0cf, 0x4e0f028d, 0x26501760, 0x38643255, 0x67094f4f, 0x480449b8,
875 0x16545143, 0x1f082e5a, 0xaa428018, 0xe411e793, 0x14c1f862, 0x2726105b, 0x9b33ea50, 0xeeef86ca,
876 0xe3210d44, 0x0dca8b63, 0x3f9dfb18, 0x860340ad, 0xf33ba17a, 0x9018375c, 0x1de4e353, 0x0fa52dcb,
877 0x89c4555b, 0x109cf37b, 0x28c55b40, 0x04c801ae, 0x275c1e80, 0x6f7f745d, 0x7a2a5653, 0xa28e26d8,
878 0xa4e65db2, 0x99a06580, 0xf253ba44, 0x82cf6ab8, 0x859c2e8e, 0xf71a815d, 0xc18f1454, 0x71c8a943,
879 0x90d24e18, 0x311789b2, 0x74aba645, 0xde0bbfc3, 0xad724fad, 0xbf1ae15e, 0xbaa6fb54, 0x06e4d145,
880 0x51528645, 0x72120cd4, 0xd4cfd145, 0x0a7afed8, 0x9b9a5fad, 0x9e9ff45e, 0x10128355, 0xd44e8646,
881 0x04a07b47, 0x5fc9d547, 0xe0491e45, 0xbac21b41, 0x7aa31bae, 0x10483c5f, 0x94a23055, 0x73d9dc47,
882 0x1a99c247, 0x822fe847, 0x7e57ba48, 0xb19ea843, 0xa60621b2, 0x778cf163, 0x125c6556, 0xf94ba44f,
883 0xa61a0948, 0x6c839e4b, 0x29af5348, 0x68d84845, 0x752b95c3, 0xcf0d4663, 0x08e11e56, 0x75109550,
884 0x5f24b94c, 0x42426d4d, 0xfbbc0a4c, 0x70a9a246, 0xda7837cb, 0xae2a986d, 0xe283c358, 0x0c7ca954,
885 0x8e9bde59, 0x61521760, 0x6884444c, 0xa194e548, 0x9b8809cc, 0x16e96a8f, 0x956ff859, 0xfad5e555,
886 0x0ea70c80, 0x5b4ce26d, 0x7984444c, 0x1080d24a, 0x22a686cf, 0x6bf8c2ad, 0xb0f7485f, 0x06b66e56,
887 0x668373bc, 0x75506279, 0x3868694e, 0x12a5954b, 0x3a8b62d1, 0xb74fcbad, 0xa7dc3360, 0xc070b359,
888 0xa2b87242, 0xc45cab7c, 0x69882050, 0x14a5464b, 0x386acad5, 0x80b85db2, 0x1f78a062, 0xc608c55b,
889 0x4257d543, 0x7636ad80, 0x4432d655, 0xb2114d4b, 0x32639bd9, 0xadd75db2, 0x9be5a362, 0x6831bc5e,
890 0xf7f77046, 0x8f35ba81, 0x09bb4e59, 0xd0fb6b4e, 0xc5daa445, 0x9c611618, 0x355dcc62, 0xf2cf435e,
891 0x31e72c46, 0xdd8a43ad, 0x171f9c5b, 0xb4c2e355, 0xbe8af945, 0x613d3942, 0xe6f9e863, 0x7a3d855f,
892 0xa66adc47, 0x261089b2, 0x5a27105b, 0x6c28105b, 0xdd247946, 0xe6c3a445, 0x43a1ec63, 0x99b4dd5f,
893 0xb6834347, 0x5e9649bc, 0xf9dd545d, 0x6ae4c15b, 0xa5318a47, 0x7984ec47, 0x93a73b63, 0x0c60195f,
894 0xa5c85e4b, 0xa0a36dc2, 0x0739a95e, 0x3d44c15b, 0xfb940f4b, 0xd67c9148, 0x614f9876, 0x0a241c5f,
895 0xad9da74c, 0x4459abc8, 0x12e71b5f, 0x1c534a5d, 0x8ff5fc50, 0x2ca8864b, 0xd894fd80, 0x82ab3160,
896 0x390d804e, 0x2cf310cc, 0x680dad80, 0x691be15e, 0x5a8f4652, 0xaad0784d, 0x0d2431ad,
901 void ThreadOpenConnections(void* parg)
903 IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
906 vnThreadsRunning[1]++;
907 ThreadOpenConnections2(parg);
908 vnThreadsRunning[1]--;
910 catch (std::exception& e) {
911 vnThreadsRunning[1]--;
912 PrintException(&e, "ThreadOpenConnections()");
913 } catch (...) {
914 vnThreadsRunning[1]--;
915 PrintException(NULL, "ThreadOpenConnections()");
917 printf("ThreadOpenConnections exiting\n");
920 void ThreadOpenConnections2(void* parg)
922 printf("ThreadOpenConnections started\n");
924 // Connect to specific addresses
925 if (mapArgs.count("-connect"))
927 for (int64 nLoop = 0;; nLoop++)
929 foreach(string strAddr, mapMultiArgs["-connect"])
931 CAddress addr(strAddr, NODE_NETWORK);
932 if (addr.IsValid())
933 OpenNetworkConnection(addr);
934 for (int i = 0; i < 10 && i < nLoop; i++)
936 Sleep(500);
937 if (fShutdown)
938 return;
944 // Connect to manually added nodes first
945 if (mapArgs.count("-addnode"))
947 foreach(string strAddr, mapMultiArgs["-addnode"])
949 CAddress addr(strAddr, NODE_NETWORK);
950 if (addr.IsValid())
952 OpenNetworkConnection(addr);
953 Sleep(500);
954 if (fShutdown)
955 return;
960 // Initiate network connections
961 int64 nStart = GetTime();
962 loop
964 // Limit outbound connections
965 vnThreadsRunning[1]--;
966 Sleep(500);
967 loop
969 int nOutbound = 0;
970 CRITICAL_BLOCK(cs_vNodes)
971 foreach(CNode* pnode, vNodes)
972 if (!pnode->fInbound)
973 nOutbound++;
974 int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
975 if (mapArgs.count("-maxconnections"))
976 nMaxOutboundConnections = min(nMaxOutboundConnections, atoi(mapArgs["-maxconnections"]));
977 if (nOutbound < nMaxOutboundConnections)
978 break;
979 Sleep(2000);
980 if (fShutdown)
981 return;
983 vnThreadsRunning[1]++;
984 if (fShutdown)
985 return;
987 CRITICAL_BLOCK(cs_mapAddresses)
989 // Add seed nodes if IRC isn't working
990 static bool fSeedUsed;
991 bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
992 if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
994 for (int i = 0; i < ARRAYLEN(pnSeed); i++)
996 // It'll only connect to one or two seed nodes because once it connects,
997 // it'll get a pile of addresses with newer timestamps.
998 CAddress addr;
999 addr.ip = pnSeed[i];
1000 addr.nTime = 0;
1001 AddAddress(addr);
1003 fSeedUsed = true;
1006 if (fSeedUsed && mapAddresses.size() > ARRAYLEN(pnSeed) + 100)
1008 // Disconnect seed nodes
1009 set<unsigned int> setSeed(pnSeed, pnSeed + ARRAYLEN(pnSeed));
1010 static int64 nSeedDisconnected;
1011 if (nSeedDisconnected == 0)
1013 nSeedDisconnected = GetTime();
1014 CRITICAL_BLOCK(cs_vNodes)
1015 foreach(CNode* pnode, vNodes)
1016 if (setSeed.count(pnode->addr.ip))
1017 pnode->fDisconnect = true;
1020 // Keep setting timestamps to 0 so they won't reconnect
1021 if (GetTime() - nSeedDisconnected < 60 * 60)
1023 foreach(PAIRTYPE(const vector<unsigned char>, CAddress)& item, mapAddresses)
1025 if (setSeed.count(item.second.ip) && item.second.nTime != 0)
1027 item.second.nTime = 0;
1028 CAddrDB().WriteAddress(item.second);
1037 // Choose an address to connect to based on most recently seen
1039 CAddress addrConnect;
1040 int64 nBest = INT64_MIN;
1042 // Only connect to one address per a.b.?.? range.
1043 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1044 set<unsigned int> setConnected;
1045 CRITICAL_BLOCK(cs_vNodes)
1046 foreach(CNode* pnode, vNodes)
1047 setConnected.insert(pnode->addr.ip & 0x0000ffff);
1049 CRITICAL_BLOCK(cs_mapAddresses)
1051 foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
1053 const CAddress& addr = item.second;
1054 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
1055 continue;
1056 int64 nSinceLastSeen = GetAdjustedTime() - addr.nTime;
1057 int64 nSinceLastTry = GetAdjustedTime() - addr.nLastTry;
1059 // Randomize the order in a deterministic way, putting the standard port first
1060 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
1061 if (addr.port != GetDefaultPort())
1062 nRandomizer += 2 * 60 * 60;
1064 // Last seen Base retry frequency
1065 // <1 hour 10 min
1066 // 1 hour 1 hour
1067 // 4 hours 2 hours
1068 // 24 hours 5 hours
1069 // 48 hours 7 hours
1070 // 7 days 13 hours
1071 // 30 days 27 hours
1072 // 90 days 46 hours
1073 // 365 days 93 hours
1074 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
1076 // Fast reconnect for one hour after last seen
1077 if (nSinceLastSeen < 60 * 60)
1078 nDelay = 10 * 60;
1080 // Limit retry frequency
1081 if (nSinceLastTry < nDelay)
1082 continue;
1084 // If we have IRC, we'll be notified when they first come online,
1085 // and again every 24 hours by the refresh broadcast.
1086 if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)
1087 continue;
1089 // Only try the old stuff if we don't have enough connections
1090 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
1091 continue;
1093 // If multiple addresses are ready, prioritize by time since
1094 // last seen and time since last tried.
1095 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
1096 if (nScore > nBest)
1098 nBest = nScore;
1099 addrConnect = addr;
1104 if (addrConnect.IsValid())
1105 OpenNetworkConnection(addrConnect);
1109 bool OpenNetworkConnection(const CAddress& addrConnect)
1112 // Initiate outbound network connection
1114 if (fShutdown)
1115 return false;
1116 if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
1117 return false;
1119 vnThreadsRunning[1]--;
1120 CNode* pnode = ConnectNode(addrConnect);
1121 vnThreadsRunning[1]++;
1122 if (fShutdown)
1123 return false;
1124 if (!pnode)
1125 return false;
1126 pnode->fNetworkNode = true;
1128 return true;
1138 void ThreadMessageHandler(void* parg)
1140 IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
1143 vnThreadsRunning[2]++;
1144 ThreadMessageHandler2(parg);
1145 vnThreadsRunning[2]--;
1147 catch (std::exception& e) {
1148 vnThreadsRunning[2]--;
1149 PrintException(&e, "ThreadMessageHandler()");
1150 } catch (...) {
1151 vnThreadsRunning[2]--;
1152 PrintException(NULL, "ThreadMessageHandler()");
1154 printf("ThreadMessageHandler exiting\n");
1157 void ThreadMessageHandler2(void* parg)
1159 printf("ThreadMessageHandler started\n");
1160 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1161 while (!fShutdown)
1163 vector<CNode*> vNodesCopy;
1164 CRITICAL_BLOCK(cs_vNodes)
1166 vNodesCopy = vNodes;
1167 foreach(CNode* pnode, vNodesCopy)
1168 pnode->AddRef();
1171 // Poll the connected nodes for messages
1172 CNode* pnodeTrickle = NULL;
1173 if (!vNodesCopy.empty())
1174 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1175 foreach(CNode* pnode, vNodesCopy)
1177 // Receive messages
1178 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
1179 ProcessMessages(pnode);
1180 if (fShutdown)
1181 return;
1183 // Send messages
1184 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
1185 SendMessages(pnode, pnode == pnodeTrickle);
1186 if (fShutdown)
1187 return;
1190 CRITICAL_BLOCK(cs_vNodes)
1192 foreach(CNode* pnode, vNodesCopy)
1193 pnode->Release();
1196 // Wait and allow messages to bunch up.
1197 // Reduce vnThreadsRunning so StopNode has permission to exit while
1198 // we're sleeping, but we must always check fShutdown after doing this.
1199 vnThreadsRunning[2]--;
1200 Sleep(100);
1201 if (fRequestShutdown)
1202 Shutdown(NULL);
1203 vnThreadsRunning[2]++;
1204 if (fShutdown)
1205 return;
1217 bool BindListenPort(string& strError)
1219 strError = "";
1220 int nOne = 1;
1221 addrLocalHost.port = GetDefaultPort();
1223 #ifdef __WXMSW__
1224 // Initialize Windows Sockets
1225 WSADATA wsadata;
1226 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1227 if (ret != NO_ERROR)
1229 strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1230 printf("%s\n", strError.c_str());
1231 return false;
1233 #endif
1235 // Create socket for listening for incoming connections
1236 hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1237 if (hListenSocket == INVALID_SOCKET)
1239 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1240 printf("%s\n", strError.c_str());
1241 return false;
1244 #ifdef BSD
1245 // Different way of disabling SIGPIPE on BSD
1246 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1247 #endif
1249 #ifndef __WXMSW__
1250 // Allow binding if the port is still in TIME_WAIT state after
1251 // the program was closed and restarted. Not an issue on windows.
1252 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1253 #endif
1255 #ifdef __WXMSW__
1256 // Set to nonblocking, incoming connections will also inherit this
1257 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1258 #else
1259 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1260 #endif
1262 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1263 printf("%s\n", strError.c_str());
1264 return false;
1267 // The sockaddr_in structure specifies the address family,
1268 // IP address, and port for the socket that is being bound
1269 struct sockaddr_in sockaddr;
1270 memset(&sockaddr, 0, sizeof(sockaddr));
1271 sockaddr.sin_family = AF_INET;
1272 sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
1273 sockaddr.sin_port = GetDefaultPort();
1274 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
1276 int nErr = WSAGetLastError();
1277 if (nErr == WSAEADDRINUSE)
1278 strError = strprintf(_("Unable to bind to port %d on this computer. Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
1279 else
1280 strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
1281 printf("%s\n", strError.c_str());
1282 return false;
1284 printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
1286 // Listen for incoming connections
1287 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1289 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1290 printf("%s\n", strError.c_str());
1291 return false;
1294 return true;
1297 void StartNode(void* parg)
1299 if (pnodeLocalHost == NULL)
1300 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices));
1302 #ifdef __WXMSW__
1303 // Get local host ip
1304 char pszHostName[1000] = "";
1305 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1307 struct hostent* phostent = gethostbyname(pszHostName);
1308 if (phostent)
1310 // Take the first IP that isn't loopback 127.x.x.x
1311 for (int i = 0; phostent->h_addr_list[i] != NULL; i++)
1312 printf("host ip %d: %s\n", i, CAddress(*(unsigned int*)phostent->h_addr_list[i]).ToStringIP().c_str());
1313 for (int i = 0; phostent->h_addr_list[i] != NULL; i++)
1315 CAddress addr(*(unsigned int*)phostent->h_addr_list[i], GetDefaultPort(), nLocalServices);
1316 if (addr.IsValid() && addr.GetByte(3) != 127)
1318 addrLocalHost = addr;
1319 break;
1324 #else
1325 // Get local host ip
1326 struct ifaddrs* myaddrs;
1327 if (getifaddrs(&myaddrs) == 0)
1329 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1331 if (ifa->ifa_addr == NULL) continue;
1332 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1333 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1334 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1335 char pszIP[100];
1336 if (ifa->ifa_addr->sa_family == AF_INET)
1338 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1339 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
1340 printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
1342 // Take the first IP that isn't loopback 127.x.x.x
1343 CAddress addr(*(unsigned int*)&s4->sin_addr, GetDefaultPort(), nLocalServices);
1344 if (addr.IsValid() && addr.GetByte(3) != 127)
1346 addrLocalHost = addr;
1347 break;
1350 else if (ifa->ifa_addr->sa_family == AF_INET6)
1352 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1353 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
1354 printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
1357 freeifaddrs(myaddrs);
1359 #endif
1360 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1362 if (fUseProxy || mapArgs.count("-connect") || fNoListen)
1364 // Proxies can't take incoming connections
1365 addrLocalHost.ip = CAddress("0.0.0.0").ip;
1366 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1368 else
1370 CreateThread(ThreadGetMyExternalIP, NULL);
1374 // Start threads
1377 // Get addresses from IRC and advertise ours
1378 if (!CreateThread(ThreadIRCSeed, NULL))
1379 printf("Error: CreateThread(ThreadIRCSeed) failed\n");
1381 // Send and receive from sockets, accept connections
1382 pthread_t hThreadSocketHandler = CreateThread(ThreadSocketHandler, NULL, true);
1384 // Initiate outbound connections
1385 if (!CreateThread(ThreadOpenConnections, NULL))
1386 printf("Error: CreateThread(ThreadOpenConnections) failed\n");
1388 // Process messages
1389 if (!CreateThread(ThreadMessageHandler, NULL))
1390 printf("Error: CreateThread(ThreadMessageHandler) failed\n");
1392 // Generate coins in the background
1393 GenerateBitcoins(fGenerateBitcoins);
1396 bool StopNode()
1398 printf("StopNode()\n");
1399 fShutdown = true;
1400 nTransactionsUpdated++;
1401 int64 nStart = GetTime();
1402 while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0)
1404 if (GetTime() - nStart > 20)
1405 break;
1406 Sleep(20);
1408 if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
1409 if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
1410 if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
1411 if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
1412 if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
1413 while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
1414 Sleep(20);
1415 Sleep(50);
1417 return true;
1420 class CNetCleanup
1422 public:
1423 CNetCleanup()
1426 ~CNetCleanup()
1428 // Close sockets
1429 foreach(CNode* pnode, vNodes)
1430 if (pnode->hSocket != INVALID_SOCKET)
1431 closesocket(pnode->hSocket);
1432 if (hListenSocket != INVALID_SOCKET)
1433 if (closesocket(hListenSocket) == SOCKET_ERROR)
1434 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1436 #ifdef __WXMSW__
1437 // Shutdown Windows Sockets
1438 WSACleanup();
1439 #endif
1442 instance_of_cnetcleanup;