greatly optimised memory usage for peer list
This commit is contained in:
parent
ecdf83547e
commit
3cf34e3a91
@ -540,6 +540,9 @@ namespace libtorrent
|
||||
, int uncongested_torrents);
|
||||
void recalculate_optimistic_unchoke_slot();
|
||||
|
||||
ptime m_created;
|
||||
int session_time() const { return total_seconds(time_now() - m_created); }
|
||||
|
||||
ptime m_last_tick;
|
||||
ptime m_last_second_tick;
|
||||
|
||||
|
@ -34,7 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#define TORRENT_POLICY_HPP_INCLUDED
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 1)
|
||||
@ -91,10 +91,10 @@ namespace libtorrent
|
||||
|
||||
// called when an incoming connection is accepted
|
||||
// false means the connection was refused or failed
|
||||
bool new_connection(peer_connection& c);
|
||||
bool new_connection(peer_connection& c, int session_time);
|
||||
|
||||
// the given connection was just closed
|
||||
void connection_closed(const peer_connection& c);
|
||||
void connection_closed(const peer_connection& c, int session_time);
|
||||
|
||||
// the peer has got at least one interesting piece
|
||||
void peer_is_interesting(peer_connection& c);
|
||||
@ -116,24 +116,48 @@ namespace libtorrent
|
||||
void check_invariant() const;
|
||||
#endif
|
||||
|
||||
// intended struct layout (on 32 bit architectures)
|
||||
// offset size alignment field
|
||||
// 0 12 1 prev_amount_upload, prev_amount_download
|
||||
// 12 4 4 connection
|
||||
// 16 2 2 last_optimistically_unchoked
|
||||
// 18 2 2 last_connected
|
||||
// 20 16 1 addr
|
||||
// 36 2 2 port
|
||||
// 38 1 1 hashfails
|
||||
// 39 1 1 failcount, connectable, optimistically_unchoked, seed
|
||||
// 40 1 1 fast_reconnects, trust_points
|
||||
// 41 1 1 source, pe_support, is_v6_addr
|
||||
// 42 1 1 on_parole, banned, added_to_dht
|
||||
// 43 1 1 <padding>
|
||||
// 44
|
||||
struct peer
|
||||
{
|
||||
enum connection_type { not_connectable, connectable };
|
||||
peer(tcp::endpoint const& ip, connection_type t, int src);
|
||||
peer(tcp::endpoint const& ip, bool connectable, int src);
|
||||
|
||||
peer(libtorrent::address const& a) { set_ip(tcp::endpoint(a, 0)); }
|
||||
|
||||
size_type total_download() const;
|
||||
size_type total_upload() const;
|
||||
|
||||
tcp::endpoint ip() const { return tcp::endpoint(addr, port); }
|
||||
void set_ip(tcp::endpoint const& endp);
|
||||
|
||||
#if TORRENT_USE_IPV6
|
||||
void set_ip(tcp::endpoint const& endp)
|
||||
{ addr = endp.address(); port = endp.port(); }
|
||||
libtorrent::address address() const
|
||||
{
|
||||
if (is_v6_addr) return address_v6(addr.v6);
|
||||
else return address_v4(addr.v4);
|
||||
}
|
||||
#else
|
||||
void set_ip(tcp::endpoint const& endp)
|
||||
{ addr = endp.address().to_v4(); port = endp.port(); }
|
||||
libtorrent::address address() const
|
||||
{ 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
|
||||
// uploaded and downloaded data to this
|
||||
// peer. It only accounts for what was
|
||||
@ -143,23 +167,9 @@ namespace libtorrent
|
||||
// total amount of upload and download
|
||||
// we'll have to add thes figures with the
|
||||
// statistics from the peer_connection.
|
||||
size_type prev_amount_upload;
|
||||
size_type prev_amount_download;
|
||||
|
||||
// the ip address this peer is or was connected on
|
||||
#if TORRENT_USE_IPV6
|
||||
address addr;
|
||||
#else
|
||||
address_v4 addr;
|
||||
#endif
|
||||
|
||||
// the time when this peer was optimistically unchoked
|
||||
// the last time.
|
||||
libtorrent::ptime last_optimistically_unchoked;
|
||||
|
||||
// the time when the peer connected to us
|
||||
// or disconnected if it isn't connected right now
|
||||
libtorrent::ptime connected;
|
||||
// 48 bits can fit 256 Terabytes
|
||||
boost::uint64_t prev_amount_upload:48;
|
||||
boost::uint64_t prev_amount_download:48;
|
||||
|
||||
// if the peer is connected now, this
|
||||
// will refer to a valid peer_connection
|
||||
@ -175,12 +185,59 @@ namespace libtorrent
|
||||
std::pair<const int, int>* inet_as;
|
||||
#endif
|
||||
|
||||
// the time when this peer was optimistically unchoked
|
||||
// the last time. in seconds since session was created
|
||||
// 16 bits is enough to last for 18.2 hours
|
||||
// when the session time reaches 18 hours, it jumps back by
|
||||
// 9 hours, and all peers' times are updated to be
|
||||
// relative to that new time offset
|
||||
boost::uint16_t last_optimistically_unchoked;
|
||||
|
||||
// the time when the peer connected to us
|
||||
// or disconnected if it isn't connected right now
|
||||
// in number of seconds since session was created
|
||||
boost::uint16_t last_connected;
|
||||
|
||||
// the ip address this peer is or was connected on
|
||||
#if TORRENT_USE_IPV6
|
||||
union
|
||||
{
|
||||
address_v6::bytes_type v6;
|
||||
address_v4::bytes_type v4;
|
||||
} addr;
|
||||
#else
|
||||
address_v4 addr;
|
||||
#endif
|
||||
|
||||
// the port this peer is or was connected on
|
||||
boost::uint16_t port;
|
||||
|
||||
// the number of times this peer has been
|
||||
// part of a piece that failed the hash check
|
||||
boost::uint8_t hashfails;
|
||||
|
||||
// the number of failed connection attempts
|
||||
// this peer has
|
||||
boost::uint8_t failcount;
|
||||
unsigned failcount:5; // [0, 31]
|
||||
|
||||
// incoming peers (that don't advertize their listen port)
|
||||
// will not be considered connectable. Peers that
|
||||
// we have a listen port for will be assumed to be.
|
||||
bool connectable:1;
|
||||
|
||||
// true if this peer currently is unchoked
|
||||
// because of an optimistic unchoke.
|
||||
// when the optimistic unchoke is moved to
|
||||
// another peer, this peer will be choked
|
||||
// if this is true
|
||||
bool optimistically_unchoked:1;
|
||||
|
||||
// this is true if the peer is a seed
|
||||
bool seed:1;
|
||||
|
||||
// the number of times we have allowed a fast
|
||||
// reconnect for this peer.
|
||||
unsigned fast_reconnects:4;
|
||||
|
||||
// for every valid piece we receive where this
|
||||
// peer was one of the participants, we increase
|
||||
@ -188,24 +245,11 @@ namespace libtorrent
|
||||
// where this peer was a participant, we decrease
|
||||
// this value. If it sinks below a threshold, its
|
||||
// considered a bad peer and will be banned.
|
||||
boost::int8_t trust_points;
|
||||
signed trust_points:4; // [-7, 8]
|
||||
|
||||
// a bitmap combining the peer_source flags
|
||||
// from peer_info.
|
||||
boost::uint8_t source;
|
||||
|
||||
// the number of times this peer has been
|
||||
// part of a piece that failed the hash check
|
||||
boost::uint8_t hashfails;
|
||||
|
||||
// type specifies if the connection was incoming
|
||||
// or outgoing. If we ever saw this peer as connectable
|
||||
// it will remain as connectable
|
||||
unsigned type:4;
|
||||
|
||||
// the number of times we have allowed a fast
|
||||
// reconnect for this peer.
|
||||
unsigned fast_reconnects:4;
|
||||
unsigned source:6;
|
||||
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
// Hints encryption support of peer. Only effective
|
||||
@ -219,15 +263,12 @@ namespace libtorrent
|
||||
// encrypted or non-encrypted handshake fails.
|
||||
bool pe_support:1;
|
||||
#endif
|
||||
// true if this peer currently is unchoked
|
||||
// because of an optimistic unchoke.
|
||||
// when the optimistic unchoke is moved to
|
||||
// another peer, this peer will be choked
|
||||
// if this is true
|
||||
bool optimistically_unchoked:1;
|
||||
|
||||
// this is true if the peer is a seed
|
||||
bool seed:1;
|
||||
#if TORRENT_USE_IPV6
|
||||
// this is true if the v6 union member in addr is
|
||||
// the one to use, false if it's the v4 one
|
||||
bool is_v6_addr:1;
|
||||
#endif
|
||||
|
||||
// if this is true, the peer has previously
|
||||
// participated in a piece that failed the piece
|
||||
@ -250,8 +291,10 @@ namespace libtorrent
|
||||
|
||||
int num_peers() const { return m_peers.size(); }
|
||||
|
||||
typedef std::multimap<address, peer>::iterator iterator;
|
||||
typedef std::multimap<address, peer>::const_iterator const_iterator;
|
||||
typedef std::multiset<peer> peers_t;
|
||||
|
||||
typedef peers_t::iterator iterator;
|
||||
typedef peers_t::const_iterator const_iterator;
|
||||
iterator begin_peer() { return m_peers.begin(); }
|
||||
iterator end_peer() { return m_peers.end(); }
|
||||
const_iterator begin_peer() const { return m_peers.begin(); }
|
||||
@ -259,7 +302,7 @@ namespace libtorrent
|
||||
std::pair<iterator, iterator> find_peers(address const& a)
|
||||
{ return m_peers.equal_range(a); }
|
||||
|
||||
bool connect_one_peer();
|
||||
bool connect_one_peer(int session_time);
|
||||
|
||||
bool has_peer(policy::peer const* p) const;
|
||||
|
||||
@ -278,11 +321,11 @@ namespace libtorrent
|
||||
bool compare_peer(policy::peer const& lhs, policy::peer const& rhs
|
||||
, address const& external_ip) const;
|
||||
|
||||
iterator find_connect_candidate();
|
||||
iterator find_connect_candidate(int session_time);
|
||||
|
||||
bool is_connect_candidate(peer const& p, bool finished);
|
||||
|
||||
std::multimap<address, peer> m_peers;
|
||||
peers_t m_peers;
|
||||
|
||||
// since the peer list can grow too large
|
||||
// to scan all of it, start at this iterator
|
||||
|
@ -1980,13 +1980,13 @@ namespace libtorrent
|
||||
: m_id(id), m_pc(pc)
|
||||
{ TORRENT_ASSERT(pc); }
|
||||
|
||||
bool operator()(std::pair<const address, policy::peer> const& p) const
|
||||
bool operator()(policy::peer const& p) const
|
||||
{
|
||||
return p.second.connection != m_pc
|
||||
&& p.second.connection
|
||||
&& p.second.connection->pid() == m_id
|
||||
&& !p.second.connection->pid().is_all_zeros()
|
||||
&& p.second.addr == 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->second.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->second.connection->disconnect("duplicate peer-id, connection closed");
|
||||
i->connection->disconnect("duplicate peer-id, connection closed");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -220,10 +220,14 @@ namespace libtorrent
|
||||
void http_tracker_connection::on_filter(http_connection& c, std::list<tcp::endpoint>& endpoints)
|
||||
{
|
||||
// remove endpoints that are filtered by the IP filter
|
||||
endpoints.erase(std::remove_if(endpoints.begin(), endpoints.end()
|
||||
, boost::bind(&ip_filter::access, boost::ref(m_ses.m_ip_filter)
|
||||
, boost::bind(&tcp::endpoint::address, _1)) == ip_filter::blocked)
|
||||
, endpoints.end());
|
||||
for (std::list<tcp::endpoint>::iterator i = endpoints.begin();
|
||||
i != endpoints.end();)
|
||||
{
|
||||
if (m_ses.m_ip_filter.access(i->address()) == ip_filter::blocked)
|
||||
i = endpoints.erase(i);
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
if (endpoints.empty())
|
||||
fail(-1, "blocked by IP filter");
|
||||
|
@ -686,10 +686,12 @@ namespace libtorrent
|
||||
if (!peer_info_struct() || peer_info_struct()->fast_reconnects > 1)
|
||||
return;
|
||||
m_fast_reconnect = r;
|
||||
peer_info_struct()->connected = time_now()
|
||||
- seconds(m_ses.settings().min_reconnect_time
|
||||
* m_ses.settings().max_failcount);
|
||||
++peer_info_struct()->fast_reconnects;
|
||||
peer_info_struct()->last_connected = m_ses.session_time()
|
||||
- (m_ses.settings().min_reconnect_time * m_ses.settings().max_failcount);
|
||||
int fast_reconnects = peer_info_struct()->fast_reconnects;
|
||||
++fast_reconnects;
|
||||
if (fast_reconnects > 15) fast_reconnects = 15;
|
||||
peer_info_struct()->fast_reconnects = fast_reconnects;
|
||||
}
|
||||
|
||||
void peer_connection::announce_piece(int index)
|
||||
@ -820,14 +822,17 @@ namespace libtorrent
|
||||
if (m_ses.settings().use_parole_mode)
|
||||
peer_info_struct()->on_parole = true;
|
||||
|
||||
++peer_info_struct()->hashfails;
|
||||
boost::int8_t& trust_points = peer_info_struct()->trust_points;
|
||||
int hashfails = peer_info_struct()->hashfails;
|
||||
int trust_points = peer_info_struct()->trust_points;
|
||||
|
||||
// we decrease more than we increase, to keep the
|
||||
// allowed failed/passed ratio low.
|
||||
// TODO: make this limit user settable
|
||||
trust_points -= 2;
|
||||
++hashfails;
|
||||
if (trust_points < -7) trust_points = -7;
|
||||
peer_info_struct()->trust_points = trust_points;
|
||||
if (hashfails > 255) hashfails = 255;
|
||||
peer_info_struct()->hashfails = hashfails;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1328,7 +1333,8 @@ namespace libtorrent
|
||||
// the first two seconds. Since some clients implements
|
||||
// lazy bitfields, these will not be reliable to use
|
||||
// for an estimated peer download rate.
|
||||
if (!peer_info_struct() || time_now() - peer_info_struct()->connected > seconds(2))
|
||||
if (!peer_info_struct()
|
||||
|| m_ses.session_time() - peer_info_struct()->last_connected > 2)
|
||||
{
|
||||
// update bytes downloaded since last timer
|
||||
m_remote_bytes_dled += t->torrent_file().piece_size(index);
|
||||
@ -4390,7 +4396,7 @@ namespace libtorrent
|
||||
policy::const_iterator end = t->get_policy().end_peer();
|
||||
for (; i != end; ++i)
|
||||
{
|
||||
if (&i->second == m_peer_info) break;
|
||||
if (&(*i) == m_peer_info) break;
|
||||
}
|
||||
TORRENT_ASSERT(i != end);
|
||||
}
|
||||
|
284
src/policy.cpp
284
src/policy.cpp
@ -143,8 +143,8 @@ namespace
|
||||
: m_ep(ep)
|
||||
{}
|
||||
|
||||
bool operator()(std::pair<const address, policy::peer> const& p) const
|
||||
{ return p.second.addr == m_ep.address() && p.second.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()(std::pair<const address, policy::peer> const& p) const
|
||||
bool operator()(policy::peer const& p) const
|
||||
{
|
||||
return p.second.connection == &m_conn
|
||||
|| (p.second.ip() == m_conn.remote()
|
||||
&& p.second.type == policy::peer::connectable);
|
||||
return p.connection == &m_conn
|
||||
|| (p.ip() == m_conn.remote()
|
||||
&& p.connectable);
|
||||
}
|
||||
|
||||
peer_connection const& m_conn;
|
||||
@ -346,24 +346,24 @@ namespace libtorrent
|
||||
p = &m_torrent->picker();
|
||||
for (iterator i = m_peers.begin(); i != m_peers.end();)
|
||||
{
|
||||
if ((ses.m_ip_filter.access(i->second.addr) & ip_filter::blocked) == 0)
|
||||
if ((ses.m_ip_filter.access(i->address()) & ip_filter::blocked) == 0)
|
||||
{
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i->second.connection)
|
||||
if (i->connection)
|
||||
{
|
||||
i->second.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->second.addr));
|
||||
TORRENT_ASSERT(i->second.connection == 0
|
||||
|| i->second.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->second.addr));
|
||||
ses.m_alerts.post_alert(peer_blocked_alert(i->address()));
|
||||
}
|
||||
erase_peer(i++);
|
||||
}
|
||||
@ -376,9 +376,9 @@ namespace libtorrent
|
||||
void policy::erase_peer(iterator i)
|
||||
{
|
||||
if (m_torrent->has_picker())
|
||||
m_torrent->picker().clear_peer(&i->second);
|
||||
if (i->second.seed) --m_num_seeds;
|
||||
if (is_connect_candidate(i->second, m_torrent->is_finished()))
|
||||
m_torrent->picker().clear_peer((void*)&(*i));
|
||||
if (i->seed) --m_num_seeds;
|
||||
if (is_connect_candidate(*i, m_torrent->is_finished()))
|
||||
--m_num_connect_candidates;
|
||||
if (m_round_robin == i) ++m_round_robin;
|
||||
|
||||
@ -389,7 +389,7 @@ namespace libtorrent
|
||||
{
|
||||
if (p.connection
|
||||
|| p.banned
|
||||
|| p.type == peer::not_connectable
|
||||
|| !p.connectable
|
||||
|| (p.seed && finished)
|
||||
|| p.failcount >= m_torrent->settings().max_failcount)
|
||||
return false;
|
||||
@ -400,12 +400,11 @@ namespace libtorrent
|
||||
return true;
|
||||
}
|
||||
|
||||
policy::iterator policy::find_connect_candidate()
|
||||
policy::iterator policy::find_connect_candidate(int session_time)
|
||||
{
|
||||
// too expensive
|
||||
// INVARIANT_CHECK;
|
||||
|
||||
ptime now = time_now();
|
||||
iterator candidate = m_peers.end();
|
||||
|
||||
int min_reconnect_time = m_torrent->settings().min_reconnect_time;
|
||||
@ -433,7 +432,7 @@ namespace libtorrent
|
||||
{
|
||||
if (m_round_robin == m_peers.end()) m_round_robin = m_peers.begin();
|
||||
|
||||
peer& pe = m_round_robin->second;
|
||||
peer& pe = (peer&)*m_round_robin;
|
||||
iterator current = m_round_robin;
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
@ -443,7 +442,7 @@ namespace libtorrent
|
||||
// advertise support)
|
||||
if (!pinged && !pe.added_to_dht)
|
||||
{
|
||||
udp::endpoint node(pe.addr, pe.port);
|
||||
udp::endpoint node(pe.address(), pe.port);
|
||||
m_torrent->session().add_dht_node(node);
|
||||
pe.added_to_dht = true;
|
||||
pinged = true;
|
||||
@ -458,8 +457,8 @@ namespace libtorrent
|
||||
// at least that long
|
||||
// don't remove peers that we still can try again
|
||||
if (pe.connection == 0
|
||||
&& pe.connected != min_time()
|
||||
&& (!pe.banned || now - pe.connected > hours(2))
|
||||
&& pe.last_connected != 0
|
||||
&& (!pe.banned || session_time - pe.last_connected > 2 * 60 * 60)
|
||||
&& !is_connect_candidate(pe, finished)
|
||||
&& m_peers.size() >= m_torrent->settings().max_peerlist_size * 0.9)
|
||||
{
|
||||
@ -472,10 +471,11 @@ namespace libtorrent
|
||||
if (!is_connect_candidate(pe, finished)) continue;
|
||||
|
||||
if (candidate != m_peers.end()
|
||||
&& !compare_peer(candidate->second, pe, external_ip)) continue;
|
||||
&& !compare_peer(*candidate, pe, external_ip)) continue;
|
||||
|
||||
if (now - pe.connected <
|
||||
seconds((pe.failcount + 1) * min_reconnect_time))
|
||||
if (pe.last_connected
|
||||
&& session_time - pe.last_connected <
|
||||
(int(pe.failcount) + 1) * min_reconnect_time)
|
||||
continue;
|
||||
|
||||
candidate = current;
|
||||
@ -486,10 +486,10 @@ namespace libtorrent
|
||||
{
|
||||
(*m_torrent->session().m_logger) << time_now_string()
|
||||
<< " *** FOUND CONNECTION CANDIDATE ["
|
||||
" ip: " << candidate->second.ip() <<
|
||||
" d: " << cidr_distance(external_ip, candidate->second.addr) <<
|
||||
" ip: " << candidate->ip() <<
|
||||
" d: " << cidr_distance(external_ip, candidate->address()) <<
|
||||
" external: " << external_ip <<
|
||||
" t: " << total_seconds(time_now() - candidate->second.connected) <<
|
||||
" t: " << (session_time - candidate->last_connected) <<
|
||||
" ]\n";
|
||||
}
|
||||
#endif
|
||||
@ -533,7 +533,7 @@ namespace libtorrent
|
||||
}
|
||||
}
|
||||
|
||||
bool policy::new_connection(peer_connection& c)
|
||||
bool policy::new_connection(peer_connection& c, int session_time)
|
||||
{
|
||||
TORRENT_ASSERT(!c.is_local());
|
||||
|
||||
@ -565,33 +565,36 @@ namespace libtorrent
|
||||
}
|
||||
#endif
|
||||
|
||||
iterator i;
|
||||
iterator iter;
|
||||
peer* i = 0;
|
||||
|
||||
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());
|
||||
i = std::find_if(range.first, range.second, match_peer_endpoint(remote));
|
||||
iter = std::find_if(range.first, range.second, match_peer_endpoint(remote));
|
||||
|
||||
if (i == range.second) i = m_peers.end();
|
||||
if (iter == range.second) iter = m_peers.end();
|
||||
}
|
||||
else
|
||||
{
|
||||
i = m_peers.find(c.remote().address());
|
||||
iter = m_peers.find(c.remote().address());
|
||||
}
|
||||
|
||||
if (i != m_peers.end())
|
||||
if (iter != m_peers.end())
|
||||
{
|
||||
if (i->second.banned)
|
||||
i = (peer*)&(*iter);
|
||||
|
||||
if (i->banned)
|
||||
{
|
||||
c.disconnect("ip address banned, closing");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (i->second.connection != 0)
|
||||
if (i->connection != 0)
|
||||
{
|
||||
boost::shared_ptr<socket_type> other_socket
|
||||
= i->second.connection->get_socket();
|
||||
= i->connection->get_socket();
|
||||
boost::shared_ptr<socket_type> this_socket
|
||||
= c.get_socket();
|
||||
|
||||
@ -610,18 +613,18 @@ namespace libtorrent
|
||||
if (self_connection)
|
||||
{
|
||||
c.disconnect("connected to ourselves", 1);
|
||||
i->second.connection->disconnect("connected to ourselves", 1);
|
||||
i->connection->disconnect("connected to ourselves", 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(i->second.connection != &c);
|
||||
TORRENT_ASSERT(i->connection != &c);
|
||||
// the new connection is a local (outgoing) connection
|
||||
// or the current one is already connected
|
||||
if (ec2)
|
||||
{
|
||||
i->second.connection->disconnect(ec2.message().c_str());
|
||||
i->connection->disconnect(ec2.message().c_str());
|
||||
}
|
||||
else if (!i->second.connection->is_connecting() || c.is_local())
|
||||
else if (!i->connection->is_connecting() || c.is_local())
|
||||
{
|
||||
c.disconnect("duplicate connection, closing");
|
||||
return false;
|
||||
@ -633,7 +636,7 @@ namespace libtorrent
|
||||
" is connecting and this connection is incoming. closing existing "
|
||||
"connection in favour of this one");
|
||||
#endif
|
||||
i->second.connection->disconnect("incoming duplicate connection "
|
||||
i->connection->disconnect("incoming duplicate connection "
|
||||
"with higher priority, closing");
|
||||
}
|
||||
}
|
||||
@ -654,26 +657,28 @@ namespace libtorrent
|
||||
return false;
|
||||
}
|
||||
|
||||
peer p(c.remote(), peer::not_connectable, 0);
|
||||
i = m_peers.insert(std::make_pair(c.remote().address(), p));
|
||||
peer p(c.remote(), false, 0);
|
||||
iter = m_peers.insert(p);
|
||||
i = (peer*)&(*iter);
|
||||
#ifndef TORRENT_DISABLE_GEO_IP
|
||||
int as = ses.as_for_ip(c.remote().address());
|
||||
#ifdef TORRENT_DEBUG
|
||||
i->second.inet_as_num = as;
|
||||
i->inet_as_num = as;
|
||||
#endif
|
||||
i->second.inet_as = ses.lookup_as(as);
|
||||
i->inet_as = ses.lookup_as(as);
|
||||
#endif
|
||||
}
|
||||
|
||||
c.set_peer_info(&i->second);
|
||||
TORRENT_ASSERT(i->second.connection == 0);
|
||||
c.add_stat(i->second.prev_amount_download, i->second.prev_amount_upload);
|
||||
i->second.prev_amount_download = 0;
|
||||
i->second.prev_amount_upload = 0;
|
||||
i->second.connection = &c;
|
||||
TORRENT_ASSERT(i->second.connection);
|
||||
TORRENT_ASSERT(i);
|
||||
c.set_peer_info(i);
|
||||
TORRENT_ASSERT(i->connection == 0);
|
||||
c.add_stat(i->prev_amount_download, i->prev_amount_upload);
|
||||
i->prev_amount_download = 0;
|
||||
i->prev_amount_upload = 0;
|
||||
i->connection = &c;
|
||||
TORRENT_ASSERT(i->connection);
|
||||
if (!c.fast_reconnect())
|
||||
i->second.connected = time_now();
|
||||
i->last_connected = session_time;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -686,13 +691,13 @@ namespace libtorrent
|
||||
|
||||
if (m_torrent->settings().allow_multiple_connections_per_ip)
|
||||
{
|
||||
tcp::endpoint remote(p->addr, port);
|
||||
tcp::endpoint remote(p->address(), port);
|
||||
std::pair<iterator, iterator> range = m_peers.equal_range(remote.address());
|
||||
iterator i = std::find_if(range.first, range.second
|
||||
, match_peer_endpoint(remote));
|
||||
if (i != m_peers.end())
|
||||
{
|
||||
policy::peer& pp = i->second;
|
||||
policy::peer& pp = (peer&)*i;
|
||||
if (pp.connection)
|
||||
{
|
||||
p->connection->disconnect("duplicate connection");
|
||||
@ -703,7 +708,7 @@ namespace libtorrent
|
||||
}
|
||||
else
|
||||
{
|
||||
TORRENT_ASSERT(m_peers.count(p->addr) == 1);
|
||||
TORRENT_ASSERT(m_peers.count(p->address()) == 1);
|
||||
}
|
||||
bool was_conn_cand = is_connect_candidate(*p, m_torrent->is_finished());
|
||||
p->port = port;
|
||||
@ -720,10 +725,10 @@ namespace libtorrent
|
||||
bool policy::has_peer(policy::peer const* p) const
|
||||
{
|
||||
// find p in m_peers
|
||||
for (std::multimap<address, peer>::const_iterator i = m_peers.begin()
|
||||
for (const_iterator i = m_peers.begin()
|
||||
, end(m_peers.end()); i != end; ++i)
|
||||
{
|
||||
if (&i->second == p) return true;
|
||||
if (&(*i) == p) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -748,20 +753,21 @@ namespace libtorrent
|
||||
return 0;
|
||||
}
|
||||
|
||||
iterator i;
|
||||
iterator iter;
|
||||
peer* i = 0;
|
||||
|
||||
if (m_torrent->settings().allow_multiple_connections_per_ip)
|
||||
{
|
||||
std::pair<iterator, iterator> range = m_peers.equal_range(remote.address());
|
||||
i = std::find_if(range.first, range.second, match_peer_endpoint(remote));
|
||||
if (i == range.second) i = m_peers.end();
|
||||
iter = std::find_if(range.first, range.second, match_peer_endpoint(remote));
|
||||
if (iter == range.second) iter = m_peers.end();
|
||||
}
|
||||
else
|
||||
{
|
||||
i = m_peers.find(remote.address());
|
||||
iter = m_peers.find(remote.address());
|
||||
}
|
||||
|
||||
if (i == m_peers.end())
|
||||
if (iter == m_peers.end())
|
||||
{
|
||||
// if the IP is blocked, don't add it
|
||||
if (ses.m_ip_filter.access(remote.address()) & ip_filter::blocked)
|
||||
@ -778,54 +784,57 @@ namespace libtorrent
|
||||
|
||||
// we don't have any info about this peer.
|
||||
// add a new entry
|
||||
i = m_peers.insert(std::make_pair(remote.address()
|
||||
, peer(remote, peer::connectable, src)));
|
||||
iter = m_peers.insert(peer(remote, true, src));
|
||||
i = (peer*)&(*iter);
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
if (flags & 0x01) i->second.pe_support = true;
|
||||
if (flags & 0x01) i->pe_support = true;
|
||||
#endif
|
||||
if (flags & 0x02)
|
||||
{
|
||||
i->second.seed = true;
|
||||
i->seed = true;
|
||||
++m_num_seeds;
|
||||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_GEO_IP
|
||||
int as = ses.as_for_ip(remote.address());
|
||||
#ifdef TORRENT_DEBUG
|
||||
i->second.inet_as_num = as;
|
||||
i->inet_as_num = as;
|
||||
#endif
|
||||
i->second.inet_as = ses.lookup_as(as);
|
||||
i->inet_as = ses.lookup_as(as);
|
||||
#endif
|
||||
if (is_connect_candidate(i->second, m_torrent->is_finished()))
|
||||
if (is_connect_candidate(*i, m_torrent->is_finished()))
|
||||
++m_num_connect_candidates;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool was_conn_cand = is_connect_candidate(i->second, m_torrent->is_finished());
|
||||
i = (peer*)&(*iter);
|
||||
|
||||
i->second.type = peer::connectable;
|
||||
bool was_conn_cand = is_connect_candidate(*i, m_torrent->is_finished());
|
||||
|
||||
i->second.set_ip(remote);
|
||||
i->second.source |= src;
|
||||
i->connectable = true;
|
||||
|
||||
TORRENT_ASSERT(i->address() == remote.address());
|
||||
i->port = remote.port();
|
||||
i->source |= src;
|
||||
|
||||
// if this peer has failed before, decrease the
|
||||
// counter to allow it another try, since somebody
|
||||
// else is appearantly able to connect to it
|
||||
// only trust this if it comes from the tracker
|
||||
if (i->second.failcount > 0 && src == peer_info::tracker)
|
||||
--i->second.failcount;
|
||||
if (i->failcount > 0 && src == peer_info::tracker)
|
||||
--i->failcount;
|
||||
|
||||
// if we're connected to this peer
|
||||
// we already know if it's a seed or not
|
||||
// so we don't have to trust this source
|
||||
if ((flags & 0x02) && !i->second.connection)
|
||||
if ((flags & 0x02) && !i->connection)
|
||||
{
|
||||
if (!i->second.seed) ++m_num_seeds;
|
||||
i->second.seed = true;
|
||||
if (!i->seed) ++m_num_seeds;
|
||||
i->seed = true;
|
||||
}
|
||||
|
||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
|
||||
if (i->second.connection)
|
||||
if (i->connection)
|
||||
{
|
||||
// this means we're already connected
|
||||
// to this peer. don't connect to
|
||||
@ -833,24 +842,24 @@ namespace libtorrent
|
||||
|
||||
error_code ec;
|
||||
char hex_pid[41];
|
||||
to_hex((char*)&i->second.connection->pid()[0], 20, hex_pid);
|
||||
to_hex((char*)&i->connection->pid()[0], 20, hex_pid);
|
||||
char msg[200];
|
||||
snprintf(msg, 200, "already connected to peer: %s %s"
|
||||
, print_endpoint(remote).c_str(), hex_pid);
|
||||
m_torrent->debug_log(msg);
|
||||
|
||||
TORRENT_ASSERT(i->second.connection->associated_torrent().lock().get() == m_torrent);
|
||||
TORRENT_ASSERT(i->connection->associated_torrent().lock().get() == m_torrent);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (was_conn_cand != is_connect_candidate(i->second, m_torrent->is_finished()))
|
||||
if (was_conn_cand != is_connect_candidate(*i, m_torrent->is_finished()))
|
||||
{
|
||||
m_num_connect_candidates += was_conn_cand ? -1 : 1;
|
||||
if (m_num_connect_candidates < 0) m_num_connect_candidates = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return &i->second;
|
||||
return i;
|
||||
}
|
||||
|
||||
// this is called when we are unchoked by a peer
|
||||
@ -872,8 +881,7 @@ namespace libtorrent
|
||||
// INVARIANT_CHECK;
|
||||
|
||||
TORRENT_ASSERT(std::find_if(m_peers.begin(), m_peers.end()
|
||||
, boost::bind<bool>(std::equal_to<peer_connection*>(), bind(&peer::connection
|
||||
, bind(&iterator::value_type::second, _1)), &c)) != m_peers.end());
|
||||
, bind(&peer::connection, _1) == &c) != m_peers.end());
|
||||
|
||||
aux::session_impl& ses = m_torrent->session();
|
||||
|
||||
@ -972,33 +980,35 @@ namespace libtorrent
|
||||
--m_num_unchoked;
|
||||
}
|
||||
*/
|
||||
bool policy::connect_one_peer()
|
||||
bool policy::connect_one_peer(int session_time)
|
||||
{
|
||||
// INVARIANT_CHECK;
|
||||
|
||||
TORRENT_ASSERT(m_torrent->want_more_peers());
|
||||
|
||||
iterator p = find_connect_candidate();
|
||||
if (p == m_peers.end()) return false;
|
||||
iterator i = find_connect_candidate(session_time);
|
||||
if (i == m_peers.end()) return false;
|
||||
peer& p = (peer&)*i;
|
||||
|
||||
TORRENT_ASSERT(!p->second.banned);
|
||||
TORRENT_ASSERT(!p->second.connection);
|
||||
TORRENT_ASSERT(p->second.type == peer::connectable);
|
||||
TORRENT_ASSERT(!p.banned);
|
||||
TORRENT_ASSERT(!p.connection);
|
||||
TORRENT_ASSERT(p.connectable);
|
||||
|
||||
TORRENT_ASSERT(is_connect_candidate(p->second, m_torrent->is_finished()));
|
||||
if (!m_torrent->connect_to_peer(&p->second))
|
||||
TORRENT_ASSERT(is_connect_candidate(p, m_torrent->is_finished()));
|
||||
if (!m_torrent->connect_to_peer(&p))
|
||||
{
|
||||
++p->second.failcount;
|
||||
// failcount is a 5 bit value
|
||||
if (p.failcount < 31) ++p.failcount;
|
||||
return false;
|
||||
}
|
||||
TORRENT_ASSERT(p->second.connection);
|
||||
TORRENT_ASSERT(!is_connect_candidate(p->second, m_torrent->is_finished()));
|
||||
TORRENT_ASSERT(p.connection);
|
||||
TORRENT_ASSERT(!is_connect_candidate(p, m_torrent->is_finished()));
|
||||
--m_num_connect_candidates;
|
||||
return true;
|
||||
}
|
||||
|
||||
// this is called whenever a peer connection is closed
|
||||
void policy::connection_closed(const peer_connection& c)
|
||||
void policy::connection_closed(const peer_connection& c, int session_time)
|
||||
{
|
||||
// too expensive
|
||||
// INVARIANT_CHECK;
|
||||
@ -1023,12 +1033,12 @@ namespace libtorrent
|
||||
// update the timestamp, and it will remain
|
||||
// the time when we initiated the connection.
|
||||
if (!c.fast_reconnect())
|
||||
p->connected = time_now();
|
||||
p->last_connected = session_time;
|
||||
|
||||
if (c.failed())
|
||||
{
|
||||
++p->failcount;
|
||||
// p->connected = time_now();
|
||||
// failcount is a 5 bit value
|
||||
if (p->failcount < 31) ++p->failcount;
|
||||
}
|
||||
|
||||
if (is_connect_candidate(*p, m_torrent->is_finished()))
|
||||
@ -1092,19 +1102,18 @@ namespace libtorrent
|
||||
for (const_iterator i = m_peers.begin();
|
||||
i != m_peers.end(); ++i)
|
||||
{
|
||||
peer const& p = i->second;
|
||||
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.addr) == 1);
|
||||
TORRENT_ASSERT(m_peers.count(p.address()) == 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
TORRENT_ASSERT(unique_test.count(p.ip()) == 0);
|
||||
unique_test.insert(p.ip());
|
||||
TORRENT_ASSERT(i->first == p.addr);
|
||||
// TORRENT_ASSERT(p.connection == 0 || p.ip() == p.connection->remote());
|
||||
}
|
||||
++total_connections;
|
||||
@ -1181,40 +1190,42 @@ namespace libtorrent
|
||||
}
|
||||
#endif
|
||||
|
||||
policy::peer::peer(const tcp::endpoint& ip_, peer::connection_type t, int src)
|
||||
policy::peer::peer(const tcp::endpoint& ip_, bool conn, int src)
|
||||
: prev_amount_upload(0)
|
||||
, prev_amount_download(0)
|
||||
#if TORRENT_USE_IPV6
|
||||
, addr(ip_.address())
|
||||
#else
|
||||
, addr(ip_.address().to_v4())
|
||||
#endif
|
||||
, last_optimistically_unchoked(min_time())
|
||||
, connected(min_time())
|
||||
, connection(0)
|
||||
#ifndef TORRENT_DISABLE_GEO_IP
|
||||
, inet_as(0)
|
||||
#endif
|
||||
, last_optimistically_unchoked(0)
|
||||
, last_connected(0)
|
||||
#if !TORRENT_USE_IPV6
|
||||
, addr(ip_.address().to_v4())
|
||||
#endif
|
||||
, port(ip_.port())
|
||||
, hashfails(0)
|
||||
, failcount(0)
|
||||
, connectable(conn)
|
||||
, optimistically_unchoked(false)
|
||||
, seed(false)
|
||||
, fast_reconnects(0)
|
||||
, trust_points(0)
|
||||
, source(src)
|
||||
, hashfails(0)
|
||||
, type(t)
|
||||
, fast_reconnects(0)
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
, pe_support(true)
|
||||
#endif
|
||||
, optimistically_unchoked(false)
|
||||
, seed(false)
|
||||
#if TORRENT_USE_IPV6
|
||||
, is_v6_addr(false)
|
||||
#endif
|
||||
, on_parole(false)
|
||||
, banned(false)
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
, added_to_dht(false)
|
||||
#endif
|
||||
{
|
||||
set_ip(ip_);
|
||||
|
||||
TORRENT_ASSERT((src & 0xff) == src);
|
||||
TORRENT_ASSERT(connected < time_now());
|
||||
}
|
||||
|
||||
size_type policy::peer::total_download() const
|
||||
@ -1230,6 +1241,27 @@ namespace libtorrent
|
||||
}
|
||||
}
|
||||
|
||||
void policy::peer::set_ip(tcp::endpoint const& endp)
|
||||
{
|
||||
#if TORRENT_USE_IPV6
|
||||
if (endp.address().is_v6())
|
||||
{
|
||||
is_v6_addr = true;
|
||||
addr.v6 = endp.address().to_v6().to_bytes();
|
||||
}
|
||||
else
|
||||
{
|
||||
is_v6_addr = false;
|
||||
addr.v4 = endp.address().to_v4().to_bytes();
|
||||
}
|
||||
#else
|
||||
TORRENT_ASSERT(endp.address().is_v4());
|
||||
addr = endp.address().to_v4();
|
||||
#endif
|
||||
|
||||
port = endp.port();
|
||||
}
|
||||
|
||||
size_type policy::peer::total_upload() const
|
||||
{
|
||||
if (connection != 0)
|
||||
@ -1252,12 +1284,12 @@ namespace libtorrent
|
||||
return lhs.failcount < rhs.failcount;
|
||||
|
||||
// Local peers should always be tried first
|
||||
bool lhs_local = is_local(lhs.addr);
|
||||
bool rhs_local = is_local(rhs.addr);
|
||||
bool lhs_local = is_local(lhs.address());
|
||||
bool rhs_local = is_local(rhs.address());
|
||||
if (lhs_local != rhs_local) return lhs_local > rhs_local;
|
||||
|
||||
if (lhs.connected != rhs.connected)
|
||||
return lhs.connected < rhs.connected;
|
||||
if (lhs.last_connected != rhs.last_connected)
|
||||
return lhs.last_connected < rhs.last_connected;
|
||||
|
||||
#ifndef TORRENT_DISABLE_GEO_IP
|
||||
// don't bias fast peers when seeding
|
||||
@ -1268,8 +1300,8 @@ namespace libtorrent
|
||||
if (lhs_as != rhs_as) return lhs_as > rhs_as;
|
||||
}
|
||||
#endif
|
||||
int lhs_distance = cidr_distance(external_ip, lhs.addr);
|
||||
int rhs_distance = cidr_distance(external_ip, rhs.addr);
|
||||
int lhs_distance = cidr_distance(external_ip, lhs.address());
|
||||
int rhs_distance = cidr_distance(external_ip, rhs.address());
|
||||
if (lhs_distance < rhs_distance) return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -177,9 +177,10 @@ namespace aux {
|
||||
, m_disconnect_time_scaler(90)
|
||||
, m_auto_scrape_time_scaler(180)
|
||||
, m_incoming_connection(false)
|
||||
, m_last_tick(time_now())
|
||||
, m_last_second_tick(m_last_tick)
|
||||
, m_last_choke(m_last_tick)
|
||||
, m_created(time_now())
|
||||
, m_last_tick(m_created)
|
||||
, m_last_second_tick(m_created)
|
||||
, m_last_choke(m_created)
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
, m_dht_same_port(true)
|
||||
, m_external_udp_port(0)
|
||||
@ -233,16 +234,31 @@ namespace aux {
|
||||
m_logger = create_log("main_session", listen_port(), false);
|
||||
(*m_logger) << time_now_string() << "\n";
|
||||
|
||||
(*m_logger) << "sizeof(torrent): " << sizeof(torrent) << "\n";
|
||||
(*m_logger) << "sizeof(peer_connection): " << sizeof(peer_connection) << "\n";
|
||||
(*m_logger) << "sizeof(bt_peer_connection): " << sizeof(bt_peer_connection) << "\n";
|
||||
(*m_logger) << "sizeof(policy::peer): " << sizeof(policy::peer) << "\n";
|
||||
(*m_logger) << "sizeof(tcp::endpoint): " << sizeof(tcp::endpoint) << "\n";
|
||||
(*m_logger) << "sizeof(address): " << sizeof(address) << "\n";
|
||||
(*m_logger) << "sizeof(address_v4): " << sizeof(address_v4) << "\n";
|
||||
(*m_logger) << "sizeof(address_v6): " << sizeof(address_v6) << "\n";
|
||||
(*m_logger) << "sizeof(void*): " << sizeof(void*) << "\n";
|
||||
(*m_logger) << "sizeof(node_entry): " << sizeof(dht::node_entry) << "\n";
|
||||
#define PRINT_SIZEOF(x) (*m_logger) << "sizeof(" #x "): " << sizeof(x) << "\n";
|
||||
#define PRINT_OFFSETOF(x, y) (*m_logger) << " offsetof(" #x "," #y "): " << offsetof(x, y) << "\n";
|
||||
|
||||
PRINT_SIZEOF(torrent)
|
||||
PRINT_SIZEOF(peer_connection)
|
||||
PRINT_SIZEOF(bt_peer_connection)
|
||||
PRINT_SIZEOF(address)
|
||||
PRINT_SIZEOF(address_v4)
|
||||
PRINT_SIZEOF(address_v6)
|
||||
PRINT_SIZEOF(address_v4::bytes_type)
|
||||
PRINT_SIZEOF(address_v6::bytes_type)
|
||||
PRINT_SIZEOF(void*)
|
||||
PRINT_SIZEOF(dht::node_entry)
|
||||
|
||||
PRINT_SIZEOF(policy::peer)
|
||||
PRINT_OFFSETOF(policy::peer, connection)
|
||||
PRINT_OFFSETOF(policy::peer, last_optimistically_unchoked)
|
||||
PRINT_OFFSETOF(policy::peer, last_connected)
|
||||
PRINT_OFFSETOF(policy::peer, addr)
|
||||
PRINT_OFFSETOF(policy::peer, port)
|
||||
PRINT_OFFSETOF(policy::peer, hashfails)
|
||||
|
||||
#undef PRINT_OFFSETOF
|
||||
#undef PRINT_SIZEOF
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef TORRENT_STATS
|
||||
@ -280,8 +296,7 @@ namespace aux {
|
||||
}
|
||||
|
||||
m_timer.expires_from_now(milliseconds(100), ec);
|
||||
m_timer.async_wait(
|
||||
bind(&session_impl::on_tick, this, _1));
|
||||
m_timer.async_wait(bind(&session_impl::on_tick, this, _1));
|
||||
|
||||
m_thread.reset(new boost::thread(boost::ref(*this)));
|
||||
}
|
||||
@ -1099,7 +1114,7 @@ namespace aux {
|
||||
if (e)
|
||||
{
|
||||
#if defined TORRENT_LOGGING
|
||||
(*m_logger) << "*** SECOND TIMER FAILED " << e.message() << "\n";
|
||||
(*m_logger) << "*** TICK TIMER FAILED " << e.message() << "\n";
|
||||
#endif
|
||||
::abort();
|
||||
return;
|
||||
@ -1109,20 +1124,53 @@ namespace aux {
|
||||
|
||||
error_code ec;
|
||||
m_timer.expires_at(now + milliseconds(100), ec);
|
||||
m_timer.async_wait(
|
||||
bind(&session_impl::on_tick, this, _1));
|
||||
m_timer.async_wait(bind(&session_impl::on_tick, this, _1));
|
||||
|
||||
m_download_rate.update_quotas(now - m_last_tick);
|
||||
m_upload_rate.update_quotas(now - m_last_tick);
|
||||
|
||||
m_last_tick = now;
|
||||
|
||||
// only tick the rest once every
|
||||
// only tick the following once per second
|
||||
if (now - m_last_second_tick < seconds(1)) return;
|
||||
|
||||
float tick_interval = total_microseconds(now - m_last_second_tick) / 1000000.f;
|
||||
m_last_second_tick = now;
|
||||
|
||||
int session_time = total_seconds(now - m_created);
|
||||
if (session_time > 65000)
|
||||
{
|
||||
// we're getting close to the point where our timestamps
|
||||
// in policy::peer are wrapping. We need to step all counters back
|
||||
// four hours. This means that any timestamp that refers to a time
|
||||
// more than 18.2 - 4 = 14.2 hours ago, will be incremented to refer to
|
||||
// 14.2 hours ago.
|
||||
|
||||
m_created += hours(4);
|
||||
|
||||
const int four_hours = 60 * 60 * 4;
|
||||
for (torrent_map::iterator i = m_torrents.begin()
|
||||
, end(m_torrents.end()); i != end; ++i)
|
||||
{
|
||||
policy& p = i->second->get_policy();
|
||||
for (policy::iterator j = p.begin_peer()
|
||||
, end(p.end_peer()); j != end; ++j)
|
||||
{
|
||||
policy::peer* pe = (policy::peer*)&(*j);
|
||||
|
||||
if (pe->last_optimistically_unchoked < four_hours)
|
||||
pe->last_optimistically_unchoked = 0;
|
||||
else
|
||||
pe->last_optimistically_unchoked -= four_hours;
|
||||
|
||||
if (pe->last_connected < four_hours)
|
||||
pe->last_connected = 0;
|
||||
else
|
||||
pe->last_connected -= four_hours;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TORRENT_STATS
|
||||
++m_second_counter;
|
||||
int downloading_torrents = 0;
|
||||
@ -1611,7 +1659,7 @@ namespace aux {
|
||||
// unchoked
|
||||
connection_map::iterator current_optimistic_unchoke = m_connections.end();
|
||||
connection_map::iterator optimistic_unchoke_candidate = m_connections.end();
|
||||
ptime last_unchoke = max_time();
|
||||
boost::uint32_t last_unchoke = UINT_MAX;
|
||||
|
||||
for (connection_map::iterator i = m_connections.begin()
|
||||
, end(m_connections.end()); i != end; ++i)
|
||||
|
@ -142,7 +142,7 @@ namespace libtorrent { namespace
|
||||
if (*i != 0)
|
||||
{
|
||||
m_torrent.filesystem().async_read(r, bind(&smart_ban_plugin::on_read_failed_block
|
||||
, shared_from_this(), pb, ((policy::peer*)*i)->addr, _1, _2));
|
||||
, shared_from_this(), pb, ((policy::peer*)*i)->address(), _1, _2));
|
||||
}
|
||||
|
||||
r.start += 16*1024;
|
||||
@ -182,7 +182,7 @@ namespace libtorrent { namespace
|
||||
// there is no peer with this address anymore
|
||||
if (range.first == range.second) return;
|
||||
|
||||
policy::peer* p = &range.first->second;
|
||||
policy::peer* p = (policy::peer*)&(*range.first);
|
||||
block_entry e = {p, crc.final()};
|
||||
|
||||
std::map<piece_block, block_entry>::iterator i = m_block_crc.lower_bound(b);
|
||||
|
@ -1637,9 +1637,10 @@ namespace libtorrent
|
||||
policy::peer* p = static_cast<policy::peer*>(*i);
|
||||
if (p == 0) continue;
|
||||
p->on_parole = false;
|
||||
++p->trust_points;
|
||||
// TODO: make this limit user settable
|
||||
if (p->trust_points > 20) p->trust_points = 20;
|
||||
int trust_points = p->trust_points;
|
||||
++trust_points;
|
||||
if (trust_points > 8) trust_points = 8;
|
||||
p->trust_points = trust_points;
|
||||
if (p->connection) p->connection->received_valid_data(index);
|
||||
}
|
||||
|
||||
@ -1765,7 +1766,6 @@ namespace libtorrent
|
||||
|
||||
// either, we have received too many failed hashes
|
||||
// or this was the only peer that sent us this piece.
|
||||
// TODO: make this a changable setting
|
||||
if (p->trust_points <= -7
|
||||
|| peers.size() == 1)
|
||||
{
|
||||
@ -2597,7 +2597,7 @@ namespace libtorrent
|
||||
m_ses.m_optimistic_unchoke_time_scaler = 0;
|
||||
}
|
||||
|
||||
m_policy.connection_closed(*p);
|
||||
m_policy.connection_closed(*p, m_ses.session_time());
|
||||
p->set_peer_info(0);
|
||||
TORRENT_ASSERT(i != m_connections.end());
|
||||
m_connections.erase(i);
|
||||
@ -2845,7 +2845,8 @@ namespace libtorrent
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
{
|
||||
boost::shared_ptr<peer_plugin> pp((*i)->new_connection(c.get()));
|
||||
boost::shared_ptr<peer_plugin>
|
||||
pp((*i)->new_connection(c.get()));
|
||||
if (pp) c->add_extension(pp);
|
||||
}
|
||||
#endif
|
||||
@ -3315,18 +3316,20 @@ namespace libtorrent
|
||||
entry::list_type& peer_list = ret["peers"].list();
|
||||
entry::list_type& banned_peer_list = ret["banned_peers"].list();
|
||||
|
||||
int max_failcount = m_ses.m_settings.max_failcount;
|
||||
// failcount is a 5 bit value
|
||||
int max_failcount = (std::min)(m_ses.m_settings.max_failcount, 31);
|
||||
|
||||
for (policy::const_iterator i = m_policy.begin_peer()
|
||||
, end(m_policy.end_peer()); i != end; ++i)
|
||||
{
|
||||
error_code ec;
|
||||
if (i->second.banned)
|
||||
policy::peer const& p = *i;
|
||||
if (p.banned)
|
||||
{
|
||||
entry peer(entry::dictionary_t);
|
||||
peer["ip"] = i->second.addr.to_string(ec);
|
||||
peer["ip"] = p.address().to_string(ec);
|
||||
if (ec) continue;
|
||||
peer["port"] = i->second.port;
|
||||
peer["port"] = p.port;
|
||||
banned_peer_list.push_back(peer);
|
||||
continue;
|
||||
}
|
||||
@ -3337,15 +3340,15 @@ 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 (i->second.type == policy::peer::not_connectable) continue;
|
||||
if (!p.connectable) continue;
|
||||
|
||||
// don't save peers that doesn't work
|
||||
if (i->second.failcount >= max_failcount) continue;
|
||||
if (p.failcount >= max_failcount) continue;
|
||||
|
||||
entry peer(entry::dictionary_t);
|
||||
peer["ip"] = i->second.addr.to_string(ec);
|
||||
peer["ip"] = p.address().to_string(ec);
|
||||
if (ec) continue;
|
||||
peer["port"] = i->second.port;
|
||||
peer["port"] = p.port;
|
||||
peer_list.push_back(peer);
|
||||
}
|
||||
|
||||
@ -3385,10 +3388,10 @@ namespace libtorrent
|
||||
i != m_policy.end_peer(); ++i)
|
||||
{
|
||||
peer_list_entry e;
|
||||
e.ip = i->second.ip();
|
||||
e.flags = i->second.banned ? peer_list_entry::banned : 0;
|
||||
e.failcount = i->second.failcount;
|
||||
e.source = i->second.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);
|
||||
}
|
||||
}
|
||||
@ -3495,7 +3498,7 @@ namespace libtorrent
|
||||
TORRENT_ASSERT(peerinfo);
|
||||
TORRENT_ASSERT(peerinfo->connection == 0);
|
||||
|
||||
peerinfo->connected = time_now();
|
||||
peerinfo->last_connected = m_ses.session_time();
|
||||
#ifdef TORRENT_DEBUG
|
||||
// this asserts that we don't have duplicates in the policy's peer list
|
||||
peer_iterator i_ = std::find_if(m_connections.begin(), m_connections.end()
|
||||
@ -3508,7 +3511,7 @@ namespace libtorrent
|
||||
TORRENT_ASSERT(m_ses.num_connections() < m_ses.max_connections());
|
||||
|
||||
tcp::endpoint a(peerinfo->ip());
|
||||
TORRENT_ASSERT((m_ses.m_ip_filter.access(peerinfo->addr) & ip_filter::blocked) == 0);
|
||||
TORRENT_ASSERT((m_ses.m_ip_filter.access(peerinfo->address()) & ip_filter::blocked) == 0);
|
||||
|
||||
boost::shared_ptr<socket_type> s(new socket_type(m_ses.m_io_service));
|
||||
|
||||
@ -3669,7 +3672,7 @@ namespace libtorrent
|
||||
if (pp) p->add_extension(pp);
|
||||
}
|
||||
#endif
|
||||
if (!m_policy.new_connection(*p))
|
||||
if (!m_policy.new_connection(*p, m_ses.session_time()))
|
||||
return false;
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
}
|
||||
@ -4167,10 +4170,18 @@ namespace libtorrent
|
||||
}
|
||||
|
||||
#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS
|
||||
for (policy::const_iterator i = m_policy.begin_peer()
|
||||
, end(m_policy.end_peer()); i != end; ++i)
|
||||
// make sure we haven't modified the peer object
|
||||
// in a way that breaks the sort order
|
||||
if (m_policy.begin_peer() != m_policy.end_peer())
|
||||
{
|
||||
TORRENT_ASSERT(i->second.addr == i->first);
|
||||
policy::const_iterator i = m_policy.begin_peer();
|
||||
policy::const_iterator prev = i++;
|
||||
policy::const_iterator end(m_policy.end_peer());
|
||||
for (; i != end; ++i, ++prev)
|
||||
{
|
||||
// this means <= but only using the < operator
|
||||
TORRENT_ASSERT(*prev < *i || !(*i < *prev));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -4993,7 +5004,7 @@ namespace libtorrent
|
||||
TORRENT_ASSERT(want_more_peers());
|
||||
if (m_deficit_counter < 100) return false;
|
||||
m_deficit_counter -= 100;
|
||||
bool ret = m_policy.connect_one_peer();
|
||||
bool ret = m_policy.connect_one_peer(m_ses.session_time());
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -225,7 +225,7 @@ int test_main()
|
||||
int tmp3;
|
||||
tcp::endpoint endp;
|
||||
piece_picker::downloading_piece st;
|
||||
policy::peer peer_struct(endp, policy::peer::connectable, 0);
|
||||
policy::peer peer_struct(endp, true, 0);
|
||||
std::vector<piece_block> picked;
|
||||
boost::shared_ptr<piece_picker> p;
|
||||
const std::vector<int> empty_vector;
|
||||
|
Loading…
x
Reference in New Issue
Block a user