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:
parent
ea91a6e077
commit
c8176cca55
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
181
src/policy.cpp
181
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<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())
|
||||
|
|
|
@ -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)
|
||||
|
|
114
src/torrent.cpp
114
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<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
|
||||
|
|
Loading…
Reference in New Issue