From fd98434c970492bf0b0cf362ab8aea7fbea918c2 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Wed, 28 May 2008 18:25:48 +0000 Subject: [PATCH] peer list optimization and introduced hard limit on peer list size --- docs/manual.rst | 8 ++ include/libtorrent/session_settings.hpp | 6 ++ src/policy.cpp | 114 +++++++++++------------- 3 files changed, 68 insertions(+), 60 deletions(-) diff --git a/docs/manual.rst b/docs/manual.rst index 6cac6b883..a2779ef42 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -2760,6 +2760,8 @@ that will be sent to the tracker. The user-agent is a good way to identify your int auto_scrape_interval; int auto_scrape_min_interval; + + int max_peerlist_size; }; ``user_agent`` this is the client identification to the tracker. @@ -2996,6 +2998,12 @@ automatic scrape (regardless of torrent). In case there are a large number of paused auto managed torrents, this puts a limit on how often a scrape request is sent. +``max_peerlist_size`` is the maximum number of peers in the list of +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. pe_settings =========== diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp index 30e76b825..677bd8b84 100644 --- a/include/libtorrent/session_settings.hpp +++ b/include/libtorrent/session_settings.hpp @@ -135,6 +135,7 @@ namespace libtorrent , close_redundant_connections(true) , auto_scrape_interval(1800) , auto_scrape_min_interval(300) + , max_peerlist_size(8000) {} // this is the user agent that will be sent to the tracker @@ -402,6 +403,11 @@ namespace libtorrent // the minimum number of seconds between any // automatic scrape (regardless of torrent) int auto_scrape_min_interval; + + // the max number of peers in the peer list + // per torrent. This is the peers we know + // about, not necessarily connected to. + int max_peerlist_size; }; #ifndef TORRENT_DISABLE_DHT diff --git a/src/policy.cpp b/src/policy.cpp index 158f3691a..53f0e66e5 100755 --- a/src/policy.cpp +++ b/src/policy.cpp @@ -150,18 +150,7 @@ namespace tcp::endpoint const& m_ep; }; - struct match_peer_id - { - match_peer_id(peer_id const& id_) - : m_id(id_) - {} - - bool operator()(std::pair const& p) const - { return p.second.connection && p.second.connection->pid() == m_id; } - - peer_id const& m_id; - }; - +#ifndef NDEBUG struct match_peer_connection { match_peer_connection(peer_connection const& c) @@ -177,7 +166,7 @@ namespace peer_connection const& m_conn; }; - +#endif } @@ -445,21 +434,56 @@ namespace libtorrent if (m_round_robin == m_peers.end()) m_round_robin = m_peers.begin(); +#ifndef TORRENT_DISABLE_DHT + bool pinged = false; +#endif + for (int iterations = (std::min)(int(m_peers.size()), 300); - iterations > 0; ++m_round_robin, --iterations) + iterations > 0; --iterations) { if (m_round_robin == m_peers.end()) m_round_robin = m_peers.begin(); - if (!is_connect_candidate(m_round_robin->second, finished)) continue; + peer& pe = m_round_robin->second; + iterator current = m_round_robin; + +#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 (pe.connection == 0 + && pe.connected != min_time() + && !pe.banned + && (now - pe.connected > minutes(120) + || m_peers.size() >= m_torrent->settings().max_peerlist_size) * 0.9) + { + erase_peer(m_round_robin++); + continue; + } + ++m_round_robin; + + + if (!is_connect_candidate(pe, finished)) continue; if (candidate != m_peers.end() - && !compare_peer(candidate->second, m_round_robin->second, external_ip)) continue; + && !compare_peer(candidate->second, pe, external_ip)) continue; - if (now - m_round_robin->second.connected < - seconds(m_round_robin->second.failcount * min_reconnect_time)) + if (now - pe.connected < + seconds(pe.failcount * min_reconnect_time)) continue; - candidate = m_round_robin; + candidate = current; } #if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING @@ -484,45 +508,6 @@ namespace libtorrent if (m_torrent->is_paused()) return; -#ifndef TORRENT_DISABLE_DHT - bool pinged = false; -#endif - - 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 (pe.connection == 0 - && pe.connected != min_time() - && !pe.banned - && now - pe.connected > minutes(120)) - { - erase_peer(i++); - } - else - { - ++i; - } - } - // ------------------------ // upload shift // ------------------------ @@ -658,6 +643,12 @@ namespace libtorrent error_code ec; TORRENT_ASSERT(c.remote() == c.get_socket()->remote_endpoint(ec) || ec); + if (m_peers.size() >= m_torrent->settings().max_peerlist_size) + { + c.disconnect("peer list size exceeded, refusing incoming connection"); + return false; + } + peer p(c.remote(), peer::not_connectable, 0); i = m_peers.insert(std::make_pair(c.remote().address(), p)); #ifndef TORRENT_DISABLE_GEO_IP @@ -750,7 +741,7 @@ namespace libtorrent if (ses.m_alerts.should_post(alert::info)) { ses.m_alerts.post_alert(peer_blocked_alert(remote.address() - , "outgoing port blocked, peer not added to peer list")); + , "outgoing port blocked, peer not added to peer list")); } return 0; } @@ -776,11 +767,14 @@ namespace libtorrent if (ses.m_alerts.should_post(alert::info)) { ses.m_alerts.post_alert(peer_blocked_alert(remote.address() - , "blocked peer not added to peer list")); + , "blocked peer not added to peer list")); } return 0; } + if (m_peers.size() >= m_torrent->settings().max_peerlist_size) + return 0; + // we don't have any info about this peer. // add a new entry i = m_peers.insert(std::make_pair(remote.address()