From c8176cca558188a52f483ffd419fdf84e451208c Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Wed, 6 May 2009 22:36:24 +0000 Subject: [PATCH] optimized peer storage in resume data an in memory. Should use far less memory than previously for the peer list. Introduced peer source affinity, to avoid problem with a peer list that's diluted with stale peers --- docs/manual.rst | 3 +- include/libtorrent/aux_/session_impl.hpp | 8 + include/libtorrent/peer_info.hpp | 3 + include/libtorrent/policy.hpp | 28 ++-- src/bt_peer_connection.cpp | 16 +- src/peer_connection.cpp | 2 +- src/policy.cpp | 181 ++++++++++++++++------- src/session_impl.cpp | 6 +- src/torrent.cpp | 114 ++++++++++---- 9 files changed, 248 insertions(+), 113 deletions(-) diff --git a/docs/manual.rst b/docs/manual.rst index e2240bd42..62ba002c4 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -3662,7 +3662,8 @@ known peers. These peers are not necessarily connected, so this number should be much greater than the maximum number of connected peers. Peers are evicted from the cache when the list grows passed 90% of this limit, and once the size hits the limit, peers are no longer -added to the list. +added to the list. If this limit is set to 0, there is no limit on +how many peers we'll keep in the peer list. ``min_announce_interval`` is the minimum allowed announce interval for a tracker. This is specified in seconds, defaults to 5 minutes and diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 4944ecdc0..1568e1197 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -50,6 +50,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #ifdef _MSC_VER #pragma warning(pop) @@ -75,6 +76,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/disk_io_thread.hpp" #include "libtorrent/udp_socket.hpp" #include "libtorrent/assert.hpp" +#include "libtorrent/policy.hpp" // for policy::peer namespace libtorrent { @@ -344,6 +346,12 @@ namespace libtorrent void on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih); void setup_socket_buffers(socket_type& s); + // this is a shared pool where policy_peer objects + // are allocated. It's a pool since we're likely + // to have tens of thousands of peers, and a pool + // saves significant overhead + boost::object_pool m_peer_pool; + #ifndef TORRENT_DISABLE_POOL_ALLOCATOR // this pool is used to allocate and recycle send // buffers from. diff --git a/include/libtorrent/peer_info.hpp b/include/libtorrent/peer_info.hpp index 1fc251823..ad8160298 100644 --- a/include/libtorrent/peer_info.hpp +++ b/include/libtorrent/peer_info.hpp @@ -225,6 +225,9 @@ namespace libtorrent boost::uint8_t failcount; boost::uint8_t source; }; + + // defined in policy.cpp + int source_rank(int source_bitmask); } #endif // TORRENT_PEER_INFO_HPP_INCLUDED diff --git a/include/libtorrent/policy.hpp b/include/libtorrent/policy.hpp index 0ba583f80..23fdf56ec 100644 --- a/include/libtorrent/policy.hpp +++ b/include/libtorrent/policy.hpp @@ -36,14 +36,6 @@ POSSIBILITY OF SUCH DAMAGE. #include #include -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - #include "libtorrent/peer.hpp" #include "libtorrent/piece_picker.hpp" #include "libtorrent/socket.hpp" @@ -153,9 +145,6 @@ namespace libtorrent { return addr; } #endif - bool operator<(peer const& rhs) const - { return address() < rhs.address(); } - tcp::endpoint ip() const { return tcp::endpoint(address(), port); } // this is the accumulated amount of @@ -291,7 +280,13 @@ namespace libtorrent int num_peers() const { return m_peers.size(); } - typedef std::multiset peers_t; + struct peer_ptr_compare + { + bool operator()(peer* lhs, peer* rhs) const + { return lhs->address() < rhs->address(); } + }; + + typedef std::deque peers_t; typedef peers_t::iterator iterator; typedef peers_t::const_iterator const_iterator; @@ -300,7 +295,12 @@ namespace libtorrent const_iterator begin_peer() const { return m_peers.begin(); } const_iterator end_peer() const { return m_peers.end(); } std::pair find_peers(address const& a) - { return m_peers.equal_range(a); } + { + peer tmp(a); + peer_ptr_compare cmp; + return std::equal_range(m_peers.begin(), m_peers.end() + , &tmp, cmp); + } bool connect_one_peer(int session_time); @@ -325,7 +325,7 @@ namespace libtorrent // since the peer list can grow too large // to scan all of it, start at this iterator - iterator m_round_robin; + int m_round_robin; torrent* m_torrent; diff --git a/src/bt_peer_connection.cpp b/src/bt_peer_connection.cpp index dc122fa73..a19198df0 100644 --- a/src/bt_peer_connection.cpp +++ b/src/bt_peer_connection.cpp @@ -1980,13 +1980,13 @@ namespace libtorrent : m_id(id), m_pc(pc) { TORRENT_ASSERT(pc); } - bool operator()(policy::peer const& p) const + bool operator()(policy::peer const* p) const { - return p.connection != m_pc - && p.connection - && p.connection->pid() == m_id - && !p.connection->pid().is_all_zeros() - && p.address() == m_pc->remote().address(); + return p->connection != m_pc + && p->connection + && p->connection->pid() == m_id + && !p->connection->pid().is_all_zeros() + && p->address() == m_pc->remote().address(); } peer_id const& m_id; @@ -2753,7 +2753,7 @@ namespace libtorrent , match_peer_id(pid, this)); if (i != p.end_peer()) { - TORRENT_ASSERT(i->connection->pid() == pid); + TORRENT_ASSERT((*i)->connection->pid() == pid); // we found another connection with the same peer-id // which connection should be closed in order to be // sure that the other end closes the same connection? @@ -2763,7 +2763,7 @@ namespace libtorrent // if not, we should close the outgoing one. if (pid < m_ses.get_peer_id() && is_local()) { - i->connection->disconnect("duplicate peer-id, connection closed"); + (*i)->connection->disconnect("duplicate peer-id, connection closed"); } else { diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 79fdfb598..2b3fda7ab 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -4410,7 +4410,7 @@ namespace libtorrent policy::const_iterator end = t->get_policy().end_peer(); for (; i != end; ++i) { - if (&(*i) == m_peer_info) break; + if (*i == m_peer_info) break; } TORRENT_ASSERT(i != end); } diff --git a/src/policy.cpp b/src/policy.cpp index 0f398d5fe..78724e9a2 100644 --- a/src/policy.cpp +++ b/src/policy.cpp @@ -143,8 +143,8 @@ namespace : m_ep(ep) {} - bool operator()(policy::peer const& p) const - { return p.address() == m_ep.address() && p.port == m_ep.port(); } + bool operator()(policy::peer const* p) const + { return p->address() == m_ep.address() && p->port == m_ep.port(); } tcp::endpoint const& m_ep; }; @@ -156,11 +156,11 @@ namespace : m_conn(c) {} - bool operator()(policy::peer const& p) const + bool operator()(policy::peer const* p) const { - return p.connection == &m_conn - || (p.ip() == m_conn.remote() - && p.connectable); + return p->connection == &m_conn + || (p->ip() == m_conn.remote() + && p->connectable); } peer_connection const& m_conn; @@ -171,6 +171,20 @@ namespace namespace libtorrent { + // returns the rank of a peer's source. We have an affinity + // to connecting to peers with higher rank. This is to avoid + // problems when out peer list is diluted by stale peers from + // the resume data for instance + int source_rank(int source_bitmask) + { + int ret = 0; + if (source_bitmask & peer_info::tracker) ret |= 1 << 5; + if (source_bitmask & peer_info::lsd) ret |= 1 << 4; + if (source_bitmask & peer_info::dht) ret |= 1 << 3; + if (source_bitmask & peer_info::pex) ret |= 1 << 2; + return ret; + } + // the case where ignore_peer is motivated is if two peers // have only one piece that we don't have, and it's the // same piece for both peers. Then they might get into an @@ -330,7 +344,7 @@ namespace libtorrent } policy::policy(torrent* t) - : m_round_robin(m_peers.end()) + : m_round_robin(0) , m_torrent(t) , m_available_free_upload(0) , m_num_connect_candidates(0) @@ -347,24 +361,24 @@ namespace libtorrent p = &m_torrent->picker(); for (iterator i = m_peers.begin(); i != m_peers.end();) { - if ((ses.m_ip_filter.access(i->address()) & ip_filter::blocked) == 0) + if ((ses.m_ip_filter.access((*i)->address()) & ip_filter::blocked) == 0) { ++i; continue; } - if (i->connection) + if ((*i)->connection) { - i->connection->disconnect("peer banned by IP filter"); + (*i)->connection->disconnect("peer banned by IP filter"); if (ses.m_alerts.should_post()) - ses.m_alerts.post_alert(peer_blocked_alert(i->address())); - TORRENT_ASSERT(i->connection == 0 - || i->connection->peer_info_struct() == 0); + ses.m_alerts.post_alert(peer_blocked_alert((*i)->address())); + TORRENT_ASSERT((*i)->connection == 0 + || (*i)->connection->peer_info_struct() == 0); } else { if (ses.m_alerts.should_post()) - ses.m_alerts.post_alert(peer_blocked_alert(i->address())); + ses.m_alerts.post_alert(peer_blocked_alert((*i)->address())); } erase_peer(i++); } @@ -378,13 +392,16 @@ namespace libtorrent { INVARIANT_CHECK; - if (m_torrent->has_picker()) - m_torrent->picker().clear_peer((void*)&(*i)); - if (i->seed) --m_num_seeds; - if (is_connect_candidate(*i, m_finished)) - --m_num_connect_candidates; - if (m_round_robin == i) ++m_round_robin; + TORRENT_ASSERT(m_finished == m_torrent->is_finished()); + if (m_torrent->has_picker()) + m_torrent->picker().clear_peer(*i); + if ((*i)->seed) --m_num_seeds; + if (is_connect_candidate(**i, m_finished)) + --m_num_connect_candidates; + if (m_round_robin > i - m_peers.begin()) --m_round_robin; + + m_torrent->session().m_peer_pool.destroy(*i); m_peers.erase(i); } @@ -407,7 +424,9 @@ namespace libtorrent { INVARIANT_CHECK; - iterator candidate = m_peers.end(); + int candidate = -1; + + TORRENT_ASSERT(m_finished == m_torrent->is_finished()); int min_reconnect_time = m_torrent->settings().min_reconnect_time; address external_ip = m_torrent->session().external_address(); @@ -422,7 +441,7 @@ namespace libtorrent external_ip = address_v4(bytes); } - if (m_round_robin == m_peers.end()) m_round_robin = m_peers.begin(); + if (m_round_robin == m_peers.size()) m_round_robin = 0; #ifndef TORRENT_DISABLE_DHT bool pinged = false; @@ -431,10 +450,10 @@ namespace libtorrent for (int iterations = (std::min)(int(m_peers.size()), 300); iterations > 0; --iterations) { - if (m_round_robin == m_peers.end()) m_round_robin = m_peers.begin(); + if (m_round_robin == m_peers.size()) m_round_robin = 0; - peer& pe = (peer&)*m_round_robin; - iterator current = m_round_robin; + peer& pe = *m_peers[m_round_robin]; + int current = m_round_robin; #ifndef TORRENT_DISABLE_DHT // try to send a DHT ping to this peer @@ -461,9 +480,11 @@ namespace libtorrent && pe.last_connected != 0 && (!pe.banned || session_time - pe.last_connected > 2 * 60 * 60) && !is_connect_candidate(pe, m_finished) - && m_peers.size() >= m_torrent->settings().max_peerlist_size * 0.9) + && m_peers.size() >= m_torrent->settings().max_peerlist_size * 0.9 + && m_torrent->settings().max_peerlist_size > 0) { - erase_peer(m_round_robin++); + if (candidate > m_round_robin) --candidate; + erase_peer(m_peers.begin() + m_round_robin); continue; } @@ -471,8 +492,12 @@ namespace libtorrent if (!is_connect_candidate(pe, m_finished)) continue; - if (candidate != m_peers.end() - && compare_peer(*candidate, pe, external_ip)) continue; + // compare peer returns true if lhs is better than rhs. In this + // case, it returns true if the current candidate is better than + // pe, which is the peer m_round_robin points to. If it is, just + // keep looking. + if (candidate != -1 + && compare_peer(*m_peers[candidate], pe, external_ip)) continue; if (pe.last_connected && session_time - pe.last_connected < @@ -487,15 +512,16 @@ namespace libtorrent { (*m_torrent->session().m_logger) << time_now_string() << " *** FOUND CONNECTION CANDIDATE [" - " ip: " << candidate->ip() << - " d: " << cidr_distance(external_ip, candidate->address()) << + " ip: " << (*candidate)->ip() << + " d: " << cidr_distance(external_ip, (*candidate)->address()) << " external: " << external_ip << - " t: " << (session_time - candidate->last_connected) << + " t: " << (session_time - (*candidate)->last_connected) << " ]\n"; } #endif - return candidate; + if (candidate == -1) return m_peers.end(); + return m_peers.begin() + candidate; } void policy::pulse() @@ -569,22 +595,27 @@ namespace libtorrent iterator iter; peer* i = 0; + bool found = false; if (m_torrent->settings().allow_multiple_connections_per_ip) { tcp::endpoint remote = c.remote(); - std::pair range = m_peers.equal_range(remote.address()); + std::pair range = find_peers(remote.address()); iter = std::find_if(range.first, range.second, match_peer_endpoint(remote)); - if (iter == range.second) iter = m_peers.end(); + if (iter != range.second) found = true; } else { - iter = m_peers.find(c.remote().address()); + peer tmp(c.remote().address()); + peer_ptr_compare cmp; + iter = std::lower_bound(m_peers.begin(), m_peers.end() + , &tmp, cmp); + if (iter != m_peers.end() && (*iter)->address() == c.remote().address()) found = true; } - if (iter != m_peers.end()) + if (found) { - i = (peer*)&(*iter); + i = *iter; if (i->banned) { @@ -658,9 +689,12 @@ namespace libtorrent return false; } - peer p(c.remote(), false, 0); - iter = m_peers.insert(p); - i = (peer*)&(*iter); + if (m_round_robin > iter - m_peers.begin()) ++m_round_robin; + peer* p = m_torrent->session().m_peer_pool.malloc(); + new (p) peer(c.remote(), false, 0); + iter = m_peers.insert(iter, p); + + i = *iter; #ifndef TORRENT_DISABLE_GEO_IP int as = ses.as_for_ip(c.remote().address()); #ifdef TORRENT_DEBUG @@ -693,12 +727,12 @@ namespace libtorrent if (m_torrent->settings().allow_multiple_connections_per_ip) { tcp::endpoint remote(p->address(), port); - std::pair range = m_peers.equal_range(remote.address()); + std::pair range = find_peers(remote.address()); iterator i = std::find_if(range.first, range.second , match_peer_endpoint(remote)); if (i != m_peers.end()) { - policy::peer& pp = (peer&)*i; + policy::peer& pp = **i; if (pp.connection) { p->connection->disconnect("duplicate connection"); @@ -707,10 +741,14 @@ namespace libtorrent erase_peer(i); } } +#ifdef TORRENT_DEBUG else { - TORRENT_ASSERT(m_peers.count(p->address()) == 1); + std::pair range = find_peers(p->address()); + TORRENT_ASSERT(range.second - range.first == 1); } +#endif + bool was_conn_cand = is_connect_candidate(*p, m_finished); p->port = port; p->source |= src; @@ -729,7 +767,7 @@ namespace libtorrent for (const_iterator i = m_peers.begin() , end(m_peers.end()); i != end; ++i) { - if (&(*i) == p) return true; + if (*i == p) return true; } return false; } @@ -756,18 +794,23 @@ namespace libtorrent iterator iter; peer* i = 0; + bool found = false; if (m_torrent->settings().allow_multiple_connections_per_ip) { - std::pair range = m_peers.equal_range(remote.address()); + std::pair range = find_peers(remote.address()); iter = std::find_if(range.first, range.second, match_peer_endpoint(remote)); - if (iter == range.second) iter = m_peers.end(); + if (iter != range.second) found = true; } else { - iter = m_peers.find(remote.address()); + peer tmp(remote.address()); + peer_ptr_compare cmp; + iter = std::lower_bound(m_peers.begin(), m_peers.end() + , &tmp, cmp); + if (iter != m_peers.end() && (*iter)->address() == remote.address()) found = true; } - if (iter == m_peers.end()) + if (!found) { // if the IP is blocked, don't add it if (ses.m_ip_filter.access(remote.address()) & ip_filter::blocked) @@ -779,13 +822,19 @@ namespace libtorrent return 0; } - if (int(m_peers.size()) >= m_torrent->settings().max_peerlist_size) + if (m_torrent->settings().max_peerlist_size + && int(m_peers.size()) >= m_torrent->settings().max_peerlist_size) return 0; + if (m_round_robin > iter - m_peers.begin()) ++m_round_robin; + // we don't have any info about this peer. // add a new entry - iter = m_peers.insert(peer(remote, true, src)); - i = (peer*)&(*iter); + peer* p = m_torrent->session().m_peer_pool.malloc(); + new (p) peer(remote, true, src); + iter = m_peers.insert(iter, p); + + i = *iter; #ifndef TORRENT_DISABLE_ENCRYPTION if (flags & 0x01) i->pe_support = true; #endif @@ -807,7 +856,7 @@ namespace libtorrent } else { - i = (peer*)&(*iter); + i = *iter; bool was_conn_cand = is_connect_candidate(*i, m_finished); @@ -988,7 +1037,7 @@ namespace libtorrent iterator i = find_connect_candidate(session_time); if (i == m_peers.end()) return false; - peer& p = (peer&)*i; + peer& p = **i; TORRENT_ASSERT(!p.banned); TORRENT_ASSERT(!p.connection); @@ -1082,7 +1131,7 @@ namespace libtorrent for (const_iterator i = m_peers.begin(); i != m_peers.end(); ++i) { - m_num_connect_candidates += is_connect_candidate(*i, m_finished); + m_num_connect_candidates += is_connect_candidate(**i, m_finished); } } @@ -1114,16 +1163,30 @@ namespace libtorrent int nonempty_connections = 0; std::set unique_test; + const_iterator prev = m_peers.end(); for (const_iterator i = m_peers.begin(); i != m_peers.end(); ++i) { - peer const& p = *i; + if (prev != m_peers.end()) ++prev; + if (i == m_peers.begin() + 1) prev = m_peers.begin(); + if (prev != m_peers.end()) + { + if (m_torrent->settings().allow_multiple_connections_per_ip) + TORRENT_ASSERT(!((*i)->address() < (*prev)->address())); + else + TORRENT_ASSERT((*prev)->address() < (*i)->address()); + } + peer const& p = **i; #ifndef TORRENT_DISABLE_GEO_IP TORRENT_ASSERT(p.inet_as == 0 || p.inet_as->first == p.inet_as_num); #endif if (!m_torrent->settings().allow_multiple_connections_per_ip) { - TORRENT_ASSERT(m_peers.count(p.address()) == 1); + peer tmp(p.address()); + peer_ptr_compare cmp; + std::pair range = std::equal_range( + m_peers.begin(), m_peers.end(), &tmp, cmp); + TORRENT_ASSERT(range.second - range.first == 1); } else { @@ -1307,6 +1370,10 @@ namespace libtorrent if (lhs.last_connected != rhs.last_connected) return lhs.last_connected < rhs.last_connected; + int lhs_rank = source_rank(lhs.source); + int rhs_rank = source_rank(rhs.source); + if (lhs_rank != rhs_rank) return lhs_rank > rhs_rank; + #ifndef TORRENT_DISABLE_GEO_IP // don't bias fast peers when seeding if (!m_finished && m_torrent->session().has_asnum_db()) diff --git a/src/session_impl.cpp b/src/session_impl.cpp index aaf17465b..2c45892b6 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -149,11 +149,11 @@ namespace aux { , fs::path const& logpath #endif ) - : + : m_peer_pool(500) #ifndef TORRENT_DISABLE_POOL_ALLOCATOR - m_send_buffers(send_buffer_size), + , m_send_buffers(send_buffer_size) #endif - m_files(40) + , m_files(40) , m_io_service() , m_disk_thread(m_io_service) , m_half_open(m_io_service) diff --git a/src/torrent.cpp b/src/torrent.cpp index 348710a80..491967fa8 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -643,11 +643,60 @@ namespace libtorrent if (m_resume_entry.type() == lazy_entry::dict_t) { + using namespace libtorrent::detail; // for read_*_endpoint() + peer_id id(0); + + if (lazy_entry const* peers_entry = m_resume_entry.dict_find_string("peers")) + { + int num_peers = peers_entry->string_length() / (sizeof(address_v4::bytes_type) + 2); + char const* ptr = peers_entry->string_ptr(); + for (int i = 0; i < num_peers; ++i) + { + m_policy.peer_from_tracker(read_v4_endpoint(ptr) + , id, peer_info::resume_data, 0); + } + } + + if (lazy_entry const* banned_peers_entry = m_resume_entry.dict_find_string("banned_peers")) + { + int num_peers = banned_peers_entry->string_length() / (sizeof(address_v4::bytes_type) + 2); + char const* ptr = banned_peers_entry->string_ptr(); + for (int i = 0; i < num_peers; ++i) + { + policy::peer* p = m_policy.peer_from_tracker(read_v4_endpoint(ptr) + , id, peer_info::resume_data, 0); + if (p) p->banned = true; + } + } + +#if TORRENT_USE_IPV6 + if (lazy_entry const* peers6_entry = m_resume_entry.dict_find_string("peers6")) + { + int num_peers = peers6_entry->string_length() / (sizeof(address_v6::bytes_type) + 2); + char const* ptr = peers6_entry->string_ptr(); + for (int i = 0; i < num_peers; ++i) + { + m_policy.peer_from_tracker(read_v6_endpoint(ptr) + , id, peer_info::resume_data, 0); + } + } + + if (lazy_entry const* banned_peers6_entry = m_resume_entry.dict_find_string("banned_peers6")) + { + int num_peers = banned_peers6_entry->string_length() / (sizeof(address_v6::bytes_type) + 2); + char const* ptr = banned_peers6_entry->string_ptr(); + for (int i = 0; i < num_peers; ++i) + { + policy::peer* p = m_policy.peer_from_tracker(read_v6_endpoint(ptr) + , id, peer_info::resume_data, 0); + if (p) p->banned = true; + } + } +#endif + // parse out "peers" from the resume data and add them to the peer list if (lazy_entry const* peers_entry = m_resume_entry.dict_find_list("peers")) { - peer_id id(0); - for (int i = 0; i < peers_entry->list_size(); ++i) { lazy_entry const* e = peers_entry->list_at(i); @@ -664,9 +713,7 @@ namespace libtorrent // parse out "banned_peers" and add them as banned if (lazy_entry const* banned_peers_entry = m_resume_entry.dict_find_list("banned_peers")) - { - peer_id id(0); - + { for (int i = 0; i < banned_peers_entry->list_size(); ++i) { lazy_entry const* e = banned_peers_entry->list_at(i); @@ -3150,6 +3197,7 @@ namespace libtorrent void torrent::write_resume_data(entry& ret) const { + using namespace libtorrent::detail; // for write_*_endpoint() ret["file-format"] = "libtorrent resume file"; ret["file-version"] = 1; @@ -3313,9 +3361,13 @@ namespace libtorrent // write local peers - entry::list_type& peer_list = ret["peers"].list(); - entry::list_type& banned_peer_list = ret["banned_peers"].list(); - + std::back_insert_iterator peers(ret["peers"].string()); + std::back_insert_iterator banned_peers(ret["banned_peers"].string()); +#if TORRENT_USE_IPV6 + std::back_insert_iterator peers6(ret["peers6"].string()); + std::back_insert_iterator banned_peers6(ret["banned_peers6"].string()); +#endif + // failcount is a 5 bit value int max_failcount = (std::min)(m_ses.m_settings.max_failcount, 31); @@ -3323,16 +3375,19 @@ namespace libtorrent , end(m_policy.end_peer()); i != end; ++i) { error_code ec; - policy::peer const& p = *i; - if (p.banned) + policy::peer const* p = *i; + address addr = p->address(); + if (p->banned) { - entry peer(entry::dictionary_t); - peer["ip"] = p.address().to_string(ec); - if (ec) continue; - peer["port"] = p.port; - banned_peer_list.push_back(peer); +#if TORRENT_USE_IPV6 + if (addr.is_v6()) + write_endpoint(tcp::endpoint(addr, p->port), banned_peers6); + else +#endif + write_endpoint(tcp::endpoint(addr, p->port), banned_peers); continue; } + // we cannot save remote connection // since we don't know their listen port // unless they gave us their listen port @@ -3340,16 +3395,17 @@ namespace libtorrent // so, if the peer is not connectable (i.e. we // don't know its listen port) or if it has // been banned, don't save it. - if (!p.connectable) continue; + if (!p->connectable) continue; - // don't save peers that doesn't work - if (p.failcount >= max_failcount) continue; + // don't save peers that don't work + if (p->failcount >= max_failcount) continue; - entry peer(entry::dictionary_t); - peer["ip"] = p.address().to_string(ec); - if (ec) continue; - peer["port"] = p.port; - peer_list.push_back(peer); +#if TORRENT_USE_IPV6 + if (addr.is_v6()) + write_endpoint(tcp::endpoint(addr, p->port), peers6); + else +#endif + write_endpoint(tcp::endpoint(addr, p->port), peers); } ret["upload_rate_limit"] = upload_limit(); @@ -3388,10 +3444,10 @@ namespace libtorrent i != m_policy.end_peer(); ++i) { peer_list_entry e; - e.ip = i->ip(); - e.flags = i->banned ? peer_list_entry::banned : 0; - e.failcount = i->failcount; - e.source = i->source; + e.ip = (*i)->ip(); + e.flags = (*i)->banned ? peer_list_entry::banned : 0; + e.failcount = (*i)->failcount; + e.source = (*i)->source; v.push_back(e); } } @@ -4189,10 +4245,10 @@ namespace libtorrent policy::const_iterator i = m_policy.begin_peer(); policy::const_iterator prev = i++; policy::const_iterator end(m_policy.end_peer()); + policy::peer_ptr_compare cmp; for (; i != end; ++i, ++prev) { - // this means <= but only using the < operator - TORRENT_ASSERT(*prev < *i || !(*i < *prev)); + TORRENT_ASSERT(!cmp(*i, *prev)); } } #endif