mirror of
https://git.deluge-torrent.org/deluge
synced 2025-08-09 01:48:40 +00:00
initial libtorrent sync 1466
This commit is contained in:
parent
7f2232f34f
commit
4164f15735
26 changed files with 525 additions and 1043 deletions
|
@ -261,6 +261,17 @@ namespace libtorrent
|
||||||
{ return std::auto_ptr<alert>(new torrent_paused_alert(*this)); }
|
{ return std::auto_ptr<alert>(new torrent_paused_alert(*this)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TORRENT_EXPORT torrent_checked_alert: torrent_alert
|
||||||
|
{
|
||||||
|
torrent_checked_alert(torrent_handle const& h, std::string const& msg)
|
||||||
|
: torrent_alert(h, alert::info, msg)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual std::auto_ptr<alert> clone() const
|
||||||
|
{ return std::auto_ptr<alert>(new torrent_checked_alert(*this)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct TORRENT_EXPORT url_seed_alert: torrent_alert
|
struct TORRENT_EXPORT url_seed_alert: torrent_alert
|
||||||
{
|
{
|
||||||
url_seed_alert(
|
url_seed_alert(
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2003, Magnus Jonsson
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions
|
|
||||||
are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in
|
|
||||||
the documentation and/or other materials provided with the distribution.
|
|
||||||
* Neither the name of the author nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived
|
|
||||||
from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TORRENT_ALLOCATE_RESOURCES_HPP_INCLUDED
|
|
||||||
#define TORRENT_ALLOCATE_RESOURCES_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
#include "libtorrent/resource_request.hpp"
|
|
||||||
#include "libtorrent/peer_id.hpp"
|
|
||||||
#include "libtorrent/socket.hpp"
|
|
||||||
#include "libtorrent/session.hpp"
|
|
||||||
|
|
||||||
namespace libtorrent
|
|
||||||
{
|
|
||||||
class peer_connection;
|
|
||||||
class torrent;
|
|
||||||
|
|
||||||
int saturated_add(int a, int b);
|
|
||||||
|
|
||||||
// Function to allocate a limited resource fairly among many consumers.
|
|
||||||
// It takes into account the current use, and the consumer's desired use.
|
|
||||||
// Should be invoked periodically to allow it adjust to the situation (make
|
|
||||||
// sure "used" is updated between calls!).
|
|
||||||
// If resources = std::numeric_limits<int>::max() it means there is an infinite
|
|
||||||
// supply of resources (so everyone can get what they want).
|
|
||||||
|
|
||||||
void allocate_resources(
|
|
||||||
int resources
|
|
||||||
, std::map<sha1_hash, boost::shared_ptr<torrent> >& torrents
|
|
||||||
, resource_request torrent::* res);
|
|
||||||
|
|
||||||
void allocate_resources(
|
|
||||||
int resources
|
|
||||||
, std::map<tcp::endpoint, peer_connection*>& connections
|
|
||||||
, resource_request peer_connection::* res);
|
|
||||||
|
|
||||||
// Used for global limits.
|
|
||||||
void allocate_resources(
|
|
||||||
int resources
|
|
||||||
, std::vector<session*>& _sessions
|
|
||||||
, resource_request session::* res);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,328 +0,0 @@
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2003, Magnus Jonsson
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions
|
|
||||||
are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in
|
|
||||||
the documentation and/or other materials provided with the distribution.
|
|
||||||
* Neither the name of the author nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived
|
|
||||||
from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TORRENT_ALLOCATE_RESOURCES_IMPL_HPP_INCLUDED
|
|
||||||
#define TORRENT_ALLOCATE_RESOURCES_IMPL_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
#include "libtorrent/resource_request.hpp"
|
|
||||||
#include "libtorrent/peer_id.hpp"
|
|
||||||
#include "libtorrent/socket.hpp"
|
|
||||||
#include "libtorrent/size_type.hpp"
|
|
||||||
|
|
||||||
#ifdef min
|
|
||||||
#undef min
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef max
|
|
||||||
#undef max
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace libtorrent
|
|
||||||
{
|
|
||||||
|
|
||||||
int saturated_add(int a, int b);
|
|
||||||
|
|
||||||
namespace aux
|
|
||||||
{
|
|
||||||
// give num_resources to r,
|
|
||||||
// return how how many were actually accepted.
|
|
||||||
inline int give(resource_request& r, int num_resources)
|
|
||||||
{
|
|
||||||
assert(num_resources >= 0);
|
|
||||||
assert(r.given <= r.max);
|
|
||||||
|
|
||||||
int accepted = (std::min)(num_resources, r.max - r.given);
|
|
||||||
assert(accepted >= 0);
|
|
||||||
|
|
||||||
r.given += accepted;
|
|
||||||
assert(r.given <= r.max);
|
|
||||||
|
|
||||||
return accepted;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int div_round_up(int numerator, int denominator)
|
|
||||||
{
|
|
||||||
return (numerator + denominator - 1) / denominator;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
template<class It, class T>
|
|
||||||
class allocate_resources_contract_check
|
|
||||||
{
|
|
||||||
int m_resources;
|
|
||||||
It m_start;
|
|
||||||
It m_end;
|
|
||||||
resource_request T::* m_res;
|
|
||||||
|
|
||||||
public:
|
|
||||||
allocate_resources_contract_check(
|
|
||||||
int resources
|
|
||||||
, It start
|
|
||||||
, It end
|
|
||||||
, resource_request T::* res)
|
|
||||||
: m_resources(resources)
|
|
||||||
, m_start(start)
|
|
||||||
, m_end(end)
|
|
||||||
, m_res(res)
|
|
||||||
{
|
|
||||||
assert(m_resources >= 0);
|
|
||||||
for (It i = m_start, end(m_end); i != end; ++i)
|
|
||||||
{
|
|
||||||
assert(((*i).*m_res).max >= 0);
|
|
||||||
assert(((*i).*m_res).given >= 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~allocate_resources_contract_check()
|
|
||||||
{
|
|
||||||
int sum_given = 0;
|
|
||||||
int sum_max = 0;
|
|
||||||
int sum_min = 0;
|
|
||||||
for (It i = m_start, end(m_end); i != end; ++i)
|
|
||||||
{
|
|
||||||
assert(((*i).*m_res).max >= 0);
|
|
||||||
assert(((*i).*m_res).min >= 0);
|
|
||||||
assert(((*i).*m_res).max >= ((*i).*m_res).min);
|
|
||||||
assert(((*i).*m_res).given >= 0);
|
|
||||||
assert(((*i).*m_res).given <= ((*i).*m_res).max);
|
|
||||||
|
|
||||||
sum_given = saturated_add(sum_given, ((*i).*m_res).given);
|
|
||||||
sum_max = saturated_add(sum_max, ((*i).*m_res).max);
|
|
||||||
sum_min = saturated_add(sum_min, ((*i).*m_res).min);
|
|
||||||
}
|
|
||||||
if (sum_given != (std::min)(std::max(m_resources, sum_min), sum_max))
|
|
||||||
{
|
|
||||||
std::cerr << sum_given << " " << m_resources << " " << sum_min << " " << sum_max << std::endl;
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<class It, class T>
|
|
||||||
void allocate_resources_impl(
|
|
||||||
int resources
|
|
||||||
, It start
|
|
||||||
, It end
|
|
||||||
, resource_request T::* res)
|
|
||||||
{
|
|
||||||
assert(resources >= 0);
|
|
||||||
#ifndef NDEBUG
|
|
||||||
allocate_resources_contract_check<It, T> contract_check(
|
|
||||||
resources
|
|
||||||
, start
|
|
||||||
, end
|
|
||||||
, res);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (It i = start; i != end; ++i)
|
|
||||||
{
|
|
||||||
resource_request& r = (*i).*res;
|
|
||||||
r.leftovers = (std::max)(r.used - r.given, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resources == resource_request::inf)
|
|
||||||
{
|
|
||||||
// No competition for resources.
|
|
||||||
// Just give everyone what they want.
|
|
||||||
for (It i = start; i != end; ++i)
|
|
||||||
{
|
|
||||||
((*i).*res).given = ((*i).*res).max;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resources are scarce
|
|
||||||
|
|
||||||
int sum_max = 0;
|
|
||||||
int sum_min = 0;
|
|
||||||
// the number of consumer that saturated their
|
|
||||||
// quota last time slice
|
|
||||||
int num_saturated = 0;
|
|
||||||
// the total resources that those saturated their
|
|
||||||
// quota used. This is used to calculate the mean
|
|
||||||
// of the saturating consumers, in order to
|
|
||||||
// balance their quotas for the next time slice.
|
|
||||||
size_type saturated_sum = 0;
|
|
||||||
for (It i = start; i != end; ++i)
|
|
||||||
{
|
|
||||||
resource_request& r = (*i).*res;
|
|
||||||
sum_max = saturated_add(sum_max, r.max);
|
|
||||||
assert(r.min < resource_request::inf);
|
|
||||||
assert(r.min >= 0);
|
|
||||||
assert(r.min <= r.max);
|
|
||||||
sum_min += r.min;
|
|
||||||
|
|
||||||
// a consumer that uses 95% or more of its assigned
|
|
||||||
// quota is considered saturating
|
|
||||||
size_type used = r.used;
|
|
||||||
if (r.given == 0) continue;
|
|
||||||
if (used * 20 / r.given >= 19)
|
|
||||||
{
|
|
||||||
++num_saturated;
|
|
||||||
saturated_sum += r.given;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sum_max <= resources)
|
|
||||||
{
|
|
||||||
// it turns out that there's no competition for resources
|
|
||||||
// after all.
|
|
||||||
for (It i = start; i != end; ++i)
|
|
||||||
{
|
|
||||||
((*i).*res).given = ((*i).*res).max;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sum_min >= resources)
|
|
||||||
{
|
|
||||||
// the amount of resources is smaller than
|
|
||||||
// the minimum resources to distribute, so
|
|
||||||
// give everyone the minimum
|
|
||||||
for (It i = start; i != end; ++i)
|
|
||||||
{
|
|
||||||
((*i).*res).given = ((*i).*res).min;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now, the "used" field will be used as a target value.
|
|
||||||
// the algorithm following this loop will then scale the
|
|
||||||
// used values to fit the available resources and store
|
|
||||||
// the scaled values as given. So, the ratios of the
|
|
||||||
// used values will be maintained.
|
|
||||||
for (It i = start; i != end; ++i)
|
|
||||||
{
|
|
||||||
resource_request& r = (*i).*res;
|
|
||||||
|
|
||||||
int target;
|
|
||||||
size_type used = r.used;
|
|
||||||
if (r.given > 0 && used * 20 / r.given >= 19)
|
|
||||||
{
|
|
||||||
assert(num_saturated > 0);
|
|
||||||
target = div_round_up(saturated_sum, num_saturated);
|
|
||||||
target += div_round_up(target, 10);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
target = r.used;
|
|
||||||
}
|
|
||||||
if (target > r.max) target = r.max;
|
|
||||||
else if (target < r.min) target = r.min;
|
|
||||||
|
|
||||||
// move 12.5% towards the the target value
|
|
||||||
r.used = r.given + div_round_up(target - r.given, 8);
|
|
||||||
r.given = r.min;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
resources = (std::max)(resources, sum_min);
|
|
||||||
int resources_to_distribute = (std::min)(resources, sum_max) - sum_min;
|
|
||||||
assert(resources_to_distribute >= 0);
|
|
||||||
#ifndef NDEBUG
|
|
||||||
int prev_resources_to_distribute = resources_to_distribute;
|
|
||||||
#endif
|
|
||||||
while (resources_to_distribute > 0)
|
|
||||||
{
|
|
||||||
// in order to scale, we need to calculate the sum of
|
|
||||||
// all the used values.
|
|
||||||
size_type total_used = 0;
|
|
||||||
size_type max_used = 0;
|
|
||||||
for (It i = start; i != end; ++i)
|
|
||||||
{
|
|
||||||
resource_request& r = (*i).*res;
|
|
||||||
if (r.given == r.max) continue;
|
|
||||||
|
|
||||||
assert(r.given < r.max);
|
|
||||||
|
|
||||||
max_used = (std::max)(max_used, (size_type)r.used + 1);
|
|
||||||
total_used += (size_type)r.used + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
size_type kNumer = resources_to_distribute;
|
|
||||||
size_type kDenom = total_used;
|
|
||||||
assert(kNumer >= 0);
|
|
||||||
assert(kDenom >= 0);
|
|
||||||
assert(kNumer <= (std::numeric_limits<int>::max)());
|
|
||||||
|
|
||||||
if (kNumer * max_used <= kDenom)
|
|
||||||
{
|
|
||||||
kNumer = 1;
|
|
||||||
kDenom = max_used;
|
|
||||||
assert(kDenom >= 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (It i = start; i != end && resources_to_distribute > 0; ++i)
|
|
||||||
{
|
|
||||||
resource_request& r = (*i).*res;
|
|
||||||
if (r.given == r.max) continue;
|
|
||||||
|
|
||||||
assert(r.given < r.max);
|
|
||||||
|
|
||||||
size_type used = (size_type)r.used + 1;
|
|
||||||
if (used < 1) used = 1;
|
|
||||||
size_type to_give = used * kNumer / kDenom;
|
|
||||||
if (to_give > resources_to_distribute)
|
|
||||||
to_give = resources_to_distribute;
|
|
||||||
assert(to_give >= 0);
|
|
||||||
assert(to_give <= resources_to_distribute);
|
|
||||||
#ifndef NDEBUG
|
|
||||||
int tmp = resources_to_distribute;
|
|
||||||
#endif
|
|
||||||
resources_to_distribute -= give(r, (int)to_give);
|
|
||||||
assert(resources_to_distribute <= tmp);
|
|
||||||
assert(resources_to_distribute >= 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(resources_to_distribute >= 0);
|
|
||||||
assert(resources_to_distribute < prev_resources_to_distribute);
|
|
||||||
#ifndef NDEBUG
|
|
||||||
prev_resources_to_distribute = resources_to_distribute;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
assert(resources_to_distribute == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace libtorrent::aux
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -273,8 +273,20 @@ namespace libtorrent
|
||||||
void set_max_connections(int limit);
|
void set_max_connections(int limit);
|
||||||
void set_max_uploads(int limit);
|
void set_max_uploads(int limit);
|
||||||
|
|
||||||
int num_uploads() const;
|
int max_connections() const { return m_max_connections; }
|
||||||
int num_connections() const;
|
int max_uploads() const { return m_max_uploads; }
|
||||||
|
|
||||||
|
int num_uploads() const { return m_num_unchoked; }
|
||||||
|
int num_connections() const
|
||||||
|
{ return m_connections.size(); }
|
||||||
|
|
||||||
|
void unchoke_peer(peer_connection& c)
|
||||||
|
{
|
||||||
|
torrent* t = c.associated_torrent().lock().get();
|
||||||
|
assert(t);
|
||||||
|
t->unchoke_peer(c);
|
||||||
|
++m_num_unchoked;
|
||||||
|
}
|
||||||
|
|
||||||
session_status status() const;
|
session_status status() const;
|
||||||
void set_peer_id(peer_id const& id);
|
void set_peer_id(peer_id const& id);
|
||||||
|
@ -417,6 +429,28 @@ namespace libtorrent
|
||||||
int m_max_uploads;
|
int m_max_uploads;
|
||||||
int m_max_connections;
|
int m_max_connections;
|
||||||
|
|
||||||
|
// the number of unchoked peers
|
||||||
|
int m_num_unchoked;
|
||||||
|
|
||||||
|
// this is initialized to the unchoke_interval
|
||||||
|
// session_setting and decreased every second.
|
||||||
|
// when it reaches zero, it is reset to the
|
||||||
|
// unchoke_interval and the unchoke set is
|
||||||
|
// recomputed.
|
||||||
|
int m_unchoke_time_scaler;
|
||||||
|
|
||||||
|
// works like unchoke_time_scaler but it
|
||||||
|
// is only decresed when the unchoke set
|
||||||
|
// is recomputed, and when it reaches zero,
|
||||||
|
// the optimistic unchoke is moved to another peer.
|
||||||
|
int m_optimistic_unchoke_time_scaler;
|
||||||
|
|
||||||
|
// works like unchoke_time_scaler. Each time
|
||||||
|
// it reaches 0, and all the connections are
|
||||||
|
// used, the worst connection will be disconnected
|
||||||
|
// from the torrent with the most peers
|
||||||
|
int m_disconnect_time_scaler;
|
||||||
|
|
||||||
// statistics gathered from all torrents.
|
// statistics gathered from all torrents.
|
||||||
stat m_stat;
|
stat m_stat;
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/alert.hpp"
|
#include "libtorrent/alert.hpp"
|
||||||
#include "libtorrent/torrent_handle.hpp"
|
#include "libtorrent/torrent_handle.hpp"
|
||||||
#include "libtorrent/torrent.hpp"
|
#include "libtorrent/torrent.hpp"
|
||||||
#include "libtorrent/allocate_resources.hpp"
|
|
||||||
#include "libtorrent/peer_request.hpp"
|
#include "libtorrent/peer_request.hpp"
|
||||||
#include "libtorrent/piece_block_progress.hpp"
|
#include "libtorrent/piece_block_progress.hpp"
|
||||||
#include "libtorrent/config.hpp"
|
#include "libtorrent/config.hpp"
|
||||||
|
|
|
@ -64,7 +64,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/alert.hpp"
|
#include "libtorrent/alert.hpp"
|
||||||
#include "libtorrent/torrent_handle.hpp"
|
#include "libtorrent/torrent_handle.hpp"
|
||||||
#include "libtorrent/torrent.hpp"
|
#include "libtorrent/torrent.hpp"
|
||||||
#include "libtorrent/allocate_resources.hpp"
|
|
||||||
#include "libtorrent/peer_request.hpp"
|
#include "libtorrent/peer_request.hpp"
|
||||||
#include "libtorrent/piece_block_progress.hpp"
|
#include "libtorrent/piece_block_progress.hpp"
|
||||||
#include "libtorrent/config.hpp"
|
#include "libtorrent/config.hpp"
|
||||||
|
@ -213,7 +212,7 @@ namespace libtorrent
|
||||||
void add_stat(size_type downloaded, size_type uploaded);
|
void add_stat(size_type downloaded, size_type uploaded);
|
||||||
|
|
||||||
// is called once every second by the main loop
|
// is called once every second by the main loop
|
||||||
void second_tick(float tick_interval);
|
void second_tick(float tick_interval) throw();
|
||||||
|
|
||||||
boost::shared_ptr<socket_type> get_socket() const { return m_socket; }
|
boost::shared_ptr<socket_type> get_socket() const { return m_socket; }
|
||||||
tcp::endpoint const& remote() const { return m_remote; }
|
tcp::endpoint const& remote() const { return m_remote; }
|
||||||
|
|
|
@ -89,7 +89,7 @@ namespace libtorrent
|
||||||
void new_connection(peer_connection& c);
|
void new_connection(peer_connection& c);
|
||||||
|
|
||||||
// the given connection was just closed
|
// the given connection was just closed
|
||||||
void connection_closed(const peer_connection& c);
|
void connection_closed(const peer_connection& c) throw();
|
||||||
|
|
||||||
// the peer has got at least one interesting piece
|
// the peer has got at least one interesting piece
|
||||||
void peer_is_interesting(peer_connection& c);
|
void peer_is_interesting(peer_connection& c);
|
||||||
|
@ -155,6 +155,13 @@ namespace libtorrent
|
||||||
// this is true if the peer is a seed
|
// this is true if the peer is a seed
|
||||||
bool seed;
|
bool seed;
|
||||||
|
|
||||||
|
// true if this peer currently is unchoked
|
||||||
|
// because of an optimistic unchoke.
|
||||||
|
// when the optimistic unchoke is moved to
|
||||||
|
// another peer, this peer will be choked
|
||||||
|
// if this is true
|
||||||
|
bool optimistically_unchoked;
|
||||||
|
|
||||||
// the time when this peer was optimistically unchoked
|
// the time when this peer was optimistically unchoked
|
||||||
// the last time.
|
// the last time.
|
||||||
libtorrent::ptime last_optimistically_unchoked;
|
libtorrent::ptime last_optimistically_unchoked;
|
||||||
|
@ -203,15 +210,7 @@ namespace libtorrent
|
||||||
peer_connection* connection;
|
peer_connection* connection;
|
||||||
};
|
};
|
||||||
|
|
||||||
int num_peers() const
|
int num_peers() const { return m_peers.size(); }
|
||||||
{
|
|
||||||
return m_peers.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
int num_uploads() const
|
|
||||||
{
|
|
||||||
return m_num_unchoked;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef std::list<peer>::iterator iterator;
|
typedef std::list<peer>::iterator iterator;
|
||||||
typedef std::list<peer>::const_iterator const_iterator;
|
typedef std::list<peer>::const_iterator const_iterator;
|
||||||
|
@ -219,9 +218,10 @@ namespace libtorrent
|
||||||
iterator end_peer() { return m_peers.end(); }
|
iterator end_peer() { return m_peers.end(); }
|
||||||
|
|
||||||
bool connect_one_peer();
|
bool connect_one_peer();
|
||||||
|
bool disconnect_one_peer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/*
|
||||||
bool unchoke_one_peer();
|
bool unchoke_one_peer();
|
||||||
void choke_one_peer();
|
void choke_one_peer();
|
||||||
iterator find_choke_candidate();
|
iterator find_choke_candidate();
|
||||||
|
@ -233,8 +233,7 @@ namespace libtorrent
|
||||||
void seed_choke_one_peer();
|
void seed_choke_one_peer();
|
||||||
iterator find_seed_choke_candidate();
|
iterator find_seed_choke_candidate();
|
||||||
iterator find_seed_unchoke_candidate();
|
iterator find_seed_unchoke_candidate();
|
||||||
|
*/
|
||||||
bool disconnect_one_peer();
|
|
||||||
iterator find_disconnect_candidate();
|
iterator find_disconnect_candidate();
|
||||||
iterator find_connect_candidate();
|
iterator find_connect_candidate();
|
||||||
|
|
||||||
|
@ -242,10 +241,6 @@ namespace libtorrent
|
||||||
|
|
||||||
torrent* m_torrent;
|
torrent* m_torrent;
|
||||||
|
|
||||||
// the number of unchoked peers
|
|
||||||
// at any given time
|
|
||||||
int m_num_unchoked;
|
|
||||||
|
|
||||||
// free download we have got that hasn't
|
// free download we have got that hasn't
|
||||||
// been distributed yet.
|
// been distributed yet.
|
||||||
size_type m_available_free_upload;
|
size_type m_available_free_upload;
|
||||||
|
@ -253,7 +248,7 @@ namespace libtorrent
|
||||||
// if there is a connection limit,
|
// if there is a connection limit,
|
||||||
// we disconnect one peer every minute in hope of
|
// we disconnect one peer every minute in hope of
|
||||||
// establishing a connection with a better peer
|
// establishing a connection with a better peer
|
||||||
ptime m_last_optimistic_disconnect;
|
// ptime m_last_optimistic_disconnect;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,99 +0,0 @@
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2003, Magnus Jonsson, Arvid Norberg
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions
|
|
||||||
are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in
|
|
||||||
the documentation and/or other materials provided with the distribution.
|
|
||||||
* Neither the name of the author nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived
|
|
||||||
from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TORRENT_RESOURCE_REQUEST_HPP_INCLUDED
|
|
||||||
#define TORRENT_RESOURCE_REQUEST_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <boost/integer_traits.hpp>
|
|
||||||
|
|
||||||
#ifdef min
|
|
||||||
#undef min
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef max
|
|
||||||
#undef max
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "libtorrent/config.hpp"
|
|
||||||
|
|
||||||
namespace libtorrent
|
|
||||||
{
|
|
||||||
struct TORRENT_EXPORT resource_request
|
|
||||||
{
|
|
||||||
resource_request()
|
|
||||||
: used(0)
|
|
||||||
, min(0)
|
|
||||||
, max(0)
|
|
||||||
, given(0)
|
|
||||||
, leftovers(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
resource_request(int used_, int min_, int max_, int given_)
|
|
||||||
: used(used_)
|
|
||||||
, min(min_)
|
|
||||||
, max(max_)
|
|
||||||
, given(given_)
|
|
||||||
, leftovers(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
int left() const
|
|
||||||
{
|
|
||||||
assert(given <= max);
|
|
||||||
assert(given >= min);
|
|
||||||
assert(used >= 0);
|
|
||||||
return (std::max)(given - used, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset() { used = leftovers; leftovers = 0; }
|
|
||||||
|
|
||||||
static const int inf = boost::integer_traits<int>::const_max;
|
|
||||||
|
|
||||||
// right now I'm actively using this amount
|
|
||||||
int used;
|
|
||||||
|
|
||||||
// given cannot be smaller than min
|
|
||||||
// and not greater than max.
|
|
||||||
int min;
|
|
||||||
int max;
|
|
||||||
|
|
||||||
// Reply: Okay, you're allowed to use this amount (a compromise):
|
|
||||||
int given;
|
|
||||||
|
|
||||||
// this is the amount of resources that exceeded the
|
|
||||||
// given limit. When the used field is reset (after resources
|
|
||||||
// have been distributed), it is reset to this number.
|
|
||||||
int leftovers;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -61,7 +61,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/version.hpp"
|
#include "libtorrent/version.hpp"
|
||||||
#include "libtorrent/fingerprint.hpp"
|
#include "libtorrent/fingerprint.hpp"
|
||||||
|
|
||||||
#include "libtorrent/resource_request.hpp"
|
|
||||||
#include "libtorrent/storage.hpp"
|
#include "libtorrent/storage.hpp"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
@ -266,12 +265,6 @@ namespace libtorrent
|
||||||
void stop_natpmp();
|
void stop_natpmp();
|
||||||
void stop_upnp();
|
void stop_upnp();
|
||||||
|
|
||||||
// Resource management used for global limits.
|
|
||||||
resource_request m_ul_bandwidth_quota;
|
|
||||||
resource_request m_dl_bandwidth_quota;
|
|
||||||
resource_request m_uploads_quota;
|
|
||||||
resource_request m_connections_quota;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// just a way to initialize boost.filesystem
|
// just a way to initialize boost.filesystem
|
||||||
|
|
|
@ -105,7 +105,8 @@ namespace libtorrent
|
||||||
, send_redundant_have(false)
|
, send_redundant_have(false)
|
||||||
, lazy_bitfields(true)
|
, lazy_bitfields(true)
|
||||||
, inactivity_timeout(600)
|
, inactivity_timeout(600)
|
||||||
, unchoke_interval(20)
|
, unchoke_interval(15)
|
||||||
|
, optimistic_unchoke_multiplier(4)
|
||||||
, num_want(200)
|
, num_want(200)
|
||||||
, initial_picker_threshold(4)
|
, initial_picker_threshold(4)
|
||||||
, allowed_fast_set_size(10)
|
, allowed_fast_set_size(10)
|
||||||
|
@ -242,6 +243,10 @@ namespace libtorrent
|
||||||
// the number of seconds between chokes/unchokes
|
// the number of seconds between chokes/unchokes
|
||||||
int unchoke_interval;
|
int unchoke_interval;
|
||||||
|
|
||||||
|
// the number of unchoke intervals between
|
||||||
|
// optimistic unchokes
|
||||||
|
int optimistic_unchoke_multiplier;
|
||||||
|
|
||||||
// if this is set, this IP will be reported do the
|
// if this is set, this IP will be reported do the
|
||||||
// tracker in the ip= parameter.
|
// tracker in the ip= parameter.
|
||||||
address announce_ip;
|
address announce_ip;
|
||||||
|
|
|
@ -62,7 +62,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/tracker_manager.hpp"
|
#include "libtorrent/tracker_manager.hpp"
|
||||||
#include "libtorrent/stat.hpp"
|
#include "libtorrent/stat.hpp"
|
||||||
#include "libtorrent/alert.hpp"
|
#include "libtorrent/alert.hpp"
|
||||||
#include "libtorrent/resource_request.hpp"
|
|
||||||
#include "libtorrent/piece_picker.hpp"
|
#include "libtorrent/piece_picker.hpp"
|
||||||
#include "libtorrent/config.hpp"
|
#include "libtorrent/config.hpp"
|
||||||
#include "libtorrent/escape_string.hpp"
|
#include "libtorrent/escape_string.hpp"
|
||||||
|
@ -154,10 +153,6 @@ namespace libtorrent
|
||||||
bool verify_resume_data(entry& rd, std::string& error)
|
bool verify_resume_data(entry& rd, std::string& error)
|
||||||
{ assert(m_storage); return m_storage->verify_resume_data(rd, error); }
|
{ assert(m_storage); return m_storage->verify_resume_data(rd, error); }
|
||||||
|
|
||||||
// is called every second by session. This will
|
|
||||||
// caclulate the upload/download and number
|
|
||||||
// of connections this torrent needs. And prepare
|
|
||||||
// it for being used by allocate_resources.
|
|
||||||
void second_tick(stat& accumulator, float tick_interval);
|
void second_tick(stat& accumulator, float tick_interval);
|
||||||
|
|
||||||
// debug purpose only
|
// debug purpose only
|
||||||
|
@ -254,6 +249,15 @@ namespace libtorrent
|
||||||
void remove_url_seed(std::string const& url)
|
void remove_url_seed(std::string const& url)
|
||||||
{ m_web_seeds.erase(url); }
|
{ m_web_seeds.erase(url); }
|
||||||
|
|
||||||
|
std::set<std::string> url_seeds() const
|
||||||
|
{ return m_web_seeds; }
|
||||||
|
|
||||||
|
bool free_upload_slots() const
|
||||||
|
{ return m_num_uploads < m_max_uploads; }
|
||||||
|
|
||||||
|
void choke_peer(peer_connection& c);
|
||||||
|
bool unchoke_peer(peer_connection& c);
|
||||||
|
|
||||||
// used by peer_connection to attach itself to a torrent
|
// used by peer_connection to attach itself to a torrent
|
||||||
// since incoming connections don't know what torrent
|
// since incoming connections don't know what torrent
|
||||||
// they're a part of until they have received an info_hash.
|
// they're a part of until they have received an info_hash.
|
||||||
|
@ -516,11 +520,6 @@ namespace libtorrent
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// RESOURCE MANAGEMENT
|
// RESOURCE MANAGEMENT
|
||||||
|
|
||||||
void distribute_resources(float tick_interval);
|
|
||||||
|
|
||||||
resource_request m_uploads_quota;
|
|
||||||
resource_request m_connections_quota;
|
|
||||||
|
|
||||||
void set_peer_upload_limit(tcp::endpoint ip, int limit);
|
void set_peer_upload_limit(tcp::endpoint ip, int limit);
|
||||||
void set_peer_download_limit(tcp::endpoint ip, int limit);
|
void set_peer_download_limit(tcp::endpoint ip, int limit);
|
||||||
|
|
||||||
|
@ -530,7 +529,9 @@ namespace libtorrent
|
||||||
int download_limit() const;
|
int download_limit() const;
|
||||||
|
|
||||||
void set_max_uploads(int limit);
|
void set_max_uploads(int limit);
|
||||||
|
int max_uploads() const { return m_max_uploads; }
|
||||||
void set_max_connections(int limit);
|
void set_max_connections(int limit);
|
||||||
|
int max_connections() const { return m_max_connections; }
|
||||||
void move_storage(fs::path const& save_path);
|
void move_storage(fs::path const& save_path);
|
||||||
|
|
||||||
// unless this returns true, new connections must wait
|
// unless this returns true, new connections must wait
|
||||||
|
@ -705,9 +706,9 @@ namespace libtorrent
|
||||||
// determine the timeout until next try.
|
// determine the timeout until next try.
|
||||||
int m_failed_trackers;
|
int m_failed_trackers;
|
||||||
|
|
||||||
// this is a counter that is increased every
|
// this is a counter that is decreased every
|
||||||
// second, and when it reaches 10, the policy::pulse()
|
// second, and when it reaches 0, the policy::pulse()
|
||||||
// is called and the time scaler is reset to 0.
|
// is called and the time scaler is reset to 10.
|
||||||
int m_time_scaler;
|
int m_time_scaler;
|
||||||
|
|
||||||
// the bitmask that says which pieces we have
|
// the bitmask that says which pieces we have
|
||||||
|
@ -775,6 +776,15 @@ namespace libtorrent
|
||||||
|
|
||||||
storage_constructor_type m_storage_constructor;
|
storage_constructor_type m_storage_constructor;
|
||||||
|
|
||||||
|
// the maximum number of uploads for this torrent
|
||||||
|
int m_max_uploads;
|
||||||
|
|
||||||
|
// the number of unchoked peers in this torrent
|
||||||
|
int m_num_uploads;
|
||||||
|
|
||||||
|
// the maximum number of connections for this torrent
|
||||||
|
int m_max_connections;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||||
typedef std::list<boost::shared_ptr<torrent_plugin> > extension_list_t;
|
typedef std::list<boost::shared_ptr<torrent_plugin> > extension_list_t;
|
||||||
extension_list_t m_extensions;
|
extension_list_t m_extensions;
|
||||||
|
|
|
@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#define TORRENT_TORRENT_HANDLE_HPP_INCLUDED
|
#define TORRENT_TORRENT_HANDLE_HPP_INCLUDED
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(push, 1)
|
#pragma warning(push, 1)
|
||||||
|
@ -273,7 +274,9 @@ namespace libtorrent
|
||||||
std::vector<announce_entry> const& trackers() const;
|
std::vector<announce_entry> const& trackers() const;
|
||||||
void replace_trackers(std::vector<announce_entry> const&) const;
|
void replace_trackers(std::vector<announce_entry> const&) const;
|
||||||
|
|
||||||
void add_url_seed(std::string const& url);
|
void add_url_seed(std::string const& url) const;
|
||||||
|
void remove_url_seed(std::string const& url) const;
|
||||||
|
std::set<std::string> url_seeds() const;
|
||||||
|
|
||||||
bool has_metadata() const;
|
bool has_metadata() const;
|
||||||
const torrent_info& get_torrent_info() const;
|
const torrent_info& get_torrent_info() const;
|
||||||
|
|
|
@ -65,7 +65,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/alert.hpp"
|
#include "libtorrent/alert.hpp"
|
||||||
#include "libtorrent/torrent_handle.hpp"
|
#include "libtorrent/torrent_handle.hpp"
|
||||||
#include "libtorrent/torrent.hpp"
|
#include "libtorrent/torrent.hpp"
|
||||||
#include "libtorrent/allocate_resources.hpp"
|
|
||||||
#include "libtorrent/peer_request.hpp"
|
#include "libtorrent/peer_request.hpp"
|
||||||
#include "libtorrent/piece_block_progress.hpp"
|
#include "libtorrent/piece_block_progress.hpp"
|
||||||
#include "libtorrent/config.hpp"
|
#include "libtorrent/config.hpp"
|
||||||
|
|
|
@ -12,8 +12,7 @@ kademlia/rpc_manager.cpp \
|
||||||
kademlia/traversal_algorithm.cpp
|
kademlia/traversal_algorithm.cpp
|
||||||
endif
|
endif
|
||||||
|
|
||||||
libtorrent_la_SOURCES = allocate_resources.cpp \
|
libtorrent_la_SOURCES = entry.cpp escape_string.cpp \
|
||||||
entry.cpp escape_string.cpp \
|
|
||||||
peer_connection.cpp bt_peer_connection.cpp web_peer_connection.cpp \
|
peer_connection.cpp bt_peer_connection.cpp web_peer_connection.cpp \
|
||||||
natpmp.cpp piece_picker.cpp policy.cpp session.cpp session_impl.cpp sha1.cpp \
|
natpmp.cpp piece_picker.cpp policy.cpp session.cpp session_impl.cpp sha1.cpp \
|
||||||
stat.cpp storage.cpp torrent.cpp torrent_handle.cpp pe_crypto.cpp \
|
stat.cpp storage.cpp torrent.cpp torrent_handle.cpp pe_crypto.cpp \
|
||||||
|
@ -28,8 +27,6 @@ $(kademlia_sources)
|
||||||
noinst_HEADERS = \
|
noinst_HEADERS = \
|
||||||
$(top_srcdir)/include/libtorrent/alert.hpp \
|
$(top_srcdir)/include/libtorrent/alert.hpp \
|
||||||
$(top_srcdir)/include/libtorrent/alert_types.hpp \
|
$(top_srcdir)/include/libtorrent/alert_types.hpp \
|
||||||
$(top_srcdir)/include/libtorrent/allocate_resources.hpp \
|
|
||||||
$(top_srcdir)/include/libtorrent/aux_/allocate_resources_impl.hpp \
|
|
||||||
$(top_srcdir)/include/libtorrent/aux_/session_impl.hpp \
|
$(top_srcdir)/include/libtorrent/aux_/session_impl.hpp \
|
||||||
$(top_srcdir)/include/libtorrent/bandwidth_manager.hpp \
|
$(top_srcdir)/include/libtorrent/bandwidth_manager.hpp \
|
||||||
$(top_srcdir)/include/libtorrent/bencode.hpp \
|
$(top_srcdir)/include/libtorrent/bencode.hpp \
|
||||||
|
@ -71,7 +68,6 @@ $(top_srcdir)/include/libtorrent/peer_request.hpp \
|
||||||
$(top_srcdir)/include/libtorrent/piece_block_progress.hpp \
|
$(top_srcdir)/include/libtorrent/piece_block_progress.hpp \
|
||||||
$(top_srcdir)/include/libtorrent/piece_picker.hpp \
|
$(top_srcdir)/include/libtorrent/piece_picker.hpp \
|
||||||
$(top_srcdir)/include/libtorrent/policy.hpp \
|
$(top_srcdir)/include/libtorrent/policy.hpp \
|
||||||
$(top_srcdir)/include/libtorrent/resource_request.hpp \
|
|
||||||
$(top_srcdir)/include/libtorrent/session.hpp \
|
$(top_srcdir)/include/libtorrent/session.hpp \
|
||||||
$(top_srcdir)/include/libtorrent/size_type.hpp \
|
$(top_srcdir)/include/libtorrent/size_type.hpp \
|
||||||
$(top_srcdir)/include/libtorrent/socket.hpp \
|
$(top_srcdir)/include/libtorrent/socket.hpp \
|
||||||
|
|
|
@ -1,225 +0,0 @@
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2006, Magnus Jonsson, Arvid Norberg
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions
|
|
||||||
are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in
|
|
||||||
the documentation and/or other materials provided with the distribution.
|
|
||||||
* Neither the name of the author nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived
|
|
||||||
from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
//The Standard Library defines the two template functions std::min()
|
|
||||||
//and std::max() in the <algorithm> header. In general, you should
|
|
||||||
//use these template functions for calculating the min and max values
|
|
||||||
//of a pair. Unfortunately, Visual C++ does not define these function
|
|
||||||
// templates. This is because the names min and max clash with
|
|
||||||
//the traditional min and max macros defined in <windows.h>.
|
|
||||||
//As a workaround, Visual C++ defines two alternative templates with
|
|
||||||
//identical functionality called _cpp_min() and _cpp_max(). You can
|
|
||||||
//use them instead of std::min() and std::max().To disable the
|
|
||||||
//generation of the min and max macros in Visual C++, #define
|
|
||||||
//NOMINMAX before #including <windows.h>.
|
|
||||||
|
|
||||||
#include "libtorrent/pch.hpp"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
//support boost1.32.0(2004-11-19 18:47)
|
|
||||||
//now all libs can be compiled and linked with static module
|
|
||||||
#define NOMINMAX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "libtorrent/allocate_resources.hpp"
|
|
||||||
#include "libtorrent/size_type.hpp"
|
|
||||||
#include "libtorrent/peer_connection.hpp"
|
|
||||||
#include "libtorrent/torrent.hpp"
|
|
||||||
#include "libtorrent/aux_/allocate_resources_impl.hpp"
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <boost/limits.hpp>
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1310
|
|
||||||
#define for if (false) {} else for
|
|
||||||
#else
|
|
||||||
#include <boost/iterator/transform_iterator.hpp>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace libtorrent
|
|
||||||
{
|
|
||||||
int saturated_add(int a, int b)
|
|
||||||
{
|
|
||||||
assert(a >= 0);
|
|
||||||
assert(b >= 0);
|
|
||||||
assert(a <= resource_request::inf);
|
|
||||||
assert(b <= resource_request::inf);
|
|
||||||
assert(resource_request::inf + resource_request::inf < 0);
|
|
||||||
|
|
||||||
unsigned int sum = unsigned(a) + unsigned(b);
|
|
||||||
if (sum > unsigned(resource_request::inf))
|
|
||||||
sum = resource_request::inf;
|
|
||||||
|
|
||||||
assert(sum >= unsigned(a) && sum >= unsigned(b));
|
|
||||||
return int(sum);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1310
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
struct iterator_wrapper
|
|
||||||
{
|
|
||||||
typedef std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator orig_iter;
|
|
||||||
|
|
||||||
orig_iter iter;
|
|
||||||
|
|
||||||
iterator_wrapper(orig_iter i): iter(i) {}
|
|
||||||
void operator++() { ++iter; }
|
|
||||||
torrent& operator*() { return *(iter->second); }
|
|
||||||
bool operator==(const iterator_wrapper& i) const
|
|
||||||
{ return iter == i.iter; }
|
|
||||||
bool operator!=(const iterator_wrapper& i) const
|
|
||||||
{ return iter != i.iter; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct iterator_wrapper2
|
|
||||||
{
|
|
||||||
typedef std::map<tcp::endpoint, peer_connection*>::iterator orig_iter;
|
|
||||||
|
|
||||||
orig_iter iter;
|
|
||||||
|
|
||||||
iterator_wrapper2(orig_iter i): iter(i) {}
|
|
||||||
void operator++() { ++iter; }
|
|
||||||
peer_connection& operator*() { return *(iter->second); }
|
|
||||||
bool operator==(const iterator_wrapper2& i) const
|
|
||||||
{ return iter == i.iter; }
|
|
||||||
bool operator!=(const iterator_wrapper2& i) const
|
|
||||||
{ return iter != i.iter; }
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void allocate_resources(
|
|
||||||
int resources
|
|
||||||
, std::map<sha1_hash, boost::shared_ptr<torrent> >& c
|
|
||||||
, resource_request torrent::* res)
|
|
||||||
{
|
|
||||||
aux::allocate_resources_impl(
|
|
||||||
resources
|
|
||||||
, detail::iterator_wrapper(c.begin())
|
|
||||||
, detail::iterator_wrapper(c.end())
|
|
||||||
, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
void allocate_resources(
|
|
||||||
int resources
|
|
||||||
, std::map<tcp::endpoint, peer_connection*>& c
|
|
||||||
, resource_request peer_connection::* res)
|
|
||||||
{
|
|
||||||
aux::allocate_resources_impl(
|
|
||||||
resources
|
|
||||||
, detail::iterator_wrapper2(c.begin())
|
|
||||||
, detail::iterator_wrapper2(c.end())
|
|
||||||
, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
namespace aux
|
|
||||||
{
|
|
||||||
peer_connection& pick_peer(
|
|
||||||
std::pair<boost::shared_ptr<stream_socket>
|
|
||||||
, boost::intrusive_ptr<peer_connection> > const& p)
|
|
||||||
{
|
|
||||||
return *p.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
peer_connection& pick_peer2(
|
|
||||||
std::pair<tcp::endpoint, peer_connection*> const& p)
|
|
||||||
{
|
|
||||||
return *p.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
torrent& deref(std::pair<sha1_hash, boost::shared_ptr<torrent> > const& p)
|
|
||||||
{
|
|
||||||
return *p.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
session& deref(session* p)
|
|
||||||
{
|
|
||||||
return *p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void allocate_resources(
|
|
||||||
int resources
|
|
||||||
, std::map<sha1_hash, boost::shared_ptr<torrent> >& c
|
|
||||||
, resource_request torrent::* res)
|
|
||||||
{
|
|
||||||
typedef std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator orig_iter;
|
|
||||||
typedef std::pair<sha1_hash, boost::shared_ptr<torrent> > in_param;
|
|
||||||
typedef boost::transform_iterator<torrent& (*)(in_param const&), orig_iter> new_iter;
|
|
||||||
|
|
||||||
aux::allocate_resources_impl(
|
|
||||||
resources
|
|
||||||
, new_iter(c.begin(), &aux::deref)
|
|
||||||
, new_iter(c.end(), &aux::deref)
|
|
||||||
, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
void allocate_resources(
|
|
||||||
int resources
|
|
||||||
, std::map<tcp::endpoint, peer_connection*>& c
|
|
||||||
, resource_request peer_connection::* res)
|
|
||||||
{
|
|
||||||
typedef std::map<tcp::endpoint, peer_connection*>::iterator orig_iter;
|
|
||||||
typedef std::pair<tcp::endpoint, peer_connection*> in_param;
|
|
||||||
typedef boost::transform_iterator<peer_connection& (*)(in_param const&), orig_iter> new_iter;
|
|
||||||
|
|
||||||
aux::allocate_resources_impl(
|
|
||||||
resources
|
|
||||||
, new_iter(c.begin(), &aux::pick_peer2)
|
|
||||||
, new_iter(c.end(), &aux::pick_peer2)
|
|
||||||
, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
void allocate_resources(
|
|
||||||
int resources
|
|
||||||
, std::vector<session*>& _sessions
|
|
||||||
, resource_request session::* res)
|
|
||||||
{
|
|
||||||
typedef std::vector<session*>::iterator orig_iter;
|
|
||||||
typedef session* in_param;
|
|
||||||
typedef boost::transform_iterator<session& (*)(in_param), orig_iter> new_iter;
|
|
||||||
|
|
||||||
aux::allocate_resources_impl(
|
|
||||||
resources
|
|
||||||
, new_iter(_sessions.begin(), &aux::deref)
|
|
||||||
, new_iter(_sessions.end(), &aux::deref)
|
|
||||||
, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace libtorrent
|
|
|
@ -1369,7 +1369,7 @@ namespace libtorrent
|
||||||
assert(t->is_seed() == (std::count(bitfield.begin(), bitfield.end(), true) == num_pieces));
|
assert(t->is_seed() == (std::count(bitfield.begin(), bitfield.end(), true) == num_pieces));
|
||||||
if (t->is_seed() && m_ses.settings().lazy_bitfields)
|
if (t->is_seed() && m_ses.settings().lazy_bitfields)
|
||||||
{
|
{
|
||||||
num_lazy_pieces = std::min(50, num_pieces / 10);
|
num_lazy_pieces = (std::min)(50, num_pieces / 10);
|
||||||
if (num_lazy_pieces < 1) num_lazy_pieces = 1;
|
if (num_lazy_pieces < 1) num_lazy_pieces = 1;
|
||||||
for (int i = 0; i < num_pieces; ++i)
|
for (int i = 0; i < num_pieces; ++i)
|
||||||
{
|
{
|
||||||
|
@ -1735,7 +1735,7 @@ namespace libtorrent
|
||||||
if (m_sync_bytes_read >= 512)
|
if (m_sync_bytes_read >= 512)
|
||||||
throw protocol_error("sync hash not found within 532 bytes");
|
throw protocol_error("sync hash not found within 532 bytes");
|
||||||
|
|
||||||
cut_receive_buffer(bytes_processed, std::min(packet_size(), (512+20) - m_sync_bytes_read));
|
cut_receive_buffer(bytes_processed, (std::min)(packet_size(), (512+20) - m_sync_bytes_read));
|
||||||
|
|
||||||
assert(!packet_finished());
|
assert(!packet_finished());
|
||||||
return;
|
return;
|
||||||
|
@ -1873,7 +1873,7 @@ namespace libtorrent
|
||||||
if (m_sync_bytes_read >= 512)
|
if (m_sync_bytes_read >= 512)
|
||||||
throw protocol_error("sync verification constant not found within 520 bytes");
|
throw protocol_error("sync verification constant not found within 520 bytes");
|
||||||
|
|
||||||
cut_receive_buffer(bytes_processed, std::min(packet_size(), (512+8) - m_sync_bytes_read));
|
cut_receive_buffer(bytes_processed, (std::min)(packet_size(), (512+8) - m_sync_bytes_read));
|
||||||
|
|
||||||
assert(!packet_finished());
|
assert(!packet_finished());
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -250,7 +250,7 @@ namespace libtorrent
|
||||||
assert(m_state == read_body);
|
assert(m_state == read_body);
|
||||||
if (m_content_length >= 0)
|
if (m_content_length >= 0)
|
||||||
return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos
|
return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos
|
||||||
, m_recv_buffer.begin + std::min(m_recv_pos
|
, m_recv_buffer.begin + (std::min)(m_recv_pos
|
||||||
, m_body_start_pos + m_content_length));
|
, m_body_start_pos + m_content_length));
|
||||||
else
|
else
|
||||||
return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos
|
return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos
|
||||||
|
@ -408,7 +408,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
m_send_buffer += "numwant=";
|
m_send_buffer += "numwant=";
|
||||||
m_send_buffer += boost::lexical_cast<std::string>(
|
m_send_buffer += boost::lexical_cast<std::string>(
|
||||||
std::min(req.num_want, 999));
|
(std::min)(req.num_want, 999));
|
||||||
m_send_buffer += '&';
|
m_send_buffer += '&';
|
||||||
}
|
}
|
||||||
if (m_settings.announce_ip != address() && !url_has_argument(request, "ip"))
|
if (m_settings.announce_ip != address() && !url_has_argument(request, "ip"))
|
||||||
|
|
|
@ -109,8 +109,8 @@ namespace libtorrent
|
||||||
, m_prefer_whole_pieces(false)
|
, m_prefer_whole_pieces(false)
|
||||||
, m_request_large_blocks(false)
|
, m_request_large_blocks(false)
|
||||||
, m_non_prioritized(false)
|
, m_non_prioritized(false)
|
||||||
, m_upload_limit(resource_request::inf)
|
, m_upload_limit(bandwidth_limit::inf)
|
||||||
, m_download_limit(resource_request::inf)
|
, m_download_limit(bandwidth_limit::inf)
|
||||||
, m_peer_info(peerinfo)
|
, m_peer_info(peerinfo)
|
||||||
, m_speed(slow)
|
, m_speed(slow)
|
||||||
, m_connection_ticket(-1)
|
, m_connection_ticket(-1)
|
||||||
|
@ -185,8 +185,8 @@ namespace libtorrent
|
||||||
, m_prefer_whole_pieces(false)
|
, m_prefer_whole_pieces(false)
|
||||||
, m_request_large_blocks(false)
|
, m_request_large_blocks(false)
|
||||||
, m_non_prioritized(false)
|
, m_non_prioritized(false)
|
||||||
, m_upload_limit(resource_request::inf)
|
, m_upload_limit(bandwidth_limit::inf)
|
||||||
, m_download_limit(resource_request::inf)
|
, m_download_limit(bandwidth_limit::inf)
|
||||||
, m_peer_info(peerinfo)
|
, m_peer_info(peerinfo)
|
||||||
, m_speed(slow)
|
, m_speed(slow)
|
||||||
, m_remote_bytes_dled(0)
|
, m_remote_bytes_dled(0)
|
||||||
|
@ -441,8 +441,6 @@ namespace libtorrent
|
||||||
|
|
||||||
void peer_connection::add_stat(size_type downloaded, size_type uploaded)
|
void peer_connection::add_stat(size_type downloaded, size_type uploaded)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
|
||||||
|
|
||||||
m_statistics.add_stat(downloaded, uploaded);
|
m_statistics.add_stat(downloaded, uploaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -527,27 +525,20 @@ namespace libtorrent
|
||||||
&& (p.start % t->block_size() == 0);
|
&& (p.start % t->block_size() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct disconnect_torrent
|
|
||||||
{
|
|
||||||
disconnect_torrent(boost::weak_ptr<torrent>& t): m_t(&t) {}
|
|
||||||
~disconnect_torrent() { if (m_t) m_t->reset(); }
|
|
||||||
void cancel() { m_t = 0; }
|
|
||||||
private:
|
|
||||||
boost::weak_ptr<torrent>* m_t;
|
|
||||||
};
|
|
||||||
|
|
||||||
void peer_connection::attach_to_torrent(sha1_hash const& ih)
|
void peer_connection::attach_to_torrent(sha1_hash const& ih)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
assert(!m_disconnecting);
|
assert(!m_disconnecting);
|
||||||
m_torrent = m_ses.find_torrent(ih);
|
assert(m_torrent.expired());
|
||||||
|
boost::weak_ptr<torrent> wpt = m_ses.find_torrent(ih);
|
||||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
boost::shared_ptr<torrent> t = wpt.lock();
|
||||||
|
|
||||||
if (t && t->is_aborted())
|
if (t && t->is_aborted())
|
||||||
{
|
{
|
||||||
m_torrent.reset();
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
|
(*m_logger) << " *** the torrent has been aborted\n";
|
||||||
|
#endif
|
||||||
t.reset();
|
t.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,12 +546,18 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
// we couldn't find the torrent!
|
// we couldn't find the torrent!
|
||||||
#ifdef TORRENT_VERBOSE_LOGGING
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
(*m_logger) << " couldn't find a torrent with the given info_hash: " << ih << "\n";
|
(*m_logger) << " *** couldn't find a torrent with the given info_hash: " << ih << "\n";
|
||||||
|
(*m_logger) << " torrents:\n";
|
||||||
|
session_impl::torrent_map const& torrents = m_ses.m_torrents;
|
||||||
|
for (session_impl::torrent_map::const_iterator i = torrents.begin()
|
||||||
|
, end(torrents.end()); i != end; ++i)
|
||||||
|
{
|
||||||
|
(*m_logger) << " " << i->second->torrent_file().info_hash() << "\n";
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
throw std::runtime_error("got info-hash that is not in our session");
|
throw std::runtime_error("got info-hash that is not in our session");
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnect_torrent disconnect(m_torrent);
|
|
||||||
if (t->is_paused())
|
if (t->is_paused())
|
||||||
{
|
{
|
||||||
// paused torrents will not accept
|
// paused torrents will not accept
|
||||||
|
@ -571,21 +568,27 @@ namespace libtorrent
|
||||||
throw std::runtime_error("connection rejected by paused torrent");
|
throw std::runtime_error("connection rejected by paused torrent");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(m_torrent.expired());
|
||||||
// check to make sure we don't have another connection with the same
|
// check to make sure we don't have another connection with the same
|
||||||
// info_hash and peer_id. If we do. close this connection.
|
// info_hash and peer_id. If we do. close this connection.
|
||||||
t->attach_peer(this);
|
t->attach_peer(this);
|
||||||
|
m_torrent = wpt;
|
||||||
|
|
||||||
|
assert(!m_torrent.expired());
|
||||||
|
|
||||||
// if the torrent isn't ready to accept
|
// if the torrent isn't ready to accept
|
||||||
// connections yet, we'll have to wait with
|
// connections yet, we'll have to wait with
|
||||||
// our initialization
|
// our initialization
|
||||||
if (t->ready_for_connections()) init();
|
if (t->ready_for_connections()) init();
|
||||||
|
|
||||||
|
assert(!m_torrent.expired());
|
||||||
|
|
||||||
// assume the other end has no pieces
|
// assume the other end has no pieces
|
||||||
// if we don't have valid metadata yet,
|
// if we don't have valid metadata yet,
|
||||||
// leave the vector unallocated
|
// leave the vector unallocated
|
||||||
assert(m_num_pieces == 0);
|
assert(m_num_pieces == 0);
|
||||||
std::fill(m_have_piece.begin(), m_have_piece.end(), false);
|
std::fill(m_have_piece.begin(), m_have_piece.end(), false);
|
||||||
disconnect.cancel();
|
assert(!m_torrent.expired());
|
||||||
}
|
}
|
||||||
|
|
||||||
// message handlers
|
// message handlers
|
||||||
|
@ -1543,7 +1546,7 @@ namespace libtorrent
|
||||||
|
|
||||||
// if the peer has the piece and we want
|
// if the peer has the piece and we want
|
||||||
// to download it, request it
|
// to download it, request it
|
||||||
if (m_have_piece.size() > index
|
if (int(m_have_piece.size()) > index
|
||||||
&& m_have_piece[index]
|
&& m_have_piece[index]
|
||||||
&& t->has_picker()
|
&& t->has_picker()
|
||||||
&& t->picker().piece_priority(index) > 0)
|
&& t->picker().piece_priority(index) > 0)
|
||||||
|
@ -1656,7 +1659,7 @@ namespace libtorrent
|
||||||
|
|
||||||
int block_offset = block.block_index * t->block_size();
|
int block_offset = block.block_index * t->block_size();
|
||||||
int block_size
|
int block_size
|
||||||
= std::min((int)t->torrent_file().piece_size(block.piece_index)-block_offset,
|
= (std::min)((int)t->torrent_file().piece_size(block.piece_index)-block_offset,
|
||||||
t->block_size());
|
t->block_size());
|
||||||
assert(block_size > 0);
|
assert(block_size > 0);
|
||||||
assert(block_size <= t->block_size());
|
assert(block_size <= t->block_size());
|
||||||
|
@ -1757,7 +1760,7 @@ namespace libtorrent
|
||||||
piece_block block = m_request_queue.front();
|
piece_block block = m_request_queue.front();
|
||||||
|
|
||||||
int block_offset = block.block_index * t->block_size();
|
int block_offset = block.block_index * t->block_size();
|
||||||
int block_size = std::min((int)t->torrent_file().piece_size(
|
int block_size = (std::min)((int)t->torrent_file().piece_size(
|
||||||
block.piece_index) - block_offset, t->block_size());
|
block.piece_index) - block_offset, t->block_size());
|
||||||
assert(block_size > 0);
|
assert(block_size > 0);
|
||||||
assert(block_size <= t->block_size());
|
assert(block_size <= t->block_size());
|
||||||
|
@ -1797,7 +1800,7 @@ namespace libtorrent
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
block_offset = block.block_index * t->block_size();
|
block_offset = block.block_index * t->block_size();
|
||||||
block_size = std::min((int)t->torrent_file().piece_size(
|
block_size = (std::min)((int)t->torrent_file().piece_size(
|
||||||
block.piece_index) - block_offset, t->block_size());
|
block.piece_index) - block_offset, t->block_size());
|
||||||
assert(block_size > 0);
|
assert(block_size > 0);
|
||||||
assert(block_size <= t->block_size());
|
assert(block_size <= t->block_size());
|
||||||
|
@ -1900,7 +1903,7 @@ namespace libtorrent
|
||||||
void peer_connection::set_upload_limit(int limit)
|
void peer_connection::set_upload_limit(int limit)
|
||||||
{
|
{
|
||||||
assert(limit >= -1);
|
assert(limit >= -1);
|
||||||
if (limit == -1) limit = resource_request::inf;
|
if (limit == -1) limit = std::numeric_limits<int>::max();
|
||||||
if (limit < 10) limit = 10;
|
if (limit < 10) limit = 10;
|
||||||
m_upload_limit = limit;
|
m_upload_limit = limit;
|
||||||
m_bandwidth_limit[upload_channel].throttle(m_upload_limit);
|
m_bandwidth_limit[upload_channel].throttle(m_upload_limit);
|
||||||
|
@ -1909,7 +1912,7 @@ namespace libtorrent
|
||||||
void peer_connection::set_download_limit(int limit)
|
void peer_connection::set_download_limit(int limit)
|
||||||
{
|
{
|
||||||
assert(limit >= -1);
|
assert(limit >= -1);
|
||||||
if (limit == -1) limit = resource_request::inf;
|
if (limit == -1) limit = std::numeric_limits<int>::max();
|
||||||
if (limit < 10) limit = 10;
|
if (limit < 10) limit = 10;
|
||||||
m_download_limit = limit;
|
m_download_limit = limit;
|
||||||
m_bandwidth_limit[download_channel].throttle(m_download_limit);
|
m_bandwidth_limit[download_channel].throttle(m_download_limit);
|
||||||
|
@ -1996,7 +1999,7 @@ namespace libtorrent
|
||||||
p.pieces = get_bitfield();
|
p.pieces = get_bitfield();
|
||||||
ptime now = time_now();
|
ptime now = time_now();
|
||||||
p.last_request = now - m_last_request;
|
p.last_request = now - m_last_request;
|
||||||
p.last_active = now - std::max(m_last_sent, m_last_receive);
|
p.last_active = now - (std::max)(m_last_sent, m_last_receive);
|
||||||
|
|
||||||
// this will set the flags so that we can update them later
|
// this will set the flags so that we can update them later
|
||||||
p.flags = 0;
|
p.flags = 0;
|
||||||
|
@ -2044,10 +2047,13 @@ namespace libtorrent
|
||||||
if (m_packet_size >= m_recv_pos) m_recv_buffer.resize(m_packet_size);
|
if (m_packet_size >= m_recv_pos) m_recv_buffer.resize(m_packet_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void peer_connection::second_tick(float tick_interval)
|
void peer_connection::second_tick(float tick_interval) throw()
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
ptime now(time_now());
|
ptime now(time_now());
|
||||||
|
|
||||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||||
|
@ -2160,14 +2166,14 @@ namespace libtorrent
|
||||||
if (t->ratio() != 1.f)
|
if (t->ratio() != 1.f)
|
||||||
soon_downloaded = (size_type)(soon_downloaded*(double)t->ratio());
|
soon_downloaded = (size_type)(soon_downloaded*(double)t->ratio());
|
||||||
|
|
||||||
double upload_speed_limit = std::min((soon_downloaded - have_uploaded
|
double upload_speed_limit = (std::min)((soon_downloaded - have_uploaded
|
||||||
+ bias) / break_even_time, double(m_upload_limit));
|
+ bias) / break_even_time, double(m_upload_limit));
|
||||||
|
|
||||||
upload_speed_limit = std::min(upload_speed_limit,
|
upload_speed_limit = (std::min)(upload_speed_limit,
|
||||||
(double)std::numeric_limits<int>::max());
|
(double)std::numeric_limits<int>::max());
|
||||||
|
|
||||||
m_bandwidth_limit[upload_channel].throttle(
|
m_bandwidth_limit[upload_channel].throttle(
|
||||||
std::min(std::max((int)upload_speed_limit, 20)
|
(std::min)((std::max)((int)upload_speed_limit, 20)
|
||||||
, m_upload_limit));
|
, m_upload_limit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2186,43 +2192,14 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
fill_send_buffer();
|
fill_send_buffer();
|
||||||
/*
|
|
||||||
size_type diff = share_diff();
|
|
||||||
|
|
||||||
enum { block_limit = 2 }; // how many blocks difference is considered unfair
|
|
||||||
|
|
||||||
// if the peer has been choked, send the current piece
|
|
||||||
// as fast as possible
|
|
||||||
if (diff > block_limit*m_torrent->block_size() || m_torrent->is_seed() || is_choked())
|
|
||||||
{
|
|
||||||
// if we have downloaded more than one piece more
|
|
||||||
// than we have uploaded OR if we are a seed
|
|
||||||
// have an unlimited upload rate
|
|
||||||
m_ul_bandwidth_quota.wanted = std::numeric_limits<int>::max();
|
|
||||||
}
|
}
|
||||||
else
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
float ratio = m_torrent->ratio();
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
// if we have downloaded too much, response with an
|
(*m_logger) << "**ERROR**: " << e.what() << "\n";
|
||||||
// upload rate of 10 kB/s more than we dowlload
|
#endif
|
||||||
// if we have uploaded too much, send with a rate of
|
m_ses.connection_failed(m_socket, remote(), e.what());
|
||||||
// 10 kB/s less than we receive
|
|
||||||
int bias = 0;
|
|
||||||
if (diff > -block_limit*m_torrent->block_size())
|
|
||||||
{
|
|
||||||
bias = static_cast<int>(m_statistics.download_rate() * ratio) / 2;
|
|
||||||
if (bias < 10*1024) bias = 10*1024;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
bias = -static_cast<int>(m_statistics.download_rate() * ratio) / 2;
|
|
||||||
}
|
|
||||||
m_ul_bandwidth_quota.wanted = static_cast<int>(m_statistics.download_rate()) + bias;
|
|
||||||
|
|
||||||
// the maximum send_quota given our download rate from this peer
|
|
||||||
if (m_ul_bandwidth_quota.wanted < 256) m_ul_bandwidth_quota.wanted = 256;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void peer_connection::fill_send_buffer()
|
void peer_connection::fill_send_buffer()
|
||||||
|
|
|
@ -189,7 +189,8 @@ namespace libtorrent
|
||||||
// infinite loop, fighting to request the same blocks.
|
// infinite loop, fighting to request the same blocks.
|
||||||
void request_a_block(torrent& t, peer_connection& c)
|
void request_a_block(torrent& t, peer_connection& c)
|
||||||
{
|
{
|
||||||
assert(!t.is_seed());
|
if (t.is_seed()) return;
|
||||||
|
|
||||||
assert(t.valid_metadata());
|
assert(t.valid_metadata());
|
||||||
assert(c.peer_info_struct() != 0 || !dynamic_cast<bt_peer_connection*>(&c));
|
assert(c.peer_info_struct() != 0 || !dynamic_cast<bt_peer_connection*>(&c));
|
||||||
int num_requests = c.desired_queue_size()
|
int num_requests = c.desired_queue_size()
|
||||||
|
@ -298,6 +299,7 @@ namespace libtorrent
|
||||||
assert(p.num_peers(*i) == 1);
|
assert(p.num_peers(*i) == 1);
|
||||||
assert(p.is_requested(*i));
|
assert(p.is_requested(*i));
|
||||||
num_requests--;
|
num_requests--;
|
||||||
|
if (num_requests == 0) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (busy_pieces.empty() || num_requests == 0)
|
if (busy_pieces.empty() || num_requests == 0)
|
||||||
|
@ -331,9 +333,8 @@ namespace libtorrent
|
||||||
|
|
||||||
policy::policy(torrent* t)
|
policy::policy(torrent* t)
|
||||||
: m_torrent(t)
|
: m_torrent(t)
|
||||||
, m_num_unchoked(0)
|
|
||||||
, m_available_free_upload(0)
|
, m_available_free_upload(0)
|
||||||
, m_last_optimistic_disconnect(min_time())
|
// , m_last_optimistic_disconnect(min_time())
|
||||||
{ assert(t); }
|
{ assert(t); }
|
||||||
|
|
||||||
// disconnects and removes all peers that are now filtered
|
// disconnects and removes all peers that are now filtered
|
||||||
|
@ -375,7 +376,7 @@ namespace libtorrent
|
||||||
m_peers.erase(i++);
|
m_peers.erase(i++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
// finds the peer that has the worst download rate
|
// finds the peer that has the worst download rate
|
||||||
// and returns it. May return 0 if all peers are
|
// and returns it. May return 0 if all peers are
|
||||||
// choked.
|
// choked.
|
||||||
|
@ -457,7 +458,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
return unchoke_peer;
|
return unchoke_peer;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
policy::iterator policy::find_disconnect_candidate()
|
policy::iterator policy::find_disconnect_candidate()
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
@ -542,7 +543,7 @@ namespace libtorrent
|
||||||
|
|
||||||
return candidate;
|
return candidate;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
policy::iterator policy::find_seed_choke_candidate()
|
policy::iterator policy::find_seed_choke_candidate()
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
@ -648,7 +649,7 @@ namespace libtorrent
|
||||||
--m_num_unchoked;
|
--m_num_unchoked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
void policy::pulse()
|
void policy::pulse()
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
@ -680,7 +681,7 @@ namespace libtorrent
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
// maintain the number of connections
|
// maintain the number of connections
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
|
/*
|
||||||
// count the number of connected peers except for peers
|
// count the number of connected peers except for peers
|
||||||
// that are currently in the process of disconnecting
|
// that are currently in the process of disconnecting
|
||||||
int num_connected_peers = 0;
|
int num_connected_peers = 0;
|
||||||
|
@ -692,10 +693,9 @@ namespace libtorrent
|
||||||
++num_connected_peers;
|
++num_connected_peers;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_torrent->m_connections_quota.given != std::numeric_limits<int>::max())
|
if (m_torrent->max_connections() != std::numeric_limits<int>::max())
|
||||||
{
|
{
|
||||||
|
int max_connections = m_torrent->max_connections();
|
||||||
int max_connections = m_torrent->m_connections_quota.given;
|
|
||||||
|
|
||||||
if (num_connected_peers >= max_connections)
|
if (num_connected_peers >= max_connections)
|
||||||
{
|
{
|
||||||
|
@ -723,7 +723,7 @@ namespace libtorrent
|
||||||
--num_connected_peers;
|
--num_connected_peers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
// ------------------------
|
// ------------------------
|
||||||
// upload shift
|
// upload shift
|
||||||
// ------------------------
|
// ------------------------
|
||||||
|
@ -754,7 +754,7 @@ namespace libtorrent
|
||||||
, m_torrent->end()
|
, m_torrent->end()
|
||||||
, m_available_free_upload);
|
, m_available_free_upload);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
// ------------------------
|
// ------------------------
|
||||||
// seed choking policy
|
// seed choking policy
|
||||||
// ------------------------
|
// ------------------------
|
||||||
|
@ -870,6 +870,7 @@ namespace libtorrent
|
||||||
while (m_num_unchoked < m_torrent->m_uploads_quota.given
|
while (m_num_unchoked < m_torrent->m_uploads_quota.given
|
||||||
&& unchoke_one_peer());
|
&& unchoke_one_peer());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
int policy::count_choked() const
|
int policy::count_choked() const
|
||||||
|
@ -902,7 +903,8 @@ namespace libtorrent
|
||||||
// override at a time
|
// override at a time
|
||||||
assert(c.remote() == c.get_socket()->remote_endpoint());
|
assert(c.remote() == c.get_socket()->remote_endpoint());
|
||||||
|
|
||||||
if (m_torrent->num_peers() >= m_torrent->m_connections_quota.given
|
if (m_torrent->num_peers() >= m_torrent->max_connections()
|
||||||
|
&& m_torrent->session().num_connections() >= m_torrent->session().max_connections()
|
||||||
&& c.remote().address() != m_torrent->current_tracker().address())
|
&& c.remote().address() != m_torrent->current_tracker().address())
|
||||||
{
|
{
|
||||||
throw protocol_error("too many connections, refusing incoming connection"); // cause a disconnect
|
throw protocol_error("too many connections, refusing incoming connection"); // cause a disconnect
|
||||||
|
@ -984,7 +986,7 @@ namespace libtorrent
|
||||||
i->connection = &c;
|
i->connection = &c;
|
||||||
assert(i->connection);
|
assert(i->connection);
|
||||||
i->connected = time_now();
|
i->connected = time_now();
|
||||||
m_last_optimistic_disconnect = time_now();
|
// m_last_optimistic_disconnect = time_now();
|
||||||
}
|
}
|
||||||
|
|
||||||
void policy::peer_from_tracker(const tcp::endpoint& remote, const peer_id& pid
|
void policy::peer_from_tracker(const tcp::endpoint& remote, const peer_id& pid
|
||||||
|
@ -1172,14 +1174,38 @@ namespace libtorrent
|
||||||
// In that case we don't care if people are leeching, they
|
// In that case we don't care if people are leeching, they
|
||||||
// can't pay for their downloads anyway.
|
// can't pay for their downloads anyway.
|
||||||
if (c.is_choked()
|
if (c.is_choked()
|
||||||
&& m_num_unchoked < m_torrent->m_uploads_quota.given
|
&& m_torrent->session().num_uploads() < m_torrent->session().max_uploads()
|
||||||
&& (m_torrent->ratio() == 0
|
&& (m_torrent->ratio() == 0
|
||||||
|| c.share_diff() >= -free_upload_amount
|
|| c.share_diff() >= -free_upload_amount
|
||||||
|| m_torrent->is_seed()))
|
|| m_torrent->is_seed()))
|
||||||
{
|
{
|
||||||
c.send_unchoke();
|
m_torrent->session().unchoke_peer(c);
|
||||||
++m_num_unchoked;
|
|
||||||
}
|
}
|
||||||
|
#if defined(TORRENT_VERBOSE_LOGGING)
|
||||||
|
else if (c.is_choked())
|
||||||
|
{
|
||||||
|
std::string reason;
|
||||||
|
if (m_torrent->session().num_uploads() >= m_torrent->session().max_uploads())
|
||||||
|
{
|
||||||
|
reason = "the number of uploads ("
|
||||||
|
+ boost::lexical_cast<std::string>(m_torrent->session().num_uploads())
|
||||||
|
+ ") is more than or equal to the limit ("
|
||||||
|
+ boost::lexical_cast<std::string>(m_torrent->session().max_uploads())
|
||||||
|
+ ")";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reason = "the share ratio ("
|
||||||
|
+ boost::lexical_cast<std::string>(c.share_diff())
|
||||||
|
+ ") is <= free_upload_amount ("
|
||||||
|
+ boost::lexical_cast<std::string>(int(free_upload_amount))
|
||||||
|
+ ") and we are not seeding and the ratio ("
|
||||||
|
+ boost::lexical_cast<std::string>(m_torrent->ratio())
|
||||||
|
+ ")is non-zero";
|
||||||
|
}
|
||||||
|
(*c.m_logger) << time_now_string() << " DID NOT UNCHOKE [ " << reason << " ]\n";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// called when a peer is no longer interested in us
|
// called when a peer is no longer interested in us
|
||||||
|
@ -1211,7 +1237,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
bool policy::unchoke_one_peer()
|
bool policy::unchoke_one_peer()
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
@ -1240,7 +1266,7 @@ namespace libtorrent
|
||||||
p->connection->send_choke();
|
p->connection->send_choke();
|
||||||
--m_num_unchoked;
|
--m_num_unchoked;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
bool policy::connect_one_peer()
|
bool policy::connect_one_peer()
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
@ -1256,7 +1282,7 @@ namespace libtorrent
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
p->connected = m_last_optimistic_disconnect = time_now();
|
p->connected = time_now();
|
||||||
p->connection = m_torrent->connect_to_peer(&*p);
|
p->connection = m_torrent->connect_to_peer(&*p);
|
||||||
if (p->connection == 0) return false;
|
if (p->connection == 0) return false;
|
||||||
p->connection->add_stat(p->prev_amount_download, p->prev_amount_upload);
|
p->connection->add_stat(p->prev_amount_download, p->prev_amount_upload);
|
||||||
|
@ -1289,33 +1315,30 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is called whenever a peer connection is closed
|
// this is called whenever a peer connection is closed
|
||||||
void policy::connection_closed(const peer_connection& c) try
|
void policy::connection_closed(const peer_connection& c) throw()
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
// assert(c.is_disconnecting());
|
peer* p = c.peer_info_struct();
|
||||||
bool unchoked = false;
|
// if we couldn't find the connection in our list, just ignore it.
|
||||||
|
if (p == 0) return;
|
||||||
|
|
||||||
iterator i = std::find_if(
|
assert(std::find_if(
|
||||||
m_peers.begin()
|
m_peers.begin()
|
||||||
, m_peers.end()
|
, m_peers.end()
|
||||||
, match_peer_connection(c));
|
, match_peer_connection(c))
|
||||||
|
!= m_peers.end());
|
||||||
|
assert(p->connection == &c);
|
||||||
|
|
||||||
// if we couldn't find the connection in our list, just ignore it.
|
p->connection = 0;
|
||||||
if (i == m_peers.end()) return;
|
p->optimistically_unchoked = false;
|
||||||
assert(i->connection == &c);
|
|
||||||
i->connection = 0;
|
|
||||||
|
|
||||||
i->connected = time_now();
|
p->connected = time_now();
|
||||||
if (!c.is_choked() && !m_torrent->is_aborted())
|
|
||||||
{
|
|
||||||
unchoked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c.failed())
|
if (c.failed())
|
||||||
{
|
{
|
||||||
++i->failcount;
|
++p->failcount;
|
||||||
// i->connected = time_now();
|
// p->connected = time_now();
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the share ratio is 0 (infinite), the
|
// if the share ratio is 0 (infinite), the
|
||||||
|
@ -1327,25 +1350,8 @@ namespace libtorrent
|
||||||
assert(c.share_diff() < std::numeric_limits<size_type>::max());
|
assert(c.share_diff() < std::numeric_limits<size_type>::max());
|
||||||
m_available_free_upload += c.share_diff();
|
m_available_free_upload += c.share_diff();
|
||||||
}
|
}
|
||||||
i->prev_amount_download += c.statistics().total_payload_download();
|
p->prev_amount_download += c.statistics().total_payload_download();
|
||||||
i->prev_amount_upload += c.statistics().total_payload_upload();
|
p->prev_amount_upload += c.statistics().total_payload_upload();
|
||||||
|
|
||||||
if (unchoked)
|
|
||||||
{
|
|
||||||
// if the peer that is diconnecting is unchoked
|
|
||||||
// then unchoke another peer in order to maintain
|
|
||||||
// the total number of unchoked peers
|
|
||||||
--m_num_unchoked;
|
|
||||||
if (m_torrent->is_seed()) seed_unchoke_one_peer();
|
|
||||||
else unchoke_one_peer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
#ifndef NDEBUG
|
|
||||||
std::string err = e.what();
|
|
||||||
#endif
|
|
||||||
assert(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void policy::peer_is_interesting(peer_connection& c)
|
void policy::peer_is_interesting(peer_connection& c)
|
||||||
|
@ -1376,7 +1382,6 @@ namespace libtorrent
|
||||||
void policy::check_invariant() const
|
void policy::check_invariant() const
|
||||||
{
|
{
|
||||||
if (m_torrent->is_aborted()) return;
|
if (m_torrent->is_aborted()) return;
|
||||||
int actual_unchoked = 0;
|
|
||||||
int connected_peers = 0;
|
int connected_peers = 0;
|
||||||
|
|
||||||
int total_connections = 0;
|
int total_connections = 0;
|
||||||
|
@ -1405,10 +1410,7 @@ namespace libtorrent
|
||||||
++nonempty_connections;
|
++nonempty_connections;
|
||||||
if (!p.connection->is_disconnecting())
|
if (!p.connection->is_disconnecting())
|
||||||
++connected_peers;
|
++connected_peers;
|
||||||
if (!p.connection->is_choked()) ++actual_unchoked;
|
|
||||||
}
|
}
|
||||||
// assert(actual_unchoked <= m_torrent->m_uploads_quota.given);
|
|
||||||
assert(actual_unchoked == m_num_unchoked);
|
|
||||||
|
|
||||||
int num_torrent_peers = 0;
|
int num_torrent_peers = 0;
|
||||||
for (torrent::const_peer_iterator i = m_torrent->begin();
|
for (torrent::const_peer_iterator i = m_torrent->begin();
|
||||||
|
@ -1475,6 +1477,7 @@ namespace libtorrent
|
||||||
, failcount(0)
|
, failcount(0)
|
||||||
, hashfails(0)
|
, hashfails(0)
|
||||||
, seed(false)
|
, seed(false)
|
||||||
|
, optimistically_unchoked(false)
|
||||||
, last_optimistically_unchoked(min_time())
|
, last_optimistically_unchoked(min_time())
|
||||||
, connected(min_time())
|
, connected(min_time())
|
||||||
, trust_points(0)
|
, trust_points(0)
|
||||||
|
|
|
@ -68,7 +68,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/alert_types.hpp"
|
#include "libtorrent/alert_types.hpp"
|
||||||
#include "libtorrent/invariant_check.hpp"
|
#include "libtorrent/invariant_check.hpp"
|
||||||
#include "libtorrent/file.hpp"
|
#include "libtorrent/file.hpp"
|
||||||
#include "libtorrent/allocate_resources.hpp"
|
|
||||||
#include "libtorrent/bt_peer_connection.hpp"
|
#include "libtorrent/bt_peer_connection.hpp"
|
||||||
#include "libtorrent/ip_filter.hpp"
|
#include "libtorrent/ip_filter.hpp"
|
||||||
#include "libtorrent/socket.hpp"
|
#include "libtorrent/socket.hpp"
|
||||||
|
|
|
@ -68,7 +68,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/alert_types.hpp"
|
#include "libtorrent/alert_types.hpp"
|
||||||
#include "libtorrent/invariant_check.hpp"
|
#include "libtorrent/invariant_check.hpp"
|
||||||
#include "libtorrent/file.hpp"
|
#include "libtorrent/file.hpp"
|
||||||
#include "libtorrent/allocate_resources.hpp"
|
|
||||||
#include "libtorrent/bt_peer_connection.hpp"
|
#include "libtorrent/bt_peer_connection.hpp"
|
||||||
#include "libtorrent/ip_filter.hpp"
|
#include "libtorrent/ip_filter.hpp"
|
||||||
#include "libtorrent/socket.hpp"
|
#include "libtorrent/socket.hpp"
|
||||||
|
@ -223,6 +222,12 @@ namespace detail
|
||||||
if (!m_ses.is_aborted())
|
if (!m_ses.is_aborted())
|
||||||
{
|
{
|
||||||
m_ses.m_torrents.insert(std::make_pair(t->info_hash, t->torrent_ptr));
|
m_ses.m_torrents.insert(std::make_pair(t->info_hash, t->torrent_ptr));
|
||||||
|
if (m_ses.m_alerts.should_post(alert::info))
|
||||||
|
{
|
||||||
|
m_ses.m_alerts.post_alert(torrent_checked_alert(
|
||||||
|
processing->torrent_ptr->get_handle()
|
||||||
|
, "torrent finished checking"));
|
||||||
|
}
|
||||||
if (t->torrent_ptr->is_seed() && m_ses.m_alerts.should_post(alert::info))
|
if (t->torrent_ptr->is_seed() && m_ses.m_alerts.should_post(alert::info))
|
||||||
{
|
{
|
||||||
m_ses.m_alerts.post_alert(torrent_finished_alert(
|
m_ses.m_alerts.post_alert(torrent_finished_alert(
|
||||||
|
@ -345,6 +350,12 @@ namespace detail
|
||||||
processing->torrent_ptr->files_checked(processing->unfinished_pieces);
|
processing->torrent_ptr->files_checked(processing->unfinished_pieces);
|
||||||
m_ses.m_torrents.insert(std::make_pair(
|
m_ses.m_torrents.insert(std::make_pair(
|
||||||
processing->info_hash, processing->torrent_ptr));
|
processing->info_hash, processing->torrent_ptr));
|
||||||
|
if (m_ses.m_alerts.should_post(alert::info))
|
||||||
|
{
|
||||||
|
m_ses.m_alerts.post_alert(torrent_checked_alert(
|
||||||
|
processing->torrent_ptr->get_handle()
|
||||||
|
, "torrent finished checking"));
|
||||||
|
}
|
||||||
if (processing->torrent_ptr->is_seed()
|
if (processing->torrent_ptr->is_seed()
|
||||||
&& m_ses.m_alerts.should_post(alert::info))
|
&& m_ses.m_alerts.should_post(alert::info))
|
||||||
{
|
{
|
||||||
|
@ -505,8 +516,12 @@ namespace detail
|
||||||
, m_listen_interface(address::from_string(listen_interface), listen_port_range.first)
|
, m_listen_interface(address::from_string(listen_interface), listen_port_range.first)
|
||||||
, m_external_listen_port(0)
|
, m_external_listen_port(0)
|
||||||
, m_abort(false)
|
, m_abort(false)
|
||||||
, m_max_uploads(-1)
|
, m_max_uploads(8)
|
||||||
, m_max_connections(-1)
|
, m_max_connections(200)
|
||||||
|
, m_num_unchoked(0)
|
||||||
|
, m_unchoke_time_scaler(0)
|
||||||
|
, m_optimistic_unchoke_time_scaler(0)
|
||||||
|
, m_disconnect_time_scaler(0)
|
||||||
, m_incoming_connection(false)
|
, m_incoming_connection(false)
|
||||||
, m_last_tick(time_now())
|
, m_last_tick(time_now())
|
||||||
#ifndef TORRENT_DISABLE_DHT
|
#ifndef TORRENT_DISABLE_DHT
|
||||||
|
@ -821,8 +836,11 @@ namespace detail
|
||||||
assert(p->is_disconnecting());
|
assert(p->is_disconnecting());
|
||||||
connection_map::iterator i = m_connections.find(p->get_socket());
|
connection_map::iterator i = m_connections.find(p->get_socket());
|
||||||
if (i != m_connections.end())
|
if (i != m_connections.end())
|
||||||
|
{
|
||||||
|
if (!i->second->is_choked()) --m_num_unchoked;
|
||||||
m_connections.erase(i);
|
m_connections.erase(i);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void session_impl::set_peer_id(peer_id const& id)
|
void session_impl::set_peer_id(peer_id const& id)
|
||||||
{
|
{
|
||||||
|
@ -901,7 +919,9 @@ namespace detail
|
||||||
// round robin fashion, so that every torrent is
|
// round robin fashion, so that every torrent is
|
||||||
// equallt likely to connect to a peer
|
// equallt likely to connect to a peer
|
||||||
|
|
||||||
if (!m_torrents.empty() && m_half_open.free_slots())
|
if (!m_torrents.empty()
|
||||||
|
&& m_half_open.free_slots()
|
||||||
|
&& num_connections() < m_max_connections)
|
||||||
{
|
{
|
||||||
// this is the maximum number of connections we will
|
// this is the maximum number of connections we will
|
||||||
// attempt this tick
|
// attempt this tick
|
||||||
|
@ -918,11 +938,13 @@ namespace detail
|
||||||
{
|
{
|
||||||
torrent& t = *i->second;
|
torrent& t = *i->second;
|
||||||
if (t.want_more_peers())
|
if (t.want_more_peers())
|
||||||
|
{
|
||||||
if (t.try_connect_peer())
|
if (t.try_connect_peer())
|
||||||
{
|
{
|
||||||
--max_connections;
|
--max_connections;
|
||||||
steps_since_last_connect = 0;
|
steps_since_last_connect = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
++m_next_connect_torrent;
|
++m_next_connect_torrent;
|
||||||
++steps_since_last_connect;
|
++steps_since_last_connect;
|
||||||
++i;
|
++i;
|
||||||
|
@ -976,19 +998,8 @@ namespace detail
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
c.keep_alive();
|
c.keep_alive();
|
||||||
}
|
}
|
||||||
catch (std::exception& exc)
|
|
||||||
{
|
|
||||||
#ifdef TORRENT_VERBOSE_LOGGING
|
|
||||||
(*c.m_logger) << "**ERROR**: " << exc.what() << "\n";
|
|
||||||
#endif
|
|
||||||
c.set_failed();
|
|
||||||
c.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check each torrent for tracker updates
|
// check each torrent for tracker updates
|
||||||
// TODO: do this in a timer-event in each torrent instead
|
// TODO: do this in a timer-event in each torrent instead
|
||||||
|
@ -1019,30 +1030,173 @@ namespace detail
|
||||||
}
|
}
|
||||||
|
|
||||||
m_stat.second_tick(tick_interval);
|
m_stat.second_tick(tick_interval);
|
||||||
// distribute the maximum upload rate among the torrents
|
|
||||||
|
|
||||||
assert(m_max_uploads >= -1);
|
// --------------------------------------------------------------
|
||||||
assert(m_max_connections >= -1);
|
// unchoke set and optimistic unchoke calculations
|
||||||
|
// --------------------------------------------------------------
|
||||||
allocate_resources(m_max_uploads == -1
|
m_unchoke_time_scaler--;
|
||||||
? std::numeric_limits<int>::max()
|
if (m_unchoke_time_scaler <= 0 && !m_connections.empty())
|
||||||
: m_max_uploads
|
|
||||||
, m_torrents
|
|
||||||
, &torrent::m_uploads_quota);
|
|
||||||
|
|
||||||
allocate_resources(m_max_connections == -1
|
|
||||||
? std::numeric_limits<int>::max()
|
|
||||||
: m_max_connections
|
|
||||||
, m_torrents
|
|
||||||
, &torrent::m_connections_quota);
|
|
||||||
|
|
||||||
for (std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator i
|
|
||||||
= m_torrents.begin(); i != m_torrents.end(); ++i)
|
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
m_unchoke_time_scaler = settings().unchoke_interval;
|
||||||
i->second->check_invariant();
|
|
||||||
#endif
|
std::vector<peer_connection*> peers;
|
||||||
i->second->distribute_resources(tick_interval);
|
for (connection_map::iterator i = m_connections.begin()
|
||||||
|
, end(m_connections.end()); i != end; ++i)
|
||||||
|
{
|
||||||
|
peer_connection* p = i->second.get();
|
||||||
|
torrent* t = p->associated_torrent().lock().get();
|
||||||
|
if (!p->peer_info_struct()
|
||||||
|
|| t == 0
|
||||||
|
|| !p->is_peer_interested()
|
||||||
|
|| p->is_disconnecting()
|
||||||
|
|| p->is_connecting()
|
||||||
|
|| (p->share_diff() < -free_upload_amount
|
||||||
|
&& !t->is_seed()))
|
||||||
|
{
|
||||||
|
if (!i->second->is_choked() && t)
|
||||||
|
t->choke_peer(*i->second);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
peers.push_back(i->second.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort the peers that are eligible for unchoke by download rate and secondary
|
||||||
|
// by total upload. The reason for this is, if all torrents are being seeded,
|
||||||
|
// the download rate will be 0, and the peers we have sent the least to should
|
||||||
|
// be unchoked
|
||||||
|
std::sort(peers.begin(), peers.end()
|
||||||
|
, bind(&stat::total_payload_upload, bind(&peer_connection::statistics, _1))
|
||||||
|
< bind(&stat::total_payload_upload, bind(&peer_connection::statistics, _2)));
|
||||||
|
|
||||||
|
std::stable_sort(peers.begin(), peers.end()
|
||||||
|
, bind(&stat::download_payload_rate, bind(&peer_connection::statistics, _1))
|
||||||
|
> bind(&stat::download_payload_rate, bind(&peer_connection::statistics, _2)));
|
||||||
|
|
||||||
|
// reserve one upload slot for optimistic unchokes
|
||||||
|
int unchoke_set_size = m_max_uploads - 1;
|
||||||
|
|
||||||
|
m_num_unchoked = 0;
|
||||||
|
// go through all the peers and unchoke the first ones and choke
|
||||||
|
// all the other ones.
|
||||||
|
for (std::vector<peer_connection*>::iterator i = peers.begin()
|
||||||
|
, end(peers.end()); i != end; ++i)
|
||||||
|
{
|
||||||
|
peer_connection* p = *i;
|
||||||
|
assert(p);
|
||||||
|
torrent* t = p->associated_torrent().lock().get();
|
||||||
|
assert(t);
|
||||||
|
if (unchoke_set_size > 0)
|
||||||
|
{
|
||||||
|
if (p->is_choked())
|
||||||
|
{
|
||||||
|
if (t->unchoke_peer(*p))
|
||||||
|
{
|
||||||
|
--unchoke_set_size;
|
||||||
|
++m_num_unchoked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
--unchoke_set_size;
|
||||||
|
++m_num_unchoked;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(p->peer_info_struct());
|
||||||
|
if (p->peer_info_struct()->optimistically_unchoked)
|
||||||
|
{
|
||||||
|
// force a new optimistic unchoke
|
||||||
|
m_optimistic_unchoke_time_scaler = 0;
|
||||||
|
p->peer_info_struct()->optimistically_unchoked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!p->is_choked() && !p->peer_info_struct()->optimistically_unchoked)
|
||||||
|
t->choke_peer(*p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_optimistic_unchoke_time_scaler--;
|
||||||
|
if (m_optimistic_unchoke_time_scaler <= 0)
|
||||||
|
{
|
||||||
|
m_optimistic_unchoke_time_scaler
|
||||||
|
= settings().optimistic_unchoke_multiplier;
|
||||||
|
|
||||||
|
// find the peer that has been waiting the longest to be optimistically
|
||||||
|
// unchoked
|
||||||
|
connection_map::iterator current_optimistic_unchoke = m_connections.end();
|
||||||
|
connection_map::iterator optimistic_unchoke_candidate = m_connections.end();
|
||||||
|
ptime last_unchoke = max_time();
|
||||||
|
|
||||||
|
for (connection_map::iterator i = m_connections.begin()
|
||||||
|
, end(m_connections.end()); i != end; ++i)
|
||||||
|
{
|
||||||
|
peer_connection* p = i->second.get();
|
||||||
|
assert(p);
|
||||||
|
policy::peer* pi = p->peer_info_struct();
|
||||||
|
if (!pi) continue;
|
||||||
|
torrent* t = p->associated_torrent().lock().get();
|
||||||
|
if (!t) continue;
|
||||||
|
|
||||||
|
if (pi->optimistically_unchoked)
|
||||||
|
{
|
||||||
|
assert(current_optimistic_unchoke == m_connections.end());
|
||||||
|
current_optimistic_unchoke = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pi->last_optimistically_unchoked < last_unchoke
|
||||||
|
&& !p->is_connecting()
|
||||||
|
&& !p->is_disconnecting()
|
||||||
|
&& p->is_peer_interested()
|
||||||
|
&& t->free_upload_slots()
|
||||||
|
&& p->is_choked())
|
||||||
|
{
|
||||||
|
last_unchoke = pi->last_optimistically_unchoked;
|
||||||
|
optimistic_unchoke_candidate = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optimistic_unchoke_candidate != m_connections.end()
|
||||||
|
&& optimistic_unchoke_candidate != current_optimistic_unchoke)
|
||||||
|
{
|
||||||
|
if (current_optimistic_unchoke != m_connections.end())
|
||||||
|
{
|
||||||
|
torrent* t = current_optimistic_unchoke->second->associated_torrent().lock().get();
|
||||||
|
assert(t);
|
||||||
|
t->choke_peer(*current_optimistic_unchoke->second);
|
||||||
|
current_optimistic_unchoke->second->peer_info_struct()->optimistically_unchoked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
torrent* t = optimistic_unchoke_candidate->second->associated_torrent().lock().get();
|
||||||
|
assert(t);
|
||||||
|
bool ret = t->unchoke_peer(*optimistic_unchoke_candidate->second);
|
||||||
|
assert(ret);
|
||||||
|
optimistic_unchoke_candidate->second->peer_info_struct()->optimistically_unchoked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optimistic_unchoke_candidate != m_connections.end())
|
||||||
|
++m_num_unchoked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------
|
||||||
|
// disconnect peers when we have too many
|
||||||
|
// --------------------------------------------------------------
|
||||||
|
--m_disconnect_time_scaler;
|
||||||
|
if (m_disconnect_time_scaler <= 0)
|
||||||
|
{
|
||||||
|
m_disconnect_time_scaler = 60;
|
||||||
|
|
||||||
|
// every 60 seconds, disconnect the worst peer
|
||||||
|
// if we have reached the connection limit
|
||||||
|
if (num_connections() >= max_connections() && !m_torrents.empty())
|
||||||
|
{
|
||||||
|
torrent_map::iterator i = std::max_element(m_torrents.begin(), m_torrents.end()
|
||||||
|
, bind(&torrent::num_peers, bind(&torrent_map::value_type::second, _1)));
|
||||||
|
|
||||||
|
assert(i != m_torrents.end());
|
||||||
|
i->second->get_policy().disconnect_one_peer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception& exc)
|
catch (std::exception& exc)
|
||||||
|
@ -1832,6 +1986,7 @@ namespace detail
|
||||||
{
|
{
|
||||||
assert(limit > 0 || limit == -1);
|
assert(limit > 0 || limit == -1);
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
if (limit <= 0) limit = std::numeric_limits<int>::max();
|
||||||
m_max_uploads = limit;
|
m_max_uploads = limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1839,6 +1994,7 @@ namespace detail
|
||||||
{
|
{
|
||||||
assert(limit > 0 || limit == -1);
|
assert(limit > 0 || limit == -1);
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
if (limit <= 0) limit = std::numeric_limits<int>::max();
|
||||||
m_max_connections = limit;
|
m_max_connections = limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1846,7 +2002,7 @@ namespace detail
|
||||||
{
|
{
|
||||||
assert(limit > 0 || limit == -1);
|
assert(limit > 0 || limit == -1);
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
if (limit <= 0) limit = std::numeric_limits<int>::max();
|
||||||
m_half_open.limit(limit);
|
m_half_open.limit(limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1854,7 +2010,7 @@ namespace detail
|
||||||
{
|
{
|
||||||
assert(bytes_per_second > 0 || bytes_per_second == -1);
|
assert(bytes_per_second > 0 || bytes_per_second == -1);
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
if (bytes_per_second == -1) bytes_per_second = bandwidth_limit::inf;
|
if (bytes_per_second <= 0) bytes_per_second = bandwidth_limit::inf;
|
||||||
m_bandwidth_manager[peer_connection::download_channel]->throttle(bytes_per_second);
|
m_bandwidth_manager[peer_connection::download_channel]->throttle(bytes_per_second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1862,28 +2018,10 @@ namespace detail
|
||||||
{
|
{
|
||||||
assert(bytes_per_second > 0 || bytes_per_second == -1);
|
assert(bytes_per_second > 0 || bytes_per_second == -1);
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
if (bytes_per_second == -1) bytes_per_second = bandwidth_limit::inf;
|
if (bytes_per_second <= 0) bytes_per_second = bandwidth_limit::inf;
|
||||||
m_bandwidth_manager[peer_connection::upload_channel]->throttle(bytes_per_second);
|
m_bandwidth_manager[peer_connection::upload_channel]->throttle(bytes_per_second);
|
||||||
}
|
}
|
||||||
|
|
||||||
int session_impl::num_uploads() const
|
|
||||||
{
|
|
||||||
int uploads = 0;
|
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
|
||||||
for (torrent_map::const_iterator i = m_torrents.begin()
|
|
||||||
, end(m_torrents.end()); i != end; i++)
|
|
||||||
{
|
|
||||||
uploads += i->second->get_policy().num_uploads();
|
|
||||||
}
|
|
||||||
return uploads;
|
|
||||||
}
|
|
||||||
|
|
||||||
int session_impl::num_connections() const
|
|
||||||
{
|
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
|
||||||
return m_connections.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::auto_ptr<alert> session_impl::pop_alert()
|
std::auto_ptr<alert> session_impl::pop_alert()
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
@ -1977,18 +2115,28 @@ namespace detail
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
void session_impl::check_invariant(const char *place)
|
void session_impl::check_invariant(const char *place)
|
||||||
{
|
{
|
||||||
|
assert(m_max_connections > 0);
|
||||||
|
assert(m_max_uploads > 0);
|
||||||
assert(place);
|
assert(place);
|
||||||
|
int unchokes = 0;
|
||||||
|
int num_optimistic = 0;
|
||||||
for (connection_map::iterator i = m_connections.begin();
|
for (connection_map::iterator i = m_connections.begin();
|
||||||
i != m_connections.end(); ++i)
|
i != m_connections.end(); ++i)
|
||||||
{
|
{
|
||||||
assert(i->second);
|
assert(i->second);
|
||||||
boost::shared_ptr<torrent> t = i->second->associated_torrent().lock();
|
boost::shared_ptr<torrent> t = i->second->associated_torrent().lock();
|
||||||
|
|
||||||
|
if (!i->second->is_choked()) ++unchokes;
|
||||||
|
if (i->second->peer_info_struct()
|
||||||
|
&& i->second->peer_info_struct()->optimistically_unchoked)
|
||||||
|
++num_optimistic;
|
||||||
if (t)
|
if (t)
|
||||||
{
|
{
|
||||||
assert(t->get_policy().has_connection(boost::get_pointer(i->second)));
|
assert(t->get_policy().has_connection(boost::get_pointer(i->second)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
assert(num_optimistic == 0 || num_optimistic == 1);
|
||||||
|
assert(m_num_unchoked == unchokes);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2101,7 +2249,7 @@ namespace detail
|
||||||
|
|
||||||
const std::string& bitmask = (*i)["bitmask"].string();
|
const std::string& bitmask = (*i)["bitmask"].string();
|
||||||
|
|
||||||
const int num_bitmask_bytes = std::max(num_blocks_per_piece / 8, 1);
|
const int num_bitmask_bytes = (std::max)(num_blocks_per_piece / 8, 1);
|
||||||
if ((int)bitmask.size() != num_bitmask_bytes)
|
if ((int)bitmask.size() != num_bitmask_bytes)
|
||||||
{
|
{
|
||||||
error = "invalid size of bitmask (" + boost::lexical_cast<std::string>(bitmask.size()) + ")";
|
error = "invalid size of bitmask (" + boost::lexical_cast<std::string>(bitmask.size()) + ")";
|
||||||
|
@ -2110,7 +2258,7 @@ namespace detail
|
||||||
for (int j = 0; j < num_bitmask_bytes; ++j)
|
for (int j = 0; j < num_bitmask_bytes; ++j)
|
||||||
{
|
{
|
||||||
unsigned char bits = bitmask[j];
|
unsigned char bits = bitmask[j];
|
||||||
int num_bits = std::min(num_blocks_per_piece - j*8, 8);
|
int num_bits = (std::min)(num_blocks_per_piece - j*8, 8);
|
||||||
for (int k = 0; k < num_bits; ++k)
|
for (int k = 0; k < num_bits; ++k)
|
||||||
{
|
{
|
||||||
const int bit = j * 8 + k;
|
const int bit = j * 8 + k;
|
||||||
|
|
|
@ -2096,7 +2096,7 @@ namespace libtorrent
|
||||||
, offset += stack_buffer_size)
|
, offset += stack_buffer_size)
|
||||||
{
|
{
|
||||||
m_storage->write(zeroes, pos, offset
|
m_storage->write(zeroes, pos, offset
|
||||||
, std::min(piece_size, stack_buffer_size));
|
, (std::min)(piece_size, stack_buffer_size));
|
||||||
}
|
}
|
||||||
written = true;
|
written = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,22 +199,16 @@ namespace libtorrent
|
||||||
, m_connections_initialized(true)
|
, m_connections_initialized(true)
|
||||||
, m_settings(s)
|
, m_settings(s)
|
||||||
, m_storage_constructor(sc)
|
, m_storage_constructor(sc)
|
||||||
|
, m_max_uploads(std::numeric_limits<int>::max())
|
||||||
|
, m_num_uploads(0)
|
||||||
|
, m_max_connections(std::numeric_limits<int>::max())
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
m_initial_done = 0;
|
m_initial_done = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_uploads_quota.min = 0;
|
|
||||||
m_connections_quota.min = 2;
|
|
||||||
// this will be corrected the next time the main session
|
|
||||||
// distributes resources, i.e. on average in 0.5 seconds
|
|
||||||
m_connections_quota.given = 100;
|
|
||||||
m_uploads_quota.max = std::numeric_limits<int>::max();
|
|
||||||
m_connections_quota.max = std::numeric_limits<int>::max();
|
|
||||||
m_policy.reset(new policy(this));
|
m_policy.reset(new policy(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
torrent::torrent(
|
torrent::torrent(
|
||||||
session_impl& ses
|
session_impl& ses
|
||||||
, aux::checker_impl& checker
|
, aux::checker_impl& checker
|
||||||
|
@ -268,6 +262,9 @@ namespace libtorrent
|
||||||
, m_connections_initialized(false)
|
, m_connections_initialized(false)
|
||||||
, m_settings(s)
|
, m_settings(s)
|
||||||
, m_storage_constructor(sc)
|
, m_storage_constructor(sc)
|
||||||
|
, m_max_uploads(std::numeric_limits<int>::max())
|
||||||
|
, m_num_uploads(0)
|
||||||
|
, m_max_connections(std::numeric_limits<int>::max())
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
m_initial_done = 0;
|
m_initial_done = 0;
|
||||||
|
@ -277,13 +274,6 @@ namespace libtorrent
|
||||||
|
|
||||||
if (name) m_name.reset(new std::string(name));
|
if (name) m_name.reset(new std::string(name));
|
||||||
|
|
||||||
m_uploads_quota.min = 0;
|
|
||||||
m_connections_quota.min = 2;
|
|
||||||
// this will be corrected the next time the main session
|
|
||||||
// distributes resources, i.e. on average in 0.5 seconds
|
|
||||||
m_connections_quota.given = 100;
|
|
||||||
m_uploads_quota.max = std::numeric_limits<int>::max();
|
|
||||||
m_connections_quota.max = std::numeric_limits<int>::max();
|
|
||||||
if (tracker_url)
|
if (tracker_url)
|
||||||
{
|
{
|
||||||
m_trackers.push_back(announce_entry(tracker_url));
|
m_trackers.push_back(announce_entry(tracker_url));
|
||||||
|
@ -329,6 +319,14 @@ namespace libtorrent
|
||||||
|
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
|
#if defined(TORRENT_VERBOSE_LOGGING)
|
||||||
|
for (peer_iterator i = m_connections.begin();
|
||||||
|
i != m_connections.end(); ++i)
|
||||||
|
{
|
||||||
|
(*i->second->m_logger) << "*** DESTRUCTING TORRENT\n";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
assert(m_abort);
|
assert(m_abort);
|
||||||
if (!m_connections.empty())
|
if (!m_connections.empty())
|
||||||
disconnect_all();
|
disconnect_all();
|
||||||
|
@ -1020,6 +1018,15 @@ namespace libtorrent
|
||||||
m_event = tracker_request::stopped;
|
m_event = tracker_request::stopped;
|
||||||
// disconnect all peers and close all
|
// disconnect all peers and close all
|
||||||
// files belonging to the torrents
|
// files belonging to the torrents
|
||||||
|
|
||||||
|
#if defined(TORRENT_VERBOSE_LOGGING)
|
||||||
|
for (peer_iterator i = m_connections.begin();
|
||||||
|
i != m_connections.end(); ++i)
|
||||||
|
{
|
||||||
|
(*i->second->m_logger) << "*** ABORTING TORRENT\n";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
disconnect_all();
|
disconnect_all();
|
||||||
if (m_owning_storage.get()) m_storage->async_release_files();
|
if (m_owning_storage.get()) m_storage->async_release_files();
|
||||||
m_owning_storage = 0;
|
m_owning_storage = 0;
|
||||||
|
@ -1383,6 +1390,27 @@ namespace libtorrent
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void torrent::choke_peer(peer_connection& c)
|
||||||
|
{
|
||||||
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
|
assert(!c.is_choked());
|
||||||
|
assert(m_num_uploads > 0);
|
||||||
|
c.send_choke();
|
||||||
|
--m_num_uploads;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool torrent::unchoke_peer(peer_connection& c)
|
||||||
|
{
|
||||||
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
|
assert(c.is_choked());
|
||||||
|
if (m_num_uploads >= m_max_uploads) return false;
|
||||||
|
c.send_unchoke();
|
||||||
|
++m_num_uploads;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void torrent::cancel_block(piece_block block)
|
void torrent::cancel_block(piece_block block)
|
||||||
{
|
{
|
||||||
for (peer_iterator i = m_connections.begin()
|
for (peer_iterator i = m_connections.begin()
|
||||||
|
@ -1394,7 +1422,7 @@ namespace libtorrent
|
||||||
|
|
||||||
void torrent::remove_peer(peer_connection* p) try
|
void torrent::remove_peer(peer_connection* p) try
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
// INVARIANT_CHECK;
|
||||||
|
|
||||||
assert(p != 0);
|
assert(p != 0);
|
||||||
|
|
||||||
|
@ -1433,6 +1461,9 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!p->is_choked())
|
||||||
|
--m_num_uploads;
|
||||||
|
|
||||||
m_policy->connection_closed(*p);
|
m_policy->connection_closed(*p);
|
||||||
p->set_peer_info(0);
|
p->set_peer_info(0);
|
||||||
m_connections.erase(i);
|
m_connections.erase(i);
|
||||||
|
@ -1890,7 +1921,7 @@ namespace libtorrent
|
||||||
|
|
||||||
void torrent::attach_peer(peer_connection* p)
|
void torrent::attach_peer(peer_connection* p)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
// INVARIANT_CHECK;
|
||||||
|
|
||||||
assert(p != 0);
|
assert(p != 0);
|
||||||
assert(!p->is_local());
|
assert(!p->is_local());
|
||||||
|
@ -1955,7 +1986,7 @@ namespace libtorrent
|
||||||
|
|
||||||
bool torrent::want_more_peers() const
|
bool torrent::want_more_peers() const
|
||||||
{
|
{
|
||||||
return int(m_connections.size()) < m_connections_quota.given
|
return int(m_connections.size()) < m_max_connections
|
||||||
&& m_ses.m_half_open.free_slots()
|
&& m_ses.m_half_open.free_slots()
|
||||||
&& !m_paused;
|
&& !m_paused;
|
||||||
}
|
}
|
||||||
|
@ -2122,7 +2153,7 @@ namespace libtorrent
|
||||||
if ((unsigned)m_currently_trying_tracker >= m_trackers.size())
|
if ((unsigned)m_currently_trying_tracker >= m_trackers.size())
|
||||||
{
|
{
|
||||||
int delay = tracker_retry_delay_min
|
int delay = tracker_retry_delay_min
|
||||||
+ std::min(m_failed_trackers, (int)tracker_failed_max)
|
+ (std::min)(m_failed_trackers, (int)tracker_failed_max)
|
||||||
* (tracker_retry_delay_max - tracker_retry_delay_min)
|
* (tracker_retry_delay_max - tracker_retry_delay_min)
|
||||||
/ tracker_failed_max;
|
/ tracker_failed_max;
|
||||||
|
|
||||||
|
@ -2354,6 +2385,7 @@ namespace libtorrent
|
||||||
// size_type download = m_stat.total_payload_download();
|
// size_type download = m_stat.total_payload_download();
|
||||||
// size_type done = boost::get<0>(bytes_done());
|
// size_type done = boost::get<0>(bytes_done());
|
||||||
// assert(download >= done - m_initial_done);
|
// assert(download >= done - m_initial_done);
|
||||||
|
int num_uploads = 0;
|
||||||
std::map<piece_block, int> num_requests;
|
std::map<piece_block, int> num_requests;
|
||||||
for (const_peer_iterator i = begin(); i != end(); ++i)
|
for (const_peer_iterator i = begin(); i != end(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -2364,10 +2396,12 @@ namespace libtorrent
|
||||||
for (std::deque<piece_block>::const_iterator i = p.download_queue().begin()
|
for (std::deque<piece_block>::const_iterator i = p.download_queue().begin()
|
||||||
, end(p.download_queue().end()); i != end; ++i)
|
, end(p.download_queue().end()); i != end; ++i)
|
||||||
++num_requests[*i];
|
++num_requests[*i];
|
||||||
|
if (!p.is_choked()) ++num_uploads;
|
||||||
torrent* associated_torrent = p.associated_torrent().lock().get();
|
torrent* associated_torrent = p.associated_torrent().lock().get();
|
||||||
if (associated_torrent != this)
|
if (associated_torrent != this)
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
assert(num_uploads == m_num_uploads);
|
||||||
|
|
||||||
if (has_picker())
|
if (has_picker())
|
||||||
{
|
{
|
||||||
|
@ -2425,15 +2459,15 @@ namespace libtorrent
|
||||||
void torrent::set_max_uploads(int limit)
|
void torrent::set_max_uploads(int limit)
|
||||||
{
|
{
|
||||||
assert(limit >= -1);
|
assert(limit >= -1);
|
||||||
if (limit == -1) limit = std::numeric_limits<int>::max();
|
if (limit <= 0) limit = std::numeric_limits<int>::max();
|
||||||
m_uploads_quota.max = std::max(m_uploads_quota.min, limit);
|
m_max_uploads = limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void torrent::set_max_connections(int limit)
|
void torrent::set_max_connections(int limit)
|
||||||
{
|
{
|
||||||
assert(limit >= -1);
|
assert(limit >= -1);
|
||||||
if (limit == -1) limit = std::numeric_limits<int>::max();
|
if (limit <= 0) limit = std::numeric_limits<int>::max();
|
||||||
m_connections_quota.max = std::max(m_connections_quota.min, limit);
|
m_max_connections = limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void torrent::set_peer_upload_limit(tcp::endpoint ip, int limit)
|
void torrent::set_peer_upload_limit(tcp::endpoint ip, int limit)
|
||||||
|
@ -2455,7 +2489,7 @@ namespace libtorrent
|
||||||
void torrent::set_upload_limit(int limit)
|
void torrent::set_upload_limit(int limit)
|
||||||
{
|
{
|
||||||
assert(limit >= -1);
|
assert(limit >= -1);
|
||||||
if (limit == -1) limit = std::numeric_limits<int>::max();
|
if (limit <= 0) limit = std::numeric_limits<int>::max();
|
||||||
if (limit < num_peers() * 10) limit = num_peers() * 10;
|
if (limit < num_peers() * 10) limit = num_peers() * 10;
|
||||||
m_bandwidth_limit[peer_connection::upload_channel].throttle(limit);
|
m_bandwidth_limit[peer_connection::upload_channel].throttle(limit);
|
||||||
}
|
}
|
||||||
|
@ -2470,7 +2504,7 @@ namespace libtorrent
|
||||||
void torrent::set_download_limit(int limit)
|
void torrent::set_download_limit(int limit)
|
||||||
{
|
{
|
||||||
assert(limit >= -1);
|
assert(limit >= -1);
|
||||||
if (limit == -1) limit = std::numeric_limits<int>::max();
|
if (limit <= 0) limit = std::numeric_limits<int>::max();
|
||||||
if (limit < num_peers() * 10) limit = num_peers() * 10;
|
if (limit < num_peers() * 10) limit = num_peers() * 10;
|
||||||
m_bandwidth_limit[peer_connection::download_channel].throttle(limit);
|
m_bandwidth_limit[peer_connection::download_channel].throttle(limit);
|
||||||
}
|
}
|
||||||
|
@ -2496,6 +2530,14 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(TORRENT_VERBOSE_LOGGING)
|
||||||
|
for (peer_iterator i = m_connections.begin();
|
||||||
|
i != m_connections.end(); ++i)
|
||||||
|
{
|
||||||
|
(*i->second->m_logger) << "*** PAUSING TORRENT\n";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
disconnect_all();
|
disconnect_all();
|
||||||
m_paused = true;
|
m_paused = true;
|
||||||
// tell the tracker that we stopped
|
// tell the tracker that we stopped
|
||||||
|
@ -2528,10 +2570,6 @@ namespace libtorrent
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_paused = false;
|
m_paused = false;
|
||||||
m_uploads_quota.min = 0;
|
|
||||||
m_connections_quota.min = 2;
|
|
||||||
m_uploads_quota.max = std::numeric_limits<int>::max();
|
|
||||||
m_connections_quota.max = std::numeric_limits<int>::max();
|
|
||||||
|
|
||||||
// tell the tracker that we're back
|
// tell the tracker that we're back
|
||||||
m_event = tracker_request::started;
|
m_event = tracker_request::started;
|
||||||
|
@ -2545,10 +2583,6 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
m_connections_quota.used = (int)m_connections.size();
|
|
||||||
m_uploads_quota.used = m_policy->num_uploads();
|
|
||||||
m_uploads_quota.max = (int)m_connections.size();
|
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||||
for (extension_list_t::iterator i = m_extensions.begin()
|
for (extension_list_t::iterator i = m_extensions.begin()
|
||||||
, end(m_extensions.end()); i != end; ++i)
|
, end(m_extensions.end()); i != end; ++i)
|
||||||
|
@ -2561,10 +2595,6 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
// let the stats fade out to 0
|
// let the stats fade out to 0
|
||||||
m_stat.second_tick(tick_interval);
|
m_stat.second_tick(tick_interval);
|
||||||
m_connections_quota.min = 0;
|
|
||||||
m_connections_quota.max = 0;
|
|
||||||
m_uploads_quota.min = 0;
|
|
||||||
m_uploads_quota.max = 0;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2623,6 +2653,13 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
accumulator += m_stat;
|
accumulator += m_stat;
|
||||||
m_stat.second_tick(tick_interval);
|
m_stat.second_tick(tick_interval);
|
||||||
|
|
||||||
|
m_time_scaler--;
|
||||||
|
if (m_time_scaler <= 0)
|
||||||
|
{
|
||||||
|
m_time_scaler = 10;
|
||||||
|
m_policy->pulse();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool torrent::try_connect_peer()
|
bool torrent::try_connect_peer()
|
||||||
|
@ -2631,18 +2668,6 @@ namespace libtorrent
|
||||||
return m_policy->connect_one_peer();
|
return m_policy->connect_one_peer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void torrent::distribute_resources(float tick_interval)
|
|
||||||
{
|
|
||||||
INVARIANT_CHECK;
|
|
||||||
|
|
||||||
m_time_scaler--;
|
|
||||||
if (m_time_scaler <= 0)
|
|
||||||
{
|
|
||||||
m_time_scaler = settings().unchoke_interval;
|
|
||||||
m_policy->pulse();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void torrent::async_verify_piece(int piece_index, boost::function<void(bool)> const& f)
|
void torrent::async_verify_piece(int piece_index, boost::function<void(bool)> const& f)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
@ -2696,7 +2721,7 @@ namespace libtorrent
|
||||||
size_type done = 0;
|
size_type done = 0;
|
||||||
while (size > 0)
|
while (size > 0)
|
||||||
{
|
{
|
||||||
size_type bytes_step = std::min(m_torrent_file.piece_size(ret.piece)
|
size_type bytes_step = (std::min)(m_torrent_file.piece_size(ret.piece)
|
||||||
- ret.start, size);
|
- ret.start, size);
|
||||||
if (m_have_pieces[ret.piece]) done += bytes_step;
|
if (m_have_pieces[ret.piece]) done += bytes_step;
|
||||||
++ret.piece;
|
++ret.piece;
|
||||||
|
@ -2764,10 +2789,10 @@ namespace libtorrent
|
||||||
= m_trackers[m_last_working_tracker].url;
|
= m_trackers[m_last_working_tracker].url;
|
||||||
}
|
}
|
||||||
|
|
||||||
st.num_uploads = m_uploads_quota.used;
|
st.num_uploads = m_num_uploads;
|
||||||
st.uploads_limit = m_uploads_quota.given;
|
st.uploads_limit = m_max_uploads;
|
||||||
st.num_connections = m_connections_quota.used;
|
st.num_connections = int(m_connections.size());
|
||||||
st.connections_limit = m_connections_quota.given;
|
st.connections_limit = m_max_connections;
|
||||||
// if we don't have any metadata, stop here
|
// if we don't have any metadata, stop here
|
||||||
|
|
||||||
if (!valid_metadata())
|
if (!valid_metadata())
|
||||||
|
@ -2780,7 +2805,7 @@ namespace libtorrent
|
||||||
// TODO: add a progress member to the torrent that will be used in this case
|
// TODO: add a progress member to the torrent that will be used in this case
|
||||||
// and that may be set by a plugin
|
// and that may be set by a plugin
|
||||||
// if (m_metadata_size == 0) st.progress = 0.f;
|
// if (m_metadata_size == 0) st.progress = 0.f;
|
||||||
// else st.progress = std::min(1.f, m_metadata_progress / (float)m_metadata_size);
|
// else st.progress = (std::min)(1.f, m_metadata_progress / (float)m_metadata_size);
|
||||||
st.progress = 0.f;
|
st.progress = 0.f;
|
||||||
|
|
||||||
st.block_size = 0;
|
st.block_size = 0;
|
||||||
|
|
|
@ -453,14 +453,30 @@ namespace libtorrent
|
||||||
, m_chk, m_info_hash, bind(&torrent::trackers, _1));
|
, m_chk, m_info_hash, bind(&torrent::trackers, _1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void torrent_handle::add_url_seed(std::string const& url)
|
void torrent_handle::add_url_seed(std::string const& url) const
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
return call_member<void>(m_ses, m_chk, m_info_hash
|
call_member<void>(m_ses, m_chk, m_info_hash
|
||||||
, bind(&torrent::add_url_seed, _1, url));
|
, bind(&torrent::add_url_seed, _1, url));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void torrent_handle::remove_url_seed(std::string const& url) const
|
||||||
|
{
|
||||||
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
|
call_member<void>(m_ses, m_chk, m_info_hash
|
||||||
|
, bind(&torrent::remove_url_seed, _1, url));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<std::string> torrent_handle::url_seeds() const
|
||||||
|
{
|
||||||
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
|
return call_member<std::set<std::string> >(m_ses, m_chk, m_info_hash
|
||||||
|
, bind(&torrent::url_seeds, _1));
|
||||||
|
}
|
||||||
|
|
||||||
void torrent_handle::replace_trackers(
|
void torrent_handle::replace_trackers(
|
||||||
std::vector<announce_entry> const& urls) const
|
std::vector<announce_entry> const& urls) const
|
||||||
{
|
{
|
||||||
|
@ -561,12 +577,12 @@ namespace libtorrent
|
||||||
|
|
||||||
std::string bitmask;
|
std::string bitmask;
|
||||||
const int num_bitmask_bytes
|
const int num_bitmask_bytes
|
||||||
= std::max(num_blocks_per_piece / 8, 1);
|
= (std::max)(num_blocks_per_piece / 8, 1);
|
||||||
|
|
||||||
for (int j = 0; j < num_bitmask_bytes; ++j)
|
for (int j = 0; j < num_bitmask_bytes; ++j)
|
||||||
{
|
{
|
||||||
unsigned char v = 0;
|
unsigned char v = 0;
|
||||||
int bits = std::min(num_blocks_per_piece - j*8, 8);
|
int bits = (std::min)(num_blocks_per_piece - j*8, 8);
|
||||||
for (int k = 0; k < bits; ++k)
|
for (int k = 0; k < bits; ++k)
|
||||||
v |= (i->info[j*8+k].state == piece_picker::block_info::state_finished)
|
v |= (i->info[j*8+k].state == piece_picker::block_info::state_finished)
|
||||||
? (1 << k) : 0;
|
? (1 << k) : 0;
|
||||||
|
|
|
@ -256,7 +256,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
// available input is 1,2 or 3 bytes
|
// available input is 1,2 or 3 bytes
|
||||||
// since we read 3 bytes at a time at most
|
// since we read 3 bytes at a time at most
|
||||||
int available_input = std::min(3, (int)std::distance(i, s.end()));
|
int available_input = (std::min)(3, (int)std::distance(i, s.end()));
|
||||||
|
|
||||||
// clear input buffer
|
// clear input buffer
|
||||||
std::fill(inbuf, inbuf+3, 0);
|
std::fill(inbuf, inbuf+3, 0);
|
||||||
|
@ -305,7 +305,7 @@ namespace libtorrent
|
||||||
m_start_time = time_now();
|
m_start_time = time_now();
|
||||||
m_read_time = time_now();
|
m_read_time = time_now();
|
||||||
|
|
||||||
m_timeout.expires_at(std::min(
|
m_timeout.expires_at((std::min)(
|
||||||
m_read_time + seconds(m_read_timeout)
|
m_read_time + seconds(m_read_timeout)
|
||||||
, m_start_time + seconds(m_completion_timeout)));
|
, m_start_time + seconds(m_completion_timeout)));
|
||||||
m_timeout.async_wait(m_strand.wrap(bind(
|
m_timeout.async_wait(m_strand.wrap(bind(
|
||||||
|
@ -341,7 +341,7 @@ namespace libtorrent
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_timeout.expires_at(std::min(
|
m_timeout.expires_at((std::min)(
|
||||||
m_read_time + seconds(m_read_timeout)
|
m_read_time + seconds(m_read_timeout)
|
||||||
, m_start_time + seconds(m_completion_timeout)));
|
, m_start_time + seconds(m_completion_timeout)));
|
||||||
m_timeout.async_wait(m_strand.wrap(
|
m_timeout.async_wait(m_strand.wrap(
|
||||||
|
|
|
@ -180,7 +180,7 @@ namespace libtorrent
|
||||||
const int block_size = t->block_size();
|
const int block_size = t->block_size();
|
||||||
while (size > 0)
|
while (size > 0)
|
||||||
{
|
{
|
||||||
int request_size = std::min(block_size, size);
|
int request_size = (std::min)(block_size, size);
|
||||||
peer_request pr = {r.piece, r.start + r.length - size
|
peer_request pr = {r.piece, r.start + r.length - size
|
||||||
, request_size};
|
, request_size};
|
||||||
m_requests.push_back(pr);
|
m_requests.push_back(pr);
|
||||||
|
@ -510,7 +510,7 @@ namespace libtorrent
|
||||||
// m_piece as buffer.
|
// m_piece as buffer.
|
||||||
|
|
||||||
int piece_size = int(m_piece.size());
|
int piece_size = int(m_piece.size());
|
||||||
int copy_size = std::min(std::min(front_request.length - piece_size
|
int copy_size = (std::min)(std::min(front_request.length - piece_size
|
||||||
, recv_buffer.left()), int(range_end - range_start - m_received_body));
|
, recv_buffer.left()), int(range_end - range_start - m_received_body));
|
||||||
m_piece.resize(piece_size + copy_size);
|
m_piece.resize(piece_size + copy_size);
|
||||||
assert(copy_size > 0);
|
assert(copy_size > 0);
|
||||||
|
@ -568,7 +568,7 @@ namespace libtorrent
|
||||||
&& (m_received_body + recv_buffer.left() >= range_end - range_start))
|
&& (m_received_body + recv_buffer.left() >= range_end - range_start))
|
||||||
{
|
{
|
||||||
int piece_size = int(m_piece.size());
|
int piece_size = int(m_piece.size());
|
||||||
int copy_size = std::min(std::min(m_requests.front().length - piece_size
|
int copy_size = (std::min)(std::min(m_requests.front().length - piece_size
|
||||||
, recv_buffer.left()), int(range_end - range_start - m_received_body));
|
, recv_buffer.left()), int(range_end - range_start - m_received_body));
|
||||||
assert(copy_size >= 0);
|
assert(copy_size >= 0);
|
||||||
if (copy_size > 0)
|
if (copy_size > 0)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue