dncurrency/nano/node/peer_exclusion.cpp
Piotr Wójcik ab093d58d6
Rework collect_container_info (..) functions (#4736)
* Move container info classes to separate file

* Introduce better `container_info` class

* Rename legacy to `container_info_entry`

* Conversion

* Test

* Fixes
2024-10-03 15:36:34 +02:00

107 lines
No EOL
3 KiB
C++

#include <nano/node/peer_exclusion.hpp>
nano::peer_exclusion::peer_exclusion (std::size_t max_size_a) :
max_size{ max_size_a }
{
}
uint64_t nano::peer_exclusion::add (nano::tcp_endpoint const & endpoint)
{
uint64_t result = 0;
nano::lock_guard<nano::mutex> guard{ mutex };
if (auto existing = peers.get<tag_endpoint> ().find (endpoint.address ()); existing == peers.get<tag_endpoint> ().end ())
{
// Clean old excluded peers
while (peers.size () > 1 && peers.size () >= max_size)
{
peers.get<tag_exclusion> ().erase (peers.get<tag_exclusion> ().begin ());
}
debug_assert (peers.size () <= max_size);
// Insert new endpoint
auto inserted = peers.insert (peer_exclusion::item{ std::chrono::steady_clock::steady_clock::now () + exclude_time_hours, endpoint.address (), 1 });
(void)inserted;
debug_assert (inserted.second);
result = 1;
}
else
{
// Update existing endpoint
peers.get<tag_endpoint> ().modify (existing, [&result] (peer_exclusion::item & item_a) {
++item_a.score;
result = item_a.score;
if (item_a.score == peer_exclusion::score_limit)
{
item_a.exclude_until = std::chrono::steady_clock::now () + peer_exclusion::exclude_time_hours;
}
else if (item_a.score > peer_exclusion::score_limit)
{
item_a.exclude_until = std::chrono::steady_clock::now () + peer_exclusion::exclude_time_hours * item_a.score * 2;
}
});
}
return result;
}
uint64_t nano::peer_exclusion::score (const nano::tcp_endpoint & endpoint) const
{
nano::lock_guard<nano::mutex> guard{ mutex };
if (auto existing = peers.get<tag_endpoint> ().find (endpoint.address ()); existing != peers.get<tag_endpoint> ().end ())
{
return existing->score;
}
return 0;
}
std::chrono::steady_clock::time_point nano::peer_exclusion::until (const nano::tcp_endpoint & endpoint) const
{
nano::lock_guard<nano::mutex> guard{ mutex };
if (auto existing = peers.get<tag_endpoint> ().find (endpoint.address ()); existing != peers.get<tag_endpoint> ().end ())
{
return existing->exclude_until;
}
return {};
}
bool nano::peer_exclusion::check (nano::tcp_endpoint const & endpoint) const
{
return check (endpoint.address ());
}
bool nano::peer_exclusion::check (boost::asio::ip::address const & address) const
{
nano::lock_guard<nano::mutex> guard{ mutex };
if (auto existing = peers.get<tag_endpoint> ().find (address); existing != peers.get<tag_endpoint> ().end ())
{
if (existing->score >= score_limit && existing->exclude_until > std::chrono::steady_clock::now ())
{
return true;
}
}
return false;
}
void nano::peer_exclusion::remove (nano::tcp_endpoint const & endpoint_a)
{
nano::lock_guard<nano::mutex> guard{ mutex };
peers.get<tag_endpoint> ().erase (endpoint_a.address ());
}
std::size_t nano::peer_exclusion::size () const
{
nano::lock_guard<nano::mutex> guard{ mutex };
return peers.size ();
}
nano::container_info nano::peer_exclusion::container_info () const
{
nano::lock_guard<nano::mutex> guard{ mutex };
nano::container_info info;
info.put ("peers", peers.size ());
return info;
}