39 #include <boost/multi_index_container.hpp> 40 #include <boost/multi_index/ordered_index.hpp> 41 #include <boost/multi_index/identity.hpp> 42 #include <boost/multi_index/member.hpp> 43 #include <boost/optional/optional.hpp> 44 #include <boost/range/adaptor/reversed.hpp> 57 std::vector<peerlist_entry>
white;
58 std::vector<peerlist_entry>
gray;
59 std::vector<anchor_peerlist_entry>
anchor;
70 static boost::optional<peerlist_storage>
open(std::istream& src,
const bool new_format);
84 bool store(
std::ostream&
dest, const peerlist_types& other) const;
87 bool store(const
std::
string& path, const peerlist_types& other) const;
93 peerlist_types m_types;
105 bool merge_peerlist(
const std::vector<peerlist_entry>& outer_bs);
107 void get_peerlist(std::vector<peerlist_entry>& pl_gray, std::vector<peerlist_entry>& pl_white);
111 template<
typename F>
bool foreach(
bool white,
const F &f);
120 bool get_and_empty_anchor_peerlist(std::vector<anchor_peerlist_entry>& apl);
129 struct modify_all_but_id
151 struct modify_last_seen
153 modify_last_seen(time_t last_seen):m_last_seen(last_seen){}
156 e.last_seen = m_last_seen;
163 typedef boost::multi_index_container<
165 boost::multi_index::indexed_by<
167 boost::multi_index::ordered_unique<boost::multi_index::tag<by_addr>, boost::multi_index::member<peerlist_entry,epee::net_utils::network_address,&peerlist_entry::adr> >,
169 boost::multi_index::ordered_non_unique<boost::multi_index::tag<by_time>, boost::multi_index::member<peerlist_entry,int64_t,&peerlist_entry::last_seen> >
173 typedef boost::multi_index_container<
175 boost::multi_index::indexed_by<
177 boost::multi_index::ordered_unique<boost::multi_index::tag<by_addr>, boost::multi_index::member<anchor_peerlist_entry,epee::net_utils::network_address,&anchor_peerlist_entry::adr> >,
179 boost::multi_index::ordered_non_unique<boost::multi_index::tag<by_time>, boost::multi_index::member<anchor_peerlist_entry,int64_t,&anchor_peerlist_entry::first_seen> >
181 > anchor_peers_indexed;
184 void trim_white_peerlist();
185 void trim_gray_peerlist();
187 friend class boost::serialization::access;
190 bool m_allow_local_ip;
193 peers_indexed m_peers_gray;
194 peers_indexed m_peers_white;
195 anchor_peers_indexed m_peers_anchor;
198 inline void peerlist_manager::trim_gray_peerlist()
202 peers_indexed::index<by_time>::type& sorted_index=m_peers_gray.get<by_time>();
203 sorted_index.erase(sorted_index.begin());
207 inline void peerlist_manager::trim_white_peerlist()
211 peers_indexed::index<by_time>::type& sorted_index=m_peers_white.get<by_time>();
212 sorted_index.erase(sorted_index.begin());
222 append_with_peer_gray(be);
225 trim_gray_peerlist();
233 if(i >= m_peers_white.size())
236 peers_indexed::index<by_time>::type& by_time_index = m_peers_white.get<by_time>();
245 if(i >= m_peers_gray.size())
248 peers_indexed::index<by_time>::type& by_time_index = m_peers_gray.get<by_time>();
260 if(!m_allow_local_ip &&
address.is_local())
270 peers_indexed::index<by_time>::type& by_time_index=m_peers_white.get<by_time>();
282 const uint32_t pick_depth = anonymize ? depth + depth / 5 : depth;
283 bs_head.reserve(pick_depth);
284 for(
const peers_indexed::value_type& vl: boost::adaptors::reverse(by_time_index))
286 if(cnt++ >= pick_depth)
289 bs_head.push_back(vl);
294 std::random_shuffle(bs_head.begin(), bs_head.end());
295 if (bs_head.size() > depth)
296 bs_head.resize(depth);
297 for (
auto &e: bs_head)
304 template<
typename F>
inline 308 peers_indexed::index<by_time>::type& by_time_index = white ? m_peers_white.get<by_time>() : m_peers_gray.get<by_time>();
309 for(
const peers_indexed::value_type& vl: boost::adaptors::reverse(by_time_index))
327 return append_with_peer_white(ple);
335 if(!is_host_allowed(ple.
adr))
340 auto by_addr_it_wt = m_peers_white.get<by_addr>().find(ple.
adr);
341 if(by_addr_it_wt == m_peers_white.get<by_addr>().end())
344 m_peers_white.insert(ple);
345 trim_white_peerlist();
350 if (by_addr_it_wt->pruning_seed && ple.
pruning_seed == 0)
352 if (by_addr_it_wt->rpc_port && ple.
rpc_port == 0)
353 new_ple.
rpc_port = by_addr_it_wt->rpc_port;
354 new_ple.
last_seen = by_addr_it_wt->last_seen;
355 m_peers_white.replace(by_addr_it_wt, new_ple);
358 auto by_addr_it_gr = m_peers_gray.get<by_addr>().find(ple.
adr);
359 if(by_addr_it_gr != m_peers_gray.get<by_addr>().end())
361 m_peers_gray.erase(by_addr_it_gr);
364 CATCH_ENTRY_L0(
"peerlist_manager::append_with_peer_white()",
false);
371 if(!is_host_allowed(ple.
adr))
376 auto by_addr_it_wt = m_peers_white.get<by_addr>().find(ple.
adr);
377 if(by_addr_it_wt != m_peers_white.get<by_addr>().end())
381 auto by_addr_it_gr = m_peers_gray.get<by_addr>().find(ple.
adr);
382 if(by_addr_it_gr == m_peers_gray.get<by_addr>().end())
385 m_peers_gray.insert(ple);
386 trim_gray_peerlist();
391 if (by_addr_it_gr->pruning_seed && ple.
pruning_seed == 0)
393 if (by_addr_it_gr->rpc_port && ple.
rpc_port == 0)
394 new_ple.
rpc_port = by_addr_it_gr->rpc_port;
395 new_ple.
last_seen = by_addr_it_gr->last_seen;
396 m_peers_gray.replace(by_addr_it_gr, new_ple);
399 CATCH_ENTRY_L0(
"peerlist_manager::append_with_peer_gray()",
false);
409 auto by_addr_it_anchor = m_peers_anchor.get<by_addr>().find(ple.
adr);
411 if(by_addr_it_anchor == m_peers_anchor.get<by_addr>().end()) {
412 m_peers_anchor.insert(ple);
417 CATCH_ENTRY_L0(
"peerlist_manager::append_with_peer_anchor()",
false);
427 if (m_peers_gray.empty()) {
433 peers_indexed::index<by_time>::type& by_time_index = m_peers_gray.get<by_time>();
438 CATCH_ENTRY_L0(
"peerlist_manager::get_random_gray_peer()",
false);
448 peers_indexed::index_iterator<by_addr>::type iterator = m_peers_white.get<by_addr>().find(pe.
adr);
450 if (iterator != m_peers_white.get<by_addr>().end()) {
451 m_peers_white.erase(iterator);
456 CATCH_ENTRY_L0(
"peerlist_manager::remove_from_peer_white()",
false);
466 peers_indexed::index_iterator<by_addr>::type iterator = m_peers_gray.get<by_addr>().find(pe.
adr);
468 if (iterator != m_peers_gray.get<by_addr>().end()) {
469 m_peers_gray.erase(iterator);
474 CATCH_ENTRY_L0(
"peerlist_manager::remove_from_peer_gray()",
false);
484 auto begin = m_peers_anchor.get<by_time>().begin();
485 auto end = m_peers_anchor.get<by_time>().end();
491 m_peers_anchor.get<by_time>().clear();
495 CATCH_ENTRY_L0(
"peerlist_manager::get_and_empty_anchor_peerlist()",
false);
505 anchor_peers_indexed::index_iterator<by_addr>::type iterator = m_peers_anchor.get<by_addr>().find(addr);
507 if (iterator != m_peers_anchor.get<by_addr>().end()) {
508 m_peers_anchor.erase(iterator);
513 CATCH_ENTRY_L0(
"peerlist_manager::remove_from_peer_anchor()",
false);
CXA_THROW_INFO_T void(* dest)(void *))
std::enable_if< std::is_unsigned< T >::value, T >::type rand_idx(T sz)
#define P2P_DEFAULT_PEERS_IN_HANDSHAKE
#define CRITICAL_REGION_LOCAL(x)
#define P2P_LOCAL_GRAY_PEERLIST_LIMIT
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
t_iterator move_it_backward(t_iterator it, size_t count)
#define CATCH_ENTRY_L0(lacation, return_val)
#define P2P_LOCAL_WHITE_PEERLIST_LIMIT