Backport Bitcoin PR#7906: net: prerequisites for p2p encapsulation changes (#1521)
* net: don't import std namespace This file is about to be broken up into chunks and moved around. Drop the namespace now rather than requiring other files to use it. * net: remove unused set * net: use the exposed GetNodeSignals() rather than g_signals directly * net: make Ban/Unban/ClearBan functionality consistent - Ban/Unban/ClearBan call uiInterface.BannedListChanged() as necessary - Ban/Unban/ClearBan sync to disk if the operation is user-invoked - Mark node for disconnection automatically when banning - Lock cs_vNodes while setting disconnected - Don't spin in a tight loop while setting disconnected * net: No need to export DumpBanlist
This commit is contained in:
parent
9a8a290b87
commit
5a1961e5e3
161
src/net.cpp
161
src/net.cpp
@ -63,7 +63,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace {
|
||||
const int MAX_OUTBOUND_CONNECTIONS = 8;
|
||||
@ -89,7 +88,7 @@ bool fDiscover = true;
|
||||
bool fListen = true;
|
||||
ServiceFlags nLocalServices = NODE_NETWORK;
|
||||
CCriticalSection cs_mapLocalHost;
|
||||
map<CNetAddr, LocalServiceInfo> mapLocalHost;
|
||||
std::map<CNetAddr, LocalServiceInfo> mapLocalHost;
|
||||
static bool vfLimited[NET_MAX] = {};
|
||||
static CNode* pnodeLocalHost = NULL;
|
||||
uint64_t nLocalHostNonce = 0;
|
||||
@ -99,20 +98,17 @@ int nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS;
|
||||
bool fAddressesInitialized = false;
|
||||
std::string strSubVersion;
|
||||
|
||||
vector<CNode*> vNodes;
|
||||
std::vector<CNode*> vNodes;
|
||||
CCriticalSection cs_vNodes;
|
||||
map<CInv, CDataStream> mapRelay;
|
||||
deque<pair<int64_t, CInv> > vRelayExpiration;
|
||||
std::map<CInv, CDataStream> mapRelay;
|
||||
std::deque<pair<int64_t, CInv> > vRelayExpiration;
|
||||
CCriticalSection cs_mapRelay;
|
||||
limitedmap<uint256, int64_t> mapAlreadyAskedFor(MAX_INV_SZ);
|
||||
|
||||
static deque<string> vOneShots;
|
||||
static std::deque<std::string> vOneShots;
|
||||
CCriticalSection cs_vOneShots;
|
||||
|
||||
set<CNetAddr> setservAddNodeAddresses;
|
||||
CCriticalSection cs_setservAddNodeAddresses;
|
||||
|
||||
vector<std::string> vAddedNodes;
|
||||
std::vector<std::string> vAddedNodes;
|
||||
CCriticalSection cs_vAddedNodes;
|
||||
|
||||
NodeId nLastNodeId = 0;
|
||||
@ -147,7 +143,7 @@ bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
|
||||
int nBestReachability = -1;
|
||||
{
|
||||
LOCK(cs_mapLocalHost);
|
||||
for (map<CNetAddr, LocalServiceInfo>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
|
||||
for (std::map<CNetAddr, LocalServiceInfo>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
|
||||
{
|
||||
int nScore = (*it).second.nScore;
|
||||
int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
|
||||
@ -456,6 +452,26 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fConnectToMas
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void DumpBanlist()
|
||||
{
|
||||
CNode::SweepBanned(); // clean unused entries (if bantime has expired)
|
||||
|
||||
if (!CNode::BannedSetIsDirty())
|
||||
return;
|
||||
|
||||
int64_t nStart = GetTimeMillis();
|
||||
|
||||
CBanDB bandb;
|
||||
banmap_t banmap;
|
||||
CNode::SetBannedSetDirty(false);
|
||||
CNode::GetBanned(banmap);
|
||||
if (!bandb.Write(banmap))
|
||||
CNode::SetBannedSetDirty(true);
|
||||
|
||||
LogPrint("net", "Flushed %d banned node ips/subnets to banlist.dat %dms\n",
|
||||
banmap.size(), GetTimeMillis() - nStart);
|
||||
}
|
||||
|
||||
void CNode::CloseSocketDisconnect()
|
||||
{
|
||||
fDisconnect = true;
|
||||
@ -473,7 +489,7 @@ void CNode::CloseSocketDisconnect()
|
||||
|
||||
void CNode::PushVersion()
|
||||
{
|
||||
int nBestHeight = g_signals.GetHeight().get_value_or(0);
|
||||
int nBestHeight = GetNodeSignals().GetHeight().get_value_or(0);
|
||||
|
||||
int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime());
|
||||
CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", 0), addr.nServices));
|
||||
@ -497,9 +513,13 @@ bool CNode::setBannedIsDirty;
|
||||
|
||||
void CNode::ClearBanned()
|
||||
{
|
||||
LOCK(cs_setBanned);
|
||||
setBanned.clear();
|
||||
setBannedIsDirty = true;
|
||||
{
|
||||
LOCK(cs_setBanned);
|
||||
setBanned.clear();
|
||||
setBannedIsDirty = true;
|
||||
}
|
||||
DumpBanlist(); //store banlist to disk
|
||||
uiInterface.BannedListChanged();
|
||||
}
|
||||
|
||||
bool CNode::IsBanned(CNetAddr ip)
|
||||
@ -550,11 +570,25 @@ void CNode::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t banti
|
||||
}
|
||||
banEntry.nBanUntil = (sinceUnixEpoch ? 0 : GetTime() )+bantimeoffset;
|
||||
|
||||
LOCK(cs_setBanned);
|
||||
if (setBanned[subNet].nBanUntil < banEntry.nBanUntil)
|
||||
setBanned[subNet] = banEntry;
|
||||
|
||||
setBannedIsDirty = true;
|
||||
{
|
||||
LOCK(cs_setBanned);
|
||||
if (setBanned[subNet].nBanUntil < banEntry.nBanUntil) {
|
||||
setBanned[subNet] = banEntry;
|
||||
setBannedIsDirty = true;
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
uiInterface.BannedListChanged();
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes) {
|
||||
if (subNet.Match((CNetAddr)pnode->addr))
|
||||
pnode->fDisconnect = true;
|
||||
}
|
||||
}
|
||||
if(banReason == BanReasonManuallyAdded)
|
||||
DumpBanlist(); //store banlist to disk immediately if user requested ban
|
||||
}
|
||||
|
||||
bool CNode::Unban(const CNetAddr &addr) {
|
||||
@ -563,13 +597,15 @@ bool CNode::Unban(const CNetAddr &addr) {
|
||||
}
|
||||
|
||||
bool CNode::Unban(const CSubNet &subNet) {
|
||||
LOCK(cs_setBanned);
|
||||
if (setBanned.erase(subNet))
|
||||
{
|
||||
LOCK(cs_setBanned);
|
||||
if (!setBanned.erase(subNet))
|
||||
return false;
|
||||
setBannedIsDirty = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
uiInterface.BannedListChanged();
|
||||
DumpBanlist(); //store banlist to disk immediately
|
||||
return true;
|
||||
}
|
||||
|
||||
void CNode::GetBanned(banmap_t &banMap)
|
||||
@ -826,7 +862,7 @@ void SocketSendData(CNode *pnode)
|
||||
pnode->vSendMsg.erase(pnode->vSendMsg.begin(), it);
|
||||
}
|
||||
|
||||
static list<CNode*> vNodesDisconnected;
|
||||
static std::list<CNode*> vNodesDisconnected;
|
||||
|
||||
struct NodeEvictionCandidate
|
||||
{
|
||||
@ -1040,7 +1076,7 @@ void ThreadSocketHandler()
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
// Disconnect unused nodes
|
||||
vector<CNode*> vNodesCopy = vNodes;
|
||||
std::vector<CNode*> vNodesCopy = vNodes;
|
||||
BOOST_FOREACH(CNode* pnode, vNodesCopy)
|
||||
{
|
||||
if (pnode->fDisconnect ||
|
||||
@ -1070,7 +1106,7 @@ void ThreadSocketHandler()
|
||||
}
|
||||
{
|
||||
// Delete disconnected nodes
|
||||
list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
|
||||
std::list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
|
||||
BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
|
||||
{
|
||||
// wait until threads are done using it
|
||||
@ -1121,7 +1157,7 @@ void ThreadSocketHandler()
|
||||
|
||||
BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket) {
|
||||
FD_SET(hListenSocket.socket, &fdsetRecv);
|
||||
hSocketMax = max(hSocketMax, hListenSocket.socket);
|
||||
hSocketMax = std::max(hSocketMax, hListenSocket.socket);
|
||||
have_fds = true;
|
||||
}
|
||||
|
||||
@ -1132,7 +1168,7 @@ void ThreadSocketHandler()
|
||||
if (pnode->hSocket == INVALID_SOCKET)
|
||||
continue;
|
||||
FD_SET(pnode->hSocket, &fdsetError);
|
||||
hSocketMax = max(hSocketMax, pnode->hSocket);
|
||||
hSocketMax = std::max(hSocketMax, pnode->hSocket);
|
||||
have_fds = true;
|
||||
|
||||
// Implement the following logic:
|
||||
@ -1199,7 +1235,7 @@ void ThreadSocketHandler()
|
||||
//
|
||||
// Service each socket
|
||||
//
|
||||
vector<CNode*> vNodesCopy = CopyNodeVector();
|
||||
std::vector<CNode*> vNodesCopy = CopyNodeVector();
|
||||
BOOST_FOREACH(CNode* pnode, vNodesCopy)
|
||||
{
|
||||
boost::this_thread::interruption_point();
|
||||
@ -1346,7 +1382,7 @@ void ThreadMapPort()
|
||||
}
|
||||
}
|
||||
|
||||
string strDesc = "Dash Core " + FormatFullVersion();
|
||||
std::string strDesc = "Dash Core " + FormatFullVersion();
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
@ -1432,7 +1468,7 @@ void ThreadDNSAddressSeed()
|
||||
}
|
||||
}
|
||||
|
||||
const vector<CDNSSeedData> &vSeeds = Params().DNSSeeds();
|
||||
const std::vector<CDNSSeedData> &vSeeds = Params().DNSSeeds();
|
||||
int found = 0;
|
||||
|
||||
LogPrintf("Loading addresses from DNS seeds (could take a while)\n");
|
||||
@ -1441,8 +1477,8 @@ void ThreadDNSAddressSeed()
|
||||
if (HaveNameProxy()) {
|
||||
AddOneShot(seed.host);
|
||||
} else {
|
||||
vector<CNetAddr> vIPs;
|
||||
vector<CAddress> vAdd;
|
||||
std::vector<CNetAddr> vIPs;
|
||||
std::vector<CAddress> vAdd;
|
||||
if (LookupHost(seed.host.c_str(), vIPs))
|
||||
{
|
||||
BOOST_FOREACH(const CNetAddr& ip, vIPs)
|
||||
@ -1491,7 +1527,7 @@ void DumpData()
|
||||
|
||||
void static ProcessOneShot()
|
||||
{
|
||||
string strDest;
|
||||
std::string strDest;
|
||||
{
|
||||
LOCK(cs_vOneShots);
|
||||
if (vOneShots.empty())
|
||||
@ -1557,7 +1593,7 @@ void ThreadOpenConnections()
|
||||
// Only connect out to one peer per network group (/16 for IPv4).
|
||||
// Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
|
||||
int nOutbound = 0;
|
||||
set<vector<unsigned char> > setConnected;
|
||||
std::set<std::vector<unsigned char> > setConnected;
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes) {
|
||||
@ -1619,7 +1655,7 @@ void ThreadOpenAddedConnections()
|
||||
|
||||
if (HaveNameProxy()) {
|
||||
while(true) {
|
||||
list<string> lAddresses(0);
|
||||
std::list<std::string> lAddresses(0);
|
||||
{
|
||||
LOCK(cs_vAddedNodes);
|
||||
BOOST_FOREACH(const std::string& strAddNode, vAddedNodes)
|
||||
@ -1637,32 +1673,25 @@ void ThreadOpenAddedConnections()
|
||||
|
||||
for (unsigned int i = 0; true; i++)
|
||||
{
|
||||
list<string> lAddresses(0);
|
||||
std::list<std::string> lAddresses(0);
|
||||
{
|
||||
LOCK(cs_vAddedNodes);
|
||||
BOOST_FOREACH(const std::string& strAddNode, vAddedNodes)
|
||||
lAddresses.push_back(strAddNode);
|
||||
}
|
||||
|
||||
list<vector<CService> > lservAddressesToAdd(0);
|
||||
std::list<std::vector<CService> > lservAddressesToAdd(0);
|
||||
BOOST_FOREACH(const std::string& strAddNode, lAddresses) {
|
||||
vector<CService> vservNode(0);
|
||||
std::vector<CService> vservNode(0);
|
||||
if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
|
||||
{
|
||||
lservAddressesToAdd.push_back(vservNode);
|
||||
{
|
||||
LOCK(cs_setservAddNodeAddresses);
|
||||
BOOST_FOREACH(const CService& serv, vservNode)
|
||||
setservAddNodeAddresses.insert(serv);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
|
||||
// (keeping in mind that addnode entries can have many IPs if fNameLookup)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
|
||||
for (std::list<std::vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
|
||||
BOOST_FOREACH(const CService& addrNode, *(it))
|
||||
if (pnode->addr == addrNode)
|
||||
{
|
||||
@ -1671,7 +1700,7 @@ void ThreadOpenAddedConnections()
|
||||
break;
|
||||
}
|
||||
}
|
||||
BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
|
||||
BOOST_FOREACH(std::vector<CService>& vserv, lservAddressesToAdd)
|
||||
{
|
||||
CSemaphoreGrant grant(*semOutbound);
|
||||
/* We want -addnode to work even for nodes that don't provide all
|
||||
@ -1764,7 +1793,7 @@ void ThreadMessageHandler()
|
||||
SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
|
||||
while (true)
|
||||
{
|
||||
vector<CNode*> vNodesCopy = CopyNodeVector();
|
||||
std::vector<CNode*> vNodesCopy = CopyNodeVector();
|
||||
|
||||
bool fSleep = true;
|
||||
|
||||
@ -1778,7 +1807,7 @@ void ThreadMessageHandler()
|
||||
TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
|
||||
if (lockRecv)
|
||||
{
|
||||
if (!g_signals.ProcessMessages(pnode))
|
||||
if (!GetNodeSignals().ProcessMessages(pnode))
|
||||
pnode->fDisconnect = true;
|
||||
|
||||
if (pnode->nSendSize < SendBufferSize())
|
||||
@ -1796,7 +1825,7 @@ void ThreadMessageHandler()
|
||||
{
|
||||
TRY_LOCK(pnode->cs_vSend, lockSend);
|
||||
if (lockSend)
|
||||
g_signals.SendMessages(pnode);
|
||||
GetNodeSignals().SendMessages(pnode);
|
||||
}
|
||||
boost::this_thread::interruption_point();
|
||||
}
|
||||
@ -1813,7 +1842,7 @@ void ThreadMessageHandler()
|
||||
|
||||
|
||||
|
||||
bool BindListenPort(const CService &addrBind, string& strError, bool fWhitelisted)
|
||||
bool BindListenPort(const CService &addrBind, std::string& strError, bool fWhitelisted)
|
||||
{
|
||||
strError = "";
|
||||
int nOne = 1;
|
||||
@ -1921,7 +1950,7 @@ void static Discover(boost::thread_group& threadGroup)
|
||||
char pszHostName[256] = "";
|
||||
if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
|
||||
{
|
||||
vector<CNetAddr> vaddr;
|
||||
std::vector<CNetAddr> vaddr;
|
||||
if (LookupHost(pszHostName, vaddr))
|
||||
{
|
||||
BOOST_FOREACH (const CNetAddr &addr, vaddr)
|
||||
@ -2379,7 +2408,7 @@ bool CAddrDB::Read(CAddrMan& addr)
|
||||
// Don't try to resize to a negative number if file is small
|
||||
if (fileSize >= sizeof(uint256))
|
||||
dataSize = fileSize - sizeof(uint256);
|
||||
vector<unsigned char> vchData;
|
||||
std::vector<unsigned char> vchData;
|
||||
vchData.resize(dataSize);
|
||||
uint256 hashIn;
|
||||
|
||||
@ -2701,7 +2730,7 @@ bool CBanDB::Read(banmap_t& banSet)
|
||||
// Don't try to resize to a negative number if file is small
|
||||
if (fileSize >= sizeof(uint256))
|
||||
dataSize = fileSize - sizeof(uint256);
|
||||
vector<unsigned char> vchData;
|
||||
std::vector<unsigned char> vchData;
|
||||
vchData.resize(dataSize);
|
||||
uint256 hashIn;
|
||||
|
||||
@ -2741,26 +2770,6 @@ bool CBanDB::Read(banmap_t& banSet)
|
||||
return true;
|
||||
}
|
||||
|
||||
void DumpBanlist()
|
||||
{
|
||||
CNode::SweepBanned(); // clean unused entries (if bantime has expired)
|
||||
|
||||
if (!CNode::BannedSetIsDirty())
|
||||
return;
|
||||
|
||||
int64_t nStart = GetTimeMillis();
|
||||
|
||||
CBanDB bandb;
|
||||
banmap_t banmap;
|
||||
CNode::SetBannedSetDirty(false);
|
||||
CNode::GetBanned(banmap);
|
||||
if (!bandb.Write(banmap))
|
||||
CNode::SetBannedSetDirty(true);
|
||||
|
||||
LogPrint("net", "Flushed %d banned node ips/subnets to banlist.dat %dms\n",
|
||||
banmap.size(), GetTimeMillis() - nStart);
|
||||
}
|
||||
|
||||
int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds) {
|
||||
return nNow + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);
|
||||
}
|
||||
|
@ -874,8 +874,6 @@ public:
|
||||
bool Read(banmap_t& banSet);
|
||||
};
|
||||
|
||||
void DumpBanlist();
|
||||
|
||||
/** Return a timestamp in the future (in microseconds) for exponentially distributed events. */
|
||||
int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds);
|
||||
|
||||
|
@ -935,15 +935,13 @@ void RPCConsole::banSelectedNode(int bantime)
|
||||
// Get currently selected peer address
|
||||
QString strNode = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::Address);
|
||||
// Find possible nodes, ban it and clear the selected node
|
||||
if (CNode *bannedNode = FindNode(strNode.toStdString())) {
|
||||
if (FindNode(strNode.toStdString())) {
|
||||
std::string nStr = strNode.toStdString();
|
||||
std::string addr;
|
||||
int port = 0;
|
||||
SplitHostPort(nStr, port, addr);
|
||||
|
||||
CNode::Ban(CNetAddr(addr), BanReasonManuallyAdded, bantime);
|
||||
bannedNode->fDisconnect = true;
|
||||
DumpBanlist();
|
||||
|
||||
clearSelectedNode();
|
||||
clientModel->getBanTableModel()->refresh();
|
||||
@ -962,7 +960,6 @@ void RPCConsole::unbanSelectedNode()
|
||||
if (possibleSubnet.IsValid())
|
||||
{
|
||||
CNode::Unban(possibleSubnet);
|
||||
DumpBanlist();
|
||||
clientModel->getBanTableModel()->refresh();
|
||||
}
|
||||
}
|
||||
|
@ -563,20 +563,12 @@ UniValue setban(const UniValue& params, bool fHelp)
|
||||
absolute = true;
|
||||
|
||||
isSubnet ? CNode::Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : CNode::Ban(netAddr, BanReasonManuallyAdded, banTime, absolute);
|
||||
|
||||
//disconnect possible nodes
|
||||
while(CNode *bannedNode = (isSubnet ? FindNode(subNet) : FindNode(netAddr)))
|
||||
bannedNode->fDisconnect = true;
|
||||
}
|
||||
else if(strCommand == "remove")
|
||||
{
|
||||
if (!( isSubnet ? CNode::Unban(subNet) : CNode::Unban(netAddr) ))
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed");
|
||||
}
|
||||
|
||||
DumpBanlist(); //store banlist to disk
|
||||
uiInterface.BannedListChanged();
|
||||
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
@ -622,8 +614,6 @@ UniValue clearbanned(const UniValue& params, bool fHelp)
|
||||
);
|
||||
|
||||
CNode::ClearBanned();
|
||||
DumpBanlist(); //store banlist to disk
|
||||
uiInterface.BannedListChanged();
|
||||
|
||||
return NullUniValue;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user