diff --git a/ChangeLog b/ChangeLog index 53ee50421..aeae887d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * fixed division by zero in anti-leech choker * fixed bug in torrent_info::swap 1.2.2 release diff --git a/src/choker.cpp b/src/choker.cpp index b67e0c2b8..89a3ea482 100644 --- a/src/choker.cpp +++ b/src/choker.cpp @@ -162,6 +162,7 @@ namespace { TORRENT_ASSERT(t); std::int64_t const total_size = t->torrent_file().total_size(); + if (total_size == 0) return 0; 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)); @@ -234,10 +235,6 @@ namespace { } #endif - int upload_slots = sett.get_int(settings_pack::unchoke_slots_limit); - if (upload_slots < 0) - upload_slots = std::numeric_limits::max(); - // ==== BitTyrant ==== // // if we're using the bittyrant unchoker, go through all peers that @@ -277,7 +274,7 @@ namespace { // now, figure out how many peers should be unchoked. We deduct the // estimated reciprocation rate from our upload_capacity estimate // until there none left - upload_slots = 0; + int upload_slots = 0; for (auto const p : peers) { @@ -292,6 +289,10 @@ namespace { return upload_slots; } + int upload_slots = sett.get_int(settings_pack::unchoke_slots_limit); + if (upload_slots < 0) + upload_slots = std::numeric_limits::max(); + // ==== rate-based ==== // // The rate based unchoker looks at our upload rate to peers, and find @@ -343,34 +344,36 @@ namespace { // we use partial sort here, because we only care about the top // upload_slots peers. + int const slots = std::min(upload_slots, int(peers.size())); + if (sett.get_int(settings_pack::seed_choking_algorithm) == settings_pack::round_robin) { int const pieces = sett.get_int(settings_pack::seeding_piece_quota); std::partial_sort(peers.begin(), peers.begin() - + std::min(upload_slots, int(peers.size())), peers.end() + + slots, peers.end() , std::bind(&unchoke_compare_rr, _1, _2, pieces)); } else if (sett.get_int(settings_pack::seed_choking_algorithm) == settings_pack::fastest_upload) { std::partial_sort(peers.begin(), peers.begin() - + std::min(upload_slots, int(peers.size())), peers.end() + + slots, peers.end() , std::bind(&unchoke_compare_fastest_upload, _1, _2)); } else if (sett.get_int(settings_pack::seed_choking_algorithm) == settings_pack::anti_leech) { std::partial_sort(peers.begin(), peers.begin() - + std::min(upload_slots, int(peers.size())), peers.end() + + slots, peers.end() , std::bind(&unchoke_compare_anti_leech, _1, _2)); } else { int const pieces = sett.get_int(settings_pack::seeding_piece_quota); std::partial_sort(peers.begin(), peers.begin() - + std::min(upload_slots, int(peers.size())), peers.end() + + slots, peers.end() , std::bind(&unchoke_compare_rr, _1, _2, pieces)); TORRENT_ASSERT_FAIL();