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
This commit is contained in:
Cory Fields 2016-04-18 17:02:43 -04:00
parent cca221fd21
commit 8b8f87714d
3 changed files with 33 additions and 26 deletions

View file

@ -462,11 +462,15 @@ CCriticalSection CNode::cs_setBanned;
bool CNode::setBannedIsDirty; bool CNode::setBannedIsDirty;
void CNode::ClearBanned() void CNode::ClearBanned()
{
{ {
LOCK(cs_setBanned); LOCK(cs_setBanned);
setBanned.clear(); setBanned.clear();
setBannedIsDirty = true; setBannedIsDirty = true;
} }
DumpBanlist(); //store banlist to disk
uiInterface.BannedListChanged();
}
bool CNode::IsBanned(CNetAddr ip) bool CNode::IsBanned(CNetAddr ip)
{ {
@ -516,12 +520,26 @@ void CNode::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t banti
} }
banEntry.nBanUntil = (sinceUnixEpoch ? 0 : GetTime() )+bantimeoffset; banEntry.nBanUntil = (sinceUnixEpoch ? 0 : GetTime() )+bantimeoffset;
{
LOCK(cs_setBanned); LOCK(cs_setBanned);
if (setBanned[subNet].nBanUntil < banEntry.nBanUntil) if (setBanned[subNet].nBanUntil < banEntry.nBanUntil) {
setBanned[subNet] = banEntry; setBanned[subNet] = banEntry;
setBannedIsDirty = true; 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) { bool CNode::Unban(const CNetAddr &addr) {
CSubNet subNet(addr); CSubNet subNet(addr);
@ -529,13 +547,15 @@ bool CNode::Unban(const CNetAddr &addr) {
} }
bool CNode::Unban(const CSubNet &subNet) { bool CNode::Unban(const CSubNet &subNet) {
LOCK(cs_setBanned);
if (setBanned.erase(subNet))
{ {
setBannedIsDirty = true; LOCK(cs_setBanned);
return true; if (!setBanned.erase(subNet))
}
return false; return false;
setBannedIsDirty = true;
}
uiInterface.BannedListChanged();
DumpBanlist(); //store banlist to disk immediately
return true;
} }
void CNode::GetBanned(banmap_t &banMap) void CNode::GetBanned(banmap_t &banMap)

View file

@ -885,15 +885,13 @@ void RPCConsole::banSelectedNode(int bantime)
// Get currently selected peer address // Get currently selected peer address
QString strNode = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::Address); QString strNode = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::Address);
// Find possible nodes, ban it and clear the selected node // 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 nStr = strNode.toStdString();
std::string addr; std::string addr;
int port = 0; int port = 0;
SplitHostPort(nStr, port, addr); SplitHostPort(nStr, port, addr);
CNode::Ban(CNetAddr(addr), BanReasonManuallyAdded, bantime); CNode::Ban(CNetAddr(addr), BanReasonManuallyAdded, bantime);
bannedNode->fDisconnect = true;
DumpBanlist();
clearSelectedNode(); clearSelectedNode();
clientModel->getBanTableModel()->refresh(); clientModel->getBanTableModel()->refresh();
@ -912,7 +910,6 @@ void RPCConsole::unbanSelectedNode()
if (possibleSubnet.IsValid()) if (possibleSubnet.IsValid())
{ {
CNode::Unban(possibleSubnet); CNode::Unban(possibleSubnet);
DumpBanlist();
clientModel->getBanTableModel()->refresh(); clientModel->getBanTableModel()->refresh();
} }
} }

View file

@ -565,20 +565,12 @@ UniValue setban(const UniValue& params, bool fHelp)
absolute = true; absolute = true;
isSubnet ? CNode::Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : CNode::Ban(netAddr, BanReasonManuallyAdded, banTime, absolute); 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") else if(strCommand == "remove")
{ {
if (!( isSubnet ? CNode::Unban(subNet) : CNode::Unban(netAddr) )) if (!( isSubnet ? CNode::Unban(subNet) : CNode::Unban(netAddr) ))
throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed"); throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed");
} }
DumpBanlist(); //store banlist to disk
uiInterface.BannedListChanged();
return NullUniValue; return NullUniValue;
} }
@ -624,8 +616,6 @@ UniValue clearbanned(const UniValue& params, bool fHelp)
); );
CNode::ClearBanned(); CNode::ClearBanned();
DumpBanlist(); //store banlist to disk
uiInterface.BannedListChanged();
return NullUniValue; return NullUniValue;
} }