|
|
@ -50,7 +50,16 @@ |
|
|
|
using namespace std; |
|
|
|
using namespace std; |
|
|
|
using namespace boost; |
|
|
|
using namespace boost; |
|
|
|
|
|
|
|
|
|
|
|
static const int MAX_OUTBOUND_CONNECTIONS = 8; |
|
|
|
namespace { |
|
|
|
|
|
|
|
const int MAX_OUTBOUND_CONNECTIONS = 8; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct ListenSocket { |
|
|
|
|
|
|
|
SOCKET socket; |
|
|
|
|
|
|
|
bool whitelisted; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ListenSocket(SOCKET socket, bool whitelisted) : socket(socket), whitelisted(whitelisted) {} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Global state variables
|
|
|
|
// Global state variables
|
|
|
@ -65,7 +74,7 @@ static bool vfLimited[NET_MAX] = {}; |
|
|
|
static CNode* pnodeLocalHost = NULL; |
|
|
|
static CNode* pnodeLocalHost = NULL; |
|
|
|
static CNode* pnodeSync = NULL; |
|
|
|
static CNode* pnodeSync = NULL; |
|
|
|
uint64_t nLocalHostNonce = 0; |
|
|
|
uint64_t nLocalHostNonce = 0; |
|
|
|
static std::vector<SOCKET> vhListenSocket; |
|
|
|
static std::vector<ListenSocket> vhListenSocket; |
|
|
|
CAddrMan addrman; |
|
|
|
CAddrMan addrman; |
|
|
|
int nMaxConnections = 125; |
|
|
|
int nMaxConnections = 125; |
|
|
|
|
|
|
|
|
|
|
@ -593,6 +602,24 @@ bool CNode::Ban(const CNetAddr &addr) { |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<CSubNet> CNode::vWhitelistedRange; |
|
|
|
|
|
|
|
CCriticalSection CNode::cs_vWhitelistedRange; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool CNode::IsWhitelistedRange(const CNetAddr &addr) { |
|
|
|
|
|
|
|
LOCK(cs_vWhitelistedRange); |
|
|
|
|
|
|
|
BOOST_FOREACH(const CSubNet& subnet, vWhitelistedRange) { |
|
|
|
|
|
|
|
if (subnet.Match(addr)) |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CNode::AddWhitelistedRange(const CSubNet &subnet) { |
|
|
|
|
|
|
|
LOCK(cs_vWhitelistedRange); |
|
|
|
|
|
|
|
vWhitelistedRange.push_back(subnet); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#undef X |
|
|
|
#undef X |
|
|
|
#define X(name) stats.name = name |
|
|
|
#define X(name) stats.name = name |
|
|
|
void CNode::copyStats(CNodeStats &stats) |
|
|
|
void CNode::copyStats(CNodeStats &stats) |
|
|
@ -609,6 +636,7 @@ void CNode::copyStats(CNodeStats &stats) |
|
|
|
X(nStartingHeight); |
|
|
|
X(nStartingHeight); |
|
|
|
X(nSendBytes); |
|
|
|
X(nSendBytes); |
|
|
|
X(nRecvBytes); |
|
|
|
X(nRecvBytes); |
|
|
|
|
|
|
|
X(fWhitelisted); |
|
|
|
stats.fSyncNode = (this == pnodeSync); |
|
|
|
stats.fSyncNode = (this == pnodeSync); |
|
|
|
|
|
|
|
|
|
|
|
// It is common for nodes with good ping times to suddenly become lagged,
|
|
|
|
// It is common for nodes with good ping times to suddenly become lagged,
|
|
|
@ -848,9 +876,9 @@ void ThreadSocketHandler() |
|
|
|
SOCKET hSocketMax = 0; |
|
|
|
SOCKET hSocketMax = 0; |
|
|
|
bool have_fds = false; |
|
|
|
bool have_fds = false; |
|
|
|
|
|
|
|
|
|
|
|
BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) { |
|
|
|
BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket) { |
|
|
|
FD_SET(hListenSocket, &fdsetRecv); |
|
|
|
FD_SET(hListenSocket.socket, &fdsetRecv); |
|
|
|
hSocketMax = max(hSocketMax, hListenSocket); |
|
|
|
hSocketMax = max(hSocketMax, hListenSocket.socket); |
|
|
|
have_fds = true; |
|
|
|
have_fds = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -917,13 +945,13 @@ void ThreadSocketHandler() |
|
|
|
//
|
|
|
|
//
|
|
|
|
// Accept new connections
|
|
|
|
// Accept new connections
|
|
|
|
//
|
|
|
|
//
|
|
|
|
BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) |
|
|
|
BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv)) |
|
|
|
if (hListenSocket.socket != INVALID_SOCKET && FD_ISSET(hListenSocket.socket, &fdsetRecv)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct sockaddr_storage sockaddr; |
|
|
|
struct sockaddr_storage sockaddr; |
|
|
|
socklen_t len = sizeof(sockaddr); |
|
|
|
socklen_t len = sizeof(sockaddr); |
|
|
|
SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len); |
|
|
|
SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len); |
|
|
|
CAddress addr; |
|
|
|
CAddress addr; |
|
|
|
int nInbound = 0; |
|
|
|
int nInbound = 0; |
|
|
|
|
|
|
|
|
|
|
@ -931,6 +959,7 @@ void ThreadSocketHandler() |
|
|
|
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) |
|
|
|
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) |
|
|
|
LogPrintf("Warning: Unknown socket family\n"); |
|
|
|
LogPrintf("Warning: Unknown socket family\n"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool whitelisted = hListenSocket.whitelisted || CNode::IsWhitelistedRange(addr); |
|
|
|
{ |
|
|
|
{ |
|
|
|
LOCK(cs_vNodes); |
|
|
|
LOCK(cs_vNodes); |
|
|
|
BOOST_FOREACH(CNode* pnode, vNodes) |
|
|
|
BOOST_FOREACH(CNode* pnode, vNodes) |
|
|
@ -948,7 +977,7 @@ void ThreadSocketHandler() |
|
|
|
{ |
|
|
|
{ |
|
|
|
closesocket(hSocket); |
|
|
|
closesocket(hSocket); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (CNode::IsBanned(addr)) |
|
|
|
else if (CNode::IsBanned(addr) && !whitelisted) |
|
|
|
{ |
|
|
|
{ |
|
|
|
LogPrintf("connection from %s dropped (banned)\n", addr.ToString()); |
|
|
|
LogPrintf("connection from %s dropped (banned)\n", addr.ToString()); |
|
|
|
closesocket(hSocket); |
|
|
|
closesocket(hSocket); |
|
|
@ -957,6 +986,7 @@ void ThreadSocketHandler() |
|
|
|
{ |
|
|
|
{ |
|
|
|
CNode* pnode = new CNode(hSocket, addr, "", true); |
|
|
|
CNode* pnode = new CNode(hSocket, addr, "", true); |
|
|
|
pnode->AddRef(); |
|
|
|
pnode->AddRef(); |
|
|
|
|
|
|
|
pnode->fWhitelisted = whitelisted; |
|
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
LOCK(cs_vNodes); |
|
|
|
LOCK(cs_vNodes); |
|
|
@ -1580,7 +1610,7 @@ void ThreadMessageHandler() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool BindListenPort(const CService &addrBind, string& strError) |
|
|
|
bool BindListenPort(const CService &addrBind, string& strError, bool fWhitelisted) |
|
|
|
{ |
|
|
|
{ |
|
|
|
strError = ""; |
|
|
|
strError = ""; |
|
|
|
int nOne = 1; |
|
|
|
int nOne = 1; |
|
|
@ -1661,9 +1691,9 @@ bool BindListenPort(const CService &addrBind, string& strError) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
vhListenSocket.push_back(hListenSocket); |
|
|
|
vhListenSocket.push_back(ListenSocket(hListenSocket, fWhitelisted)); |
|
|
|
|
|
|
|
|
|
|
|
if (addrBind.IsRoutable() && fDiscover) |
|
|
|
if (addrBind.IsRoutable() && fDiscover && !fWhitelisted) |
|
|
|
AddLocal(addrBind, LOCAL_BIND); |
|
|
|
AddLocal(addrBind, LOCAL_BIND); |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
@ -1788,9 +1818,9 @@ public: |
|
|
|
BOOST_FOREACH(CNode* pnode, vNodes) |
|
|
|
BOOST_FOREACH(CNode* pnode, vNodes) |
|
|
|
if (pnode->hSocket != INVALID_SOCKET) |
|
|
|
if (pnode->hSocket != INVALID_SOCKET) |
|
|
|
closesocket(pnode->hSocket); |
|
|
|
closesocket(pnode->hSocket); |
|
|
|
BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) |
|
|
|
BOOST_FOREACH(ListenSocket& hListenSocket, vhListenSocket) |
|
|
|
if (hListenSocket != INVALID_SOCKET) |
|
|
|
if (hListenSocket.socket != INVALID_SOCKET) |
|
|
|
if (closesocket(hListenSocket) == SOCKET_ERROR) |
|
|
|
if (closesocket(hListenSocket.socket) == SOCKET_ERROR) |
|
|
|
LogPrintf("closesocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError())); |
|
|
|
LogPrintf("closesocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError())); |
|
|
|
|
|
|
|
|
|
|
|
// clean up some globals (to help leak detection)
|
|
|
|
// clean up some globals (to help leak detection)
|
|
|
|