-
+ D0A589479579F42563423AE34037BD0655A0A666EF698E50FA461BC1AC84FA5CDD0638539CBA6B528D770CFC191BEFEF20FF470F1C4CA104C7BB2445835D50F1bitcoin/src/net.cpp(0 . 0)(1 . 1982)
15553 // /****************************\
15554 // * EXPERIMENTAL BRANCH. *
15555 // * FOR LABORATORY USE ONLY. *
15556 // ********************************
15557 // ************
15558 // **************
15559 // ****************
15560 // **** **** ****
15561 // *** *** ***
15562 // *** *** ***
15563 // *** * * **
15564 // ******** ********
15565 // ******* ******
15566 // *** **
15567 // * ******* **
15568 // ** * * * * *
15569 // ** * * ***
15570 // **** * * * * ****
15571 // **** *** * * ** ***
15572 // **** ********* ******
15573 // ******* ***** *******
15574 // ********* ****** **
15575 // ** ****** ******
15576 // ** ******* **
15577 // ** ******* ***
15578 // **** ******** ************
15579 // ************ ************
15580 // ******** *******
15581 // ****** ****
15582 // *** ***
15583 // ********************************
15584 // Copyright (c) 2009-2010 Satoshi Nakamoto
15585 // Copyright (c) 2009-2012 The Bitcoin developers
15586 // Distributed under the MIT/X11 software license, see the accompanying
15587 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
15588
15589 #include "headers.h"
15590 #include "irc.h"
15591 #include "db.h"
15592 #include "net.h"
15593 #include "init.h"
15594 #include "strlcpy.h"
15595
15596 #ifdef WIN32
15597 #include <string.h>
15598 #endif
15599
15600 #ifdef USE_UPNP
15601 #include <miniupnpc/miniwget.h>
15602 #include <miniupnpc/miniupnpc.h>
15603 #include <miniupnpc/upnpcommands.h>
15604 #include <miniupnpc/upnperrors.h>
15605 #endif
15606
15607 using namespace std;
15608 using namespace boost;
15609
15610 static const int MAX_OUTBOUND_CONNECTIONS = 8;
15611
15612 void ThreadMessageHandler2(void* parg);
15613 void ThreadSocketHandler2(void* parg);
15614 void ThreadOpenConnections2(void* parg);
15615 #ifdef USE_UPNP
15616 void ThreadMapPort2(void* parg);
15617 #endif
15618 void ThreadDNSAddressSeed2(void* parg);
15619 bool OpenNetworkConnection(const CAddress& addrConnect);
15620
15621
15622
15623
15624
15625 //
15626 // Global state variables
15627 //
15628 bool fClient = false;
15629 bool fAllowDNS = false;
15630 uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
15631 CAddress addrLocalHost("0.0.0.0", 0, false, nLocalServices);
15632 static CNode* pnodeLocalHost = NULL;
15633 uint64 nLocalHostNonce = 0;
15634 array<int, 10> vnThreadsRunning;
15635 static SOCKET hListenSocket = INVALID_SOCKET;
15636
15637 vector<CNode*> vNodes;
15638 CCriticalSection cs_vNodes;
15639 map<vector<unsigned char>, CAddress> mapAddresses;
15640 CCriticalSection cs_mapAddresses;
15641 map<CInv, CDataStream> mapRelay;
15642 deque<pair<int64, CInv> > vRelayExpiration;
15643 CCriticalSection cs_mapRelay;
15644 map<CInv, int64> mapAlreadyAskedFor;
15645
15646 // Settings
15647 int fUseProxy = false;
15648 int nConnectTimeout = 5000;
15649 CAddress addrProxy("127.0.0.1",9050);
15650
15651
15652
15653
15654 unsigned short GetListenPort()
15655 {
15656 return (unsigned short)(GetArg("-port", GetDefaultPort()));
15657 }
15658
15659 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
15660 {
15661 // Filter out duplicate requests
15662 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
15663 return;
15664 pindexLastGetBlocksBegin = pindexBegin;
15665 hashLastGetBlocksEnd = hashEnd;
15666
15667 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
15668 }
15669
15670
15671
15672
15673
15674 bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout)
15675 {
15676 hSocketRet = INVALID_SOCKET;
15677
15678 SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
15679 if (hSocket == INVALID_SOCKET)
15680 return false;
15681 #ifdef SO_NOSIGPIPE
15682 int set = 1;
15683 setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
15684 #endif
15685
15686 bool fProxy = (fUseProxy && addrConnect.IsRoutable());
15687 struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
15688
15689 #ifdef WIN32
15690 u_long fNonblock = 1;
15691 if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
15692 #else
15693 int fFlags = fcntl(hSocket, F_GETFL, 0);
15694 if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
15695 #endif
15696 {
15697 closesocket(hSocket);
15698 return false;
15699 }
15700
15701
15702 if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
15703 {
15704 // WSAEINVAL is here because some legacy version of winsock uses it
15705 if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
15706 {
15707 struct timeval timeout;
15708 timeout.tv_sec = nTimeout / 1000;
15709 timeout.tv_usec = (nTimeout % 1000) * 1000;
15710
15711 fd_set fdset;
15712 FD_ZERO(&fdset);
15713 FD_SET(hSocket, &fdset);
15714 int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
15715 if (nRet == 0)
15716 {
15717 printf("connection timeout\n");
15718 closesocket(hSocket);
15719 return false;
15720 }
15721 if (nRet == SOCKET_ERROR)
15722 {
15723 printf("select() for connection failed: %i\n",WSAGetLastError());
15724 closesocket(hSocket);
15725 return false;
15726 }
15727 socklen_t nRetSize = sizeof(nRet);
15728 #ifdef WIN32
15729 if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
15730 #else
15731 if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
15732 #endif
15733 {
15734 printf("getsockopt() for connection failed: %i\n",WSAGetLastError());
15735 closesocket(hSocket);
15736 return false;
15737 }
15738 if (nRet != 0)
15739 {
15740 printf("connect() failed after select(): %s\n",strerror(nRet));
15741 closesocket(hSocket);
15742 return false;
15743 }
15744 }
15745 #ifdef WIN32
15746 else if (WSAGetLastError() != WSAEISCONN)
15747 #else
15748 else
15749 #endif
15750 {
15751 printf("connect() failed: %i\n",WSAGetLastError());
15752 closesocket(hSocket);
15753 return false;
15754 }
15755 }
15756
15757 /*
15758 this isn't even strictly necessary
15759 CNode::ConnectNode immediately turns the socket back to non-blocking
15760 but we'll turn it back to blocking just in case
15761 */
15762 #ifdef WIN32
15763 fNonblock = 0;
15764 if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
15765 #else
15766 fFlags = fcntl(hSocket, F_GETFL, 0);
15767 if (fcntl(hSocket, F_SETFL, fFlags & !O_NONBLOCK) == SOCKET_ERROR)
15768 #endif
15769 {
15770 closesocket(hSocket);
15771 return false;
15772 }
15773
15774 if (fProxy)
15775 {
15776 printf("proxy connecting %s\n", addrConnect.ToString().c_str());
15777 char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
15778 memcpy(pszSocks4IP + 2, &addrConnect.port, 2);
15779 memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);
15780 char* pszSocks4 = pszSocks4IP;
15781 int nSize = sizeof(pszSocks4IP);
15782
15783 int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
15784 if (ret != nSize)
15785 {
15786 closesocket(hSocket);
15787 return error("Error sending to proxy");
15788 }
15789 char pchRet[8];
15790 if (recv(hSocket, pchRet, 8, 0) != 8)
15791 {
15792 closesocket(hSocket);
15793 return error("Error reading proxy response");
15794 }
15795 if (pchRet[1] != 0x5a)
15796 {
15797 closesocket(hSocket);
15798 if (pchRet[1] != 0x5b)
15799 printf("ERROR: Proxy returned error %d\n", pchRet[1]);
15800 return false;
15801 }
15802 printf("proxy connected %s\n", addrConnect.ToString().c_str());
15803 }
15804
15805 hSocketRet = hSocket;
15806 return true;
15807 }
15808
15809 // portDefault is in host order
15810 bool Lookup(const char *pszName, vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup, int portDefault, bool fAllowPort)
15811 {
15812 vaddr.clear();
15813 if (pszName[0] == 0)
15814 return false;
15815 int port = portDefault;
15816 char psz[256];
15817 char *pszHost = psz;
15818 strlcpy(psz, pszName, sizeof(psz));
15819 if (fAllowPort)
15820 {
15821 char* pszColon = strrchr(psz+1,':');
15822 char *pszPortEnd = NULL;
15823 int portParsed = pszColon ? strtoul(pszColon+1, &pszPortEnd, 10) : 0;
15824 if (pszColon && pszPortEnd && pszPortEnd[0] == 0)
15825 {
15826 if (psz[0] == '[' && pszColon[-1] == ']')
15827 {
15828 // Future: enable IPv6 colon-notation inside []
15829 pszHost = psz+1;
15830 pszColon[-1] = 0;
15831 }
15832 else
15833 pszColon[0] = 0;
15834 port = portParsed;
15835 if (port < 0 || port > USHRT_MAX)
15836 port = USHRT_MAX;
15837 }
15838 }
15839
15840 unsigned int addrIP = inet_addr(pszHost);
15841 if (addrIP != INADDR_NONE)
15842 {
15843 // valid IP address passed
15844 vaddr.push_back(CAddress(addrIP, port, nServices));
15845 return true;
15846 }
15847
15848 if (!fAllowLookup)
15849 return false;
15850
15851 struct hostent* phostent = gethostbyname(pszHost);
15852 if (!phostent)
15853 return false;
15854
15855 if (phostent->h_addrtype != AF_INET)
15856 return false;
15857
15858 char** ppAddr = phostent->h_addr_list;
15859 while (*ppAddr != NULL && vaddr.size() != nMaxSolutions)
15860 {
15861 CAddress addr(((struct in_addr*)ppAddr[0])->s_addr, port, nServices);
15862 if (addr.IsValid())
15863 vaddr.push_back(addr);
15864 ppAddr++;
15865 }
15866
15867 return (vaddr.size() > 0);
15868 }
15869
15870 // portDefault is in host order
15871 bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup, int portDefault, bool fAllowPort)
15872 {
15873 vector<CAddress> vaddr;
15874 bool fRet = Lookup(pszName, vaddr, nServices, 1, fAllowLookup, portDefault, fAllowPort);
15875 if (fRet)
15876 addr = vaddr[0];
15877 return fRet;
15878 }
15879
15880 bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const char* pszKeyword, unsigned int& ipRet)
15881 {
15882 SOCKET hSocket;
15883 if (!ConnectSocket(addrConnect, hSocket))
15884 return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
15885
15886 send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
15887
15888 string strLine;
15889 while (RecvLine(hSocket, strLine))
15890 {
15891 if (strLine.empty()) // HTTP response is separated from headers by blank line
15892 {
15893 loop
15894 {
15895 if (!RecvLine(hSocket, strLine))
15896 {
15897 closesocket(hSocket);
15898 return false;
15899 }
15900 if (pszKeyword == NULL)
15901 break;
15902 if (strLine.find(pszKeyword) != -1)
15903 {
15904 strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
15905 break;
15906 }
15907 }
15908 closesocket(hSocket);
15909 if (strLine.find("<") != -1)
15910 strLine = strLine.substr(0, strLine.find("<"));
15911 strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
15912 while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
15913 strLine.resize(strLine.size()-1);
15914 CAddress addr(strLine,0,true);
15915 printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
15916 if (addr.ip == 0 || addr.ip == INADDR_NONE || !addr.IsRoutable())
15917 return false;
15918 ipRet = addr.ip;
15919 return true;
15920 }
15921 }
15922 closesocket(hSocket);
15923 return error("GetMyExternalIP() : connection closed");
15924 }
15925
15926 // We now get our external IP from the IRC server first and only use this as a backup
15927 bool GetMyExternalIP(unsigned int& ipRet)
15928 {
15929 CAddress addrConnect;
15930 const char* pszGet;
15931 const char* pszKeyword;
15932
15933 if (fUseProxy)
15934 return false;
15935
15936 for (int nLookup = 0; nLookup <= 1; nLookup++)
15937 for (int nHost = 1; nHost <= 2; nHost++)
15938 {
15939 // We should be phasing out our use of sites like these. If we need
15940 // replacements, we should ask for volunteers to put this simple
15941 // php file on their webserver that prints the client IP:
15942 // <?php echo $_SERVER["REMOTE_ADDR"]; ?>
15943 if (nHost == 1)
15944 {
15945 addrConnect = CAddress("91.198.22.70",80); // checkip.dyndns.org
15946
15947 if (nLookup == 1)
15948 {
15949 CAddress addrIP("checkip.dyndns.org", 80, true);
15950 if (addrIP.IsValid())
15951 addrConnect = addrIP;
15952 }
15953
15954 pszGet = "GET / HTTP/1.1\r\n"
15955 "Host: checkip.dyndns.org\r\n"
15956 "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
15957 "Connection: close\r\n"
15958 "\r\n";
15959
15960 pszKeyword = "Address:";
15961 }
15962 else if (nHost == 2)
15963 {
15964 addrConnect = CAddress("74.208.43.192", 80); // www.showmyip.com
15965
15966 if (nLookup == 1)
15967 {
15968 CAddress addrIP("www.showmyip.com", 80, true);
15969 if (addrIP.IsValid())
15970 addrConnect = addrIP;
15971 }
15972
15973 pszGet = "GET /simple/ HTTP/1.1\r\n"
15974 "Host: www.showmyip.com\r\n"
15975 "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
15976 "Connection: close\r\n"
15977 "\r\n";
15978
15979 pszKeyword = NULL; // Returns just IP address
15980 }
15981
15982 if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
15983 return true;
15984 }
15985
15986 return false;
15987 }
15988
15989 void ThreadGetMyExternalIP(void* parg)
15990 {
15991 // Wait for IRC to get it first
15992 if (!GetBoolArg("-noirc"))
15993 {
15994 for (int i = 0; i < 2 * 60; i++)
15995 {
15996 Sleep(1000);
15997 if (fGotExternalIP || fShutdown)
15998 return;
15999 }
16000 }
16001
16002 // Fallback in case IRC fails to get it
16003 if (GetMyExternalIP(addrLocalHost.ip))
16004 {
16005 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
16006 if (addrLocalHost.IsRoutable())
16007 {
16008 // If we already connected to a few before we had our IP, go back and addr them.
16009 // setAddrKnown automatically filters any duplicate sends.
16010 CAddress addr(addrLocalHost);
16011 addr.nTime = GetAdjustedTime();
16012 CRITICAL_BLOCK(cs_vNodes)
16013 BOOST_FOREACH(CNode* pnode, vNodes)
16014 pnode->PushAddress(addr);
16015 }
16016 }
16017 }
16018
16019
16020
16021
16022
16023 bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB)
16024 {
16025 if (!addr.IsRoutable())
16026 return false;
16027 if (addr.ip == addrLocalHost.ip)
16028 return false;
16029 addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty);
16030 bool fUpdated = false;
16031 bool fNew = false;
16032 CAddress addrFound = addr;
16033
16034 CRITICAL_BLOCK(cs_mapAddresses)
16035 {
16036 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
16037 if (it == mapAddresses.end())
16038 {
16039 // New address
16040 printf("AddAddress(%s)\n", addr.ToString().c_str());
16041 mapAddresses.insert(make_pair(addr.GetKey(), addr));
16042 fUpdated = true;
16043 fNew = true;
16044 }
16045 else
16046 {
16047 addrFound = (*it).second;
16048 if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
16049 {
16050 // Services have been added
16051 addrFound.nServices |= addr.nServices;
16052 fUpdated = true;
16053 }
16054 bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
16055 int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
16056 if (addrFound.nTime < addr.nTime - nUpdateInterval)
16057 {
16058 // Periodically update most recently seen time
16059 addrFound.nTime = addr.nTime;
16060 fUpdated = true;
16061 }
16062 }
16063 }
16064 // There is a nasty deadlock bug if this is done inside the cs_mapAddresses
16065 // CRITICAL_BLOCK:
16066 // Thread 1: begin db transaction (locks inside-db-mutex)
16067 // then AddAddress (locks cs_mapAddresses)
16068 // Thread 2: AddAddress (locks cs_mapAddresses)
16069 // ... then db operation hangs waiting for inside-db-mutex
16070 if (fUpdated)
16071 {
16072 if (pAddrDB)
16073 pAddrDB->WriteAddress(addrFound);
16074 else
16075 CAddrDB().WriteAddress(addrFound);
16076 }
16077 return fNew;
16078 }
16079
16080 void AddressCurrentlyConnected(const CAddress& addr)
16081 {
16082 CAddress *paddrFound = NULL;
16083
16084 CRITICAL_BLOCK(cs_mapAddresses)
16085 {
16086 // Only if it's been published already
16087 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
16088 if (it != mapAddresses.end())
16089 paddrFound = &(*it).second;
16090 }
16091
16092 if (paddrFound)
16093 {
16094 int64 nUpdateInterval = 20 * 60;
16095 if (paddrFound->nTime < GetAdjustedTime() - nUpdateInterval)
16096 {
16097 // Periodically update most recently seen time
16098 paddrFound->nTime = GetAdjustedTime();
16099 CAddrDB addrdb;
16100 addrdb.WriteAddress(*paddrFound);
16101 }
16102 }
16103 }
16104
16105
16106
16107
16108
16109 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
16110 {
16111 // If the dialog might get closed before the reply comes back,
16112 // call this in the destructor so it doesn't get called after it's deleted.
16113 CRITICAL_BLOCK(cs_vNodes)
16114 {
16115 BOOST_FOREACH(CNode* pnode, vNodes)
16116 {
16117 CRITICAL_BLOCK(pnode->cs_mapRequests)
16118 {
16119 for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
16120 {
16121 CRequestTracker& tracker = (*mi).second;
16122 if (tracker.fn == fn && tracker.param1 == param1)
16123 pnode->mapRequests.erase(mi++);
16124 else
16125 mi++;
16126 }
16127 }
16128 }
16129 }
16130 }
16131
16132
16133
16134
16135
16136
16137
16138 //
16139 // Subscription methods for the broadcast and subscription system.
16140 // Channel numbers are message numbers, i.e. MSG_TABLE and MSG_PRODUCT.
16141 //
16142 // The subscription system uses a meet-in-the-middle strategy.
16143 // With 100,000 nodes, if senders broadcast to 1000 random nodes and receivers
16144 // subscribe to 1000 random nodes, 99.995% (1 - 0.99^1000) of messages will get through.
16145 //
16146
16147 bool AnySubscribed(unsigned int nChannel)
16148 {
16149 if (pnodeLocalHost->IsSubscribed(nChannel))
16150 return true;
16151 CRITICAL_BLOCK(cs_vNodes)
16152 BOOST_FOREACH(CNode* pnode, vNodes)
16153 if (pnode->IsSubscribed(nChannel))
16154 return true;
16155 return false;
16156 }
16157
16158 bool CNode::IsSubscribed(unsigned int nChannel)
16159 {
16160 if (nChannel >= vfSubscribe.size())
16161 return false;
16162 return vfSubscribe[nChannel];
16163 }
16164
16165 void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
16166 {
16167 if (nChannel >= vfSubscribe.size())
16168 return;
16169
16170 if (!AnySubscribed(nChannel))
16171 {
16172 // Relay subscribe
16173 CRITICAL_BLOCK(cs_vNodes)
16174 BOOST_FOREACH(CNode* pnode, vNodes)
16175 if (pnode != this)
16176 pnode->PushMessage("subscribe", nChannel, nHops);
16177 }
16178
16179 vfSubscribe[nChannel] = true;
16180 }
16181
16182 void CNode::CancelSubscribe(unsigned int nChannel)
16183 {
16184 if (nChannel >= vfSubscribe.size())
16185 return;
16186
16187 // Prevent from relaying cancel if wasn't subscribed
16188 if (!vfSubscribe[nChannel])
16189 return;
16190 vfSubscribe[nChannel] = false;
16191
16192 if (!AnySubscribed(nChannel))
16193 {
16194 // Relay subscription cancel
16195 CRITICAL_BLOCK(cs_vNodes)
16196 BOOST_FOREACH(CNode* pnode, vNodes)
16197 if (pnode != this)
16198 pnode->PushMessage("sub-cancel", nChannel);
16199 }
16200 }
16201
16202
16203
16204
16205
16206
16207
16208
16209
16210 CNode* FindNode(unsigned int ip)
16211 {
16212 CRITICAL_BLOCK(cs_vNodes)
16213 {
16214 BOOST_FOREACH(CNode* pnode, vNodes)
16215 if (pnode->addr.ip == ip)
16216 return (pnode);
16217 }
16218 return NULL;
16219 }
16220
16221 CNode* FindNode(CAddress addr)
16222 {
16223 CRITICAL_BLOCK(cs_vNodes)
16224 {
16225 BOOST_FOREACH(CNode* pnode, vNodes)
16226 if (pnode->addr == addr)
16227 return (pnode);
16228 }
16229 return NULL;
16230 }
16231
16232 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
16233 {
16234 if (addrConnect.ip == addrLocalHost.ip)
16235 return NULL;
16236
16237 // Look for an existing connection
16238 CNode* pnode = FindNode(addrConnect.ip);
16239 if (pnode)
16240 {
16241 if (nTimeout != 0)
16242 pnode->AddRef(nTimeout);
16243 else
16244 pnode->AddRef();
16245 return pnode;
16246 }
16247
16248 /// debug print
16249 printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",
16250 addrConnect.ToString().c_str(),
16251 (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
16252 (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
16253
16254 CRITICAL_BLOCK(cs_mapAddresses)
16255 mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
16256
16257 // Connect
16258 SOCKET hSocket;
16259 if (ConnectSocket(addrConnect, hSocket))
16260 {
16261 /// debug print
16262 printf("connected %s\n", addrConnect.ToString().c_str());
16263
16264 // Set to nonblocking
16265 #ifdef WIN32
16266 u_long nOne = 1;
16267 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
16268 printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
16269 #else
16270 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
16271 printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
16272 #endif
16273
16274 // Add node
16275 CNode* pnode = new CNode(hSocket, addrConnect, false);
16276 if (nTimeout != 0)
16277 pnode->AddRef(nTimeout);
16278 else
16279 pnode->AddRef();
16280 CRITICAL_BLOCK(cs_vNodes)
16281 vNodes.push_back(pnode);
16282
16283 pnode->nTimeConnected = GetTime();
16284 return pnode;
16285 }
16286 else
16287 {
16288 return NULL;
16289 }
16290 }
16291
16292 void CNode::CloseSocketDisconnect()
16293 {
16294 fDisconnect = true;
16295 if (hSocket != INVALID_SOCKET)
16296 {
16297 if (fDebug)
16298 printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
16299 printf("disconnecting node %s\n", addr.ToString().c_str());
16300 closesocket(hSocket);
16301 hSocket = INVALID_SOCKET;
16302 }
16303 }
16304
16305 void CNode::Cleanup()
16306 {
16307 // All of a nodes broadcasts and subscriptions are automatically torn down
16308 // when it goes down, so a node has to stay up to keep its broadcast going.
16309
16310 // Cancel subscriptions
16311 for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
16312 if (vfSubscribe[nChannel])
16313 CancelSubscribe(nChannel);
16314 }
16315
16316
16317 std::map<unsigned int, int64> CNode::setBanned;
16318 CCriticalSection CNode::cs_setBanned;
16319
16320 void CNode::ClearBanned()
16321 {
16322 setBanned.clear();
16323 }
16324
16325 bool CNode::IsBanned(unsigned int ip)
16326 {
16327 bool fResult = false;
16328 CRITICAL_BLOCK(cs_setBanned)
16329 {
16330 std::map<unsigned int, int64>::iterator i = setBanned.find(ip);
16331 if (i != setBanned.end())
16332 {
16333 int64 t = (*i).second;
16334 if (GetTime() < t)
16335 fResult = true;
16336 }
16337 }
16338 return fResult;
16339 }
16340
16341 bool CNode::Misbehaving(int howmuch)
16342 {
16343 if (addr.IsLocal())
16344 {
16345 printf("Warning: local node %s misbehaving\n", addr.ToString().c_str());
16346 return false;
16347 }
16348
16349 nMisbehavior += howmuch;
16350 if (nMisbehavior >= GetArg("-banscore", 100))
16351 {
16352 int64 banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
16353 CRITICAL_BLOCK(cs_setBanned)
16354 if (setBanned[addr.ip] < banTime)
16355 setBanned[addr.ip] = banTime;
16356 CloseSocketDisconnect();
16357 printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior);
16358 return true;
16359 }
16360 return false;
16361 }
16362
16363
16364
16365
16366
16367
16368
16369
16370
16371
16372
16373
16374 void ThreadSocketHandler(void* parg)
16375 {
16376 IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
16377 try
16378 {
16379 vnThreadsRunning[0]++;
16380 ThreadSocketHandler2(parg);
16381 vnThreadsRunning[0]--;
16382 }
16383 catch (std::exception& e) {
16384 vnThreadsRunning[0]--;
16385 PrintException(&e, "ThreadSocketHandler()");
16386 } catch (...) {
16387 vnThreadsRunning[0]--;
16388 throw; // support pthread_cancel()
16389 }
16390 printf("ThreadSocketHandler exiting\n");
16391 }
16392
16393 void ThreadSocketHandler2(void* parg)
16394 {
16395 printf("ThreadSocketHandler started\n");
16396 list<CNode*> vNodesDisconnected;
16397 int nPrevNodeCount = 0;
16398
16399 loop
16400 {
16401 //
16402 // Disconnect nodes
16403 //
16404 CRITICAL_BLOCK(cs_vNodes)
16405 {
16406 // Disconnect unused nodes
16407 vector<CNode*> vNodesCopy = vNodes;
16408 BOOST_FOREACH(CNode* pnode, vNodesCopy)
16409 {
16410 if (pnode->fDisconnect ||
16411 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
16412 {
16413 // remove from vNodes
16414 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
16415
16416 // close socket and cleanup
16417 pnode->CloseSocketDisconnect();
16418 pnode->Cleanup();
16419
16420 // hold in disconnected pool until all refs are released
16421 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
16422 if (pnode->fNetworkNode || pnode->fInbound)
16423 pnode->Release();
16424 vNodesDisconnected.push_back(pnode);
16425 }
16426 }
16427
16428 // Delete disconnected nodes
16429 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
16430 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
16431 {
16432 // wait until threads are done using it
16433 if (pnode->GetRefCount() <= 0)
16434 {
16435 bool fDelete = false;
16436 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
16437 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
16438 TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
16439 TRY_CRITICAL_BLOCK(pnode->cs_inventory)
16440 fDelete = true;
16441 if (fDelete)
16442 {
16443 vNodesDisconnected.remove(pnode);
16444 delete pnode;
16445 }
16446 }
16447 }
16448 }
16449 if (vNodes.size() != nPrevNodeCount)
16450 {
16451 nPrevNodeCount = vNodes.size();
16452 MainFrameRepaint();
16453 }
16454
16455
16456 //
16457 // Find which sockets have data to receive
16458 //
16459 struct timeval timeout;
16460 timeout.tv_sec = 0;
16461 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
16462
16463 fd_set fdsetRecv;
16464 fd_set fdsetSend;
16465 fd_set fdsetError;
16466 FD_ZERO(&fdsetRecv);
16467 FD_ZERO(&fdsetSend);
16468 FD_ZERO(&fdsetError);
16469 SOCKET hSocketMax = 0;
16470
16471 if(hListenSocket != INVALID_SOCKET)
16472 FD_SET(hListenSocket, &fdsetRecv);
16473 hSocketMax = max(hSocketMax, hListenSocket);
16474 CRITICAL_BLOCK(cs_vNodes)
16475 {
16476 BOOST_FOREACH(CNode* pnode, vNodes)
16477 {
16478 if (pnode->hSocket == INVALID_SOCKET)
16479 continue;
16480 FD_SET(pnode->hSocket, &fdsetRecv);
16481 FD_SET(pnode->hSocket, &fdsetError);
16482 hSocketMax = max(hSocketMax, pnode->hSocket);
16483 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
16484 if (!pnode->vSend.empty())
16485 FD_SET(pnode->hSocket, &fdsetSend);
16486 }
16487 }
16488
16489 vnThreadsRunning[0]--;
16490 int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
16491 vnThreadsRunning[0]++;
16492 if (fShutdown)
16493 return;
16494 if (nSelect == SOCKET_ERROR)
16495 {
16496 int nErr = WSAGetLastError();
16497 if (hSocketMax > -1)
16498 {
16499 printf("socket select error %d\n", nErr);
16500 for (int i = 0; i <= hSocketMax; i++)
16501 FD_SET(i, &fdsetRecv);
16502 }
16503 FD_ZERO(&fdsetSend);
16504 FD_ZERO(&fdsetError);
16505 Sleep(timeout.tv_usec/1000);
16506 }
16507
16508
16509 //
16510 // Accept new connections
16511 //
16512 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
16513 {
16514 struct sockaddr_in sockaddr;
16515 socklen_t len = sizeof(sockaddr);
16516 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
16517 CAddress addr;
16518 int nInbound = 0;
16519
16520 if (hSocket != INVALID_SOCKET)
16521 addr = CAddress(sockaddr);
16522
16523 CRITICAL_BLOCK(cs_vNodes)
16524 BOOST_FOREACH(CNode* pnode, vNodes)
16525 if (pnode->fInbound)
16526 nInbound++;
16527
16528 if (hSocket == INVALID_SOCKET)
16529 {
16530 if (WSAGetLastError() != WSAEWOULDBLOCK)
16531 printf("socket error accept failed: %d\n", WSAGetLastError());
16532 }
16533 else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
16534 {
16535 closesocket(hSocket);
16536 }
16537 else if (CNode::IsBanned(addr.ip))
16538 {
16539 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
16540 closesocket(hSocket);
16541 }
16542 else
16543 {
16544 printf("accepted connection %s\n", addr.ToString().c_str());
16545 CNode* pnode = new CNode(hSocket, addr, true);
16546 pnode->AddRef();
16547 CRITICAL_BLOCK(cs_vNodes)
16548 vNodes.push_back(pnode);
16549 }
16550 }
16551
16552
16553 //
16554 // Service each socket
16555 //
16556 vector<CNode*> vNodesCopy;
16557 CRITICAL_BLOCK(cs_vNodes)
16558 {
16559 vNodesCopy = vNodes;
16560 BOOST_FOREACH(CNode* pnode, vNodesCopy)
16561 pnode->AddRef();
16562 }
16563 BOOST_FOREACH(CNode* pnode, vNodesCopy)
16564 {
16565 if (fShutdown)
16566 return;
16567
16568 //
16569 // Receive
16570 //
16571 if (pnode->hSocket == INVALID_SOCKET)
16572 continue;
16573 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
16574 {
16575 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
16576 {
16577 CDataStream& vRecv = pnode->vRecv;
16578 unsigned int nPos = vRecv.size();
16579
16580 if (nPos > ReceiveBufferSize()) {
16581 if (!pnode->fDisconnect)
16582 printf("socket recv flood control disconnect (%d bytes)\n", vRecv.size());
16583 pnode->CloseSocketDisconnect();
16584 }
16585 else {
16586 // typical socket buffer is 8K-64K
16587 char pchBuf[0x10000];
16588 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
16589 if (nBytes > 0)
16590 {
16591 vRecv.resize(nPos + nBytes);
16592 memcpy(&vRecv[nPos], pchBuf, nBytes);
16593 pnode->nLastRecv = GetTime();
16594 }
16595 else if (nBytes == 0)
16596 {
16597 // socket closed gracefully
16598 if (!pnode->fDisconnect)
16599 printf("socket closed\n");
16600 pnode->CloseSocketDisconnect();
16601 }
16602 else if (nBytes < 0)
16603 {
16604 // error
16605 int nErr = WSAGetLastError();
16606 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
16607 {
16608 if (!pnode->fDisconnect)
16609 printf("socket recv error %d\n", nErr);
16610 pnode->CloseSocketDisconnect();
16611 }
16612 }
16613 }
16614 }
16615 }
16616
16617 //
16618 // Send
16619 //
16620 if (pnode->hSocket == INVALID_SOCKET)
16621 continue;
16622 if (FD_ISSET(pnode->hSocket, &fdsetSend))
16623 {
16624 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
16625 {
16626 CDataStream& vSend = pnode->vSend;
16627 if (!vSend.empty())
16628 {
16629 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
16630 if (nBytes > 0)
16631 {
16632 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
16633 pnode->nLastSend = GetTime();
16634 }
16635 else if (nBytes < 0)
16636 {
16637 // error
16638 int nErr = WSAGetLastError();
16639 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
16640 {
16641 printf("socket send error %d\n", nErr);
16642 pnode->CloseSocketDisconnect();
16643 }
16644 }
16645 if (vSend.size() > SendBufferSize()) {
16646 if (!pnode->fDisconnect)
16647 printf("socket send flood control disconnect (%d bytes)\n", vSend.size());
16648 pnode->CloseSocketDisconnect();
16649 }
16650 }
16651 }
16652 }
16653
16654 //
16655 // Inactivity checking
16656 //
16657 if (pnode->vSend.empty())
16658 pnode->nLastSendEmpty = GetTime();
16659 if (GetTime() - pnode->nTimeConnected > 60)
16660 {
16661 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
16662 {
16663 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
16664 pnode->fDisconnect = true;
16665 }
16666 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
16667 {
16668 printf("socket not sending\n");
16669 pnode->fDisconnect = true;
16670 }
16671 else if (GetTime() - pnode->nLastRecv > 90*60)
16672 {
16673 printf("socket inactivity timeout\n");
16674 pnode->fDisconnect = true;
16675 }
16676 }
16677 }
16678 CRITICAL_BLOCK(cs_vNodes)
16679 {
16680 BOOST_FOREACH(CNode* pnode, vNodesCopy)
16681 pnode->Release();
16682 }
16683
16684 Sleep(10);
16685 }
16686 }
16687
16688
16689
16690
16691
16692
16693
16694
16695
16696 #ifdef USE_UPNP
16697 void ThreadMapPort(void* parg)
16698 {
16699 IMPLEMENT_RANDOMIZE_STACK(ThreadMapPort(parg));
16700 try
16701 {
16702 vnThreadsRunning[5]++;
16703 ThreadMapPort2(parg);
16704 vnThreadsRunning[5]--;
16705 }
16706 catch (std::exception& e) {
16707 vnThreadsRunning[5]--;
16708 PrintException(&e, "ThreadMapPort()");
16709 } catch (...) {
16710 vnThreadsRunning[5]--;
16711 PrintException(NULL, "ThreadMapPort()");
16712 }
16713 printf("ThreadMapPort exiting\n");
16714 }
16715
16716 void ThreadMapPort2(void* parg)
16717 {
16718 printf("ThreadMapPort started\n");
16719
16720 char port[6];
16721 sprintf(port, "%d", GetListenPort());
16722
16723 const char * multicastif = 0;
16724 const char * minissdpdpath = 0;
16725 struct UPNPDev * devlist = 0;
16726 char lanaddr[64];
16727
16728 #ifndef UPNPDISCOVER_SUCCESS
16729 /* miniupnpc 1.5 */
16730 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
16731 #else
16732 /* miniupnpc 1.6 */
16733 int error = 0;
16734 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
16735 #endif
16736
16737 struct UPNPUrls urls;
16738 struct IGDdatas data;
16739 int r;
16740
16741 r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
16742 if (r == 1)
16743 {
16744 if (!addrLocalHost.IsRoutable())
16745 {
16746 char externalIPAddress[40];
16747 r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
16748 if(r != UPNPCOMMAND_SUCCESS)
16749 printf("UPnP: GetExternalIPAddress() returned %d\n", r);
16750 else
16751 {
16752 if(externalIPAddress[0])
16753 {
16754 printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
16755 CAddress addrExternalFromUPnP(externalIPAddress, 0, false, nLocalServices);
16756 if (addrExternalFromUPnP.IsRoutable())
16757 addrLocalHost = addrExternalFromUPnP;
16758 }
16759 else
16760 printf("UPnP: GetExternalIPAddress failed.\n");
16761 }
16762 }
16763
16764 string strDesc = "Bitcoin " + FormatFullVersion();
16765 #ifndef UPNPDISCOVER_SUCCESS
16766 /* miniupnpc 1.5 */
16767 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
16768 port, port, lanaddr, strDesc.c_str(), "TCP", 0);
16769 #else
16770 /* miniupnpc 1.6 */
16771 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
16772 port, port, lanaddr, strDesc.c_str(), "TCP", 0, "0");
16773 #endif
16774
16775 if(r!=UPNPCOMMAND_SUCCESS)
16776 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
16777 port, port, lanaddr, r, strupnperror(r));
16778 else
16779 printf("UPnP Port Mapping successful.\n");
16780 int i = 1;
16781 loop {
16782 if (fShutdown || !fUseUPnP)
16783 {
16784 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port, "TCP", 0);
16785 printf("UPNP_DeletePortMapping() returned : %d\n", r);
16786 freeUPNPDevlist(devlist); devlist = 0;
16787 FreeUPNPUrls(&urls);
16788 return;
16789 }
16790 if (i % 600 == 0) // Refresh every 20 minutes
16791 {
16792 #ifndef UPNPDISCOVER_SUCCESS
16793 /* miniupnpc 1.5 */
16794 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
16795 port, port, lanaddr, strDesc.c_str(), "TCP", 0);
16796 #else
16797 /* miniupnpc 1.6 */
16798 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
16799 port, port, lanaddr, strDesc.c_str(), "TCP", 0, "0");
16800 #endif
16801
16802 if(r!=UPNPCOMMAND_SUCCESS)
16803 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
16804 port, port, lanaddr, r, strupnperror(r));
16805 else
16806 printf("UPnP Port Mapping successful.\n");;
16807 }
16808 Sleep(2000);
16809 i++;
16810 }
16811 } else {
16812 printf("No valid UPnP IGDs found\n");
16813 freeUPNPDevlist(devlist); devlist = 0;
16814 if (r != 0)
16815 FreeUPNPUrls(&urls);
16816 loop {
16817 if (fShutdown || !fUseUPnP)
16818 return;
16819 Sleep(2000);
16820 }
16821 }
16822 }
16823
16824 void MapPort(bool fMapPort)
16825 {
16826 if (fUseUPnP != fMapPort)
16827 {
16828 fUseUPnP = fMapPort;
16829 WriteSetting("fUseUPnP", fUseUPnP);
16830 }
16831 if (fUseUPnP && vnThreadsRunning[5] < 1)
16832 {
16833 if (!CreateThread(ThreadMapPort, NULL))
16834 printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
16835 }
16836 }
16837 #else
16838 void MapPort(bool /* unused fMapPort */)
16839 {
16840 // Intentionally left blank.
16841 }
16842 #endif
16843
16844
16845
16846
16847
16848
16849
16850
16851
16852
16853 static const char *strDNSSeed[] = {
16854 "bitseed.xf2.org",
16855 "dnsseed.bluematt.me",
16856 "seed.bitcoin.sipa.be",
16857 "dnsseed.bitcoin.dashjr.org",
16858 };
16859
16860 void ThreadDNSAddressSeed(void* parg)
16861 {
16862 IMPLEMENT_RANDOMIZE_STACK(ThreadDNSAddressSeed(parg));
16863 try
16864 {
16865 vnThreadsRunning[6]++;
16866 ThreadDNSAddressSeed2(parg);
16867 vnThreadsRunning[6]--;
16868 }
16869 catch (std::exception& e) {
16870 vnThreadsRunning[6]--;
16871 PrintException(&e, "ThreadDNSAddressSeed()");
16872 } catch (...) {
16873 vnThreadsRunning[6]--;
16874 throw; // support pthread_cancel()
16875 }
16876 printf("ThreadDNSAddressSeed exiting\n");
16877 }
16878
16879 void ThreadDNSAddressSeed2(void* parg)
16880 {
16881 printf("ThreadDNSAddressSeed started\n");
16882 int found = 0;
16883
16884 if (!fTestNet)
16885 {
16886 printf("Loading addresses from DNS seeds (could take a while)\n");
16887
16888 for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
16889 vector<CAddress> vaddr;
16890 if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, -1, true))
16891 {
16892 CAddrDB addrDB;
16893 addrDB.TxnBegin();
16894 BOOST_FOREACH (CAddress& addr, vaddr)
16895 {
16896 if (addr.GetByte(3) != 127)
16897 {
16898 addr.nTime = 0;
16899 AddAddress(addr, 0, &addrDB);
16900 found++;
16901 }
16902 }
16903 addrDB.TxnCommit(); // Save addresses (it's ok if this fails)
16904 }
16905 }
16906 }
16907
16908 printf("%d addresses found from DNS seeds\n", found);
16909 }
16910
16911
16912
16913
16914
16915
16916
16917
16918
16919
16920
16921
16922 unsigned int pnSeed[] =
16923 {
16924 0x959bd347, 0xf8de42b2, 0x73bc0518, 0xea6edc50, 0x21b00a4d, 0xc725b43d, 0xd665464d, 0x1a2a770e,
16925 0x27c93946, 0x65b2fa46, 0xb80ae255, 0x66b3b446, 0xb1877a3e, 0x6ee89e3e, 0xc3175b40, 0x2a01a83c,
16926 0x95b1363a, 0xa079ad3d, 0xe6ca801f, 0x027f4f4a, 0x34f7f03a, 0xf790f04a, 0x16ca801f, 0x2f4d5e40,
16927 0x3a4d5e40, 0xc43a322e, 0xc8159753, 0x14d4724c, 0x7919a118, 0xe0bdb34e, 0x68a16b2e, 0xff64b44d,
16928 0x6099115b, 0x9b57b05b, 0x7bd1b4ad, 0xdf95944f, 0x29d2b73d, 0xafa8db79, 0xe247ba41, 0x24078348,
16929 0xf722f03c, 0x33567ebc, 0xace64ed4, 0x984d3932, 0xb5f34e55, 0x27b7024d, 0x94579247, 0x8894042e,
16930 0x9357d34c, 0x1063c24b, 0xcaa228b1, 0xa3c5a8b2, 0x5dc64857, 0xa2c23643, 0xa8369a54, 0x31203077,
16931 0x00707c5c, 0x09fc0b3a, 0x272e9e2e, 0xf80f043e, 0x9449ca3e, 0x5512c33e, 0xd106b555, 0xe8024157,
16932 0xe288ec29, 0xc79c5461, 0xafb63932, 0xdb02ab4b, 0x0e512777, 0x8a145a4c, 0xb201ff4f, 0x5e09314b,
16933 0xcd9bfbcd, 0x1c023765, 0x4394e75c, 0xa728bd4d, 0x65331552, 0xa98420b1, 0x89ecf559, 0x6e80801f,
16934 0xf404f118, 0xefd62b51, 0x05918346, 0x9b186d5f, 0xacabab46, 0xf912e255, 0xc188ea62, 0xcc55734e,
16935 0xc668064d, 0xd77a4558, 0x46201c55, 0xf17dfc80, 0xf7142f2e, 0x87bfb718, 0x8aa54fb2, 0xc451d518,
16936 0xc4ae8831, 0x8dd44d55, 0x5bbd206c, 0x64536b5d, 0x5c667e60, 0x3b064242, 0xfe963a42, 0xa28e6dc8,
16937 0xe8a9604a, 0xc989464e, 0xd124a659, 0x50065140, 0xa44dfe5e, 0x1079e655, 0x3fb986d5, 0x47895b18,
16938 0x7d3ce4ad, 0x4561ba50, 0x296eec62, 0x255b41ad, 0xaed35ec9, 0x55556f12, 0xc7d3154d, 0x3297b65d,
16939 0x8930121f, 0xabf42e4e, 0x4a29e044, 0x1212685d, 0x676c1e40, 0xce009744, 0x383a8948, 0xa2dbd0ad,
16940 0xecc2564d, 0x07dbc252, 0x887ee24b, 0x5171644c, 0x6bb798c1, 0x847f495d, 0x4cbb7145, 0x3bb81c32,
16941 0x45eb262e, 0xc8015a4e, 0x250a361b, 0xf694f946, 0xd64a183e, 0xd4f1dd59, 0x8f20ffd4, 0x51d9e55c,
16942 0x09521763, 0x5e02002e, 0x32c8074d, 0xe685762e, 0x8290b0bc, 0x762a922e, 0xfc5ee754, 0x83a24829,
16943 0x775b224d, 0x6295bb4d, 0x38ec0555, 0xbffbba50, 0xe5560260, 0x86b16a7c, 0xd372234e, 0x49a3c24b,
16944 0x2f6a171f, 0x4d75ed60, 0xae94115b, 0xcb543744, 0x63080c59, 0x3f9c724c, 0xc977ce18, 0x532efb18,
16945 0x69dc3b2e, 0x5f94d929, 0x1732bb4d, 0x9c814b4d, 0xe6b3762e, 0xc024f662, 0x8face35b, 0x6b5b044d,
16946 0x798c7b57, 0x79a6b44c, 0x067d3057, 0xf9e94e5f, 0x91cbe15b, 0x71405eb2, 0x2662234e, 0xcbcc4a6d,
16947 0xbf69d54b, 0xa79b4e55, 0xec6d3e51, 0x7c0b3c02, 0x60f83653, 0x24c1e15c, 0x1110b62e, 0x10350f59,
16948 0xa56f1d55, 0x3509e7a9, 0xeb128354, 0x14268e2e, 0x934e28bc, 0x8e32692e, 0x8331a21f, 0x3e633932,
16949 0xc812b12e, 0xc684bf2e, 0x80112d2e, 0xe0ddc96c, 0xc630ca4a, 0x5c09b3b2, 0x0b580518, 0xc8e9d54b,
16950 0xd169aa43, 0x17d0d655, 0x1d029963, 0x7ff87559, 0xcb701f1f, 0x6fa3e85d, 0xe45e9a54, 0xf05d1802,
16951 0x44d03b2e, 0x837b692e, 0xccd4354e, 0x3d6da13c, 0x3423084d, 0xf707c34a, 0x55f6db3a, 0xad26e442,
16952 0x6233a21f, 0x09e80e59, 0x8caeb54d, 0xbe870941, 0xb407d20e, 0x20b51018, 0x56fb152e, 0x460d2a4e,
16953 0xbb9a2946, 0x560eb12e, 0xed83dd29, 0xd6724f53, 0xa50aafb8, 0x451346d9, 0x88348e2e, 0x7312fead,
16954 0x8ecaf96f, 0x1bda4e5f, 0xf1671e40, 0x3c8c3e3b, 0x4716324d, 0xdde24ede, 0xf98cd17d, 0xa91d4644,
16955 0x28124eb2, 0x147d5129, 0xd022042e, 0x61733d3b, 0xad0d5e02, 0x8ce2932e, 0xe5c18502, 0x549c1e32,
16956 0x9685801f, 0x86e217ad, 0xd948214b, 0x4110f462, 0x3a2e894e, 0xbd35492e, 0x87e0d558, 0x64b8ef7d,
16957 0x7c3eb962, 0x72a84b3e, 0x7cd667c9, 0x28370a2e, 0x4bc60e7b, 0x6fc1ec60, 0x14a6983f, 0x86739a4b,
16958 0x46954e5f, 0x32e2e15c, 0x2e9326cf, 0xe5801c5e, 0x379607b2, 0x32151145, 0xf0e39744, 0xacb54c55,
16959 0xa37dfb60, 0x83b55cc9, 0x388f7ca5, 0x15034f5f, 0x3e94965b, 0x68e0ffad, 0x35280f59, 0x8fe190cf,
16960 0x7c6ba5b2, 0xa5e9db43, 0x4ee1fc60, 0xd9d94e5f, 0x04040677, 0x0ea9b35e, 0x5961f14f, 0x67fda063,
16961 0xa48a5a31, 0xc6524e55, 0x283d325e, 0x3f37515f, 0x96b94b3e, 0xacce620e, 0x6481cc5b, 0xa4a06d4b,
16962 0x9e95d2d9, 0xe40c03d5, 0xc2f4514b, 0xb79aad44, 0xf64be843, 0xb2064070, 0xfca00455, 0x429dfa4e,
16963 0x2323f173, 0xeda4185e, 0xabd5227d, 0x9efd4d58, 0xb1104758, 0x4811e955, 0xbd9ab355, 0xe921f44b,
16964 0x9f166dce, 0x09e279b2, 0xe0c9ac7b, 0x7901a5ad, 0xa145d4b0, 0x79104671, 0xec31e35a, 0x4fe0b555,
16965 0xc7d9cbad, 0xad057f55, 0xe94cc759, 0x7fe0b043, 0xe4529f2e, 0x0d4dd4b2, 0x9f11a54d, 0x031e2e4e,
16966 0xe6014f5f, 0x11d1ca6c, 0x26bd7f61, 0xeb86854f, 0x4d347b57, 0x116bbe2e, 0xdba7234e, 0x7bcbfd2e,
16967 0x174dd4b2, 0x6686762e, 0xb089ba50, 0xc6258246, 0x087e767b, 0xc4a8cb4a, 0x595dba50, 0x7f0ae502,
16968 0x7b1dbd5a, 0xa0603492, 0x57d1af4b, 0x9e21ffd4, 0x6393064d, 0x7407376e, 0xe484762e, 0x122a4e53,
16969 0x4a37aa43, 0x3888a6be, 0xee77864e, 0x039c8dd5, 0x688d89af, 0x0e988f62, 0x08218246, 0xfc2f8246,
16970 0xd1d97040, 0xd64cd4b2, 0x5ae4a6b8, 0x7d0de9bc, 0x8d304d61, 0x06c5c672, 0xa4c8bd4d, 0xe0fd373b,
16971 0x575ebe4d, 0x72d26277, 0x55570f55, 0x77b154d9, 0xe214293a, 0xfc740f4b, 0xfe3f6a57, 0xa9c55f02,
16972 0xae4054db, 0x2394d918, 0xb511b24a, 0xb8741ab2, 0x0758e65e, 0xc7b5795b, 0xb0a30a4c, 0xaf7f170c,
16973 0xf3b4762e, 0x8179576d, 0x738a1581, 0x4b95b64c, 0x9829b618, 0x1bea932e, 0x7bdeaa4b, 0xcb5e0281,
16974 0x65618f54, 0x0658474b, 0x27066acf, 0x40556d65, 0x7d204d53, 0xf28bc244, 0xdce23455, 0xadc0ff54,
16975 0x3863c948, 0xcee34e5f, 0xdeb85e02, 0x2ed17a61, 0x6a7b094d, 0x7f0cfc40, 0x59603f54, 0x3220afbc,
16976 0xb5dfd962, 0x125d21c0, 0x13f8d243, 0xacfefb4e, 0x86c2c147, 0x3d8bbd59, 0xbd02a21f, 0x2593042e,
16977 0xc6a17a7c, 0x28925861, 0xb487ed44, 0xb5f4fd6d, 0x90c28a45, 0x5a14f74d, 0x43d71b4c, 0x728ebb5d,
16978 0x885bf950, 0x08134dd0, 0x38ec046e, 0xc575684b, 0x50082d2e, 0xa2f47757, 0x270f86ae, 0xf3ff6462,
16979 0x10ed3f4e, 0x4b58d462, 0xe01ce23e, 0x8c5b092e, 0x63e52f4e, 0x22c1e85d, 0xa908f54e, 0x8591624f,
16980 0x2c0fb94e, 0xa280ba3c, 0xb6f41b4c, 0x24f9aa47, 0x27201647, 0x3a3ea6dc, 0xa14fc3be, 0x3c34bdd5,
16981 0x5b8d4f5b, 0xaadeaf4b, 0xc71cab50, 0x15697a4c, 0x9a1a734c, 0x2a037d81, 0x2590bd59, 0x48ec2741,
16982 0x53489c5b, 0x7f00314b, 0x2170d362, 0xf2e92542, 0x42c10b44, 0x98f0f118, 0x883a3456, 0x099a932e,
16983 0xea38f7bc, 0x644e9247, 0xbb61b62e, 0x30e0863d, 0x5f51be54, 0x207215c7, 0x5f306c45, 0xaa7f3932,
16984 0x98da7d45, 0x4e339b59, 0x2e411581, 0xa808f618, 0xad2c0c59, 0x54476741, 0x09e99fd1, 0x5db8f752,
16985 0xc16df8bd, 0x1dd4b44f, 0x106edf2e, 0x9e15c180, 0x2ad6b56f, 0x633a5332, 0xff33787c, 0x077cb545,
16986 0x6610be6d, 0x75aad2c4, 0x72fb4d5b, 0xe81e0f59, 0x576f6332, 0x47333373, 0x351ed783, 0x2d90fb50,
16987 0x8d5e0f6c, 0x5b27a552, 0xdb293ebb, 0xe55ef950, 0x4b133ad8, 0x75df975a, 0x7b6a8740, 0xa899464b,
16988 0xfab15161, 0x10f8b64d, 0xd055ea4d, 0xee8e146b, 0x4b14afb8, 0x4bc1c44a, 0x9b961dcc, 0xd111ff43,
16989 0xfca0b745, 0xc800e412, 0x0afad9d1, 0xf751c350, 0xf9f0cccf, 0xa290a545, 0x8ef13763, 0x7ec70d59,
16990 0x2b066acf, 0x65496c45, 0xade02c1b, 0xae6eb077, 0x92c1e65b, 0xc064e6a9, 0xc649e56d, 0x5287a243,
16991 0x36de4f5b, 0x5b1df6ad, 0x65c39a59, 0xdba805b2, 0x20067aa8, 0x6457e56d, 0x3cee26cf, 0xfd3ff26d,
16992 0x04f86d4a, 0x06b8e048, 0xa93bcd5c, 0x91135852, 0xbe90a643, 0x8fa0094d, 0x06d8215f, 0x2677094d,
16993 0xd735685c, 0x164a00c9, 0x5209ac5f, 0xa9564c5c, 0x3b504f5f, 0xcc826bd0, 0x4615042e, 0x5fe13b4a,
16994 0x8c81b86d, 0x879ab68c, 0x1de564b8, 0x434487d8, 0x2dcb1b63, 0x82ab524a, 0xb0676abb, 0xa13d9c62,
16995 0xdbb5b86d, 0x5b7f4b59, 0xaddfb44d, 0xad773532, 0x3997054c, 0x72cebd89, 0xb194544c, 0xc5b8046e,
16996 0x6e1adeb2, 0xaa5abb51, 0xefb54b44, 0x15efc54f, 0xe9f1bc4d, 0x5f401b6c, 0x97f018ad, 0xc82f9252,
16997 0x2cdc762e, 0x8e52e56d, 0x1827175e, 0x9b7d7d80, 0xb2ad6845, 0x51065140, 0x71180a18, 0x5b27006c,
16998 0x0621e255, 0x721cbe58, 0x670c0cb8, 0xf8bd715d, 0xe0bdc5d9, 0xed843501, 0x4b84554d, 0x7f1a18bc,
16999 0x53bcaf47, 0x5729d35f, 0xf0dda246, 0x22382bd0, 0x4d641fb0, 0x316afcde, 0x50a22f1f, 0x73608046,
17000 0xc461d84a, 0xb2dbe247,
17001 };
17002
17003
17004
17005 void ThreadOpenConnections(void* parg)
17006 {
17007 IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
17008 try
17009 {
17010 vnThreadsRunning[1]++;
17011 ThreadOpenConnections2(parg);
17012 vnThreadsRunning[1]--;
17013 }
17014 catch (std::exception& e) {
17015 vnThreadsRunning[1]--;
17016 PrintException(&e, "ThreadOpenConnections()");
17017 } catch (...) {
17018 vnThreadsRunning[1]--;
17019 PrintException(NULL, "ThreadOpenConnections()");
17020 }
17021 printf("ThreadOpenConnections exiting\n");
17022 }
17023
17024 void ThreadOpenConnections2(void* parg)
17025 {
17026 printf("ThreadOpenConnections started\n");
17027
17028 // Connect to specific addresses
17029 if (mapArgs.count("-connect"))
17030 {
17031 for (int64 nLoop = 0;; nLoop++)
17032 {
17033 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
17034 {
17035 CAddress addr(strAddr, fAllowDNS);
17036 if (addr.IsValid())
17037 OpenNetworkConnection(addr);
17038 for (int i = 0; i < 10 && i < nLoop; i++)
17039 {
17040 Sleep(500);
17041 if (fShutdown)
17042 return;
17043 }
17044 }
17045 }
17046 }
17047
17048 // Connect to manually added nodes first
17049 if (mapArgs.count("-addnode"))
17050 {
17051 BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
17052 {
17053 CAddress addr(strAddr, fAllowDNS);
17054 if (addr.IsValid())
17055 {
17056 OpenNetworkConnection(addr);
17057 Sleep(500);
17058 if (fShutdown)
17059 return;
17060 }
17061 }
17062 }
17063
17064 // Initiate network connections
17065 int64 nStart = GetTime();
17066 loop
17067 {
17068 vnThreadsRunning[1]--;
17069 Sleep(500);
17070 vnThreadsRunning[1]++;
17071 if (fShutdown)
17072 return;
17073
17074 // Limit outbound connections
17075 loop
17076 {
17077 int nOutbound = 0;
17078 CRITICAL_BLOCK(cs_vNodes)
17079 BOOST_FOREACH(CNode* pnode, vNodes)
17080 if (!pnode->fInbound)
17081 nOutbound++;
17082 int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
17083 nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
17084 if (nOutbound < nMaxOutboundConnections)
17085 break;
17086 vnThreadsRunning[1]--;
17087 Sleep(2000);
17088 vnThreadsRunning[1]++;
17089 if (fShutdown)
17090 return;
17091 }
17092
17093 bool fAddSeeds = false;
17094
17095 CRITICAL_BLOCK(cs_mapAddresses)
17096 {
17097 // Add seed nodes if IRC isn't working
17098 bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
17099 if (mapAddresses.empty() && (GetTime() - nStart > 60 || fUseProxy) && !fTestNet)
17100 fAddSeeds = true;
17101 }
17102
17103 if (fAddSeeds)
17104 {
17105 for (int i = 0; i < ARRAYLEN(pnSeed); i++)
17106 {
17107 // It'll only connect to one or two seed nodes because once it connects,
17108 // it'll get a pile of addresses with newer timestamps.
17109 // Seed nodes are given a random 'last seen time' of between one and two
17110 // weeks ago.
17111 const int64 nOneWeek = 7*24*60*60;
17112 CAddress addr;
17113 addr.ip = pnSeed[i];
17114 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
17115 AddAddress(addr);
17116 }
17117 }
17118
17119 //
17120 // Choose an address to connect to based on most recently seen
17121 //
17122 CAddress addrConnect;
17123 int64 nBest = INT64_MIN;
17124
17125 // Only connect to one address per a.b.?.? range.
17126 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
17127 set<unsigned int> setConnected;
17128 CRITICAL_BLOCK(cs_vNodes)
17129 BOOST_FOREACH(CNode* pnode, vNodes)
17130 setConnected.insert(pnode->addr.ip & 0x0000ffff);
17131
17132 int64 nANow = GetAdjustedTime();
17133
17134 CRITICAL_BLOCK(cs_mapAddresses)
17135 {
17136 BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
17137 {
17138 const CAddress& addr = item.second;
17139 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
17140 continue;
17141 int64 nSinceLastSeen = nANow - addr.nTime;
17142 int64 nSinceLastTry = nANow - addr.nLastTry;
17143
17144 // Randomize the order in a deterministic way, putting the standard port first
17145 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
17146 if (addr.port != htons(GetDefaultPort()))
17147 nRandomizer += 2 * 60 * 60;
17148
17149 // Last seen Base retry frequency
17150 // <1 hour 10 min
17151 // 1 hour 1 hour
17152 // 4 hours 2 hours
17153 // 24 hours 5 hours
17154 // 48 hours 7 hours
17155 // 7 days 13 hours
17156 // 30 days 27 hours
17157 // 90 days 46 hours
17158 // 365 days 93 hours
17159 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
17160
17161 // Fast reconnect for one hour after last seen
17162 if (nSinceLastSeen < 60 * 60)
17163 nDelay = 10 * 60;
17164
17165 // Limit retry frequency
17166 if (nSinceLastTry < nDelay)
17167 continue;
17168
17169 // If we have IRC, we'll be notified when they first come online,
17170 // and again every 24 hours by the refresh broadcast.
17171 if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)
17172 continue;
17173
17174 // Only try the old stuff if we don't have enough connections
17175 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
17176 continue;
17177
17178 // If multiple addresses are ready, prioritize by time since
17179 // last seen and time since last tried.
17180 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
17181 if (nScore > nBest)
17182 {
17183 nBest = nScore;
17184 addrConnect = addr;
17185 }
17186 }
17187 }
17188
17189 if (addrConnect.IsValid())
17190 OpenNetworkConnection(addrConnect);
17191 }
17192 }
17193
17194 bool OpenNetworkConnection(const CAddress& addrConnect)
17195 {
17196 //
17197 // Initiate outbound network connection
17198 //
17199 if (fShutdown)
17200 return false;
17201 if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() ||
17202 FindNode(addrConnect.ip) || CNode::IsBanned(addrConnect.ip))
17203 return false;
17204
17205 vnThreadsRunning[1]--;
17206 CNode* pnode = ConnectNode(addrConnect);
17207 vnThreadsRunning[1]++;
17208 if (fShutdown)
17209 return false;
17210 if (!pnode)
17211 return false;
17212 pnode->fNetworkNode = true;
17213
17214 return true;
17215 }
17216
17217
17218
17219
17220
17221
17222
17223
17224 void ThreadMessageHandler(void* parg)
17225 {
17226 IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
17227 try
17228 {
17229 vnThreadsRunning[2]++;
17230 ThreadMessageHandler2(parg);
17231 vnThreadsRunning[2]--;
17232 }
17233 catch (std::exception& e) {
17234 vnThreadsRunning[2]--;
17235 PrintException(&e, "ThreadMessageHandler()");
17236 } catch (...) {
17237 vnThreadsRunning[2]--;
17238 PrintException(NULL, "ThreadMessageHandler()");
17239 }
17240 printf("ThreadMessageHandler exiting\n");
17241 }
17242
17243 void ThreadMessageHandler2(void* parg)
17244 {
17245 printf("ThreadMessageHandler started\n");
17246 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
17247 while (!fShutdown)
17248 {
17249 vector<CNode*> vNodesCopy;
17250 CRITICAL_BLOCK(cs_vNodes)
17251 {
17252 vNodesCopy = vNodes;
17253 BOOST_FOREACH(CNode* pnode, vNodesCopy)
17254 pnode->AddRef();
17255 }
17256
17257 // Poll the connected nodes for messages
17258 CNode* pnodeTrickle = NULL;
17259 if (!vNodesCopy.empty())
17260 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
17261 BOOST_FOREACH(CNode* pnode, vNodesCopy)
17262 {
17263 // Receive messages
17264 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
17265 ProcessMessages(pnode);
17266 if (fShutdown)
17267 return;
17268
17269 // Send messages
17270 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
17271 SendMessages(pnode, pnode == pnodeTrickle);
17272 if (fShutdown)
17273 return;
17274 }
17275
17276 CRITICAL_BLOCK(cs_vNodes)
17277 {
17278 BOOST_FOREACH(CNode* pnode, vNodesCopy)
17279 pnode->Release();
17280 }
17281
17282 // Wait and allow messages to bunch up.
17283 // Reduce vnThreadsRunning so StopNode has permission to exit while
17284 // we're sleeping, but we must always check fShutdown after doing this.
17285 vnThreadsRunning[2]--;
17286 Sleep(100);
17287 if (fRequestShutdown)
17288 Shutdown(NULL);
17289 vnThreadsRunning[2]++;
17290 if (fShutdown)
17291 return;
17292 }
17293 }
17294
17295
17296
17297
17298
17299
17300 bool BindListenPort(string& strError)
17301 {
17302 strError = "";
17303 int nOne = 1;
17304 addrLocalHost.port = htons(GetListenPort());
17305
17306 #ifdef WIN32
17307 // Initialize Windows Sockets
17308 WSADATA wsadata;
17309 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
17310 if (ret != NO_ERROR)
17311 {
17312 strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
17313 printf("%s\n", strError.c_str());
17314 return false;
17315 }
17316 #endif
17317
17318 // Create socket for listening for incoming connections
17319 hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
17320 if (hListenSocket == INVALID_SOCKET)
17321 {
17322 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
17323 printf("%s\n", strError.c_str());
17324 return false;
17325 }
17326
17327 #ifdef SO_NOSIGPIPE
17328 // Different way of disabling SIGPIPE on BSD
17329 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
17330 #endif
17331
17332 #ifndef WIN32
17333 // Allow binding if the port is still in TIME_WAIT state after
17334 // the program was closed and restarted. Not an issue on windows.
17335 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
17336 #endif
17337
17338 #ifdef WIN32
17339 // Set to nonblocking, incoming connections will also inherit this
17340 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
17341 #else
17342 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
17343 #endif
17344 {
17345 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
17346 printf("%s\n", strError.c_str());
17347 return false;
17348 }
17349
17350 // The sockaddr_in structure specifies the address family,
17351 // IP address, and port for the socket that is being bound
17352 struct sockaddr_in sockaddr;
17353 memset(&sockaddr, 0, sizeof(sockaddr));
17354 sockaddr.sin_family = AF_INET;
17355 sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
17356 sockaddr.sin_port = htons(GetListenPort());
17357 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
17358 {
17359 int nErr = WSAGetLastError();
17360 if (nErr == WSAEADDRINUSE)
17361 strError = strprintf(_("Unable to bind to port %d on this computer. Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
17362 else
17363 strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
17364 printf("%s\n", strError.c_str());
17365 return false;
17366 }
17367 printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
17368
17369 // Listen for incoming connections
17370 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
17371 {
17372 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
17373 printf("%s\n", strError.c_str());
17374 return false;
17375 }
17376
17377 return true;
17378 }
17379
17380 void StartNode(void* parg)
17381 {
17382 if (pnodeLocalHost == NULL)
17383 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, false, nLocalServices));
17384
17385 #ifdef WIN32
17386 // Get local host ip
17387 char pszHostName[1000] = "";
17388 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
17389 {
17390 vector<CAddress> vaddr;
17391 if (Lookup(pszHostName, vaddr, nLocalServices, -1, true))
17392 BOOST_FOREACH (const CAddress &addr, vaddr)
17393 if (addr.GetByte(3) != 127)
17394 {
17395 addrLocalHost = addr;
17396 break;
17397 }
17398 }
17399 #else
17400 // Get local host ip
17401 struct ifaddrs* myaddrs;
17402 if (getifaddrs(&myaddrs) == 0)
17403 {
17404 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
17405 {
17406 if (ifa->ifa_addr == NULL) continue;
17407 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
17408 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
17409 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
17410 char pszIP[100];
17411 if (ifa->ifa_addr->sa_family == AF_INET)
17412 {
17413 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
17414 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
17415 printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
17416
17417 // Take the first IP that isn't loopback 127.x.x.x
17418 CAddress addr(*(unsigned int*)&s4->sin_addr, GetListenPort(), nLocalServices);
17419 if (addr.IsValid() && addr.GetByte(3) != 127)
17420 {
17421 addrLocalHost = addr;
17422 break;
17423 }
17424 }
17425 else if (ifa->ifa_addr->sa_family == AF_INET6)
17426 {
17427 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
17428 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
17429 printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
17430 }
17431 }
17432 freeifaddrs(myaddrs);
17433 }
17434 #endif
17435 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
17436
17437 if (fUseProxy || mapArgs.count("-connect") || fNoListen)
17438 {
17439 // Proxies can't take incoming connections
17440 addrLocalHost.ip = CAddress("0.0.0.0").ip;
17441 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
17442 }
17443 else
17444 {
17445 CreateThread(ThreadGetMyExternalIP, NULL);
17446 }
17447
17448 //
17449 // Start threads
17450 //
17451
17452 if (GetBoolArg("-nodnsseed"))
17453 printf("DNS seeding disabled\n");
17454 else
17455 if (!CreateThread(ThreadDNSAddressSeed, NULL))
17456 printf("Error: CreateThread(ThreadDNSAddressSeed) failed\n");
17457
17458 // Map ports with UPnP
17459 if (fHaveUPnP)
17460 MapPort(fUseUPnP);
17461
17462 // Get addresses from IRC and advertise ours
17463 if (!CreateThread(ThreadIRCSeed, NULL))
17464 printf("Error: CreateThread(ThreadIRCSeed) failed\n");
17465
17466 // Send and receive from sockets, accept connections
17467 if (!CreateThread(ThreadSocketHandler, NULL))
17468 printf("Error: CreateThread(ThreadSocketHandler) failed\n");
17469
17470 // Initiate outbound connections
17471 if (!CreateThread(ThreadOpenConnections, NULL))
17472 printf("Error: CreateThread(ThreadOpenConnections) failed\n");
17473
17474 // Process messages
17475 if (!CreateThread(ThreadMessageHandler, NULL))
17476 printf("Error: CreateThread(ThreadMessageHandler) failed\n");
17477
17478 // Generate coins in the background
17479 GenerateBitcoins(fGenerateBitcoins, pwalletMain);
17480 }
17481
17482 bool StopNode()
17483 {
17484 printf("StopNode()\n");
17485 fShutdown = true;
17486 nTransactionsUpdated++;
17487 int64 nStart = GetTime();
17488 while (vnThreadsRunning[0] > 0 || vnThreadsRunning[1] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0
17489 #ifdef USE_UPNP
17490 || vnThreadsRunning[5] > 0
17491 #endif
17492 )
17493 {
17494 if (GetTime() - nStart > 20)
17495 break;
17496 Sleep(20);
17497 }
17498 if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
17499 if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
17500 if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
17501 if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
17502 if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
17503 if (fHaveUPnP && vnThreadsRunning[5] > 0) printf("ThreadMapPort still running\n");
17504 if (vnThreadsRunning[6] > 0) printf("ThreadDNSAddressSeed still running\n");
17505 while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
17506 Sleep(20);
17507 Sleep(50);
17508
17509 return true;
17510 }
17511
17512 class CNetCleanup
17513 {
17514 public:
17515 CNetCleanup()
17516 {
17517 }
17518 ~CNetCleanup()
17519 {
17520 // Close sockets
17521 BOOST_FOREACH(CNode* pnode, vNodes)
17522 if (pnode->hSocket != INVALID_SOCKET)
17523 closesocket(pnode->hSocket);
17524 if (hListenSocket != INVALID_SOCKET)
17525 if (closesocket(hListenSocket) == SOCKET_ERROR)
17526 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
17527
17528 #ifdef WIN32
17529 // Shutdown Windows Sockets
17530 WSACleanup();
17531 #endif
17532 }
17533 }
17534 instance_of_cnetcleanup;