diff --git a/include/libtorrent/policy.hpp b/include/libtorrent/policy.hpp index 2735d14cb..0bb894b5f 100755 --- a/include/libtorrent/policy.hpp +++ b/include/libtorrent/policy.hpp @@ -139,43 +139,9 @@ namespace libtorrent tcp::endpoint ip; connection_type type; -#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; -#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; + // the number of failed connection attempts + // this peer has + boost::uint8_t failcount; // for every valid piece we receive where this // peer was one of the participants, we increase @@ -183,15 +149,63 @@ 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. - int trust_points; + boost::int8_t trust_points; - // 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 + // 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; + + // 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. - 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 // uploaded and downloaded data to this @@ -205,16 +219,13 @@ namespace libtorrent size_type prev_amount_upload; size_type prev_amount_download; - // is set to true if this peer has been banned - bool banned; + // the time when this peer was optimistically unchoked + // the last time. + libtorrent::ptime last_optimistically_unchoked; - // a bitmap combining the peer_source flags - // from peer_info. - int source; - - // if the peer is connected now, this - // will refer to a valid peer_connection - peer_connection* connection; + // the time when the peer connected to us + // or disconnected if it isn't connected right now + libtorrent::ptime connected; }; int num_peers() const { return m_peers.size(); } @@ -231,6 +242,7 @@ namespace libtorrent 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; } void recalculate_connect_candidates() { @@ -260,6 +272,9 @@ namespace libtorrent // have the connectable state (we have a listen // port for them). int m_num_connect_candidates; + + // the number of seeds in the peer list + int m_num_seeds; }; } diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index a6a486869..f6c5a973d 100755 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -456,12 +456,13 @@ namespace libtorrent 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; peer_info_struct()->connected = time_now() - seconds(m_ses.settings().min_reconnect_time * 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) @@ -565,7 +566,7 @@ namespace libtorrent { peer_info_struct()->on_parole = true; ++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 // allowed failed/passed ratio low. diff --git a/src/policy.cpp b/src/policy.cpp index 5d977dd7b..23c2318bd 100755 --- a/src/policy.cpp +++ b/src/policy.cpp @@ -385,6 +385,7 @@ namespace libtorrent } } if (p) p->clear_peer(&i->second); + if (i->second.seed) --m_num_seeds; m_peers.erase(i++); } } @@ -471,8 +472,10 @@ namespace libtorrent } int connect_candidates = 0; + int seeds = 0; for (iterator i = m_peers.begin(); i != m_peers.end(); ++i) { + if (i->second.seed) ++seeds; if (!is_connect_candidate(i->second, finished)) continue; ++connect_candidates; @@ -504,6 +507,7 @@ namespace libtorrent } m_num_connect_candidates = connect_candidates; + m_num_seeds = seeds; TORRENT_ASSERT(min_connect_time <= now); #if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING @@ -532,19 +536,37 @@ namespace libtorrent if (m_torrent->has_picker()) p = &m_torrent->picker(); + bool pinged = false; + ptime now = time_now(); // remove old disconnected peers from the list 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! // don't remove banned peers, they should // remain banned - if (i->second.connection == 0 - && i->second.connected != min_time() - && !i->second.banned - && now - i->second.connected > minutes(120)) + if (pe.connection == 0 + && pe.connected != min_time() + && !pe.banned + && 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++); } else @@ -770,6 +792,7 @@ namespace libtorrent } if (m_torrent->has_picker()) m_torrent->picker().clear_peer(&i->second); + if (i->second.seed) --m_num_seeds; m_peers.erase(i); } } @@ -851,16 +874,11 @@ namespace libtorrent #ifndef TORRENT_DISABLE_ENCRYPTION if (flags & 0x01) i->second.pe_support = true; #endif - if (flags & 0x02) i->second.seed = true; - - // 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) -#ifndef TORRENT_DISABLE_DHT - udp::endpoint node(remote.address(), remote.port()); - m_torrent->session().add_dht_node(node); -#endif + if (flags & 0x02) + { + i->second.seed = true; + ++m_num_seeds; + } } else { @@ -879,7 +897,11 @@ namespace libtorrent // 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) 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 (i->second.connection) @@ -1295,24 +1317,28 @@ namespace libtorrent policy::peer::peer(const tcp::endpoint& ip_, peer::connection_type t, int src) : ip(ip_) , type(t) + , failcount(0) + , trust_points(0) + , source(src) + , hashfails(0) + , fast_reconnects(0) #ifndef TORRENT_DISABLE_ENCRYPTION , pe_support(true) #endif - , failcount(0) - , hashfails(0) - , seed(false) - , fast_reconnects(0) , optimistically_unchoked(false) - , last_optimistically_unchoked(min_time()) - , connected(min_time()) - , trust_points(0) + , seed(false) , on_parole(false) + , banned(false) +#ifndef TORRENT_DISABLE_DHT + , added_to_dht(false) +#endif + , connection(0) , prev_amount_upload(0) , prev_amount_download(0) - , banned(false) - , source(src) - , connection(0) + , last_optimistically_unchoked(min_time()) + , connected(min_time()) { + TORRENT_ASSERT((src & 0xff) == src); TORRENT_ASSERT(connected < time_now()); } diff --git a/src/torrent.cpp b/src/torrent.cpp index 8c16bfc78..44c21aed7 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -3392,9 +3392,8 @@ namespace libtorrent st.num_peers = (int)std::count_if(m_connections.begin(), m_connections.end() , !boost::bind(&peer_connection::is_connecting, _1)); - st.list_peers = std::distance(m_policy.begin_peer(), m_policy.end_peer()); - st.list_seeds = (int)std::count_if(m_policy.begin_peer(), m_policy.end_peer() - , boost::bind(&policy::peer::seed, bind(&policy::iterator::value_type::second, _1))); + st.list_peers = m_policy.num_peers(); + st.list_seeds = m_policy.num_seeds(); st.connect_candidates = m_policy.num_connect_candidates(); st.storage_mode = m_storage_mode;