2016-01-18 15:33:29 +00:00
|
|
|
// Copyright (c) 2011-2016 The Cryptonote developers
|
2015-09-18 11:55:31 +00:00
|
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
2015-05-27 12:08:46 +00:00
|
|
|
|
|
|
|
#include "PeerListManager.h"
|
|
|
|
|
|
|
|
#include <time.h>
|
|
|
|
#include <boost/foreach.hpp>
|
|
|
|
#include <System/Ipv4Address.h>
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
#include "Serialization/SerializationOverloads.h"
|
|
|
|
|
2015-05-27 12:08:46 +00:00
|
|
|
using namespace CryptoNote;
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
namespace CryptoNote {
|
|
|
|
template <typename T, typename Indexes>
|
|
|
|
bool serialize(boost::multi_index_container<T, Indexes>& value, Common::StringView name, ISerializer& s) {
|
|
|
|
if (s.type() == ISerializer::INPUT) {
|
|
|
|
readSequence<T>(std::inserter(value, value.end()), name, s);
|
|
|
|
} else {
|
|
|
|
writeSequence<T>(value.begin(), value.end(), name, s);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void serialize(NetworkAddress& na, ISerializer& s) {
|
|
|
|
s(na.ip, "ip");
|
|
|
|
s(na.port, "port");
|
|
|
|
}
|
|
|
|
|
|
|
|
void serialize(PeerlistEntry& pe, ISerializer& s) {
|
|
|
|
s(pe.adr, "adr");
|
|
|
|
s(pe.id, "id");
|
|
|
|
s(pe.last_seen, "last_seen");
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
PeerlistManager::Peerlist::Peerlist(peers_indexed& peers, size_t maxSize) :
|
|
|
|
m_peers(peers), m_maxSize(maxSize) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void PeerlistManager::serialize(ISerializer& s) {
|
|
|
|
const uint8_t currentVersion = 1;
|
|
|
|
uint8_t version = currentVersion;
|
|
|
|
|
|
|
|
s(version, "version");
|
|
|
|
|
|
|
|
if (version != currentVersion) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
s(m_peers_white, "whitelist");
|
|
|
|
s(m_peers_gray, "graylist");
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t PeerlistManager::Peerlist::count() const {
|
|
|
|
return m_peers.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PeerlistManager::Peerlist::get(PeerlistEntry& entry, size_t i) const {
|
|
|
|
if (i >= m_peers.size())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
peers_indexed::index<by_time>::type& by_time_index = m_peers.get<by_time>();
|
|
|
|
|
|
|
|
auto it = by_time_index.rbegin();
|
|
|
|
std::advance(it, i);
|
|
|
|
entry = *it;
|
|
|
|
|
2015-05-27 12:08:46 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
void PeerlistManager::Peerlist::trim() {
|
|
|
|
peers_indexed::index<by_time>::type& sorted_index = m_peers.get<by_time>();
|
|
|
|
while (m_peers.size() > m_maxSize) {
|
2015-05-27 12:08:46 +00:00
|
|
|
sorted_index.erase(sorted_index.begin());
|
|
|
|
}
|
|
|
|
}
|
2015-07-30 15:22:07 +00:00
|
|
|
|
|
|
|
PeerlistManager::PeerlistManager() :
|
|
|
|
m_whitePeerlist(m_peers_white, CryptoNote::P2P_LOCAL_WHITE_PEERLIST_LIMIT),
|
|
|
|
m_grayPeerlist(m_peers_gray, CryptoNote::P2P_LOCAL_GRAY_PEERLIST_LIMIT) {}
|
|
|
|
|
2015-05-27 12:08:46 +00:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2015-07-30 15:22:07 +00:00
|
|
|
bool PeerlistManager::init(bool allow_local_ip)
|
2015-05-27 12:08:46 +00:00
|
|
|
{
|
2015-07-30 15:22:07 +00:00
|
|
|
m_allow_local_ip = allow_local_ip;
|
|
|
|
return true;
|
2015-05-27 12:08:46 +00:00
|
|
|
}
|
2015-07-30 15:22:07 +00:00
|
|
|
|
2015-05-27 12:08:46 +00:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2015-07-30 15:22:07 +00:00
|
|
|
void PeerlistManager::trim_white_peerlist() {
|
|
|
|
m_whitePeerlist.trim();
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
void PeerlistManager::trim_gray_peerlist() {
|
|
|
|
m_grayPeerlist.trim();
|
|
|
|
}
|
2015-05-27 12:08:46 +00:00
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
bool PeerlistManager::merge_peerlist(const std::list<PeerlistEntry>& outer_bs)
|
2015-05-27 12:08:46 +00:00
|
|
|
{
|
2015-07-30 15:22:07 +00:00
|
|
|
for(const PeerlistEntry& be : outer_bs) {
|
2015-05-27 12:08:46 +00:00
|
|
|
append_with_peer_gray(be);
|
|
|
|
}
|
|
|
|
|
|
|
|
// delete extra elements
|
|
|
|
trim_gray_peerlist();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
bool PeerlistManager::get_white_peer_by_index(PeerlistEntry& p, size_t i) const {
|
|
|
|
return m_whitePeerlist.get(p, i);
|
2015-05-27 12:08:46 +00:00
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
2015-05-27 12:08:46 +00:00
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
bool PeerlistManager::get_gray_peer_by_index(PeerlistEntry& p, size_t i) const {
|
|
|
|
return m_grayPeerlist.get(p, i);
|
2015-05-27 12:08:46 +00:00
|
|
|
}
|
2015-07-30 15:22:07 +00:00
|
|
|
|
2015-05-27 12:08:46 +00:00
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
bool PeerlistManager::is_ip_allowed(uint32_t ip) const
|
2015-05-27 12:08:46 +00:00
|
|
|
{
|
|
|
|
System::Ipv4Address addr(networkToHost(ip));
|
|
|
|
|
|
|
|
//never allow loopback ip
|
|
|
|
if (addr.isLoopback()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_allow_local_ip && addr.isPrivate()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
bool PeerlistManager::get_peerlist_head(std::list<PeerlistEntry>& bs_head, uint32_t depth) const
|
2015-05-27 12:08:46 +00:00
|
|
|
{
|
2015-07-30 15:22:07 +00:00
|
|
|
const peers_indexed::index<by_time>::type& by_time_index = m_peers_white.get<by_time>();
|
2015-05-27 12:08:46 +00:00
|
|
|
uint32_t cnt = 0;
|
|
|
|
|
|
|
|
BOOST_REVERSE_FOREACH(const peers_indexed::value_type& vl, by_time_index)
|
|
|
|
{
|
|
|
|
if (!vl.last_seen)
|
|
|
|
continue;
|
|
|
|
bs_head.push_back(vl);
|
|
|
|
if (cnt++ > depth)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
bool PeerlistManager::get_peerlist_full(std::list<PeerlistEntry>& pl_gray, std::list<PeerlistEntry>& pl_white) const
|
2015-05-27 12:08:46 +00:00
|
|
|
{
|
2015-07-30 15:22:07 +00:00
|
|
|
const peers_indexed::index<by_time>::type& by_time_index_gr = m_peers_gray.get<by_time>();
|
|
|
|
const peers_indexed::index<by_time>::type& by_time_index_wt = m_peers_white.get<by_time>();
|
2015-05-27 12:08:46 +00:00
|
|
|
|
|
|
|
std::copy(by_time_index_gr.rbegin(), by_time_index_gr.rend(), std::back_inserter(pl_gray));
|
|
|
|
std::copy(by_time_index_wt.rbegin(), by_time_index_wt.rend(), std::back_inserter(pl_white));
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
bool PeerlistManager::set_peer_just_seen(PeerIdType peer, uint32_t ip, uint32_t port)
|
2015-05-27 12:08:46 +00:00
|
|
|
{
|
2015-07-30 15:22:07 +00:00
|
|
|
NetworkAddress addr;
|
2015-05-27 12:08:46 +00:00
|
|
|
addr.ip = ip;
|
|
|
|
addr.port = port;
|
|
|
|
return set_peer_just_seen(peer, addr);
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
bool PeerlistManager::set_peer_just_seen(PeerIdType peer, const NetworkAddress& addr)
|
2015-05-27 12:08:46 +00:00
|
|
|
{
|
|
|
|
try {
|
|
|
|
//find in white list
|
2015-07-30 15:22:07 +00:00
|
|
|
PeerlistEntry ple;
|
2015-05-27 12:08:46 +00:00
|
|
|
ple.adr = addr;
|
|
|
|
ple.id = peer;
|
|
|
|
ple.last_seen = time(NULL);
|
|
|
|
return append_with_peer_white(ple);
|
|
|
|
} catch (std::exception&) {
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
bool PeerlistManager::append_with_peer_white(const PeerlistEntry& ple)
|
2015-05-27 12:08:46 +00:00
|
|
|
{
|
|
|
|
try {
|
|
|
|
if (!is_ip_allowed(ple.adr.ip))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
//find in white list
|
|
|
|
auto by_addr_it_wt = m_peers_white.get<by_addr>().find(ple.adr);
|
|
|
|
if (by_addr_it_wt == m_peers_white.get<by_addr>().end()) {
|
|
|
|
//put new record into white list
|
|
|
|
m_peers_white.insert(ple);
|
|
|
|
trim_white_peerlist();
|
|
|
|
} else {
|
|
|
|
//update record in white list
|
|
|
|
m_peers_white.replace(by_addr_it_wt, ple);
|
|
|
|
}
|
|
|
|
//remove from gray list, if need
|
|
|
|
auto by_addr_it_gr = m_peers_gray.get<by_addr>().find(ple.adr);
|
|
|
|
if (by_addr_it_gr != m_peers_gray.get<by_addr>().end()) {
|
|
|
|
m_peers_gray.erase(by_addr_it_gr);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} catch (std::exception&) {
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
bool PeerlistManager::append_with_peer_gray(const PeerlistEntry& ple)
|
2015-05-27 12:08:46 +00:00
|
|
|
{
|
|
|
|
try {
|
|
|
|
if (!is_ip_allowed(ple.adr.ip))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
//find in white list
|
|
|
|
auto by_addr_it_wt = m_peers_white.get<by_addr>().find(ple.adr);
|
|
|
|
if (by_addr_it_wt != m_peers_white.get<by_addr>().end())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
//update gray list
|
|
|
|
auto by_addr_it_gr = m_peers_gray.get<by_addr>().find(ple.adr);
|
|
|
|
if (by_addr_it_gr == m_peers_gray.get<by_addr>().end())
|
|
|
|
{
|
|
|
|
//put new record into white list
|
|
|
|
m_peers_gray.insert(ple);
|
|
|
|
trim_gray_peerlist();
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
//update record in white list
|
|
|
|
m_peers_gray.replace(by_addr_it_gr, ple);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} catch (std::exception&) {
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2015-07-30 15:22:07 +00:00
|
|
|
|
|
|
|
PeerlistManager::Peerlist& PeerlistManager::getWhite() {
|
|
|
|
return m_whitePeerlist;
|
|
|
|
}
|
|
|
|
|
|
|
|
PeerlistManager::Peerlist& PeerlistManager::getGray() {
|
|
|
|
return m_grayPeerlist;
|
|
|
|
}
|