diff --git a/docs/manual.rst b/docs/manual.rst index 01658d747..6c058d71d 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -3750,7 +3750,8 @@ session_settings enum seed_choking_algorithm_t { round_robin, - fastest_upload + fastest_upload, + anti_leech }; int seed_choking_algorithm; @@ -4116,6 +4117,10 @@ options are: * ``fastest_upload`` unchokes the peers we can send to the fastest. This might be a bit more reliable in utilizing all available capacity. +* ``anti_leech`` prioritizes peers who have just started or are just about to finish + the download. The intention is to force peers in the middle of the download to + trade with each other. + ``use_parole_mode`` specifies if parole mode should be used. Parole mode means that peers that participate in pieces that fail the hash check are put in a mode where they are only allowed to download whole pieces. If the whole piece a peer diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp index 4ac7c66a6..a20f22366 100644 --- a/include/libtorrent/session_settings.hpp +++ b/include/libtorrent/session_settings.hpp @@ -467,7 +467,8 @@ namespace libtorrent enum seed_choking_algorithm_t { round_robin, - fastest_upload + fastest_upload, + anti_leech }; // the choking algorithm to use for seeding torrents diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 97ff7ed71..5b7b55acf 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -422,6 +422,36 @@ namespace libtorrent if (c1 > c2) return true; if (c2 > c1) return false; } + else if (m_ses.settings().seed_choking_algorithm == session_settings::anti_leech) + { + // the anti-leech seeding algorithm ranks peers based on how many pieces + // they have, prefering to unchoke peers that just started and peers that + // are close to completing. Like this: + // ^ + // | \ / | + // | \ / | + // | \ / | + // s | \ / | + // c | \ / | + // o | \ / | + // r | \ / | + // e | \ / | + // | \ / | + // | \ / | + // | \ / | + // | \ / | + // | V | + // +---------------------------+ + // 0% num have pieces 100% + int t1_total = t1->torrent_file().num_pieces(); + int t2_total = t2->torrent_file().num_pieces(); + int score1 = (num_have_pieces() < t1_total / 2 + ? t1_total - num_have_pieces() : num_have_pieces()) * 1000 / t1_total; + int score2 = (rhs.num_have_pieces() < t2_total / 2 + ? t2_total - rhs.num_have_pieces() : rhs.num_have_pieces()) * 1000 / t2_total; + if (score1 > score2) return true; + if (score2 > score1) return false; + } // if both peers are still in their send quota or not in their send quota // prioritize the one that has waited the longest to be unchoked