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.
13 #include <miniupnpc/miniwget.h>
14 #include <miniupnpc/miniupnpc.h>
15 #include <miniupnpc/upnpcommands.h>
16 #include <miniupnpc/upnperrors.h>
20 using namespace boost;
22 static const int MAX_OUTBOUND_CONNECTIONS = 8;
24 void ThreadMessageHandler2(void* parg);
25 void ThreadSocketHandler2(void* parg);
26 void ThreadOpenConnections2(void* parg);
28 void ThreadMapPort2(void* parg);
30 bool OpenNetworkConnection(const CAddress& addrConnect);
37 // Global state variables
40 bool fAllowDNS = false;
41 uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
42 CAddress addrLocalHost("0.0.0.0", 0, false, nLocalServices);
43 CNode* pnodeLocalHost = NULL;
44 uint64 nLocalHostNonce = 0;
45 array<int, 10> vnThreadsRunning;
46 SOCKET hListenSocket = INVALID_SOCKET;
48 vector<CNode*> vNodes;
49 CCriticalSection cs_vNodes;
50 map<vector<unsigned char>, CAddress> mapAddresses;
51 CCriticalSection cs_mapAddresses;
52 map<CInv, CDataStream> mapRelay;
53 deque<pair<int64, CInv> > vRelayExpiration;
54 CCriticalSection cs_mapRelay;
55 map<CInv, int64> mapAlreadyAskedFor;
58 int fUseProxy = false;
59 int nConnectTimeout = 5000;
60 CAddress addrProxy("127.0.0.1",9050);
65 unsigned short GetListenPort()
67 return (unsigned short)(GetArg("-port", GetDefaultPort()));
70 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
72 // Filter out duplicate requests
73 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
75 pindexLastGetBlocksBegin = pindexBegin;
76 hashLastGetBlocksEnd = hashEnd;
78 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
85 bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout)
87 hSocketRet = INVALID_SOCKET;
89 SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
90 if (hSocket == INVALID_SOCKET)
94 setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
97 bool fProxy = (fUseProxy && addrConnect.IsRoutable());
98 struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
101 u_long fNonblock = 1;
102 if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
104 int fFlags = fcntl(hSocket, F_GETFL, 0);
105 if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
108 closesocket(hSocket);
113 if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
115 // WSAEINVAL is here because some legacy version of winsock uses it
116 if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
118 struct timeval timeout;
119 timeout.tv_sec = nTimeout / 1000;
120 timeout.tv_usec = (nTimeout % 1000) * 1000;
124 FD_SET(hSocket, &fdset);
125 int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
128 printf("connection timeout\n");
129 closesocket(hSocket);
132 if (nRet == SOCKET_ERROR)
134 printf("select() for connection failed: %i\n",WSAGetLastError());
135 closesocket(hSocket);
138 socklen_t nRetSize = sizeof(nRet);
140 if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
142 if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
145 printf("getsockopt() for connection failed: %i\n",WSAGetLastError());
146 closesocket(hSocket);
151 printf("connect() failed after select(): %i\n",nRet);
152 closesocket(hSocket);
157 else if (WSAGetLastError() != WSAEISCONN)
162 printf("connect() failed: %i\n",WSAGetLastError());
163 closesocket(hSocket);
169 this isn't even strictly necessary
170 CNode::ConnectNode immediately turns the socket back to non-blocking
171 but we'll turn it back to blocking just in case
175 if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
177 fFlags = fcntl(hSocket, F_GETFL, 0);
178 if (fcntl(hSocket, F_SETFL, fFlags & !O_NONBLOCK) == SOCKET_ERROR)
181 closesocket(hSocket);
187 printf("proxy connecting %s\n", addrConnect.ToString().c_str());
188 char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
189 memcpy(pszSocks4IP + 2, &addrConnect.port, 2);
190 memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);
191 char* pszSocks4 = pszSocks4IP;
192 int nSize = sizeof(pszSocks4IP);
194 int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
197 closesocket(hSocket);
198 return error("Error sending to proxy");
201 if (recv(hSocket, pchRet, 8, 0) != 8)
203 closesocket(hSocket);
204 return error("Error reading proxy response");
206 if (pchRet[1] != 0x5a)
208 closesocket(hSocket);
209 if (pchRet[1] != 0x5b)
210 printf("ERROR: Proxy returned error %d\n", pchRet[1]);
213 printf("proxy connected %s\n", addrConnect.ToString().c_str());
216 hSocketRet = hSocket;
220 // portDefault is in host order
221 bool Lookup(const char *pszName, vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup, int portDefault, bool fAllowPort)
226 int port = portDefault;
229 strlcpy(psz, pszName, sizeof(psz));
232 char* pszColon = strrchr(psz+1,':');
233 char *pszPortEnd = NULL;
234 int portParsed = pszColon ? strtoul(pszColon+1, &pszPortEnd, 10) : 0;
235 if (pszColon && pszPortEnd && pszPortEnd[0] == 0)
237 if (psz[0] == '[' && pszColon[-1] == ']')
239 // Future: enable IPv6 colon-notation inside []
246 if (port < 0 || port > USHRT_MAX)
251 unsigned int addrIP = inet_addr(pszHost);
252 if (addrIP != INADDR_NONE)
254 // valid IP address passed
255 vaddr.push_back(CAddress(addrIP, port, nServices));
262 struct hostent* phostent = gethostbyname(pszHost);
266 if (phostent->h_addrtype != AF_INET)
269 char** ppAddr = phostent->h_addr_list;
270 while (*ppAddr != NULL && vaddr.size() != nMaxSolutions)
272 CAddress addr(((struct in_addr*)ppAddr[0])->s_addr, port, nServices);
274 vaddr.push_back(addr);
278 return (vaddr.size() > 0);
281 // portDefault is in host order
282 bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup, int portDefault, bool fAllowPort)
284 vector<CAddress> vaddr;
285 bool fRet = Lookup(pszName, vaddr, nServices, 1, fAllowLookup, portDefault, fAllowPort);
291 bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const char* pszKeyword, unsigned int& ipRet)
294 if (!ConnectSocket(addrConnect, hSocket))
295 return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
297 send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
300 while (RecvLine(hSocket, strLine))
302 if (strLine.empty()) // HTTP response is separated from headers by blank line
306 if (!RecvLine(hSocket, strLine))
308 closesocket(hSocket);
311 if (pszKeyword == NULL)
313 if (strLine.find(pszKeyword) != -1)
315 strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
319 closesocket(hSocket);
320 if (strLine.find("<") != -1)
321 strLine = strLine.substr(0, strLine.find("<"));
322 strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
323 while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
324 strLine.resize(strLine.size()-1);
325 CAddress addr(strLine,0,true);
326 printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
327 if (addr.ip == 0 || addr.ip == INADDR_NONE || !addr.IsRoutable())
333 closesocket(hSocket);
334 return error("GetMyExternalIP() : connection closed");
337 // We now get our external IP from the IRC server first and only use this as a backup
338 bool GetMyExternalIP(unsigned int& ipRet)
340 CAddress addrConnect;
342 const char* pszKeyword;
347 for (int nLookup = 0; nLookup <= 1; nLookup++)
348 for (int nHost = 1; nHost <= 2; nHost++)
350 // We should be phasing out our use of sites like these. If we need
351 // replacements, we should ask for volunteers to put this simple
352 // php file on their webserver that prints the client IP:
353 // <?php echo $_SERVER["REMOTE_ADDR"]; ?>
356 addrConnect = CAddress("91.198.22.70",80); // checkip.dyndns.org
360 CAddress addrIP("checkip.dyndns.org", 80, true);
361 if (addrIP.IsValid())
362 addrConnect = addrIP;
365 pszGet = "GET / HTTP/1.1\r\n"
366 "Host: checkip.dyndns.org\r\n"
367 "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
368 "Connection: close\r\n"
371 pszKeyword = "Address:";
375 addrConnect = CAddress("74.208.43.192", 80); // www.showmyip.com
379 CAddress addrIP("www.showmyip.com", 80, true);
380 if (addrIP.IsValid())
381 addrConnect = addrIP;
384 pszGet = "GET /simple/ HTTP/1.1\r\n"
385 "Host: www.showmyip.com\r\n"
386 "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
387 "Connection: close\r\n"
390 pszKeyword = NULL; // Returns just IP address
393 if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
400 void ThreadGetMyExternalIP(void* parg)
402 // Wait for IRC to get it first
403 if (!GetBoolArg("-noirc"))
405 for (int i = 0; i < 2 * 60; i++)
408 if (fGotExternalIP || fShutdown)
413 // Fallback in case IRC fails to get it
414 if (GetMyExternalIP(addrLocalHost.ip))
416 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
417 if (addrLocalHost.IsRoutable())
419 // If we already connected to a few before we had our IP, go back and addr them.
420 // setAddrKnown automatically filters any duplicate sends.
421 CAddress addr(addrLocalHost);
422 addr.nTime = GetAdjustedTime();
423 CRITICAL_BLOCK(cs_vNodes)
424 BOOST_FOREACH(CNode* pnode, vNodes)
425 pnode->PushAddress(addr);
434 bool AddAddress(CAddress addr, int64 nTimePenalty)
436 if (!addr.IsRoutable())
438 if (addr.ip == addrLocalHost.ip)
440 addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty);
441 CRITICAL_BLOCK(cs_mapAddresses)
443 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
444 if (it == mapAddresses.end())
447 printf("AddAddress(%s)\n", addr.ToString().c_str());
448 mapAddresses.insert(make_pair(addr.GetKey(), addr));
449 CAddrDB().WriteAddress(addr);
454 bool fUpdated = false;
455 CAddress& addrFound = (*it).second;
456 if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
458 // Services have been added
459 addrFound.nServices |= addr.nServices;
462 bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
463 int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
464 if (addrFound.nTime < addr.nTime - nUpdateInterval)
466 // Periodically update most recently seen time
467 addrFound.nTime = addr.nTime;
471 CAddrDB().WriteAddress(addrFound);
477 void AddressCurrentlyConnected(const CAddress& addr)
479 CRITICAL_BLOCK(cs_mapAddresses)
481 // Only if it's been published already
482 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
483 if (it != mapAddresses.end())
485 CAddress& addrFound = (*it).second;
486 int64 nUpdateInterval = 20 * 60;
487 if (addrFound.nTime < GetAdjustedTime() - nUpdateInterval)
489 // Periodically update most recently seen time
490 addrFound.nTime = GetAdjustedTime();
492 addrdb.WriteAddress(addrFound);
502 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
504 // If the dialog might get closed before the reply comes back,
505 // call this in the destructor so it doesn't get called after it's deleted.
506 CRITICAL_BLOCK(cs_vNodes)
508 BOOST_FOREACH(CNode* pnode, vNodes)
510 CRITICAL_BLOCK(pnode->cs_mapRequests)
512 for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
514 CRequestTracker& tracker = (*mi).second;
515 if (tracker.fn == fn && tracker.param1 == param1)
516 pnode->mapRequests.erase(mi++);
532 // Subscription methods for the broadcast and subscription system.
533 // Channel numbers are message numbers, i.e. MSG_TABLE and MSG_PRODUCT.
535 // The subscription system uses a meet-in-the-middle strategy.
536 // With 100,000 nodes, if senders broadcast to 1000 random nodes and receivers
537 // subscribe to 1000 random nodes, 99.995% (1 - 0.99^1000) of messages will get through.
540 bool AnySubscribed(unsigned int nChannel)
542 if (pnodeLocalHost->IsSubscribed(nChannel))
544 CRITICAL_BLOCK(cs_vNodes)
545 BOOST_FOREACH(CNode* pnode, vNodes)
546 if (pnode->IsSubscribed(nChannel))
551 bool CNode::IsSubscribed(unsigned int nChannel)
553 if (nChannel >= vfSubscribe.size())
555 return vfSubscribe[nChannel];
558 void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
560 if (nChannel >= vfSubscribe.size())
563 if (!AnySubscribed(nChannel))
566 CRITICAL_BLOCK(cs_vNodes)
567 BOOST_FOREACH(CNode* pnode, vNodes)
569 pnode->PushMessage("subscribe", nChannel, nHops);
572 vfSubscribe[nChannel] = true;
575 void CNode::CancelSubscribe(unsigned int nChannel)
577 if (nChannel >= vfSubscribe.size())
580 // Prevent from relaying cancel if wasn't subscribed
581 if (!vfSubscribe[nChannel])
583 vfSubscribe[nChannel] = false;
585 if (!AnySubscribed(nChannel))
587 // Relay subscription cancel
588 CRITICAL_BLOCK(cs_vNodes)
589 BOOST_FOREACH(CNode* pnode, vNodes)
591 pnode->PushMessage("sub-cancel", nChannel);
603 CNode* FindNode(unsigned int ip)
605 CRITICAL_BLOCK(cs_vNodes)
607 BOOST_FOREACH(CNode* pnode, vNodes)
608 if (pnode->addr.ip == ip)
614 CNode* FindNode(CAddress addr)
616 CRITICAL_BLOCK(cs_vNodes)
618 BOOST_FOREACH(CNode* pnode, vNodes)
619 if (pnode->addr == addr)
625 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
627 if (addrConnect.ip == addrLocalHost.ip)
630 // Look for an existing connection
631 CNode* pnode = FindNode(addrConnect.ip);
635 pnode->AddRef(nTimeout);
642 printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",
643 addrConnect.ToString().c_str(),
644 (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
645 (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
647 CRITICAL_BLOCK(cs_mapAddresses)
648 mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
652 if (ConnectSocket(addrConnect, hSocket))
655 printf("connected %s\n", addrConnect.ToString().c_str());
657 // Set to nonblocking
660 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
661 printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
663 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
664 printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
668 CNode* pnode = new CNode(hSocket, addrConnect, false);
670 pnode->AddRef(nTimeout);
673 CRITICAL_BLOCK(cs_vNodes)
674 vNodes.push_back(pnode);
676 pnode->nTimeConnected = GetTime();
685 void CNode::CloseSocketDisconnect()
688 if (hSocket != INVALID_SOCKET)
691 printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
692 printf("disconnecting node %s\n", addr.ToString().c_str());
693 closesocket(hSocket);
694 hSocket = INVALID_SOCKET;
698 void CNode::Cleanup()
700 // All of a nodes broadcasts and subscriptions are automatically torn down
701 // when it goes down, so a node has to stay up to keep its broadcast going.
703 // Cancel subscriptions
704 for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
705 if (vfSubscribe[nChannel])
706 CancelSubscribe(nChannel);
721 void ThreadSocketHandler(void* parg)
723 IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
726 vnThreadsRunning[0]++;
727 ThreadSocketHandler2(parg);
728 vnThreadsRunning[0]--;
730 catch (std::exception& e) {
731 vnThreadsRunning[0]--;
732 PrintException(&e, "ThreadSocketHandler()");
734 vnThreadsRunning[0]--;
735 throw; // support pthread_cancel()
737 printf("ThreadSocketHandler exiting\n");
740 void ThreadSocketHandler2(void* parg)
742 printf("ThreadSocketHandler started\n");
743 list<CNode*> vNodesDisconnected;
744 int nPrevNodeCount = 0;
751 CRITICAL_BLOCK(cs_vNodes)
753 // Disconnect unused nodes
754 vector<CNode*> vNodesCopy = vNodes;
755 BOOST_FOREACH(CNode* pnode, vNodesCopy)
757 if (pnode->fDisconnect ||
758 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
760 // remove from vNodes
761 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
763 // close socket and cleanup
764 pnode->CloseSocketDisconnect();
767 // hold in disconnected pool until all refs are released
768 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
769 if (pnode->fNetworkNode || pnode->fInbound)
771 vNodesDisconnected.push_back(pnode);
775 // Delete disconnected nodes
776 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
777 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
779 // wait until threads are done using it
780 if (pnode->GetRefCount() <= 0)
782 bool fDelete = false;
783 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
784 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
785 TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
786 TRY_CRITICAL_BLOCK(pnode->cs_inventory)
790 vNodesDisconnected.remove(pnode);
796 if (vNodes.size() != nPrevNodeCount)
798 nPrevNodeCount = vNodes.size();
804 // Find which sockets have data to receive
806 struct timeval timeout;
808 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
815 FD_ZERO(&fdsetError);
816 SOCKET hSocketMax = 0;
818 if(hListenSocket != INVALID_SOCKET)
819 FD_SET(hListenSocket, &fdsetRecv);
820 hSocketMax = max(hSocketMax, hListenSocket);
821 CRITICAL_BLOCK(cs_vNodes)
823 BOOST_FOREACH(CNode* pnode, vNodes)
825 if (pnode->hSocket == INVALID_SOCKET || pnode->hSocket < 0)
827 FD_SET(pnode->hSocket, &fdsetRecv);
828 FD_SET(pnode->hSocket, &fdsetError);
829 hSocketMax = max(hSocketMax, pnode->hSocket);
830 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
831 if (!pnode->vSend.empty())
832 FD_SET(pnode->hSocket, &fdsetSend);
836 vnThreadsRunning[0]--;
837 int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
838 vnThreadsRunning[0]++;
841 if (nSelect == SOCKET_ERROR)
843 int nErr = WSAGetLastError();
846 printf("socket select error %d\n", nErr);
847 for (int i = 0; i <= hSocketMax; i++)
848 FD_SET(i, &fdsetRecv);
851 FD_ZERO(&fdsetError);
852 Sleep(timeout.tv_usec/1000);
857 // Accept new connections
859 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
861 struct sockaddr_in sockaddr;
862 socklen_t len = sizeof(sockaddr);
863 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
864 CAddress addr(sockaddr);
867 CRITICAL_BLOCK(cs_vNodes)
868 BOOST_FOREACH(CNode* pnode, vNodes)
871 if (hSocket == INVALID_SOCKET)
873 if (WSAGetLastError() != WSAEWOULDBLOCK)
874 printf("socket error accept failed: %d\n", WSAGetLastError());
876 else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
878 closesocket(hSocket);
882 printf("accepted connection %s\n", addr.ToString().c_str());
883 CNode* pnode = new CNode(hSocket, addr, true);
885 CRITICAL_BLOCK(cs_vNodes)
886 vNodes.push_back(pnode);
892 // Service each socket
894 vector<CNode*> vNodesCopy;
895 CRITICAL_BLOCK(cs_vNodes)
898 BOOST_FOREACH(CNode* pnode, vNodesCopy)
901 BOOST_FOREACH(CNode* pnode, vNodesCopy)
909 if (pnode->hSocket == INVALID_SOCKET)
911 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
913 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
915 CDataStream& vRecv = pnode->vRecv;
916 unsigned int nPos = vRecv.size();
918 if (nPos > ReceiveBufferSize()) {
919 if (!pnode->fDisconnect)
920 printf("socket recv flood control disconnect (%d bytes)\n", vRecv.size());
921 pnode->CloseSocketDisconnect();
924 // typical socket buffer is 8K-64K
925 char pchBuf[0x10000];
926 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
929 vRecv.resize(nPos + nBytes);
930 memcpy(&vRecv[nPos], pchBuf, nBytes);
931 pnode->nLastRecv = GetTime();
933 else if (nBytes == 0)
935 // socket closed gracefully
936 if (!pnode->fDisconnect)
937 printf("socket closed\n");
938 pnode->CloseSocketDisconnect();
943 int nErr = WSAGetLastError();
944 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
946 if (!pnode->fDisconnect)
947 printf("socket recv error %d\n", nErr);
948 pnode->CloseSocketDisconnect();
958 if (pnode->hSocket == INVALID_SOCKET)
960 if (FD_ISSET(pnode->hSocket, &fdsetSend))
962 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
964 CDataStream& vSend = pnode->vSend;
967 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
970 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
971 pnode->nLastSend = GetTime();
976 int nErr = WSAGetLastError();
977 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
979 printf("socket send error %d\n", nErr);
980 pnode->CloseSocketDisconnect();
983 if (vSend.size() > SendBufferSize()) {
984 if (!pnode->fDisconnect)
985 printf("socket send flood control disconnect (%d bytes)\n", vSend.size());
986 pnode->CloseSocketDisconnect();
993 // Inactivity checking
995 if (pnode->vSend.empty())
996 pnode->nLastSendEmpty = GetTime();
997 if (GetTime() - pnode->nTimeConnected > 60)
999 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
1001 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
1002 pnode->fDisconnect = true;
1004 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
1006 printf("socket not sending\n");
1007 pnode->fDisconnect = true;
1009 else if (GetTime() - pnode->nLastRecv > 90*60)
1011 printf("socket inactivity timeout\n");
1012 pnode->fDisconnect = true;
1016 CRITICAL_BLOCK(cs_vNodes)
1018 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1035 void ThreadMapPort(void* parg)
1037 IMPLEMENT_RANDOMIZE_STACK(ThreadMapPort(parg));
1040 vnThreadsRunning[5]++;
1041 ThreadMapPort2(parg);
1042 vnThreadsRunning[5]--;
1044 catch (std::exception& e) {
1045 vnThreadsRunning[5]--;
1046 PrintException(&e, "ThreadMapPort()");
1048 vnThreadsRunning[5]--;
1049 PrintException(NULL, "ThreadMapPort()");
1051 printf("ThreadMapPort exiting\n");
1054 void ThreadMapPort2(void* parg)
1056 printf("ThreadMapPort started\n");
1059 sprintf(port, "%d", GetListenPort());
1061 const char * rootdescurl = 0;
1062 const char * multicastif = 0;
1063 const char * minissdpdpath = 0;
1064 struct UPNPDev * devlist = 0;
1067 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
1069 struct UPNPUrls urls;
1070 struct IGDdatas data;
1073 r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
1080 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1081 port, port, lanaddr, 0, "TCP", 0);
1083 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1084 port, port, lanaddr, 0, "TCP", 0, "0");
1086 if(r!=UPNPCOMMAND_SUCCESS)
1087 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1088 port, port, lanaddr, r, strupnperror(r));
1090 printf("UPnP Port Mapping successful.\n");
1092 if (fShutdown || !fUseUPnP)
1094 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port, "TCP", 0);
1095 printf("UPNP_DeletePortMapping() returned : %d\n", r);
1096 freeUPNPDevlist(devlist); devlist = 0;
1097 FreeUPNPUrls(&urls);
1103 printf("No valid UPnP IGDs found\n");
1104 freeUPNPDevlist(devlist); devlist = 0;
1106 FreeUPNPUrls(&urls);
1108 if (fShutdown || !fUseUPnP)
1115 void MapPort(bool fMapPort)
1117 if (fUseUPnP != fMapPort)
1119 fUseUPnP = fMapPort;
1120 WriteSetting("fUseUPnP", fUseUPnP);
1122 if (fUseUPnP && vnThreadsRunning[5] < 1)
1124 if (!CreateThread(ThreadMapPort, NULL))
1125 printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
1139 static const char *strDNSSeed[] = {
1141 "bitseed.bitcoin.org.uk",
1142 "dnsseed.bluematt.me",
1145 void DNSAddressSeed()
1151 printf("Loading addresses from DNS seeds (could take a while)\n");
1153 for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1154 vector<CAddress> vaddr;
1155 if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, -1, true))
1157 BOOST_FOREACH (CAddress& addr, vaddr)
1159 if (addr.GetByte(3) != 127)
1170 printf("%d addresses found from DNS seeds\n", found);
1175 unsigned int pnSeed[] =
1177 0x1ddb1032, 0x6242ce40, 0x52d6a445, 0x2dd7a445, 0x8a53cd47, 0x73263750, 0xda23c257, 0xecd4ed57,
1178 0x0a40ec59, 0x75dce160, 0x7df76791, 0x89370bad, 0xa4f214ad, 0x767700ae, 0x638b0418, 0x868a1018,
1179 0xcd9f332e, 0x0129653e, 0xcc92dc3e, 0x96671640, 0x56487e40, 0x5b66f440, 0xb1d01f41, 0xf1dc6041,
1180 0xc1d12b42, 0x86ba1243, 0x6be4df43, 0x6d4cef43, 0xd18e0644, 0x1ab0b344, 0x6584a345, 0xe7c1a445,
1181 0x58cea445, 0xc5daa445, 0x21dda445, 0x3d3b5346, 0x13e55347, 0x1080d24a, 0x8e611e4b, 0x81518e4b,
1182 0x6c839e4b, 0xe2ad0a4c, 0xfbbc0a4c, 0x7f5b6e4c, 0x7244224e, 0x1300554e, 0x20690652, 0x5a48b652,
1183 0x75c5c752, 0x4335cc54, 0x340fd154, 0x87c07455, 0x087b2b56, 0x8a133a57, 0xac23c257, 0x70374959,
1184 0xfb63d45b, 0xb9a1685c, 0x180d765c, 0x674f645d, 0x04d3495e, 0x1de44b5e, 0x4ee8a362, 0x0ded1b63,
1185 0xc1b04b6d, 0x8d921581, 0x97b7ea82, 0x1cf83a8e, 0x91490bad, 0x09dc75ae, 0x9a6d79ae, 0xa26d79ae,
1186 0x0fd08fae, 0x0f3e3fb2, 0x4f944fb2, 0xcca448b8, 0x3ecd6ab8, 0xa9d5a5bc, 0x8d0119c1, 0x045997d5,
1187 0xca019dd9, 0x0d526c4d, 0xabf1ba44, 0x66b1ab55, 0x1165f462, 0x3ed7cbad, 0xa38fae6e, 0x3bd2cbad,
1188 0xd36f0547, 0x20df7840, 0x7a337742, 0x549f8e4b, 0x9062365c, 0xd399f562, 0x2b5274a1, 0x8edfa153,
1189 0x3bffb347, 0x7074bf58, 0xb74fcbad, 0x5b5a795b, 0x02fa29ce, 0x5a6738d4, 0xe8a1d23e, 0xef98c445,
1190 0x4b0f494c, 0xa2bc1e56, 0x7694ad63, 0xa4a800c3, 0x05fda6cd, 0x9f22175e, 0x364a795b, 0x536285d5,
1191 0xac44c9d4, 0x0b06254d, 0x150c2fd4, 0x32a50dcc, 0xfd79ce48, 0xf15cfa53, 0x66c01e60, 0x6bc26661,
1192 0xc03b47ae, 0x4dda1b81, 0x3285a4c1, 0x883ca96d, 0x35d60a4c, 0xdae09744, 0x2e314d61, 0x84e247cf,
1193 0x6c814552, 0x3a1cc658, 0x98d8f382, 0xe584cb5b, 0x15e86057, 0x7b01504e, 0xd852dd48, 0x56382f56,
1194 0x0a5df454, 0xa0d18d18, 0x2e89b148, 0xa79c114c, 0xcbdcd054, 0x5523bc43, 0xa9832640, 0x8a066144,
1195 0x3894c3bc, 0xab76bf58, 0x6a018ac1, 0xfebf4f43, 0x2f26c658, 0x31102f4e, 0x85e929d5, 0x2a1c175e,
1196 0xfc6c2cd1, 0x27b04b6d, 0xdf024650, 0x161748b8, 0x28be6580, 0x57be6580, 0x1cee677a, 0xaa6bb742,
1197 0x9a53964b, 0x0a5a2d4d, 0x2434c658, 0x9a494f57, 0x1ebb0e48, 0xf610b85d, 0x077ecf44, 0x085128bc,
1198 0x5ba17a18, 0x27ca1b42, 0xf8a00b56, 0xfcd4c257, 0xcf2fc15e, 0xd897e052, 0x4cada04f, 0x2f35f6d5,
1199 0x382ce8c9, 0xe523984b, 0x3f946846, 0x60c8be43, 0x41da6257, 0xde0be142, 0xae8a544b, 0xeff0c254,
1200 0x1e0f795b, 0xaeb28890, 0xca16acd9, 0x1e47ddd8, 0x8c8c4829, 0xd27dc747, 0xd53b1663, 0x4096b163,
1201 0x9c8dd958, 0xcb12f860, 0x9e79305c, 0x40c1a445, 0x4a90c2bc, 0x2c3a464d, 0x2727f23c, 0x30b04b6d,
1202 0x59024cb8, 0xa091e6ad, 0x31b04b6d, 0xc29d46a6, 0x63934fb2, 0xd9224dbe, 0x9f5910d8, 0x7f530a6b,
1203 0x752e9c95, 0x65453548, 0xa484be46, 0xce5a1b59, 0x710e0718, 0x46a13d18, 0xdaaf5318, 0xc4a8ff53,
1204 0x87abaa52, 0xb764cf51, 0xb2025d4a, 0x6d351e41, 0xc035c33e, 0xa432c162, 0x61ef34ae, 0xd16fddbc,
1205 0x0870e8c1, 0x3070e8c1, 0x9c71e8c1, 0xa4992363, 0x85a1f663, 0x4184e559, 0x18d96ed8, 0x17b8dbd5,
1206 0x60e7cd18, 0xe5ee104c, 0xab17ac62, 0x1e786e1b, 0x5d23b762, 0xf2388fae, 0x88270360, 0x9e5b3d80,
1207 0x7da518b2, 0xb5613b45, 0x1ad41f3e, 0xd550854a, 0x8617e9a9, 0x925b229c, 0xf2e92542, 0x47af0544,
1208 0x73b5a843, 0xb9b7a0ad, 0x03a748d0, 0x0a6ff862, 0x6694df62, 0x3bfac948, 0x8e098f4f, 0x746916c3,
1209 0x02f38e4f, 0x40bb1243, 0x6a54d162, 0x6008414b, 0xa513794c, 0x514aa343, 0x63781747, 0xdbb6795b,
1210 0xed065058, 0x42d24b46, 0x1518794c, 0x9b271681, 0x73e4ffad, 0x0654784f, 0x438dc945, 0x641846a6,
1211 0x2d1b0944, 0x94b59148, 0x8d369558, 0xa5a97662, 0x8b705b42, 0xce9204ae, 0x8d584450, 0x2df61555,
1212 0xeebff943, 0x2e75fb4d, 0x3ef8fc57, 0x9921135e, 0x8e31042e, 0xb5afad43, 0x89ecedd1, 0x9cfcc047,
1213 0x8fcd0f4c, 0xbe49f5ad, 0x146a8d45, 0x98669ab8, 0x98d9175e, 0xd1a8e46d, 0x839a3ab8, 0x40a0016c,
1214 0x6d27c257, 0x977fffad, 0x7baa5d5d, 0x1213be43, 0xb167e5a9, 0x640fe8ca, 0xbc9ea655, 0x0f820a4c,
1215 0x0f097059, 0x69ac957c, 0x366d8453, 0xb1ba2844, 0x8857f081, 0x70b5be63, 0xc545454b, 0xaf36ded1,
1216 0xb5a4b052, 0x21f062d1, 0x72ab89b2, 0x74a45318, 0x8312e6bc, 0xb916965f, 0x8aa7c858, 0xfe7effad,
1221 void ThreadOpenConnections(void* parg)
1223 IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
1226 vnThreadsRunning[1]++;
1227 ThreadOpenConnections2(parg);
1228 vnThreadsRunning[1]--;
1230 catch (std::exception& e) {
1231 vnThreadsRunning[1]--;
1232 PrintException(&e, "ThreadOpenConnections()");
1234 vnThreadsRunning[1]--;
1235 PrintException(NULL, "ThreadOpenConnections()");
1237 printf("ThreadOpenConnections exiting\n");
1240 void ThreadOpenConnections2(void* parg)
1242 printf("ThreadOpenConnections started\n");
1244 // Connect to specific addresses
1245 if (mapArgs.count("-connect"))
1247 for (int64 nLoop = 0;; nLoop++)
1249 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1251 CAddress addr(strAddr, fAllowDNS);
1253 OpenNetworkConnection(addr);
1254 for (int i = 0; i < 10 && i < nLoop; i++)
1264 // Connect to manually added nodes first
1265 if (mapArgs.count("-addnode"))
1267 BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
1269 CAddress addr(strAddr, fAllowDNS);
1272 OpenNetworkConnection(addr);
1280 // Initiate network connections
1281 int64 nStart = GetTime();
1284 // Limit outbound connections
1285 vnThreadsRunning[1]--;
1290 CRITICAL_BLOCK(cs_vNodes)
1291 BOOST_FOREACH(CNode* pnode, vNodes)
1292 if (!pnode->fInbound)
1294 int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
1295 nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
1296 if (nOutbound < nMaxOutboundConnections)
1302 vnThreadsRunning[1]++;
1306 CRITICAL_BLOCK(cs_mapAddresses)
1308 // Add seed nodes if IRC isn't working
1309 static bool fSeedUsed;
1310 bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
1311 if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
1313 for (int i = 0; i < ARRAYLEN(pnSeed); i++)
1315 // It'll only connect to one or two seed nodes because once it connects,
1316 // it'll get a pile of addresses with newer timestamps.
1318 addr.ip = pnSeed[i];
1325 if (fSeedUsed && mapAddresses.size() > ARRAYLEN(pnSeed) + 100)
1327 // Disconnect seed nodes
1328 set<unsigned int> setSeed(pnSeed, pnSeed + ARRAYLEN(pnSeed));
1329 static int64 nSeedDisconnected;
1330 if (nSeedDisconnected == 0)
1332 nSeedDisconnected = GetTime();
1333 CRITICAL_BLOCK(cs_vNodes)
1334 BOOST_FOREACH(CNode* pnode, vNodes)
1335 if (setSeed.count(pnode->addr.ip))
1336 pnode->fDisconnect = true;
1339 // Keep setting timestamps to 0 so they won't reconnect
1340 if (GetTime() - nSeedDisconnected < 60 * 60)
1342 BOOST_FOREACH(PAIRTYPE(const vector<unsigned char>, CAddress)& item, mapAddresses)
1344 if (setSeed.count(item.second.ip) && item.second.nTime != 0)
1346 item.second.nTime = 0;
1347 CAddrDB().WriteAddress(item.second);
1356 // Choose an address to connect to based on most recently seen
1358 CAddress addrConnect;
1359 int64 nBest = INT64_MIN;
1361 // Only connect to one address per a.b.?.? range.
1362 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1363 set<unsigned int> setConnected;
1364 CRITICAL_BLOCK(cs_vNodes)
1365 BOOST_FOREACH(CNode* pnode, vNodes)
1366 setConnected.insert(pnode->addr.ip & 0x0000ffff);
1368 CRITICAL_BLOCK(cs_mapAddresses)
1370 BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
1372 const CAddress& addr = item.second;
1373 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
1375 int64 nSinceLastSeen = GetAdjustedTime() - addr.nTime;
1376 int64 nSinceLastTry = GetAdjustedTime() - addr.nLastTry;
1378 // Randomize the order in a deterministic way, putting the standard port first
1379 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
1380 if (addr.port != htons(GetDefaultPort()))
1381 nRandomizer += 2 * 60 * 60;
1383 // Last seen Base retry frequency
1392 // 365 days 93 hours
1393 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
1395 // Fast reconnect for one hour after last seen
1396 if (nSinceLastSeen < 60 * 60)
1399 // Limit retry frequency
1400 if (nSinceLastTry < nDelay)
1403 // If we have IRC, we'll be notified when they first come online,
1404 // and again every 24 hours by the refresh broadcast.
1405 if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)
1408 // Only try the old stuff if we don't have enough connections
1409 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
1412 // If multiple addresses are ready, prioritize by time since
1413 // last seen and time since last tried.
1414 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
1423 if (addrConnect.IsValid())
1424 OpenNetworkConnection(addrConnect);
1428 bool OpenNetworkConnection(const CAddress& addrConnect)
1431 // Initiate outbound network connection
1435 if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
1438 vnThreadsRunning[1]--;
1439 CNode* pnode = ConnectNode(addrConnect);
1440 vnThreadsRunning[1]++;
1445 pnode->fNetworkNode = true;
1457 void ThreadMessageHandler(void* parg)
1459 IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
1462 vnThreadsRunning[2]++;
1463 ThreadMessageHandler2(parg);
1464 vnThreadsRunning[2]--;
1466 catch (std::exception& e) {
1467 vnThreadsRunning[2]--;
1468 PrintException(&e, "ThreadMessageHandler()");
1470 vnThreadsRunning[2]--;
1471 PrintException(NULL, "ThreadMessageHandler()");
1473 printf("ThreadMessageHandler exiting\n");
1476 void ThreadMessageHandler2(void* parg)
1478 printf("ThreadMessageHandler started\n");
1479 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1482 vector<CNode*> vNodesCopy;
1483 CRITICAL_BLOCK(cs_vNodes)
1485 vNodesCopy = vNodes;
1486 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1490 // Poll the connected nodes for messages
1491 CNode* pnodeTrickle = NULL;
1492 if (!vNodesCopy.empty())
1493 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1494 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1497 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
1498 ProcessMessages(pnode);
1503 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
1504 SendMessages(pnode, pnode == pnodeTrickle);
1509 CRITICAL_BLOCK(cs_vNodes)
1511 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1515 // Wait and allow messages to bunch up.
1516 // Reduce vnThreadsRunning so StopNode has permission to exit while
1517 // we're sleeping, but we must always check fShutdown after doing this.
1518 vnThreadsRunning[2]--;
1520 if (fRequestShutdown)
1522 vnThreadsRunning[2]++;
1533 bool BindListenPort(string& strError)
1537 addrLocalHost.port = htons(GetListenPort());
1540 // Initialize Windows Sockets
1542 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1543 if (ret != NO_ERROR)
1545 strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1546 printf("%s\n", strError.c_str());
1551 // Create socket for listening for incoming connections
1552 hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1553 if (hListenSocket == INVALID_SOCKET)
1555 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1556 printf("%s\n", strError.c_str());
1561 // Different way of disabling SIGPIPE on BSD
1562 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1566 // Allow binding if the port is still in TIME_WAIT state after
1567 // the program was closed and restarted. Not an issue on windows.
1568 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1572 // Set to nonblocking, incoming connections will also inherit this
1573 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1575 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1578 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1579 printf("%s\n", strError.c_str());
1583 // The sockaddr_in structure specifies the address family,
1584 // IP address, and port for the socket that is being bound
1585 struct sockaddr_in sockaddr;
1586 memset(&sockaddr, 0, sizeof(sockaddr));
1587 sockaddr.sin_family = AF_INET;
1588 sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
1589 sockaddr.sin_port = htons(GetListenPort());
1590 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
1592 int nErr = WSAGetLastError();
1593 if (nErr == WSAEADDRINUSE)
1594 strError = strprintf(_("Unable to bind to port %d on this computer. Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
1596 strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
1597 printf("%s\n", strError.c_str());
1600 printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
1602 // Listen for incoming connections
1603 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1605 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1606 printf("%s\n", strError.c_str());
1613 void StartNode(void* parg)
1615 if (pnodeLocalHost == NULL)
1616 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, false, nLocalServices));
1619 // Get local host ip
1620 char pszHostName[1000] = "";
1621 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1623 vector<CAddress> vaddr;
1624 if (Lookup(pszHostName, vaddr, nLocalServices, -1, true))
1625 BOOST_FOREACH (const CAddress &addr, vaddr)
1626 if (addr.GetByte(3) != 127)
1628 addrLocalHost = addr;
1633 // Get local host ip
1634 struct ifaddrs* myaddrs;
1635 if (getifaddrs(&myaddrs) == 0)
1637 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1639 if (ifa->ifa_addr == NULL) continue;
1640 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1641 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1642 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1644 if (ifa->ifa_addr->sa_family == AF_INET)
1646 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1647 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
1648 printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
1650 // Take the first IP that isn't loopback 127.x.x.x
1651 CAddress addr(*(unsigned int*)&s4->sin_addr, GetListenPort(), nLocalServices);
1652 if (addr.IsValid() && addr.GetByte(3) != 127)
1654 addrLocalHost = addr;
1658 else if (ifa->ifa_addr->sa_family == AF_INET6)
1660 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1661 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
1662 printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
1665 freeifaddrs(myaddrs);
1668 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1670 if (fUseProxy || mapArgs.count("-connect") || fNoListen)
1672 // Proxies can't take incoming connections
1673 addrLocalHost.ip = CAddress("0.0.0.0").ip;
1674 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1678 CreateThread(ThreadGetMyExternalIP, NULL);
1685 // Map ports with UPnP
1689 // Get addresses from IRC and advertise ours
1690 if (!CreateThread(ThreadIRCSeed, NULL))
1691 printf("Error: CreateThread(ThreadIRCSeed) failed\n");
1693 // Send and receive from sockets, accept connections
1694 pthread_t hThreadSocketHandler = CreateThread(ThreadSocketHandler, NULL, true);
1696 // Initiate outbound connections
1697 if (!CreateThread(ThreadOpenConnections, NULL))
1698 printf("Error: CreateThread(ThreadOpenConnections) failed\n");
1701 if (!CreateThread(ThreadMessageHandler, NULL))
1702 printf("Error: CreateThread(ThreadMessageHandler) failed\n");
1704 // Generate coins in the background
1705 GenerateBitcoins(fGenerateBitcoins, pwalletMain);
1710 printf("StopNode()\n");
1712 nTransactionsUpdated++;
1713 int64 nStart = GetTime();
1714 while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0
1716 || vnThreadsRunning[5] > 0
1720 if (GetTime() - nStart > 20)
1724 if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
1725 if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
1726 if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
1727 if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
1728 if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
1729 if (fHaveUPnP && vnThreadsRunning[5] > 0) printf("ThreadMapPort still running\n");
1730 while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
1746 BOOST_FOREACH(CNode* pnode, vNodes)
1747 if (pnode->hSocket != INVALID_SOCKET)
1748 closesocket(pnode->hSocket);
1749 if (hListenSocket != INVALID_SOCKET)
1750 if (closesocket(hListenSocket) == SOCKET_ERROR)
1751 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1754 // Shutdown Windows Sockets
1759 instance_of_cnetcleanup;