diff --git a/src/choker.cpp b/src/choker.cpp index c7797410a..b67e0c2b8 100644 --- a/src/choker.cpp +++ b/src/choker.cpp @@ -136,18 +136,8 @@ namespace { return lhs->time_of_last_unchoke() < rhs->time_of_last_unchoke(); } - // return true if 'lhs' peer should be preferred to be unchoke over 'rhs' - bool unchoke_compare_anti_leech(peer_connection const* lhs - , peer_connection const* rhs) + int anti_leech_score(peer_connection const* peer) { - int const cmp = compare_peers(lhs, rhs); - if (cmp != 0) return cmp > 0; - - std::shared_ptr const t1 = lhs->associated_torrent().lock(); - std::shared_ptr const t2 = rhs->associated_torrent().lock(); - TORRENT_ASSERT(t1); - TORRENT_ASSERT(t2); - // the anti-leech seeding algorithm is based on the paper "Improving // BitTorrent: A Simple Approach" from Chow et. al. and ranks peers based // on how many pieces they have, preferring to unchoke peers that just @@ -168,13 +158,24 @@ namespace { // | V | // +---------------------------+ // 0% num have pieces 100% - int const t1_total = t1->torrent_file().num_pieces(); - int const t2_total = t2->torrent_file().num_pieces(); - int const score1 = (lhs->num_have_pieces() < t1_total / 2 - ? t1_total - lhs->num_have_pieces() : lhs->num_have_pieces()) * 1000 / t1_total; - int const score2 = (rhs->num_have_pieces() < t2_total / 2 - ? t2_total - rhs->num_have_pieces() : rhs->num_have_pieces()) * 1000 / t2_total; + std::shared_ptr const t = peer->associated_torrent().lock(); + TORRENT_ASSERT(t); + std::int64_t const total_size = t->torrent_file().total_size(); + std::int64_t const have_size = std::max(peer->statistics().total_payload_upload() + , std::int64_t(t->torrent_file().piece_length()) * peer->num_have_pieces()); + return int(std::abs((have_size - total_size / 2) * 2000 / total_size)); + } + + // return true if 'lhs' peer should be preferred to be unchoke over 'rhs' + bool unchoke_compare_anti_leech(peer_connection const* lhs + , peer_connection const* rhs) + { + int const cmp = compare_peers(lhs, rhs); + if (cmp != 0) return cmp > 0; + + int const score1 = anti_leech_score(lhs); + int const score2 = anti_leech_score(rhs); if (score1 != score2) return score1 > score2; // prioritize the one that has waited the longest to be unchoked