removed dht ping from peer_from_tracker. in trunk: implemented a rate limited DHT ping (once a second per torrent) and space optimized the peer structure

This commit is contained in:
Arvid Norberg
2008-04-01 17:38:19 +00:00
parent 1511f2f59b
commit 4161be867e
4 changed files with 126 additions and 85 deletions

View File

@@ -139,43 +139,9 @@ namespace libtorrent
tcp::endpoint ip; tcp::endpoint ip;
connection_type type; connection_type type;
#ifndef TORRENT_DISABLE_ENCRYPTION // the number of failed connection attempts
// Hints encryption support of peer. Only effective for // this peer has
// and when the outgoing encryption policy allows both boost::uint8_t failcount;
// encrypted and non encrypted connections
// (pe_settings::out_enc_policy == enabled). The initial
// state of this flag determines the initial connection
// attempt type (true = encrypted, false = standard).
// This will be toggled everytime either an encrypted or
// non-encrypted handshake fails.
bool pe_support;
#endif
// the number of failed connection attempts this peer has
int failcount;
// the number of times this peer has been
// part of a piece that failed the hash check
int hashfails;
// this is true if the peer is a seed
bool seed;
int fast_reconnects;
// 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;
// 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;
// for every valid piece we receive where this // for every valid piece we receive where this
// peer was one of the participants, we increase // peer was one of the participants, we increase
@@ -183,15 +149,63 @@ namespace libtorrent
// where this peer was a participant, we decrease // where this peer was a participant, we decrease
// this value. If it sinks below a threshold, its // this value. If it sinks below a threshold, its
// considered a bad peer and will be banned. // considered a bad peer and will be banned.
int trust_points; boost::int8_t trust_points;
// if this is true, the peer has previously participated // a bitmap combining the peer_source flags
// in a piece that failed the piece hash check. This will // from peer_info.
// put the peer on parole and only request entire pieces. boost::uint8_t source;
// if a piece pass that was partially requested from this
// peer it will leave parole mode and continue download // the number of times this peer has been
// part of a piece that failed the hash check
boost::uint8_t hashfails;
// the number of times we have allowed a fast
// reconnect for this peer.
boost::uint8_t fast_reconnects:4;
#ifndef TORRENT_DISABLE_ENCRYPTION
// Hints encryption support of peer. Only effective
// for and when the outgoing encryption policy
// allows both encrypted and non encrypted
// connections (pe_settings::out_enc_policy
// == enabled). The initial state of this flag
// determines the initial connection attempt
// type (true = encrypted, false = standard).
// This will be toggled everytime either an
// 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 this is true, the peer has previously
// participated in a piece that failed the piece
// hash check. This will put the peer on parole
// and only request entire pieces. If a piece pass
// that was partially requested from this peer it
// will leave parole mode and continue download
// pieces as normal peers. // pieces as normal peers.
bool on_parole; bool on_parole:1;
// is set to true if this peer has been banned
bool banned:1;
#ifndef TORRENT_DISABLE_DHT
// this is set to true when this peer as been
// pinged by the DHT
bool added_to_dht:1;
#endif
// if the peer is connected now, this
// will refer to a valid peer_connection
peer_connection* connection;
// this is the accumulated amount of // this is the accumulated amount of
// uploaded and downloaded data to this // uploaded and downloaded data to this
@@ -205,16 +219,13 @@ namespace libtorrent
size_type prev_amount_upload; size_type prev_amount_upload;
size_type prev_amount_download; size_type prev_amount_download;
// is set to true if this peer has been banned // the time when this peer was optimistically unchoked
bool banned; // the last time.
libtorrent::ptime last_optimistically_unchoked;
// a bitmap combining the peer_source flags // the time when the peer connected to us
// from peer_info. // or disconnected if it isn't connected right now
int source; libtorrent::ptime connected;
// if the peer is connected now, this
// will refer to a valid peer_connection
peer_connection* connection;
}; };
int num_peers() const { return m_peers.size(); } int num_peers() const { return m_peers.size(); }
@@ -231,6 +242,7 @@ namespace libtorrent
bool has_peer(policy::peer const* p) const; bool has_peer(policy::peer const* p) const;
int num_seeds() const { return m_num_seeds; }
int num_connect_candidates() const { return m_num_connect_candidates; } int num_connect_candidates() const { return m_num_connect_candidates; }
void recalculate_connect_candidates() void recalculate_connect_candidates()
{ {
@@ -260,6 +272,9 @@ namespace libtorrent
// have the connectable state (we have a listen // have the connectable state (we have a listen
// port for them). // port for them).
int m_num_connect_candidates; int m_num_connect_candidates;
// the number of seeds in the peer list
int m_num_seeds;
}; };
} }

View File

@@ -456,12 +456,13 @@ namespace libtorrent
void peer_connection::fast_reconnect(bool r) void peer_connection::fast_reconnect(bool r)
{ {
if (peer_info_struct() && peer_info_struct()->fast_reconnects > 1) return; if (!peer_info_struct() || peer_info_struct()->fast_reconnects > 1)
return;
m_fast_reconnect = r; m_fast_reconnect = r;
peer_info_struct()->connected = time_now() peer_info_struct()->connected = time_now()
- seconds(m_ses.settings().min_reconnect_time - seconds(m_ses.settings().min_reconnect_time
* m_ses.settings().max_failcount); * m_ses.settings().max_failcount);
if (peer_info_struct()) ++peer_info_struct()->fast_reconnects; ++peer_info_struct()->fast_reconnects;
} }
void peer_connection::announce_piece(int index) void peer_connection::announce_piece(int index)
@@ -565,7 +566,7 @@ namespace libtorrent
{ {
peer_info_struct()->on_parole = true; peer_info_struct()->on_parole = true;
++peer_info_struct()->hashfails; ++peer_info_struct()->hashfails;
int& trust_points = peer_info_struct()->trust_points; boost::int8_t& trust_points = peer_info_struct()->trust_points;
// we decrease more than we increase, to keep the // we decrease more than we increase, to keep the
// allowed failed/passed ratio low. // allowed failed/passed ratio low.

View File

@@ -385,6 +385,7 @@ namespace libtorrent
} }
} }
if (p) p->clear_peer(&i->second); if (p) p->clear_peer(&i->second);
if (i->second.seed) --m_num_seeds;
m_peers.erase(i++); m_peers.erase(i++);
} }
} }
@@ -471,8 +472,10 @@ namespace libtorrent
} }
int connect_candidates = 0; int connect_candidates = 0;
int seeds = 0;
for (iterator i = m_peers.begin(); i != m_peers.end(); ++i) for (iterator i = m_peers.begin(); i != m_peers.end(); ++i)
{ {
if (i->second.seed) ++seeds;
if (!is_connect_candidate(i->second, finished)) continue; if (!is_connect_candidate(i->second, finished)) continue;
++connect_candidates; ++connect_candidates;
@@ -504,6 +507,7 @@ namespace libtorrent
} }
m_num_connect_candidates = connect_candidates; m_num_connect_candidates = connect_candidates;
m_num_seeds = seeds;
TORRENT_ASSERT(min_connect_time <= now); TORRENT_ASSERT(min_connect_time <= now);
#if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING #if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING
@@ -532,19 +536,37 @@ namespace libtorrent
if (m_torrent->has_picker()) if (m_torrent->has_picker())
p = &m_torrent->picker(); p = &m_torrent->picker();
bool pinged = false;
ptime now = time_now(); ptime now = time_now();
// remove old disconnected peers from the list // remove old disconnected peers from the list
for (iterator i = m_peers.begin(); i != m_peers.end();) for (iterator i = m_peers.begin(); i != m_peers.end();)
{ {
peer& pe = i->second;
#ifndef TORRENT_DISABLE_DHT
// try to send a DHT ping to this peer
// as well, to figure out if it supports
// DHT (uTorrent and BitComet doesn't
// advertise support)
if (!pinged && !pe.added_to_dht)
{
udp::endpoint node(pe.ip.address(), pe.ip.port());
m_torrent->session().add_dht_node(node);
pe.added_to_dht = true;
pinged = true;
}
#endif
// this timeout has to be customizable! // this timeout has to be customizable!
// don't remove banned peers, they should // don't remove banned peers, they should
// remain banned // remain banned
if (i->second.connection == 0 if (pe.connection == 0
&& i->second.connected != min_time() && pe.connected != min_time()
&& !i->second.banned && !pe.banned
&& now - i->second.connected > minutes(120)) && now - pe.connected > minutes(120))
{ {
if (p) p->clear_peer(&i->second); if (p) p->clear_peer(&pe);
if (pe.seed) --m_num_seeds;
m_peers.erase(i++); m_peers.erase(i++);
} }
else else
@@ -770,6 +792,7 @@ namespace libtorrent
} }
if (m_torrent->has_picker()) if (m_torrent->has_picker())
m_torrent->picker().clear_peer(&i->second); m_torrent->picker().clear_peer(&i->second);
if (i->second.seed) --m_num_seeds;
m_peers.erase(i); m_peers.erase(i);
} }
} }
@@ -851,16 +874,11 @@ namespace libtorrent
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
if (flags & 0x01) i->second.pe_support = true; if (flags & 0x01) i->second.pe_support = true;
#endif #endif
if (flags & 0x02) i->second.seed = true; if (flags & 0x02)
{
// try to send a DHT ping to this peer i->second.seed = true;
// as well, to figure out if it supports ++m_num_seeds;
// DHT (uTorrent and BitComet doesn't }
// advertise support)
#ifndef TORRENT_DISABLE_DHT
udp::endpoint node(remote.address(), remote.port());
m_torrent->session().add_dht_node(node);
#endif
} }
else else
{ {
@@ -879,7 +897,11 @@ namespace libtorrent
// if we're connected to this peer // if we're connected to this peer
// we already know if it's a seed or not // we already know if it's a seed or not
// so we don't have to trust this source // so we don't have to trust this source
if ((flags & 0x02) && !i->second.connection) i->second.seed = true; if ((flags & 0x02) && !i->second.connection)
{
if (!i->second.seed) ++m_num_seeds;
i->second.seed = true;
}
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
if (i->second.connection) if (i->second.connection)
@@ -1295,24 +1317,28 @@ namespace libtorrent
policy::peer::peer(const tcp::endpoint& ip_, peer::connection_type t, int src) policy::peer::peer(const tcp::endpoint& ip_, peer::connection_type t, int src)
: ip(ip_) : ip(ip_)
, type(t) , type(t)
, failcount(0)
, trust_points(0)
, source(src)
, hashfails(0)
, fast_reconnects(0)
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
, pe_support(true) , pe_support(true)
#endif #endif
, failcount(0)
, hashfails(0)
, seed(false)
, fast_reconnects(0)
, optimistically_unchoked(false) , optimistically_unchoked(false)
, last_optimistically_unchoked(min_time()) , seed(false)
, connected(min_time())
, trust_points(0)
, on_parole(false) , on_parole(false)
, banned(false)
#ifndef TORRENT_DISABLE_DHT
, added_to_dht(false)
#endif
, connection(0)
, prev_amount_upload(0) , prev_amount_upload(0)
, prev_amount_download(0) , prev_amount_download(0)
, banned(false) , last_optimistically_unchoked(min_time())
, source(src) , connected(min_time())
, connection(0)
{ {
TORRENT_ASSERT((src & 0xff) == src);
TORRENT_ASSERT(connected < time_now()); TORRENT_ASSERT(connected < time_now());
} }

View File

@@ -3392,9 +3392,8 @@ namespace libtorrent
st.num_peers = (int)std::count_if(m_connections.begin(), m_connections.end() st.num_peers = (int)std::count_if(m_connections.begin(), m_connections.end()
, !boost::bind(&peer_connection::is_connecting, _1)); , !boost::bind(&peer_connection::is_connecting, _1));
st.list_peers = std::distance(m_policy.begin_peer(), m_policy.end_peer()); st.list_peers = m_policy.num_peers();
st.list_seeds = (int)std::count_if(m_policy.begin_peer(), m_policy.end_peer() st.list_seeds = m_policy.num_seeds();
, boost::bind(&policy::peer::seed, bind(&policy::iterator::value_type::second, _1)));
st.connect_candidates = m_policy.num_connect_candidates(); st.connect_candidates = m_policy.num_connect_candidates();
st.storage_mode = m_storage_mode; st.storage_mode = m_storage_mode;