mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Initial import of IP blacklist code.
This commit is contained in:
182
src/ripple_basics/containers/BlackList.h
Normal file
182
src/ripple_basics/containers/BlackList.h
Normal file
@@ -0,0 +1,182 @@
|
||||
#ifndef RIPPLE_BLACKLIST_H_INCLUDED
|
||||
#define RIPPLE_BLACKLIST_H_INCLUDED
|
||||
|
||||
|
||||
template <class Timer>
|
||||
class BlackList
|
||||
{
|
||||
struct iBlackList
|
||||
{
|
||||
int mBalance; // Exponentially-decaying "cost" balance
|
||||
int mLastUpdate; // The uptime when the balance was last decayed
|
||||
|
||||
iBlackList(int now) : mBalance(0), mLastUpdate(now) { ; }
|
||||
iBlackList() : mBalance(0), mLastUpdate(0) { ; }
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
// Used for import/export of current blacklist information
|
||||
typedef std::pair<std::string, int> BlackListEntry;
|
||||
typedef std::vector<BlackListEntry> BlackListEntryList;
|
||||
|
||||
BlackList()
|
||||
{ }
|
||||
|
||||
// We are issuing a warning to a source, update its entry
|
||||
bool doWarning(const std::string& source)
|
||||
{
|
||||
return chargeEntry(source, mWarnCost);
|
||||
}
|
||||
|
||||
// We are disconnecting a source, update its entry
|
||||
bool doDisconnect(const std::string& source)
|
||||
{
|
||||
return chargeEntry(source, mDiscCost);
|
||||
}
|
||||
|
||||
// We are connecting a source and need to know if it's allowed
|
||||
bool isAllowed(const std::string& source)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
|
||||
iBlackList* e = findEntry(source, true);
|
||||
return e ? (e->mBalance <= (mCreditLimit * mDecaySeconds)) : true;
|
||||
}
|
||||
|
||||
// Clean up stale entries
|
||||
void sweep()
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
int expire = Timer::getElapsedSeconds() - mStaleTime;
|
||||
|
||||
typename BlackListTable::iterator it = mList.begin();
|
||||
while (it != mList.end())
|
||||
{
|
||||
if (it->second.mLastUpdate < expire)
|
||||
mList.erase(it++);
|
||||
else
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
// Synchronize blacklist data across servers
|
||||
BlackListEntryList getBlackList(int cutoff)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
|
||||
BlackListEntryList list;
|
||||
list.reserve(mList.size());
|
||||
|
||||
int now = Timer::getElapsedSeconds();
|
||||
cutoff *= mDecaySeconds;
|
||||
|
||||
typename BlackListTable::iterator it = mList.begin();
|
||||
while (it != mList.end())
|
||||
{
|
||||
if (!ageEntry(now, &it->second))
|
||||
mList.erase(it++);
|
||||
else if (it->second.mBalance >= cutoff)
|
||||
{
|
||||
list.push_back(std::make_pair(it->first, it->second.mBalance / mDecaySeconds));
|
||||
++it;
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void mergeBlackList(const BlackListEntryList& list)
|
||||
{ // Merge our black list with another black list, presumably received from a trusted peer
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
|
||||
BOOST_FOREACH(const BlackListEntry& entry, list)
|
||||
{
|
||||
// Find/make an entry for us corresponding to our peer's entry
|
||||
iBlackList* e = findEntry(entry.first, true);
|
||||
|
||||
// Decay the value at least once to ensure we don't pass the same value
|
||||
// around forever without ever decaying it
|
||||
int decayValue = entry.second;
|
||||
decayValue -= (decayValue + mDecaySeconds - 1) / mDecaySeconds;
|
||||
|
||||
// Raise our value to the decayed peer's value
|
||||
e->mBalance = std::max(e->mBalance, decayValue);
|
||||
}
|
||||
}
|
||||
|
||||
static const int mWarnCost = 10; // The cost of being warned
|
||||
static const int mDiscCost = 100; // The cost of being disconnected for abuse
|
||||
static const int mRejectCost = 1; // The cost of having a connection disconnected
|
||||
static const int mCreditsPerSecond = 2; // Maximum cost rate permitted continuously
|
||||
static const int mCreditLimit = 1000; // Maximum cost before rejections
|
||||
static const int mStaleTime = 300; // Time to purge stale entries
|
||||
static const int mDecaySeconds = 32; // Exponential decay constant
|
||||
|
||||
private:
|
||||
|
||||
typedef std::map<std::string, iBlackList> BlackListTable;
|
||||
|
||||
BlackListTable mList;
|
||||
boost::mutex mMutex;
|
||||
|
||||
bool chargeEntry(const std::string& source, int charge)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
|
||||
iBlackList* e = findEntry(source, true);
|
||||
e->mBalance += charge;
|
||||
return e->mBalance > (mDecaySeconds * mCreditLimit);
|
||||
}
|
||||
|
||||
bool ageEntry(int now, iBlackList* entry)
|
||||
{
|
||||
if (entry->mLastUpdate != now)
|
||||
{
|
||||
if ((entry->mLastUpdate + mStaleTime) <= now)
|
||||
{ // stale entry
|
||||
entry->mLastUpdate = now;
|
||||
entry->mBalance = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((entry->mLastUpdate < now) && (entry->mLastUpdate != 0))
|
||||
{
|
||||
++entry->mLastUpdate;
|
||||
entry->mBalance -= (entry->mBalance + mDecaySeconds - 1) / mDecaySeconds;
|
||||
}
|
||||
entry->mLastUpdate = now;
|
||||
}
|
||||
}
|
||||
return entry->mBalance != 0;
|
||||
}
|
||||
|
||||
iBlackList* findEntry(const std::string& source, bool create)
|
||||
{
|
||||
iBlackList* ret = nullptr;
|
||||
|
||||
typename BlackListTable::iterator it = mList.find(source);
|
||||
|
||||
if (it != mList.end())
|
||||
{
|
||||
ret = &it->second;
|
||||
if (!ageEntry(Timer::getElapsedSeconds(), ret) && !create)
|
||||
{ // entry has expired, and we don't need it
|
||||
mList.erase(it);
|
||||
ret = nullptr;
|
||||
}
|
||||
}
|
||||
else if (create)
|
||||
{
|
||||
ret = &mList[source];
|
||||
ret->mLastUpdate = Timer::getElapsedSeconds();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user