diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 060f41a75..9c5df4f7c 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -636,6 +636,7 @@ namespace libtorrent void update_listen_interfaces(); void update_privileged_ports(); void update_auto_sequential(); + void update_max_failcount(); void update_upnp(); void update_natpmp(); diff --git a/include/libtorrent/peer_list.hpp b/include/libtorrent/peer_list.hpp index ffb1d01a8..5b5eaf82b 100644 --- a/include/libtorrent/peer_list.hpp +++ b/include/libtorrent/peer_list.hpp @@ -67,6 +67,7 @@ namespace libtorrent , min_reconnect_time(60) , loop_counter(0) , ip(NULL), port(0) + , max_failcount(3) , peer_allocator(NULL) {} bool is_paused; @@ -90,6 +91,10 @@ namespace libtorrent external_ip const* ip; int port; + // the number of times a peer must fail before it's no longer considered + // a connect candidate + int max_failcount; + // this must be set to a torrent_peer allocator torrent_peer_allocator_interface* peer_allocator; @@ -193,6 +198,8 @@ namespace libtorrent void erase_peer(torrent_peer* p, torrent_state* state); void erase_peer(iterator i, torrent_state* state); + void set_max_failcount(torrent_state* st); + private: void recalculate_connect_candidates(torrent_state* state); @@ -207,7 +214,8 @@ namespace libtorrent bool compare_peer(torrent_peer const* lhs, torrent_peer const* rhs , external_ip const& external, int source_port) const; - void find_connect_candidates(std::vector& peers, int session_time, torrent_state* state); + void find_connect_candidates(std::vector& peers + , int session_time, torrent_state* state); bool is_connect_candidate(torrent_peer const& p) const; bool is_erase_candidate(torrent_peer const& p) const; @@ -255,6 +263,9 @@ namespace libtorrent // port for them). int m_num_connect_candidates; + // if a peer has failed this many times or more, we don't consider + // it a connect candidate anymore. + int m_max_failcount; }; } diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index 7dbaedd52..acf6cac23 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -977,6 +977,12 @@ namespace libtorrent return m_picker.get() != 0; } + void update_max_failcount() + { + if (!m_peer_list) return; + torrent_state st = get_policy_state(); + m_peer_list->set_max_failcount(&st); + } int num_known_peers() const { return m_peer_list ? m_peer_list->num_peers() : 0; } int num_connect_candidates() const { return m_peer_list ? m_peer_list->num_connect_candidates() : 0; } diff --git a/src/peer_list.cpp b/src/peer_list.cpp index f0bd25e91..410415eec 100644 --- a/src/peer_list.cpp +++ b/src/peer_list.cpp @@ -129,15 +129,25 @@ namespace libtorrent , m_finished(0) , m_round_robin(0) , m_num_connect_candidates(0) + , m_max_failcount(3) { thread_started(); } - // disconnects and removes all peers that are now filtered - // fills in 'erased' with torrent_peer pointers that were removed - // from the peer list. Any references to these peers must be cleared - // immediately after this call returns. For instance, in the piece picker. - void peer_list::apply_ip_filter(ip_filter const& filter, torrent_state* state, std::vector
& banned) + void peer_list::set_max_failcount(torrent_state* state) + { + if (state->max_failcount == m_max_failcount) return; + + m_max_failcount = state->max_failcount; + recalculate_connect_candidates(state); + } + + // disconnects and removes all peers that are now filtered fills in 'erased' + // with torrent_peer pointers that were removed from the peer list. Any + // references to these peers must be cleared immediately after this call + // returns. For instance, in the piece picker. + void peer_list::apply_ip_filter(ip_filter const& filter + , torrent_state* state, std::vector
& banned) { TORRENT_ASSERT(is_single_thread()); INVARIANT_CHECK; @@ -169,7 +179,9 @@ namespace libtorrent banned.push_back(p->remote().address()); - p->disconnect(errors::banned_by_ip_filter, peer_connection_interface::op_bittorrent); + p->disconnect(errors::banned_by_ip_filter + , peer_connection_interface::op_bittorrent); + // what *i refers to has changed, i.e. cur was deleted if (m_peers.size() < count) { @@ -196,7 +208,8 @@ namespace libtorrent // fills in 'erased' with torrent_peer pointers that were removed // from the peer list. Any references to these peers must be cleared // immediately after this call returns. For instance, in the piece picker. - void peer_list::apply_port_filter(port_filter const& filter, torrent_state* state, std::vector
& banned) + void peer_list::apply_port_filter(port_filter const& filter + , torrent_state* state, std::vector
& banned) { TORRENT_ASSERT(is_single_thread()); INVARIANT_CHECK; @@ -457,14 +470,14 @@ namespace libtorrent || p.web_seed || !p.connectable || (p.seed && m_finished) - // TODO: 3 settings_pack::max_failcount should be used here, not 3 - || int(p.failcount) >= 3) + || int(p.failcount) >= m_max_failcount) return false; return true; } - void peer_list::find_connect_candidates(std::vector& peers, int session_time, torrent_state* state) + void peer_list::find_connect_candidates(std::vector& peers + , int session_time, torrent_state* state) { TORRENT_ASSERT(is_single_thread()); INVARIANT_CHECK; diff --git a/src/session_impl.cpp b/src/session_impl.cpp index bfd4a6ab5..bbbb744b4 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -5012,6 +5012,15 @@ retry: , end(m_torrents.end()); i != end; ++i) i->second->update_auto_sequential(); } + + void session_impl::update_max_failcount() + { + for (torrent_map::iterator i = m_torrents.begin() + , end(m_torrents.end()); i != end; ++i) + { + i->second->update_max_failcount(); + } + } void session_impl::update_proxy() { diff --git a/src/settings_pack.cpp b/src/settings_pack.cpp index 991cc53a9..058ccb538 100644 --- a/src/settings_pack.cpp +++ b/src/settings_pack.cpp @@ -229,7 +229,7 @@ namespace libtorrent SET(urlseed_pipeline_size, 5, 0), SET(urlseed_wait_retry, 30, 0), SET(file_pool_size, 40, 0), - SET(max_failcount, 3, 0), + SET(max_failcount, 3, &session_impl::update_max_failcount), SET(min_reconnect_time, 60, 0), SET(peer_connect_timeout, 15, 0), SET(connection_speed, 6, &session_impl::update_connection_speed), diff --git a/src/torrent.cpp b/src/torrent.cpp index efadc0c9d..46d8bbafc 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -10639,6 +10639,7 @@ namespace libtorrent ret.peer_allocator = m_ses.get_peer_allocator(); ret.ip = &m_ses.external_address(); ret.port = m_ses.listen_port(); + ret.max_failcount = settings().get_int(settings_pack::max_failcount); return ret; }