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.
8 #include <miniupnpc/miniwget.h>
9 #include <miniupnpc/miniupnpc.h>
10 #include <miniupnpc/upnpcommands.h>
11 #include <miniupnpc/upnperrors.h>
15 using namespace boost;
17 static const int MAX_OUTBOUND_CONNECTIONS = 8;
19 void ThreadMessageHandler2(void* parg);
20 void ThreadSocketHandler2(void* parg);
21 void ThreadOpenConnections2(void* parg);
23 void ThreadMapPort2(void* parg);
25 bool OpenNetworkConnection(const CAddress& addrConnect);
32 // Global state variables
35 bool fAllowDNS = false;
36 uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
37 CAddress addrLocalHost("0.0.0.0", 0, false, nLocalServices);
38 CNode* pnodeLocalHost = NULL;
39 uint64 nLocalHostNonce = 0;
40 array<int, 10> vnThreadsRunning;
41 SOCKET hListenSocket = INVALID_SOCKET;
43 vector<CNode*> vNodes;
44 CCriticalSection cs_vNodes;
45 map<vector<unsigned char>, CAddress> mapAddresses;
46 CCriticalSection cs_mapAddresses;
47 map<CInv, CDataStream> mapRelay;
48 deque<pair<int64, CInv> > vRelayExpiration;
49 CCriticalSection cs_mapRelay;
50 map<CInv, int64> mapAlreadyAskedFor;
53 int fUseProxy = false;
54 int nConnectTimeout = 5000;
55 CAddress addrProxy("127.0.0.1",9050);
60 unsigned short GetListenPort()
62 return (unsigned short)(GetArg("-port", GetDefaultPort()));
65 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
67 // Filter out duplicate requests
68 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
70 pindexLastGetBlocksBegin = pindexBegin;
71 hashLastGetBlocksEnd = hashEnd;
73 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
80 bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout)
82 hSocketRet = INVALID_SOCKET;
84 SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
85 if (hSocket == INVALID_SOCKET)
89 setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
92 bool fProxy = (fUseProxy && addrConnect.IsRoutable());
93 struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
97 if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
99 int fFlags = fcntl(hSocket, F_GETFL, 0);
100 if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
103 closesocket(hSocket);
108 if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
110 // WSAEINVAL is here because some legacy version of winsock uses it
111 if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
113 struct timeval timeout;
114 timeout.tv_sec = nTimeout / 1000;
115 timeout.tv_usec = (nTimeout % 1000) * 1000;
119 FD_SET(hSocket, &fdset);
120 int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
123 printf("connection timeout\n");
124 closesocket(hSocket);
127 if (nRet == SOCKET_ERROR)
129 printf("select() for connection failed: %i\n",WSAGetLastError());
130 closesocket(hSocket);
133 socklen_t nRetSize = sizeof(nRet);
135 if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
137 if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
140 printf("getsockopt() for connection failed: %i\n",WSAGetLastError());
141 closesocket(hSocket);
146 printf("connect() failed after select(): %i\n",nRet);
147 closesocket(hSocket);
152 else if (WSAGetLastError() != WSAEISCONN)
157 printf("connect() failed: %s\n",WSAGetLastError());
158 closesocket(hSocket);
164 this isn't even strictly necessary
165 CNode::ConnectNode immediately turns the socket back to non-blocking
166 but we'll turn it back to blocking just in case
170 if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
172 fFlags = fcntl(hSocket, F_GETFL, 0);
173 if (fcntl(hSocket, F_SETFL, fFlags & !O_NONBLOCK) == SOCKET_ERROR)
176 closesocket(hSocket);
182 printf("proxy connecting %s\n", addrConnect.ToString().c_str());
183 char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
184 memcpy(pszSocks4IP + 2, &addrConnect.port, 2);
185 memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);
186 char* pszSocks4 = pszSocks4IP;
187 int nSize = sizeof(pszSocks4IP);
189 int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
192 closesocket(hSocket);
193 return error("Error sending to proxy");
196 if (recv(hSocket, pchRet, 8, 0) != 8)
198 closesocket(hSocket);
199 return error("Error reading proxy response");
201 if (pchRet[1] != 0x5a)
203 closesocket(hSocket);
204 if (pchRet[1] != 0x5b)
205 printf("ERROR: Proxy returned error %d\n", pchRet[1]);
208 printf("proxy connected %s\n", addrConnect.ToString().c_str());
211 hSocketRet = hSocket;
215 // portDefault is in host order
216 bool Lookup(const char *pszName, vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup, int portDefault, bool fAllowPort)
221 int port = portDefault;
224 strlcpy(psz, pszName, sizeof(psz));
227 char* pszColon = strrchr(psz+1,':');
228 char *pszPortEnd = NULL;
229 int portParsed = pszColon ? strtoul(pszColon+1, &pszPortEnd, 10) : 0;
230 if (pszColon && pszPortEnd && pszPortEnd[0] == 0)
232 if (psz[0] == '[' && pszColon[-1] == ']')
234 // Future: enable IPv6 colon-notation inside []
241 if (port < 0 || port > USHRT_MAX)
246 unsigned int addrIP = inet_addr(pszHost);
247 if (addrIP != INADDR_NONE)
249 // valid IP address passed
250 vaddr.push_back(CAddress(addrIP, port, nServices));
257 struct hostent* phostent = gethostbyname(pszHost);
261 if (phostent->h_addrtype != AF_INET)
264 char** ppAddr = phostent->h_addr_list;
265 while (*ppAddr != NULL && vaddr.size() != nMaxSolutions)
267 CAddress addr(((struct in_addr*)ppAddr[0])->s_addr, port, nServices);
269 vaddr.push_back(addr);
273 return (vaddr.size() > 0);
276 // portDefault is in host order
277 bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup, int portDefault, bool fAllowPort)
279 vector<CAddress> vaddr;
280 bool fRet = Lookup(pszName, vaddr, nServices, 1, fAllowLookup, portDefault, fAllowPort);
286 bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const char* pszKeyword, unsigned int& ipRet)
289 if (!ConnectSocket(addrConnect, hSocket))
290 return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
292 send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
295 while (RecvLine(hSocket, strLine))
297 if (strLine.empty()) // HTTP response is separated from headers by blank line
301 if (!RecvLine(hSocket, strLine))
303 closesocket(hSocket);
306 if (pszKeyword == NULL)
308 if (strLine.find(pszKeyword) != -1)
310 strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
314 closesocket(hSocket);
315 if (strLine.find("<") != -1)
316 strLine = strLine.substr(0, strLine.find("<"));
317 strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
318 while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
319 strLine.resize(strLine.size()-1);
320 CAddress addr(strLine,0,true);
321 printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
322 if (addr.ip == 0 || addr.ip == INADDR_NONE || !addr.IsRoutable())
328 closesocket(hSocket);
329 return error("GetMyExternalIP() : connection closed");
332 // We now get our external IP from the IRC server first and only use this as a backup
333 bool GetMyExternalIP(unsigned int& ipRet)
335 CAddress addrConnect;
337 const char* pszKeyword;
342 for (int nLookup = 0; nLookup <= 1; nLookup++)
343 for (int nHost = 1; nHost <= 2; nHost++)
345 // We should be phasing out our use of sites like these. If we need
346 // replacements, we should ask for volunteers to put this simple
347 // php file on their webserver that prints the client IP:
348 // <?php echo $_SERVER["REMOTE_ADDR"]; ?>
351 addrConnect = CAddress("91.198.22.70",80); // checkip.dyndns.org
355 CAddress addrIP("checkip.dyndns.org", 80, true);
356 if (addrIP.IsValid())
357 addrConnect = addrIP;
360 pszGet = "GET / HTTP/1.1\r\n"
361 "Host: checkip.dyndns.org\r\n"
362 "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
363 "Connection: close\r\n"
366 pszKeyword = "Address:";
370 addrConnect = CAddress("74.208.43.192", 80); // www.showmyip.com
374 CAddress addrIP("www.showmyip.com", 80, true);
375 if (addrIP.IsValid())
376 addrConnect = addrIP;
379 pszGet = "GET /simple/ HTTP/1.1\r\n"
380 "Host: www.showmyip.com\r\n"
381 "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
382 "Connection: close\r\n"
385 pszKeyword = NULL; // Returns just IP address
388 if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
395 void ThreadGetMyExternalIP(void* parg)
397 // Wait for IRC to get it first
398 if (!GetBoolArg("-noirc"))
400 for (int i = 0; i < 2 * 60; i++)
403 if (fGotExternalIP || fShutdown)
408 // Fallback in case IRC fails to get it
409 if (GetMyExternalIP(addrLocalHost.ip))
411 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
412 if (addrLocalHost.IsRoutable())
414 // If we already connected to a few before we had our IP, go back and addr them.
415 // setAddrKnown automatically filters any duplicate sends.
416 CAddress addr(addrLocalHost);
417 addr.nTime = GetAdjustedTime();
418 CRITICAL_BLOCK(cs_vNodes)
419 BOOST_FOREACH(CNode* pnode, vNodes)
420 pnode->PushAddress(addr);
429 bool AddAddress(CAddress addr, int64 nTimePenalty)
431 if (!addr.IsRoutable())
433 if (addr.ip == addrLocalHost.ip)
435 addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty);
436 CRITICAL_BLOCK(cs_mapAddresses)
438 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
439 if (it == mapAddresses.end())
442 printf("AddAddress(%s)\n", addr.ToString().c_str());
443 mapAddresses.insert(make_pair(addr.GetKey(), addr));
444 CAddrDB().WriteAddress(addr);
449 bool fUpdated = false;
450 CAddress& addrFound = (*it).second;
451 if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
453 // Services have been added
454 addrFound.nServices |= addr.nServices;
457 bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
458 int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
459 if (addrFound.nTime < addr.nTime - nUpdateInterval)
461 // Periodically update most recently seen time
462 addrFound.nTime = addr.nTime;
466 CAddrDB().WriteAddress(addrFound);
472 void AddressCurrentlyConnected(const CAddress& addr)
474 CRITICAL_BLOCK(cs_mapAddresses)
476 // Only if it's been published already
477 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
478 if (it != mapAddresses.end())
480 CAddress& addrFound = (*it).second;
481 int64 nUpdateInterval = 20 * 60;
482 if (addrFound.nTime < GetAdjustedTime() - nUpdateInterval)
484 // Periodically update most recently seen time
485 addrFound.nTime = GetAdjustedTime();
487 addrdb.WriteAddress(addrFound);
497 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
499 // If the dialog might get closed before the reply comes back,
500 // call this in the destructor so it doesn't get called after it's deleted.
501 CRITICAL_BLOCK(cs_vNodes)
503 BOOST_FOREACH(CNode* pnode, vNodes)
505 CRITICAL_BLOCK(pnode->cs_mapRequests)
507 for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
509 CRequestTracker& tracker = (*mi).second;
510 if (tracker.fn == fn && tracker.param1 == param1)
511 pnode->mapRequests.erase(mi++);
527 // Subscription methods for the broadcast and subscription system.
528 // Channel numbers are message numbers, i.e. MSG_TABLE and MSG_PRODUCT.
530 // The subscription system uses a meet-in-the-middle strategy.
531 // With 100,000 nodes, if senders broadcast to 1000 random nodes and receivers
532 // subscribe to 1000 random nodes, 99.995% (1 - 0.99^1000) of messages will get through.
535 bool AnySubscribed(unsigned int nChannel)
537 if (pnodeLocalHost->IsSubscribed(nChannel))
539 CRITICAL_BLOCK(cs_vNodes)
540 BOOST_FOREACH(CNode* pnode, vNodes)
541 if (pnode->IsSubscribed(nChannel))
546 bool CNode::IsSubscribed(unsigned int nChannel)
548 if (nChannel >= vfSubscribe.size())
550 return vfSubscribe[nChannel];
553 void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
555 if (nChannel >= vfSubscribe.size())
558 if (!AnySubscribed(nChannel))
561 CRITICAL_BLOCK(cs_vNodes)
562 BOOST_FOREACH(CNode* pnode, vNodes)
564 pnode->PushMessage("subscribe", nChannel, nHops);
567 vfSubscribe[nChannel] = true;
570 void CNode::CancelSubscribe(unsigned int nChannel)
572 if (nChannel >= vfSubscribe.size())
575 // Prevent from relaying cancel if wasn't subscribed
576 if (!vfSubscribe[nChannel])
578 vfSubscribe[nChannel] = false;
580 if (!AnySubscribed(nChannel))
582 // Relay subscription cancel
583 CRITICAL_BLOCK(cs_vNodes)
584 BOOST_FOREACH(CNode* pnode, vNodes)
586 pnode->PushMessage("sub-cancel", nChannel);
598 CNode* FindNode(unsigned int ip)
600 CRITICAL_BLOCK(cs_vNodes)
602 BOOST_FOREACH(CNode* pnode, vNodes)
603 if (pnode->addr.ip == ip)
609 CNode* FindNode(CAddress addr)
611 CRITICAL_BLOCK(cs_vNodes)
613 BOOST_FOREACH(CNode* pnode, vNodes)
614 if (pnode->addr == addr)
620 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
622 if (addrConnect.ip == addrLocalHost.ip)
625 // Look for an existing connection
626 CNode* pnode = FindNode(addrConnect.ip);
630 pnode->AddRef(nTimeout);
637 printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",
638 addrConnect.ToString().c_str(),
639 (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
640 (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
642 CRITICAL_BLOCK(cs_mapAddresses)
643 mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
647 if (ConnectSocket(addrConnect, hSocket))
650 printf("connected %s\n", addrConnect.ToString().c_str());
652 // Set to nonblocking
655 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
656 printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
658 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
659 printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
663 CNode* pnode = new CNode(hSocket, addrConnect, false);
665 pnode->AddRef(nTimeout);
668 CRITICAL_BLOCK(cs_vNodes)
669 vNodes.push_back(pnode);
671 pnode->nTimeConnected = GetTime();
680 void CNode::CloseSocketDisconnect()
683 if (hSocket != INVALID_SOCKET)
686 printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
687 printf("disconnecting node %s\n", addr.ToString().c_str());
688 closesocket(hSocket);
689 hSocket = INVALID_SOCKET;
693 void CNode::Cleanup()
695 // All of a nodes broadcasts and subscriptions are automatically torn down
696 // when it goes down, so a node has to stay up to keep its broadcast going.
698 // Cancel subscriptions
699 for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
700 if (vfSubscribe[nChannel])
701 CancelSubscribe(nChannel);
716 void ThreadSocketHandler(void* parg)
718 IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
721 vnThreadsRunning[0]++;
722 ThreadSocketHandler2(parg);
723 vnThreadsRunning[0]--;
725 catch (std::exception& e) {
726 vnThreadsRunning[0]--;
727 PrintException(&e, "ThreadSocketHandler()");
729 vnThreadsRunning[0]--;
730 throw; // support pthread_cancel()
732 printf("ThreadSocketHandler exiting\n");
735 void ThreadSocketHandler2(void* parg)
737 printf("ThreadSocketHandler started\n");
738 list<CNode*> vNodesDisconnected;
739 int nPrevNodeCount = 0;
746 CRITICAL_BLOCK(cs_vNodes)
748 // Disconnect unused nodes
749 vector<CNode*> vNodesCopy = vNodes;
750 BOOST_FOREACH(CNode* pnode, vNodesCopy)
752 if (pnode->fDisconnect ||
753 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
755 // remove from vNodes
756 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
758 // close socket and cleanup
759 pnode->CloseSocketDisconnect();
762 // hold in disconnected pool until all refs are released
763 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
764 if (pnode->fNetworkNode || pnode->fInbound)
766 vNodesDisconnected.push_back(pnode);
770 // Delete disconnected nodes
771 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
772 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
774 // wait until threads are done using it
775 if (pnode->GetRefCount() <= 0)
777 bool fDelete = false;
778 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
779 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
780 TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
781 TRY_CRITICAL_BLOCK(pnode->cs_inventory)
785 vNodesDisconnected.remove(pnode);
791 if (vNodes.size() != nPrevNodeCount)
793 nPrevNodeCount = vNodes.size();
799 // Find which sockets have data to receive
801 struct timeval timeout;
803 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
810 FD_ZERO(&fdsetError);
811 SOCKET hSocketMax = 0;
813 if(hListenSocket != INVALID_SOCKET)
814 FD_SET(hListenSocket, &fdsetRecv);
815 hSocketMax = max(hSocketMax, hListenSocket);
816 CRITICAL_BLOCK(cs_vNodes)
818 BOOST_FOREACH(CNode* pnode, vNodes)
820 if (pnode->hSocket == INVALID_SOCKET || pnode->hSocket < 0)
822 FD_SET(pnode->hSocket, &fdsetRecv);
823 FD_SET(pnode->hSocket, &fdsetError);
824 hSocketMax = max(hSocketMax, pnode->hSocket);
825 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
826 if (!pnode->vSend.empty())
827 FD_SET(pnode->hSocket, &fdsetSend);
831 vnThreadsRunning[0]--;
832 int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
833 vnThreadsRunning[0]++;
836 if (nSelect == SOCKET_ERROR)
838 int nErr = WSAGetLastError();
841 printf("socket select error %d\n", nErr);
842 for (int i = 0; i <= hSocketMax; i++)
843 FD_SET(i, &fdsetRecv);
846 FD_ZERO(&fdsetError);
847 Sleep(timeout.tv_usec/1000);
852 // Accept new connections
854 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
856 struct sockaddr_in sockaddr;
857 socklen_t len = sizeof(sockaddr);
858 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
859 CAddress addr(sockaddr);
862 CRITICAL_BLOCK(cs_vNodes)
863 BOOST_FOREACH(CNode* pnode, vNodes)
866 if (hSocket == INVALID_SOCKET)
868 if (WSAGetLastError() != WSAEWOULDBLOCK)
869 printf("socket error accept failed: %d\n", WSAGetLastError());
871 else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
873 closesocket(hSocket);
877 printf("accepted connection %s\n", addr.ToString().c_str());
878 CNode* pnode = new CNode(hSocket, addr, true);
880 CRITICAL_BLOCK(cs_vNodes)
881 vNodes.push_back(pnode);
887 // Service each socket
889 vector<CNode*> vNodesCopy;
890 CRITICAL_BLOCK(cs_vNodes)
893 BOOST_FOREACH(CNode* pnode, vNodesCopy)
896 BOOST_FOREACH(CNode* pnode, vNodesCopy)
904 if (pnode->hSocket == INVALID_SOCKET)
906 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
908 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
910 CDataStream& vRecv = pnode->vRecv;
911 unsigned int nPos = vRecv.size();
913 if (nPos > 1000*GetArg("-maxreceivebuffer", 10*1000)) {
914 if (!pnode->fDisconnect)
915 printf("socket recv flood control disconnect (%d bytes)\n", vRecv.size());
916 pnode->CloseSocketDisconnect();
919 // typical socket buffer is 8K-64K
920 char pchBuf[0x10000];
921 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
924 vRecv.resize(nPos + nBytes);
925 memcpy(&vRecv[nPos], pchBuf, nBytes);
926 pnode->nLastRecv = GetTime();
928 else if (nBytes == 0)
930 // socket closed gracefully
931 if (!pnode->fDisconnect)
932 printf("socket closed\n");
933 pnode->CloseSocketDisconnect();
938 int nErr = WSAGetLastError();
939 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
941 if (!pnode->fDisconnect)
942 printf("socket recv error %d\n", nErr);
943 pnode->CloseSocketDisconnect();
953 if (pnode->hSocket == INVALID_SOCKET)
955 if (FD_ISSET(pnode->hSocket, &fdsetSend))
957 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
959 CDataStream& vSend = pnode->vSend;
962 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
965 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
966 pnode->nLastSend = GetTime();
971 int nErr = WSAGetLastError();
972 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
974 printf("socket send error %d\n", nErr);
975 pnode->CloseSocketDisconnect();
978 if (vSend.size() > 1000*GetArg("-maxsendbuffer", 10*1000)) {
979 if (!pnode->fDisconnect)
980 printf("socket send flood control disconnect (%d bytes)\n", vSend.size());
981 pnode->CloseSocketDisconnect();
988 // Inactivity checking
990 if (pnode->vSend.empty())
991 pnode->nLastSendEmpty = GetTime();
992 if (GetTime() - pnode->nTimeConnected > 60)
994 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
996 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
997 pnode->fDisconnect = true;
999 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
1001 printf("socket not sending\n");
1002 pnode->fDisconnect = true;
1004 else if (GetTime() - pnode->nLastRecv > 90*60)
1006 printf("socket inactivity timeout\n");
1007 pnode->fDisconnect = true;
1011 CRITICAL_BLOCK(cs_vNodes)
1013 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1030 void ThreadMapPort(void* parg)
1032 IMPLEMENT_RANDOMIZE_STACK(ThreadMapPort(parg));
1035 vnThreadsRunning[5]++;
1036 ThreadMapPort2(parg);
1037 vnThreadsRunning[5]--;
1039 catch (std::exception& e) {
1040 vnThreadsRunning[5]--;
1041 PrintException(&e, "ThreadMapPort()");
1043 vnThreadsRunning[5]--;
1044 PrintException(NULL, "ThreadMapPort()");
1046 printf("ThreadMapPort exiting\n");
1049 void ThreadMapPort2(void* parg)
1051 printf("ThreadMapPort started\n");
1054 sprintf(port, "%d", GetListenPort());
1056 const char * rootdescurl = 0;
1057 const char * multicastif = 0;
1058 const char * minissdpdpath = 0;
1059 struct UPNPDev * devlist = 0;
1062 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
1064 struct UPNPUrls urls;
1065 struct IGDdatas data;
1068 r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
1075 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1076 port, port, lanaddr, 0, "TCP", 0);
1078 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1079 port, port, lanaddr, 0, "TCP", 0, "0");
1081 if(r!=UPNPCOMMAND_SUCCESS)
1082 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1083 port, port, lanaddr, r, strupnperror(r));
1085 printf("UPnP Port Mapping successful.\n");
1087 if (fShutdown || !fUseUPnP)
1089 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port, "TCP", 0);
1090 printf("UPNP_DeletePortMapping() returned : %d\n", r);
1091 freeUPNPDevlist(devlist); devlist = 0;
1092 FreeUPNPUrls(&urls);
1098 printf("No valid UPnP IGDs found\n");
1099 freeUPNPDevlist(devlist); devlist = 0;
1101 FreeUPNPUrls(&urls);
1103 if (fShutdown || !fUseUPnP)
1110 void MapPort(bool fMapPort)
1112 if (fUseUPnP != fMapPort)
1114 fUseUPnP = fMapPort;
1115 CWalletDB().WriteSetting("fUseUPnP", fUseUPnP);
1117 if (fUseUPnP && vnThreadsRunning[5] < 1)
1119 if (!CreateThread(ThreadMapPort, NULL))
1120 printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
1134 static const char *strDNSSeed[] = {
1136 "bitseed.bitcoin.org.uk",
1139 void DNSAddressSeed()
1143 printf("Loading addresses from DNS seeds (could take a while)\n");
1145 for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1146 vector<CAddress> vaddr;
1147 if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, -1, true))
1149 BOOST_FOREACH (CAddress& addr, vaddr)
1151 if (addr.GetByte(3) != 127)
1161 printf("%d addresses found from DNS seeds\n", found);
1166 unsigned int pnSeed[] =
1168 0x1ddb1032, 0x6242ce40, 0x52d6a445, 0x2dd7a445, 0x8a53cd47, 0x73263750, 0xda23c257, 0xecd4ed57,
1169 0x0a40ec59, 0x75dce160, 0x7df76791, 0x89370bad, 0xa4f214ad, 0x767700ae, 0x638b0418, 0x868a1018,
1170 0xcd9f332e, 0x0129653e, 0xcc92dc3e, 0x96671640, 0x56487e40, 0x5b66f440, 0xb1d01f41, 0xf1dc6041,
1171 0xc1d12b42, 0x86ba1243, 0x6be4df43, 0x6d4cef43, 0xd18e0644, 0x1ab0b344, 0x6584a345, 0xe7c1a445,
1172 0x58cea445, 0xc5daa445, 0x21dda445, 0x3d3b5346, 0x13e55347, 0x1080d24a, 0x8e611e4b, 0x81518e4b,
1173 0x6c839e4b, 0xe2ad0a4c, 0xfbbc0a4c, 0x7f5b6e4c, 0x7244224e, 0x1300554e, 0x20690652, 0x5a48b652,
1174 0x75c5c752, 0x4335cc54, 0x340fd154, 0x87c07455, 0x087b2b56, 0x8a133a57, 0xac23c257, 0x70374959,
1175 0xfb63d45b, 0xb9a1685c, 0x180d765c, 0x674f645d, 0x04d3495e, 0x1de44b5e, 0x4ee8a362, 0x0ded1b63,
1176 0xc1b04b6d, 0x8d921581, 0x97b7ea82, 0x1cf83a8e, 0x91490bad, 0x09dc75ae, 0x9a6d79ae, 0xa26d79ae,
1177 0x0fd08fae, 0x0f3e3fb2, 0x4f944fb2, 0xcca448b8, 0x3ecd6ab8, 0xa9d5a5bc, 0x8d0119c1, 0x045997d5,
1178 0xca019dd9, 0x0d526c4d, 0xabf1ba44, 0x66b1ab55, 0x1165f462, 0x3ed7cbad, 0xa38fae6e, 0x3bd2cbad,
1179 0xd36f0547, 0x20df7840, 0x7a337742, 0x549f8e4b, 0x9062365c, 0xd399f562, 0x2b5274a1, 0x8edfa153,
1180 0x3bffb347, 0x7074bf58, 0xb74fcbad, 0x5b5a795b, 0x02fa29ce, 0x5a6738d4, 0xe8a1d23e, 0xef98c445,
1181 0x4b0f494c, 0xa2bc1e56, 0x7694ad63, 0xa4a800c3, 0x05fda6cd, 0x9f22175e, 0x364a795b, 0x536285d5,
1182 0xac44c9d4, 0x0b06254d, 0x150c2fd4, 0x32a50dcc, 0xfd79ce48, 0xf15cfa53, 0x66c01e60, 0x6bc26661,
1183 0xc03b47ae, 0x4dda1b81, 0x3285a4c1, 0x883ca96d, 0x35d60a4c, 0xdae09744, 0x2e314d61, 0x84e247cf,
1184 0x6c814552, 0x3a1cc658, 0x98d8f382, 0xe584cb5b, 0x15e86057, 0x7b01504e, 0xd852dd48, 0x56382f56,
1185 0x0a5df454, 0xa0d18d18, 0x2e89b148, 0xa79c114c, 0xcbdcd054, 0x5523bc43, 0xa9832640, 0x8a066144,
1186 0x3894c3bc, 0xab76bf58, 0x6a018ac1, 0xfebf4f43, 0x2f26c658, 0x31102f4e, 0x85e929d5, 0x2a1c175e,
1187 0xfc6c2cd1, 0x27b04b6d, 0xdf024650, 0x161748b8, 0x28be6580, 0x57be6580, 0x1cee677a, 0xaa6bb742,
1188 0x9a53964b, 0x0a5a2d4d, 0x2434c658, 0x9a494f57, 0x1ebb0e48, 0xf610b85d, 0x077ecf44, 0x085128bc,
1189 0x5ba17a18, 0x27ca1b42, 0xf8a00b56, 0xfcd4c257, 0xcf2fc15e, 0xd897e052, 0x4cada04f, 0x2f35f6d5,
1190 0x382ce8c9, 0xe523984b, 0x3f946846, 0x60c8be43, 0x41da6257, 0xde0be142, 0xae8a544b, 0xeff0c254,
1191 0x1e0f795b, 0xaeb28890, 0xca16acd9, 0x1e47ddd8, 0x8c8c4829, 0xd27dc747, 0xd53b1663, 0x4096b163,
1192 0x9c8dd958, 0xcb12f860, 0x9e79305c, 0x40c1a445, 0x4a90c2bc, 0x2c3a464d, 0x2727f23c, 0x30b04b6d,
1193 0x59024cb8, 0xa091e6ad, 0x31b04b6d, 0xc29d46a6, 0x63934fb2, 0xd9224dbe, 0x9f5910d8, 0x7f530a6b,
1194 0x752e9c95, 0x65453548, 0xa484be46, 0xce5a1b59, 0x710e0718, 0x46a13d18, 0xdaaf5318, 0xc4a8ff53,
1195 0x87abaa52, 0xb764cf51, 0xb2025d4a, 0x6d351e41, 0xc035c33e, 0xa432c162, 0x61ef34ae, 0xd16fddbc,
1196 0x0870e8c1, 0x3070e8c1, 0x9c71e8c1, 0xa4992363, 0x85a1f663, 0x4184e559, 0x18d96ed8, 0x17b8dbd5,
1197 0x60e7cd18, 0xe5ee104c, 0xab17ac62, 0x1e786e1b, 0x5d23b762, 0xf2388fae, 0x88270360, 0x9e5b3d80,
1198 0x7da518b2, 0xb5613b45, 0x1ad41f3e, 0xd550854a, 0x8617e9a9, 0x925b229c, 0xf2e92542, 0x47af0544,
1199 0x73b5a843, 0xb9b7a0ad, 0x03a748d0, 0x0a6ff862, 0x6694df62, 0x3bfac948, 0x8e098f4f, 0x746916c3,
1200 0x02f38e4f, 0x40bb1243, 0x6a54d162, 0x6008414b, 0xa513794c, 0x514aa343, 0x63781747, 0xdbb6795b,
1201 0xed065058, 0x42d24b46, 0x1518794c, 0x9b271681, 0x73e4ffad, 0x0654784f, 0x438dc945, 0x641846a6,
1202 0x2d1b0944, 0x94b59148, 0x8d369558, 0xa5a97662, 0x8b705b42, 0xce9204ae, 0x8d584450, 0x2df61555,
1203 0xeebff943, 0x2e75fb4d, 0x3ef8fc57, 0x9921135e, 0x8e31042e, 0xb5afad43, 0x89ecedd1, 0x9cfcc047,
1204 0x8fcd0f4c, 0xbe49f5ad, 0x146a8d45, 0x98669ab8, 0x98d9175e, 0xd1a8e46d, 0x839a3ab8, 0x40a0016c,
1205 0x6d27c257, 0x977fffad, 0x7baa5d5d, 0x1213be43, 0xb167e5a9, 0x640fe8ca, 0xbc9ea655, 0x0f820a4c,
1206 0x0f097059, 0x69ac957c, 0x366d8453, 0xb1ba2844, 0x8857f081, 0x70b5be63, 0xc545454b, 0xaf36ded1,
1207 0xb5a4b052, 0x21f062d1, 0x72ab89b2, 0x74a45318, 0x8312e6bc, 0xb916965f, 0x8aa7c858, 0xfe7effad,
1212 void ThreadOpenConnections(void* parg)
1214 IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
1217 vnThreadsRunning[1]++;
1218 ThreadOpenConnections2(parg);
1219 vnThreadsRunning[1]--;
1221 catch (std::exception& e) {
1222 vnThreadsRunning[1]--;
1223 PrintException(&e, "ThreadOpenConnections()");
1225 vnThreadsRunning[1]--;
1226 PrintException(NULL, "ThreadOpenConnections()");
1228 printf("ThreadOpenConnections exiting\n");
1231 void ThreadOpenConnections2(void* parg)
1233 printf("ThreadOpenConnections started\n");
1235 // Connect to specific addresses
1236 if (mapArgs.count("-connect"))
1238 for (int64 nLoop = 0;; nLoop++)
1240 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1242 CAddress addr(strAddr, fAllowDNS);
1244 OpenNetworkConnection(addr);
1245 for (int i = 0; i < 10 && i < nLoop; i++)
1255 // Connect to manually added nodes first
1256 if (mapArgs.count("-addnode"))
1258 BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
1260 CAddress addr(strAddr, fAllowDNS);
1263 OpenNetworkConnection(addr);
1271 // Initiate network connections
1272 int64 nStart = GetTime();
1275 // Limit outbound connections
1276 vnThreadsRunning[1]--;
1281 CRITICAL_BLOCK(cs_vNodes)
1282 BOOST_FOREACH(CNode* pnode, vNodes)
1283 if (!pnode->fInbound)
1285 int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
1286 nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
1287 if (nOutbound < nMaxOutboundConnections)
1293 vnThreadsRunning[1]++;
1297 CRITICAL_BLOCK(cs_mapAddresses)
1299 // Add seed nodes if IRC isn't working
1300 static bool fSeedUsed;
1301 bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
1302 if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
1304 for (int i = 0; i < ARRAYLEN(pnSeed); i++)
1306 // It'll only connect to one or two seed nodes because once it connects,
1307 // it'll get a pile of addresses with newer timestamps.
1309 addr.ip = pnSeed[i];
1316 if (fSeedUsed && mapAddresses.size() > ARRAYLEN(pnSeed) + 100)
1318 // Disconnect seed nodes
1319 set<unsigned int> setSeed(pnSeed, pnSeed + ARRAYLEN(pnSeed));
1320 static int64 nSeedDisconnected;
1321 if (nSeedDisconnected == 0)
1323 nSeedDisconnected = GetTime();
1324 CRITICAL_BLOCK(cs_vNodes)
1325 BOOST_FOREACH(CNode* pnode, vNodes)
1326 if (setSeed.count(pnode->addr.ip))
1327 pnode->fDisconnect = true;
1330 // Keep setting timestamps to 0 so they won't reconnect
1331 if (GetTime() - nSeedDisconnected < 60 * 60)
1333 BOOST_FOREACH(PAIRTYPE(const vector<unsigned char>, CAddress)& item, mapAddresses)
1335 if (setSeed.count(item.second.ip) && item.second.nTime != 0)
1337 item.second.nTime = 0;
1338 CAddrDB().WriteAddress(item.second);
1347 // Choose an address to connect to based on most recently seen
1349 CAddress addrConnect;
1350 int64 nBest = INT64_MIN;
1352 // Only connect to one address per a.b.?.? range.
1353 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1354 set<unsigned int> setConnected;
1355 CRITICAL_BLOCK(cs_vNodes)
1356 BOOST_FOREACH(CNode* pnode, vNodes)
1357 setConnected.insert(pnode->addr.ip & 0x0000ffff);
1359 CRITICAL_BLOCK(cs_mapAddresses)
1361 BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
1363 const CAddress& addr = item.second;
1364 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
1366 int64 nSinceLastSeen = GetAdjustedTime() - addr.nTime;
1367 int64 nSinceLastTry = GetAdjustedTime() - addr.nLastTry;
1369 // Randomize the order in a deterministic way, putting the standard port first
1370 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
1371 if (addr.port != htons(GetDefaultPort()))
1372 nRandomizer += 2 * 60 * 60;
1374 // Last seen Base retry frequency
1383 // 365 days 93 hours
1384 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
1386 // Fast reconnect for one hour after last seen
1387 if (nSinceLastSeen < 60 * 60)
1390 // Limit retry frequency
1391 if (nSinceLastTry < nDelay)
1394 // If we have IRC, we'll be notified when they first come online,
1395 // and again every 24 hours by the refresh broadcast.
1396 if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)
1399 // Only try the old stuff if we don't have enough connections
1400 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
1403 // If multiple addresses are ready, prioritize by time since
1404 // last seen and time since last tried.
1405 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
1414 if (addrConnect.IsValid())
1415 OpenNetworkConnection(addrConnect);
1419 bool OpenNetworkConnection(const CAddress& addrConnect)
1422 // Initiate outbound network connection
1426 if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
1429 vnThreadsRunning[1]--;
1430 CNode* pnode = ConnectNode(addrConnect);
1431 vnThreadsRunning[1]++;
1436 pnode->fNetworkNode = true;
1448 void ThreadMessageHandler(void* parg)
1450 IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
1453 vnThreadsRunning[2]++;
1454 ThreadMessageHandler2(parg);
1455 vnThreadsRunning[2]--;
1457 catch (std::exception& e) {
1458 vnThreadsRunning[2]--;
1459 PrintException(&e, "ThreadMessageHandler()");
1461 vnThreadsRunning[2]--;
1462 PrintException(NULL, "ThreadMessageHandler()");
1464 printf("ThreadMessageHandler exiting\n");
1467 void ThreadMessageHandler2(void* parg)
1469 printf("ThreadMessageHandler started\n");
1470 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1473 vector<CNode*> vNodesCopy;
1474 CRITICAL_BLOCK(cs_vNodes)
1476 vNodesCopy = vNodes;
1477 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1481 // Poll the connected nodes for messages
1482 CNode* pnodeTrickle = NULL;
1483 if (!vNodesCopy.empty())
1484 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1485 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1488 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
1489 ProcessMessages(pnode);
1494 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
1495 SendMessages(pnode, pnode == pnodeTrickle);
1500 CRITICAL_BLOCK(cs_vNodes)
1502 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1506 // Wait and allow messages to bunch up.
1507 // Reduce vnThreadsRunning so StopNode has permission to exit while
1508 // we're sleeping, but we must always check fShutdown after doing this.
1509 vnThreadsRunning[2]--;
1511 if (fRequestShutdown)
1513 vnThreadsRunning[2]++;
1524 bool BindListenPort(string& strError)
1528 addrLocalHost.port = htons(GetListenPort());
1531 // Initialize Windows Sockets
1533 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1534 if (ret != NO_ERROR)
1536 strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1537 printf("%s\n", strError.c_str());
1542 // Create socket for listening for incoming connections
1543 hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1544 if (hListenSocket == INVALID_SOCKET)
1546 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1547 printf("%s\n", strError.c_str());
1552 // Different way of disabling SIGPIPE on BSD
1553 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1557 // Allow binding if the port is still in TIME_WAIT state after
1558 // the program was closed and restarted. Not an issue on windows.
1559 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1563 // Set to nonblocking, incoming connections will also inherit this
1564 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1566 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1569 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1570 printf("%s\n", strError.c_str());
1574 // The sockaddr_in structure specifies the address family,
1575 // IP address, and port for the socket that is being bound
1576 struct sockaddr_in sockaddr;
1577 memset(&sockaddr, 0, sizeof(sockaddr));
1578 sockaddr.sin_family = AF_INET;
1579 sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
1580 sockaddr.sin_port = htons(GetListenPort());
1581 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
1583 int nErr = WSAGetLastError();
1584 if (nErr == WSAEADDRINUSE)
1585 strError = strprintf(_("Unable to bind to port %d on this computer. Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
1587 strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
1588 printf("%s\n", strError.c_str());
1591 printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
1593 // Listen for incoming connections
1594 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1596 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1597 printf("%s\n", strError.c_str());
1604 void StartNode(void* parg)
1606 if (pnodeLocalHost == NULL)
1607 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, false, nLocalServices));
1610 // Get local host ip
1611 char pszHostName[1000] = "";
1612 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1614 vector<CAddress> vaddr;
1615 if (Lookup(pszHostName, vaddr, nLocalServices, -1, true))
1616 BOOST_FOREACH (const CAddress &addr, vaddr)
1617 if (addr.GetByte(3) != 127)
1619 addrLocalHost = addr;
1624 // Get local host ip
1625 struct ifaddrs* myaddrs;
1626 if (getifaddrs(&myaddrs) == 0)
1628 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1630 if (ifa->ifa_addr == NULL) continue;
1631 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1632 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1633 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1635 if (ifa->ifa_addr->sa_family == AF_INET)
1637 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1638 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
1639 printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
1641 // Take the first IP that isn't loopback 127.x.x.x
1642 CAddress addr(*(unsigned int*)&s4->sin_addr, GetListenPort(), nLocalServices);
1643 if (addr.IsValid() && addr.GetByte(3) != 127)
1645 addrLocalHost = addr;
1649 else if (ifa->ifa_addr->sa_family == AF_INET6)
1651 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1652 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
1653 printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
1656 freeifaddrs(myaddrs);
1659 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1661 if (fUseProxy || mapArgs.count("-connect") || fNoListen)
1663 // Proxies can't take incoming connections
1664 addrLocalHost.ip = CAddress("0.0.0.0").ip;
1665 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1669 CreateThread(ThreadGetMyExternalIP, NULL);
1676 // Map ports with UPnP
1680 // Get addresses from IRC and advertise ours
1681 if (!CreateThread(ThreadIRCSeed, NULL))
1682 printf("Error: CreateThread(ThreadIRCSeed) failed\n");
1684 // Send and receive from sockets, accept connections
1685 pthread_t hThreadSocketHandler = CreateThread(ThreadSocketHandler, NULL, true);
1687 // Initiate outbound connections
1688 if (!CreateThread(ThreadOpenConnections, NULL))
1689 printf("Error: CreateThread(ThreadOpenConnections) failed\n");
1692 if (!CreateThread(ThreadMessageHandler, NULL))
1693 printf("Error: CreateThread(ThreadMessageHandler) failed\n");
1695 // Generate coins in the background
1696 GenerateBitcoins(fGenerateBitcoins);
1701 printf("StopNode()\n");
1703 nTransactionsUpdated++;
1704 int64 nStart = GetTime();
1705 while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0
1707 || vnThreadsRunning[5] > 0
1711 if (GetTime() - nStart > 20)
1715 if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
1716 if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
1717 if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
1718 if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
1719 if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
1720 if (fHaveUPnP && vnThreadsRunning[5] > 0) printf("ThreadMapPort still running\n");
1721 while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
1737 BOOST_FOREACH(CNode* pnode, vNodes)
1738 if (pnode->hSocket != INVALID_SOCKET)
1739 closesocket(pnode->hSocket);
1740 if (hListenSocket != INVALID_SOCKET)
1741 if (closesocket(hListenSocket) == SOCKET_ERROR)
1742 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1745 // Shutdown Windows Sockets
1750 instance_of_cnetcleanup;