fix bandwith rate limit calculation (#2134)

back-port of fc0cbfb789
This commit is contained in:
d-komarov 2017-07-12 07:35:12 +03:00 committed by Arvid Norberg
parent 11d6a00bec
commit 85cf521145
3 changed files with 24 additions and 15 deletions

View File

@ -47,7 +47,7 @@ namespace libtorrent {
// member of peer_connection // member of peer_connection
struct TORRENT_EXTRA_EXPORT bandwidth_channel struct TORRENT_EXTRA_EXPORT bandwidth_channel
{ {
static const int inf = boost::integer_traits<int>::const_max; static boost::int32_t const inf = boost::integer_traits<boost::int32_t>::const_max;
bandwidth_channel(); bandwidth_channel();
@ -55,8 +55,9 @@ struct TORRENT_EXTRA_EXPORT bandwidth_channel
void throttle(int limit); void throttle(int limit);
int throttle() const int throttle() const
{ {
TORRENT_ASSERT_VAL(m_limit < INT_MAX, m_limit); TORRENT_ASSERT_VAL(m_limit >= 0, m_limit);
return int(m_limit); TORRENT_ASSERT_VAL(m_limit < inf, m_limit);
return m_limit;
} }
int quota_left() const; int quota_left() const;
@ -96,10 +97,9 @@ private:
// the limit is the number of bytes // the limit is the number of bytes
// per second we are allowed to use. // per second we are allowed to use.
boost::int64_t m_limit; boost::int32_t m_limit;
}; };
} }
#endif #endif

View File

@ -33,8 +33,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/bandwidth_limit.hpp" #include "libtorrent/bandwidth_limit.hpp"
#include <algorithm> #include <algorithm>
namespace libtorrent namespace libtorrent {
{
bandwidth_channel::bandwidth_channel() bandwidth_channel::bandwidth_channel()
: tmp(0) : tmp(0)
, distribute_quota(0) , distribute_quota(0)
@ -45,9 +45,9 @@ namespace libtorrent
// 0 means infinite // 0 means infinite
void bandwidth_channel::throttle(int limit) void bandwidth_channel::throttle(int limit)
{ {
TORRENT_ASSERT(limit >= 0); TORRENT_ASSERT_VAL(limit >= 0, limit);
// if the throttle is more than this, we might overflow // if the throttle is more than this, we might overflow
TORRENT_ASSERT(limit < INT_MAX); TORRENT_ASSERT_VAL(limit < inf, limit);
m_limit = limit; m_limit = limit;
} }
@ -59,19 +59,27 @@ namespace libtorrent
void bandwidth_channel::update_quota(int dt_milliseconds) void bandwidth_channel::update_quota(int dt_milliseconds)
{ {
TORRENT_ASSERT_VAL(m_limit >= 0, m_limit);
TORRENT_ASSERT_VAL(m_limit < inf, m_limit);
if (m_limit == 0) return; if (m_limit == 0) return;
// avoid integer overflow // "to_add" should never have int64 overflow: "m_limit" contains < "<int>::max"
if (m_limit >= std::numeric_limits<int>::max() / dt_milliseconds) boost::int64_t to_add = (boost::int64_t(m_limit) * dt_milliseconds + 500) / 1000;
if (to_add > inf - m_quota_left)
{ {
m_quota_left = std::numeric_limits<int>::max(); m_quota_left = inf;
} }
else else
{ {
m_quota_left += (m_limit * dt_milliseconds + 500) / 1000; m_quota_left += to_add;
if (m_quota_left / 3 > m_limit) m_quota_left = m_limit * 3; if (m_quota_left / 3 > m_limit) m_quota_left = boost::int64_t(m_limit) * 3;
// "m_quota_left" will never have int64 overflow but may exceed "<int>::max"
m_quota_left = std::min(m_quota_left, boost::int64_t(inf));
} }
distribute_quota = int((std::max)(m_quota_left, boost::int64_t(0)));
distribute_quota = int(std::max(m_quota_left, boost::int64_t(0)));
} }
// this is used when connections disconnect with // this is used when connections disconnect with

View File

@ -467,6 +467,7 @@ TORRENT_TEST(equal_connection)
test_equal_connections(33, 60000); test_equal_connections(33, 60000);
test_equal_connections(33, 500000); test_equal_connections(33, 500000);
test_equal_connections( 1, 1000000); test_equal_connections( 1, 1000000);
test_equal_connections( 1, 6000000);
} }
TORRENT_TEST(conn_var_rate) TORRENT_TEST(conn_var_rate)