Skip to content

Commit

Permalink
banman: create and split out banman
Browse files Browse the repository at this point in the history
Some say he has always been.
theuni authored and dongcarl committed Jan 16, 2019
1 parent 83c1ea2 commit 4c0d961
Showing 10 changed files with 172 additions and 125 deletions.
17 changes: 14 additions & 3 deletions src/init.cpp
Original file line number Diff line number Diff line change
@@ -73,8 +73,12 @@ static const bool DEFAULT_PROXYRANDOMIZE = true;
static const bool DEFAULT_REST_ENABLE = false;
static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;

// Dump addresses to banlist.dat every 15 minutes (900s)
static constexpr int DUMP_BANS_INTERVAL = 60 * 15;

std::unique_ptr<CConnman> g_connman;
std::unique_ptr<PeerLogicValidation> peerLogic;
std::unique_ptr<BanMan> g_banman;

#ifdef WIN32
// Win32 LevelDB doesn't use filedescriptors, and the ones used for
@@ -199,6 +203,7 @@ void Shutdown(InitInterfaces& interfaces)
// destruct and reset all to nullptr.
peerLogic.reset();
g_connman.reset();
g_banman.reset();
g_txindex.reset();

if (g_is_mempool_loaded && gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
@@ -1290,11 +1295,12 @@ bool AppInitMain(InitInterfaces& interfaces)
// is not yet setup and may end up being set up twice if we
// need to reindex later.

assert(!g_banman);
g_banman = MakeUnique<BanMan>(&uiInterface);
assert(!g_connman);
g_connman = std::unique_ptr<CConnman>(new CConnman(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max())));
CConnman& connman = *g_connman;

peerLogic.reset(new PeerLogicValidation(&connman, scheduler, gArgs.GetBoolArg("-enablebip61", DEFAULT_ENABLE_BIP61)));
peerLogic.reset(new PeerLogicValidation(g_connman.get(), g_banman.get(), scheduler, gArgs.GetBoolArg("-enablebip61", DEFAULT_ENABLE_BIP61)));
RegisterValidationInterface(peerLogic.get());

// sanitize comments per BIP-0014, format user agent and check total size
@@ -1704,6 +1710,7 @@ bool AppInitMain(InitInterfaces& interfaces)
connOptions.nMaxFeeler = 1;
connOptions.nBestHeight = chain_active_height;
connOptions.uiInterface = &uiInterface;
connOptions.m_banman = g_banman.get();
connOptions.m_msgproc = peerLogic.get();
connOptions.nSendBufferMaxSize = 1000*gArgs.GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER);
connOptions.nReceiveFloodSize = 1000*gArgs.GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER);
@@ -1749,7 +1756,7 @@ bool AppInitMain(InitInterfaces& interfaces)
connOptions.m_specified_outgoing = connect;
}
}
if (!connman.Start(scheduler, connOptions)) {
if (!g_connman->Start(scheduler, connOptions)) {
return false;
}

@@ -1762,5 +1769,9 @@ bool AppInitMain(InitInterfaces& interfaces)
client->start(scheduler);
}

scheduler.scheduleEvery([]{
g_banman->DumpBanlist();
}, DUMP_BANS_INTERVAL * 1000);

return true;
}
12 changes: 6 additions & 6 deletions src/interfaces/node.cpp
Original file line number Diff line number Diff line change
@@ -122,24 +122,24 @@ class NodeImpl : public Node
}
bool getBanned(banmap_t& banmap) override
{
if (g_connman) {
g_connman->GetBanned(banmap);
if (g_banman) {
g_banman->GetBanned(banmap);
return true;
}
return false;
}
bool ban(const CNetAddr& net_addr, BanReason reason, int64_t ban_time_offset) override
{
if (g_connman) {
g_connman->Ban(net_addr, reason, ban_time_offset);
if (g_banman) {
g_banman->Ban(net_addr, reason, ban_time_offset);
return true;
}
return false;
}
bool unban(const CSubNet& ip) override
{
if (g_connman) {
g_connman->Unban(ip);
if (g_banman) {
g_banman->Unban(ip);
return true;
}
return false;
81 changes: 43 additions & 38 deletions src/net.cpp
Original file line number Diff line number Diff line change
@@ -44,9 +44,6 @@
// Dump addresses to peers.dat every 15 minutes (900s)
static constexpr int DUMP_PEERS_INTERVAL = 15 * 60;

// Dump addresses to banlist.dat every 15 minutes (900s)
static constexpr int DUMP_BANS_INTERVAL = 60 * 15;

// We add a random period time (0 to 1 seconds) to feeler connections to prevent synchronization.
#define FEELER_SLEEP_WINDOW 1

@@ -460,7 +457,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
return pnode;
}

void CConnman::DumpBanlist()
void BanMan::DumpBanlist()
{
SweepBanned(); // clean unused entries (if bantime has expired)

@@ -491,7 +488,7 @@ void CNode::CloseSocketDisconnect()
}
}

void CConnman::ClearBanned()
void BanMan::ClearBanned()
{
{
LOCK(cs_setBanned);
@@ -503,7 +500,7 @@ void CConnman::ClearBanned()
clientInterface->BannedListChanged();
}

bool CConnman::IsBanned(CNetAddr ip)
bool BanMan::IsBanned(CNetAddr ip)
{
LOCK(cs_setBanned);
for (const auto& it : setBanned) {
@@ -517,7 +514,7 @@ bool CConnman::IsBanned(CNetAddr ip)
return false;
}

bool CConnman::IsBanned(CSubNet subnet)
bool BanMan::IsBanned(CSubNet subnet)
{
LOCK(cs_setBanned);
banmap_t::iterator i = setBanned.find(subnet);
@@ -531,12 +528,12 @@ bool CConnman::IsBanned(CSubNet subnet)
return false;
}

void CConnman::Ban(const CNetAddr& addr, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) {
void BanMan::Ban(const CNetAddr& addr, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) {
CSubNet subNet(addr);
Ban(subNet, banReason, bantimeoffset, sinceUnixEpoch);
}

void CConnman::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) {
void BanMan::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) {
CBanEntry banEntry(GetTime());
banEntry.banReason = banReason;
if (bantimeoffset <= 0)
@@ -561,12 +558,12 @@ void CConnman::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t ba
DumpBanlist(); //store banlist to disk immediately if user requested ban
}

bool CConnman::Unban(const CNetAddr &addr) {
bool BanMan::Unban(const CNetAddr &addr) {
CSubNet subNet(addr);
return Unban(subNet);
}

bool CConnman::Unban(const CSubNet &subNet) {
bool BanMan::Unban(const CSubNet &subNet) {
{
LOCK(cs_setBanned);
if (!setBanned.erase(subNet))
@@ -579,22 +576,22 @@ bool CConnman::Unban(const CSubNet &subNet) {
return true;
}

void CConnman::GetBanned(banmap_t &banMap)
void BanMan::GetBanned(banmap_t &banMap)
{
LOCK(cs_setBanned);
// Sweep the banlist so expired bans are not returned
SweepBanned();
banMap = setBanned; //create a thread safe copy
}

void CConnman::SetBanned(const banmap_t &banMap)
void BanMan::SetBanned(const banmap_t &banMap)
{
LOCK(cs_setBanned);
setBanned = banMap;
setBannedIsDirty = true;
}

void CConnman::SweepBanned()
void BanMan::SweepBanned()
{
int64_t now = GetTime();
bool notifyUI = false;
@@ -622,13 +619,13 @@ void CConnman::SweepBanned()
}
}

bool CConnman::BannedSetIsDirty()
bool BanMan::BannedSetIsDirty()
{
LOCK(cs_setBanned);
return setBannedIsDirty;
}

void CConnman::SetBannedSetDirty(bool dirty)
void BanMan::SetBannedSetDirty(bool dirty)
{
LOCK(cs_setBanned); //reuse setBanned lock for the isDirty flag
setBannedIsDirty = dirty;
@@ -1103,7 +1100,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
// on all platforms. Set it again here just to be sure.
SetSocketNoDelay(hSocket);

if (IsBanned(addr) && !whitelisted)
if (m_banman && m_banman->IsBanned(addr) && !whitelisted)
{
LogPrint(BCLog::NET, "connection from %s dropped (banned)\n", addr.ToString());
CloseSocket(hSocket);
@@ -2075,7 +2072,7 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
}
if (!pszDest) {
if (IsLocal(addrConnect) ||
FindNode(static_cast<CNetAddr>(addrConnect)) || IsBanned(addrConnect) ||
FindNode(static_cast<CNetAddr>(addrConnect)) || (m_banman && m_banman->IsBanned(addrConnect)) ||
FindNode(addrConnect.ToStringIPPort()))
return;
} else if (FindNode(std::string(pszDest)))
@@ -2376,24 +2373,6 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
DumpAddresses();
}
}
if (clientInterface)
clientInterface->InitMessage(_("Loading banlist..."));
// Load addresses from banlist.dat
nStart = GetTimeMillis();
CBanDB bandb;
banmap_t banmap;
if (bandb.Read(banmap)) {
SetBanned(banmap); // thread save setter
SetBannedSetDirty(false); // no need to write down, just read data
SweepBanned(); // sweep out unused entries

LogPrint(BCLog::NET, "Loaded %d banned node ips/subnets from banlist.dat %dms\n",
banmap.size(), GetTimeMillis() - nStart);
} else {
LogPrintf("Invalid or missing banlist.dat; recreating\n");
SetBannedSetDirty(true); // force write
DumpBanlist();
}

uiInterface.InitMessage(_("Starting network threads..."));

@@ -2448,11 +2427,38 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)

// Dump network addresses
scheduler.scheduleEvery(std::bind(&CConnman::DumpAddresses, this), DUMP_PEERS_INTERVAL * 1000);
scheduler.scheduleEvery(std::bind(&CConnman::DumpBanlist, this), DUMP_BANS_INTERVAL * 1000);

return true;
}

BanMan::BanMan(CClientUIInterface* client_interface) : clientInterface(client_interface)
{
if (clientInterface) clientInterface->InitMessage(_("Loading banlist..."));
// Load addresses from banlist.dat

int64_t nStart = GetTimeMillis();
setBannedIsDirty = false;
CBanDB bandb;
banmap_t banmap;
if (bandb.Read(banmap)) {
SetBanned(banmap); // thread save setter
SetBannedSetDirty(false); // no need to write down, just read data
SweepBanned(); // sweep out unused entries

LogPrint(BCLog::NET, "Loaded %d banned node ips/subnets from banlist.dat %dms\n",
banmap.size(), GetTimeMillis() - nStart);
} else {
LogPrintf("Invalid or missing banlist.dat; recreating\n");
SetBannedSetDirty(true); // force write
DumpBanlist();
}
}

BanMan::~BanMan()
{
DumpBanlist();
}

class CNetCleanup
{
public:
@@ -2508,7 +2514,6 @@ void CConnman::Stop()
if (fAddressesInitialized)
{
DumpAddresses();
DumpBanlist();
fAddressesInitialized = false;
}

Loading

0 comments on commit 4c0d961

Please sign in to comment.