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

This commit is contained in:
Arvid Norberg 2009-05-06 22:36:24 +00:00
parent ea91a6e077
commit c8176cca55
9 changed files with 248 additions and 113 deletions

View File

@ -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

View File

@ -50,6 +50,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/thread.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/pool/object_pool.hpp>
#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<policy::peer> m_peer_pool;
#ifndef TORRENT_DISABLE_POOL_ALLOCATOR
// this pool is used to allocate and recycle send
// buffers from.

View File

@ -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

View File

@ -36,14 +36,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include <algorithm>
#include <set>
#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<peer> peers_t;
struct peer_ptr_compare
{
bool operator()(peer* lhs, peer* rhs) const
{ return lhs->address() < rhs->address(); }
};
typedef std::deque<peer*> 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<iterator, iterator> 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;

View File

@ -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
{

View File

@ -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);
}

View File

@ -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<peer_blocked_alert>())
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<peer_blocked_alert>())
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<iterator, iterator> range = m_peers.equal_range(remote.address());
std::pair<iterator, iterator> 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<iterator, iterator> range = m_peers.equal_range(remote.address());
std::pair<iterator, iterator> 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<iterator, iterator> 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<iterator, iterator> range = m_peers.equal_range(remote.address());
std::pair<iterator, iterator> 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<tcp::endpoint> 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<const_iterator, const_iterator> 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())

View File

@ -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)

View File

@ -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<tcp::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<tcp::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<tcp::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<tcp::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<entry::string_type> peers(ret["peers"].string());
std::back_insert_iterator<entry::string_type> banned_peers(ret["banned_peers"].string());
#if TORRENT_USE_IPV6
std::back_insert_iterator<entry::string_type> peers6(ret["peers6"].string());
std::back_insert_iterator<entry::string_type> 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