lt sync 1912
This commit is contained in:
parent
5c485afe5e
commit
e491ecf0df
|
@ -41,6 +41,7 @@ TORRENT_EXPORT void assert_fail(const char* expr, int line, char const* file, ch
|
|||
#define TORRENT_ASSERT(x) if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__)
|
||||
|
||||
#else
|
||||
#include <cassert>
|
||||
#define TORRENT_ASSERT(x) assert(x)
|
||||
#endif
|
||||
|
||||
|
|
|
@ -379,6 +379,7 @@ namespace libtorrent
|
|||
// this pool is used to allocate and recycle send
|
||||
// buffers from.
|
||||
boost::pool<> m_send_buffers;
|
||||
boost::mutex m_send_buffer_mutex;
|
||||
|
||||
// the file pool that all storages in this session's
|
||||
// torrents uses. It sets a limit on the number of
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2007, 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_BANDWIDTH_LIMIT_HPP_INCLUDED
|
||||
#define TORRENT_BANDWIDTH_LIMIT_HPP_INCLUDED
|
||||
|
||||
#include <boost/integer_traits.hpp>
|
||||
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent {
|
||||
|
||||
// member of peer_connection
|
||||
struct bandwidth_limit
|
||||
{
|
||||
static const int inf = boost::integer_traits<int>::const_max;
|
||||
|
||||
bandwidth_limit()
|
||||
: m_quota_left(0)
|
||||
, m_local_limit(inf)
|
||||
, m_current_rate(0)
|
||||
{}
|
||||
|
||||
void throttle(int limit)
|
||||
{
|
||||
TORRENT_ASSERT(limit > 0);
|
||||
m_local_limit = limit;
|
||||
}
|
||||
|
||||
int throttle() const
|
||||
{
|
||||
return m_local_limit;
|
||||
}
|
||||
|
||||
void assign(int amount)
|
||||
{
|
||||
TORRENT_ASSERT(amount >= 0);
|
||||
m_current_rate += amount;
|
||||
m_quota_left += amount;
|
||||
}
|
||||
|
||||
void use_quota(int amount)
|
||||
{
|
||||
TORRENT_ASSERT(amount <= m_quota_left);
|
||||
m_quota_left -= amount;
|
||||
}
|
||||
|
||||
int quota_left() const
|
||||
{
|
||||
return (std::max)(m_quota_left, 0);
|
||||
}
|
||||
|
||||
void expire(int amount)
|
||||
{
|
||||
TORRENT_ASSERT(amount >= 0);
|
||||
m_current_rate -= amount;
|
||||
}
|
||||
|
||||
int max_assignable() const
|
||||
{
|
||||
if (m_local_limit == inf) return inf;
|
||||
if (m_local_limit <= m_current_rate) return 0;
|
||||
return m_local_limit - m_current_rate;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// this is the amount of bandwidth we have
|
||||
// been assigned without using yet. i.e.
|
||||
// the bandwidth that we use up every time
|
||||
// we receive or send a message. Once this
|
||||
// hits zero, we need to request more
|
||||
// bandwidth from the torrent which
|
||||
// in turn will request bandwidth from
|
||||
// the bandwidth manager
|
||||
int m_quota_left;
|
||||
|
||||
// the local limit is the number of bytes
|
||||
// per window size we are allowed to use.
|
||||
int m_local_limit;
|
||||
|
||||
// the current rate is the number of
|
||||
// bytes we have been assigned within
|
||||
// the window size.
|
||||
int m_current_rate;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -44,6 +44,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/socket.hpp"
|
||||
#include "libtorrent/invariant_check.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
#include "libtorrent/bandwidth_limit.hpp"
|
||||
#include "libtorrent/bandwidth_queue_entry.hpp"
|
||||
|
||||
using boost::weak_ptr;
|
||||
using boost::shared_ptr;
|
||||
|
@ -77,91 +79,6 @@ struct history_entry
|
|||
weak_ptr<Torrent> tor;
|
||||
};
|
||||
|
||||
template<class PeerConnection>
|
||||
struct bw_queue_entry
|
||||
{
|
||||
bw_queue_entry(boost::intrusive_ptr<PeerConnection> const& pe
|
||||
, int blk, bool no_prio)
|
||||
: peer(pe), max_block_size(blk), non_prioritized(no_prio) {}
|
||||
boost::intrusive_ptr<PeerConnection> peer;
|
||||
int max_block_size;
|
||||
bool non_prioritized;
|
||||
};
|
||||
|
||||
// member of peer_connection
|
||||
struct bandwidth_limit
|
||||
{
|
||||
static const int inf = boost::integer_traits<int>::const_max;
|
||||
|
||||
bandwidth_limit() throw()
|
||||
: m_quota_left(0)
|
||||
, m_local_limit(inf)
|
||||
, m_current_rate(0)
|
||||
{}
|
||||
|
||||
void throttle(int limit) throw()
|
||||
{
|
||||
m_local_limit = limit;
|
||||
}
|
||||
|
||||
int throttle() const throw()
|
||||
{
|
||||
return m_local_limit;
|
||||
}
|
||||
|
||||
void assign(int amount) throw()
|
||||
{
|
||||
TORRENT_ASSERT(amount >= 0);
|
||||
m_current_rate += amount;
|
||||
m_quota_left += amount;
|
||||
}
|
||||
|
||||
void use_quota(int amount) throw()
|
||||
{
|
||||
TORRENT_ASSERT(amount <= m_quota_left);
|
||||
m_quota_left -= amount;
|
||||
}
|
||||
|
||||
int quota_left() const throw()
|
||||
{
|
||||
return (std::max)(m_quota_left, 0);
|
||||
}
|
||||
|
||||
void expire(int amount) throw()
|
||||
{
|
||||
TORRENT_ASSERT(amount >= 0);
|
||||
m_current_rate -= amount;
|
||||
}
|
||||
|
||||
int max_assignable() const throw()
|
||||
{
|
||||
if (m_local_limit == inf) return inf;
|
||||
if (m_local_limit <= m_current_rate) return 0;
|
||||
return m_local_limit - m_current_rate;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// this is the amount of bandwidth we have
|
||||
// been assigned without using yet. i.e.
|
||||
// the bandwidth that we use up every time
|
||||
// we receive or send a message. Once this
|
||||
// hits zero, we need to request more
|
||||
// bandwidth from the torrent which
|
||||
// in turn will request bandwidth from
|
||||
// the bandwidth manager
|
||||
int m_quota_left;
|
||||
|
||||
// the local limit is the number of bytes
|
||||
// per window size we are allowed to use.
|
||||
int m_local_limit;
|
||||
|
||||
// the current rate is the number of
|
||||
// bytes we have been assigned within
|
||||
// the window size.
|
||||
int m_current_rate;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
T clamp(T val, T ceiling, T floor) throw()
|
||||
{
|
||||
|
@ -203,6 +120,19 @@ struct bandwidth_manager
|
|||
m_history_timer.cancel();
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool is_in_history(PeerConnection const* peer) const
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
for (typename history_t::const_iterator i
|
||||
= m_history.begin(), end(m_history.end()); i != end; ++i)
|
||||
{
|
||||
if (i->peer.get() == peer) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// non prioritized means that, if there's a line for bandwidth,
|
||||
// others will cut in front of the non-prioritized peers.
|
||||
// this is used by web seeds
|
||||
|
@ -213,6 +143,7 @@ struct bandwidth_manager
|
|||
INVARIANT_CHECK;
|
||||
TORRENT_ASSERT(blk > 0);
|
||||
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
TORRENT_ASSERT(!peer->ignore_bandwidth_limits());
|
||||
|
||||
// make sure this peer isn't already in line
|
||||
|
@ -224,6 +155,7 @@ struct bandwidth_manager
|
|||
TORRENT_ASSERT(i->peer < peer || peer < i->peer);
|
||||
}
|
||||
#endif
|
||||
TORRENT_ASSERT(peer->max_assignable_bandwidth(m_channel) > 0);
|
||||
|
||||
boost::shared_ptr<Torrent> t = peer->associated_torrent().lock();
|
||||
|
||||
|
@ -257,7 +189,7 @@ struct bandwidth_manager
|
|||
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
|
||||
std::cerr << " req_bandwidht. m_queue.size() = " << m_queue.size() << std::endl;
|
||||
#endif
|
||||
if (!m_queue.empty()) hand_out_bandwidth();
|
||||
if (!m_queue.empty()) hand_out_bandwidth(l);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
@ -309,6 +241,7 @@ private:
|
|||
|
||||
TORRENT_ASSERT(!m_history.empty());
|
||||
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
ptime now(time_now());
|
||||
while (!m_history.empty() && m_history.back().expires_at <= now)
|
||||
{
|
||||
|
@ -318,8 +251,10 @@ private:
|
|||
TORRENT_ASSERT(m_current_quota >= 0);
|
||||
intrusive_ptr<PeerConnection> c = e.peer;
|
||||
shared_ptr<Torrent> t = e.tor.lock();
|
||||
l.unlock();
|
||||
if (!c->is_disconnecting()) c->expire_bandwidth(m_channel, e.amount);
|
||||
if (t) t->expire_bandwidth(m_channel, e.amount);
|
||||
l.lock();
|
||||
}
|
||||
|
||||
// now, wait for the next chunk to expire
|
||||
|
@ -332,7 +267,7 @@ private:
|
|||
// since some bandwidth just expired, it
|
||||
// means we can hand out more (in case there
|
||||
// are still consumers in line)
|
||||
if (!m_queue.empty()) hand_out_bandwidth();
|
||||
if (!m_queue.empty()) hand_out_bandwidth(l);
|
||||
#ifndef NDEBUG
|
||||
}
|
||||
catch (std::exception&)
|
||||
|
@ -342,7 +277,7 @@ private:
|
|||
#endif
|
||||
}
|
||||
|
||||
void hand_out_bandwidth() throw()
|
||||
void hand_out_bandwidth(boost::mutex::scoped_lock& l) throw()
|
||||
{
|
||||
// if we're already handing out bandwidth, just return back
|
||||
// to the loop further down on the callstack
|
||||
|
@ -355,9 +290,7 @@ private:
|
|||
|
||||
ptime now(time_now());
|
||||
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
int limit = m_limit;
|
||||
l.unlock();
|
||||
|
||||
// available bandwidth to hand out
|
||||
int amount = limit - m_current_quota;
|
||||
|
@ -369,34 +302,41 @@ private:
|
|||
<< " m_current_quota = " << m_current_quota << std::endl;
|
||||
#endif
|
||||
|
||||
while (!m_queue.empty() && amount > 0)
|
||||
if (amount <= 0)
|
||||
{
|
||||
m_in_hand_out_bandwidth = false;
|
||||
return;
|
||||
}
|
||||
|
||||
queue_t q;
|
||||
queue_t tmp;
|
||||
m_queue.swap(q);
|
||||
while (!q.empty() && amount > 0)
|
||||
{
|
||||
TORRENT_ASSERT(amount == limit - m_current_quota);
|
||||
bw_queue_entry<PeerConnection> qe = m_queue.front();
|
||||
bw_queue_entry<PeerConnection> qe = q.front();
|
||||
TORRENT_ASSERT(qe.max_block_size > 0);
|
||||
m_queue.pop_front();
|
||||
q.pop_front();
|
||||
|
||||
shared_ptr<Torrent> t = qe.peer->associated_torrent().lock();
|
||||
if (!t) continue;
|
||||
if (qe.peer->is_disconnecting())
|
||||
{
|
||||
l.unlock();
|
||||
t->expire_bandwidth(m_channel, qe.max_block_size);
|
||||
TORRENT_ASSERT(amount == limit - m_current_quota);
|
||||
l.lock();
|
||||
amount = limit - m_current_quota;
|
||||
continue;
|
||||
}
|
||||
|
||||
// at this point, max_assignable may actually be zero. Since
|
||||
// the bandwidth quota is subtracted once the data has been
|
||||
// sent. If the peer was added to the queue while the data was
|
||||
// still being sent, max_assignable may have been > 0 at that time.
|
||||
int max_assignable = (std::min)(
|
||||
qe.peer->max_assignable_bandwidth(m_channel)
|
||||
, t->max_assignable_bandwidth(m_channel));
|
||||
// the rate limit of the peer might have changed while it
|
||||
// was in the queue.
|
||||
int max_assignable = qe.peer->max_assignable_bandwidth(m_channel);
|
||||
if (max_assignable == 0)
|
||||
{
|
||||
t->expire_bandwidth(m_channel, qe.max_block_size);
|
||||
qe.peer->assign_bandwidth(m_channel, 0);
|
||||
TORRENT_ASSERT(amount == limit - m_current_quota);
|
||||
TORRENT_ASSERT(is_in_history(qe.peer.get()));
|
||||
tmp.push_back(qe);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -441,7 +381,7 @@ private:
|
|||
#endif
|
||||
if (amount < block_size / 2)
|
||||
{
|
||||
m_queue.push_front(qe);
|
||||
tmp.push_back(qe);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -454,12 +394,16 @@ private:
|
|||
TORRENT_ASSERT(amount == limit - m_current_quota);
|
||||
amount -= hand_out_amount;
|
||||
TORRENT_ASSERT(hand_out_amount <= qe.max_block_size);
|
||||
l.unlock();
|
||||
t->assign_bandwidth(m_channel, hand_out_amount, qe.max_block_size);
|
||||
qe.peer->assign_bandwidth(m_channel, hand_out_amount);
|
||||
l.lock();
|
||||
add_history_entry(history_entry<PeerConnection, Torrent>(
|
||||
qe.peer, t, hand_out_amount, now + bw_window_size));
|
||||
TORRENT_ASSERT(amount == limit - m_current_quota);
|
||||
amount = limit - m_current_quota;
|
||||
}
|
||||
if (!q.empty()) m_queue.insert(m_queue.begin(), q.begin(), q.end());
|
||||
if (!tmp.empty()) m_queue.insert(m_queue.begin(), tmp.begin(), tmp.end());
|
||||
#ifndef NDEBUG
|
||||
}
|
||||
catch (std::exception& e)
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2007, 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_BANDWIDTH_QUEUE_ENTRY_HPP_INCLUDED
|
||||
#define TORRENT_BANDWIDTH_QUEUE_ENTRY_HPP_INCLUDED
|
||||
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
|
||||
namespace libtorrent {
|
||||
|
||||
template<class PeerConnection>
|
||||
struct bw_queue_entry
|
||||
{
|
||||
bw_queue_entry(boost::intrusive_ptr<PeerConnection> const& pe
|
||||
, int blk, bool no_prio)
|
||||
: peer(pe), max_block_size(blk), non_prioritized(no_prio) {}
|
||||
boost::intrusive_ptr<PeerConnection> peer;
|
||||
int max_block_size;
|
||||
bool non_prioritized;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -30,6 +30,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
*/
|
||||
|
||||
#ifndef TORRENT_DISK_IO_THREAD
|
||||
#define TORRENT_DISK_IO_THREAD
|
||||
|
||||
#ifdef TORRENT_DISK_STATS
|
||||
#include <fstream>
|
||||
#endif
|
||||
|
@ -100,6 +103,8 @@ namespace libtorrent
|
|||
{ return m_allocations; }
|
||||
#endif
|
||||
|
||||
void join();
|
||||
|
||||
// aborts read operations
|
||||
void stop(boost::intrusive_ptr<piece_manager> s);
|
||||
void add_job(disk_io_job const& j
|
||||
|
@ -152,3 +157,5 @@ namespace libtorrent
|
|||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -76,9 +76,9 @@ namespace detail
|
|||
template<class Addr>
|
||||
Addr zero()
|
||||
{
|
||||
typename Addr::bytes_type zero;
|
||||
Addr zero;
|
||||
std::fill(zero.begin(), zero.end(), 0);
|
||||
return Addr(zero);
|
||||
return zero;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -87,8 +87,8 @@ namespace detail
|
|||
template<class Addr>
|
||||
Addr plus_one(Addr const& a)
|
||||
{
|
||||
typename Addr::bytes_type tmp(a.to_bytes());
|
||||
typedef typename Addr::bytes_type::reverse_iterator iter;
|
||||
Addr tmp(a);
|
||||
typedef typename Addr::reverse_iterator iter;
|
||||
for (iter i = tmp.rbegin()
|
||||
, end(tmp.rend()); i != end; ++i)
|
||||
{
|
||||
|
@ -99,7 +99,7 @@ namespace detail
|
|||
}
|
||||
*i = 0;
|
||||
}
|
||||
return Addr(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline boost::uint16_t plus_one(boost::uint16_t val) { return val + 1; }
|
||||
|
@ -107,8 +107,8 @@ namespace detail
|
|||
template<class Addr>
|
||||
Addr minus_one(Addr const& a)
|
||||
{
|
||||
typename Addr::bytes_type tmp(a.to_bytes());
|
||||
typedef typename Addr::bytes_type::reverse_iterator iter;
|
||||
Addr tmp(a);
|
||||
typedef typename Addr::reverse_iterator iter;
|
||||
for (iter i = tmp.rbegin()
|
||||
, end(tmp.rend()); i != end; ++i)
|
||||
{
|
||||
|
@ -119,7 +119,7 @@ namespace detail
|
|||
}
|
||||
*i = (std::numeric_limits<typename iter::value_type>::max)();
|
||||
}
|
||||
return Addr(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline boost::uint16_t minus_one(boost::uint16_t val) { return val - 1; }
|
||||
|
@ -127,9 +127,9 @@ namespace detail
|
|||
template<class Addr>
|
||||
Addr max_addr()
|
||||
{
|
||||
typename Addr::bytes_type tmp;
|
||||
Addr tmp;
|
||||
std::fill(tmp.begin(), tmp.end()
|
||||
, (std::numeric_limits<typename Addr::bytes_type::value_type>::max)());
|
||||
, (std::numeric_limits<typename Addr::value_type>::max)());
|
||||
return Addr(tmp);
|
||||
}
|
||||
|
||||
|
@ -220,23 +220,24 @@ namespace detail
|
|||
return i->access;
|
||||
}
|
||||
|
||||
std::vector<ip_range<Addr> > export_filter() const
|
||||
template <class ExternalAddressType>
|
||||
std::vector<ip_range<ExternalAddressType> > export_filter() const
|
||||
{
|
||||
std::vector<ip_range<Addr> > ret;
|
||||
std::vector<ip_range<ExternalAddressType> > ret;
|
||||
ret.reserve(m_access_list.size());
|
||||
|
||||
for (typename range_t::const_iterator i = m_access_list.begin()
|
||||
, end(m_access_list.end()); i != end;)
|
||||
{
|
||||
ip_range<Addr> r;
|
||||
r.first = i->start;
|
||||
ip_range<ExternalAddressType> r;
|
||||
r.first = ExternalAddressType(i->start);
|
||||
r.flags = i->access;
|
||||
|
||||
++i;
|
||||
if (i == end)
|
||||
r.last = max_addr<Addr>();
|
||||
r.last = ExternalAddressType(max_addr<Addr>());
|
||||
else
|
||||
r.last = minus_one(i->start);
|
||||
r.last = ExternalAddressType(minus_one(i->start));
|
||||
|
||||
ret.push_back(r);
|
||||
}
|
||||
|
@ -288,8 +289,8 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
detail::filter_impl<address_v4> m_filter4;
|
||||
detail::filter_impl<address_v6> m_filter6;
|
||||
detail::filter_impl<address_v4::bytes_type> m_filter4;
|
||||
detail::filter_impl<address_v6::bytes_type> m_filter6;
|
||||
};
|
||||
|
||||
class TORRENT_EXPORT port_filter
|
||||
|
|
|
@ -62,7 +62,7 @@ namespace libtorrent
|
|||
private:
|
||||
int get_local_key_size () const
|
||||
{
|
||||
assert (m_DH);
|
||||
TORRENT_ASSERT(m_DH);
|
||||
return BN_num_bytes (m_DH->pub_key);
|
||||
}
|
||||
|
||||
|
@ -97,8 +97,8 @@ namespace libtorrent
|
|||
|
||||
void encrypt (char* pos, int len)
|
||||
{
|
||||
assert (len >= 0);
|
||||
assert (pos);
|
||||
TORRENT_ASSERT(len >= 0);
|
||||
TORRENT_ASSERT(pos);
|
||||
|
||||
RC4 (&m_local_key, len, reinterpret_cast<unsigned char const*>(pos),
|
||||
reinterpret_cast<unsigned char*>(pos));
|
||||
|
@ -106,8 +106,8 @@ namespace libtorrent
|
|||
|
||||
void decrypt (char* pos, int len)
|
||||
{
|
||||
assert (len >= 0);
|
||||
assert (pos);
|
||||
TORRENT_ASSERT(len >= 0);
|
||||
TORRENT_ASSERT(pos);
|
||||
|
||||
RC4 (&m_remote_key, len, reinterpret_cast<unsigned char const*>(pos),
|
||||
reinterpret_cast<unsigned char*>(pos));
|
||||
|
|
|
@ -69,7 +69,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/piece_block_progress.hpp"
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/session.hpp"
|
||||
#include "libtorrent/bandwidth_manager.hpp"
|
||||
#include "libtorrent/bandwidth_limit.hpp"
|
||||
#include "libtorrent/policy.hpp"
|
||||
#include "libtorrent/socket_type.hpp"
|
||||
#include "libtorrent/intrusive_ptr_base.hpp"
|
||||
|
|
|
@ -117,6 +117,7 @@ namespace libtorrent
|
|||
, use_dht_as_fallback(true)
|
||||
#endif
|
||||
, free_torrent_hashes(true)
|
||||
, upnp_ignore_nonrouters(true)
|
||||
{}
|
||||
|
||||
// this is the user agent that will be sent to the tracker
|
||||
|
@ -292,6 +293,11 @@ namespace libtorrent
|
|||
// make the get_torrent_info() function to return an incomplete
|
||||
// torrent object that cannot be passed back to add_torrent()
|
||||
bool free_torrent_hashes;
|
||||
|
||||
// when this is true, the upnp port mapper will ignore
|
||||
// any upnp devices that don't have an address that matches
|
||||
// our currently configured router.
|
||||
bool upnp_ignore_nonrouters;
|
||||
};
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
|
|
|
@ -65,7 +65,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/piece_picker.hpp"
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/escape_string.hpp"
|
||||
#include "libtorrent/bandwidth_manager.hpp"
|
||||
#include "libtorrent/bandwidth_limit.hpp"
|
||||
#include "libtorrent/bandwidth_queue_entry.hpp"
|
||||
#include "libtorrent/storage.hpp"
|
||||
#include "libtorrent/hasher.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
|
|
@ -68,13 +68,14 @@ class upnp : public intrusive_ptr_base<upnp>
|
|||
public:
|
||||
upnp(io_service& ios, connection_queue& cc
|
||||
, address const& listen_interface, std::string const& user_agent
|
||||
, portmap_callback_t const& cb);
|
||||
, portmap_callback_t const& cb, bool ignore_nonrouters);
|
||||
~upnp();
|
||||
|
||||
// maps the ports, if a port is set to 0
|
||||
// it will not be mapped
|
||||
void set_mappings(int tcp, int udp);
|
||||
|
||||
void discover_device();
|
||||
void close();
|
||||
|
||||
private:
|
||||
|
@ -89,7 +90,6 @@ private:
|
|||
void resend_request(asio::error_code const& e);
|
||||
void on_reply(udp::endpoint const& from, char* buffer
|
||||
, std::size_t bytes_transferred);
|
||||
void discover_device();
|
||||
|
||||
struct rootdevice;
|
||||
|
||||
|
@ -233,6 +233,8 @@ private:
|
|||
|
||||
connection_queue& m_cc;
|
||||
|
||||
std::vector<address> m_filter;
|
||||
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
std::ofstream m_log;
|
||||
#endif
|
||||
|
|
|
@ -120,7 +120,8 @@ namespace libtorrent
|
|||
void write_interested() {}
|
||||
void write_not_interested() {}
|
||||
void write_request(peer_request const& r);
|
||||
void write_cancel(peer_request const& r) {}
|
||||
void write_cancel(peer_request const& r)
|
||||
{ incoming_reject_request(r); }
|
||||
void write_have(int index) {}
|
||||
void write_piece(peer_request const& r, char* buffer) { TORRENT_ASSERT(false); }
|
||||
void write_keepalive() {}
|
||||
|
|
|
@ -170,12 +170,17 @@ namespace libtorrent
|
|||
for (std::list<socket_entry>::iterator i = m_sockets.begin()
|
||||
, end(m_sockets.end()); i != end; ++i)
|
||||
{
|
||||
if (!i->socket) continue;
|
||||
asio::error_code e;
|
||||
i->socket->send_to(asio::buffer(buffer, size), m_multicast_endpoint, 0, e);
|
||||
#ifndef NDEBUG
|
||||
// std::cerr << " sending on " << i->socket->local_endpoint().address().to_string() << std::endl;
|
||||
#endif
|
||||
if (e) ec = e;
|
||||
if (e)
|
||||
{
|
||||
i->socket->close(e);
|
||||
i->socket.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,6 +189,7 @@ namespace libtorrent
|
|||
{
|
||||
if (ec || bytes_transferred == 0 || !m_on_receive) return;
|
||||
m_on_receive(s->remote, s->buffer, bytes_transferred);
|
||||
if (!s->socket) return;
|
||||
s->socket->async_receive_from(asio::buffer(s->buffer, sizeof(s->buffer))
|
||||
, s->remote, bind(&broadcast_socket::on_receive, this, s, _1, _2));
|
||||
}
|
||||
|
@ -195,6 +201,7 @@ namespace libtorrent
|
|||
for (std::list<socket_entry>::iterator i = m_sockets.begin()
|
||||
, end(m_sockets.end()); i != end; ++i)
|
||||
{
|
||||
if (!i->socket) continue;
|
||||
i->socket->close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -295,6 +295,8 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (!m_supports_fast) return;
|
||||
|
||||
TORRENT_ASSERT(m_sent_handshake && m_sent_bitfield);
|
||||
TORRENT_ASSERT(associated_torrent().lock()->valid_metadata());
|
||||
|
||||
|
@ -312,6 +314,7 @@ namespace libtorrent
|
|||
|
||||
TORRENT_ASSERT(m_sent_handshake && m_sent_bitfield);
|
||||
TORRENT_ASSERT(associated_torrent().lock()->valid_metadata());
|
||||
TORRENT_ASSERT(m_supports_fast);
|
||||
|
||||
char msg[] = {0,0,0,5, msg_allowed_fast, 0, 0, 0, 0};
|
||||
char* ptr = msg + 5;
|
||||
|
@ -1297,6 +1300,9 @@ namespace libtorrent
|
|||
detail::write_int32(r.start, ptr); // begin
|
||||
detail::write_int32(r.length, ptr); // length
|
||||
send_buffer(msg, sizeof(msg));
|
||||
|
||||
if (!m_supports_fast)
|
||||
incoming_reject_request(r);
|
||||
}
|
||||
|
||||
void bt_peer_connection::write_request(peer_request const& r)
|
||||
|
|
|
@ -62,12 +62,7 @@ namespace libtorrent
|
|||
|
||||
disk_io_thread::~disk_io_thread()
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
m_abort = true;
|
||||
m_signal.notify_all();
|
||||
l.unlock();
|
||||
|
||||
m_disk_io_thread.join();
|
||||
TORRENT_ASSERT(m_abort == true);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
@ -95,6 +90,16 @@ namespace libtorrent
|
|||
|
||||
#endif
|
||||
|
||||
void disk_io_thread::join()
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
m_abort = true;
|
||||
m_signal.notify_all();
|
||||
l.unlock();
|
||||
|
||||
m_disk_io_thread.join();
|
||||
}
|
||||
|
||||
// aborts read operations
|
||||
void disk_io_thread::stop(boost::intrusive_ptr<piece_manager> s)
|
||||
{
|
||||
|
|
|
@ -44,12 +44,12 @@ namespace libtorrent
|
|||
if (first.is_v4())
|
||||
{
|
||||
TORRENT_ASSERT(last.is_v4());
|
||||
m_filter4.add_rule(first.to_v4(), last.to_v4(), flags);
|
||||
m_filter4.add_rule(first.to_v4().to_bytes(), last.to_v4().to_bytes(), flags);
|
||||
}
|
||||
else if (first.is_v6())
|
||||
{
|
||||
TORRENT_ASSERT(last.is_v6());
|
||||
m_filter6.add_rule(first.to_v6(), last.to_v6(), flags);
|
||||
m_filter6.add_rule(first.to_v6().to_bytes(), last.to_v6().to_bytes(), flags);
|
||||
}
|
||||
else
|
||||
TORRENT_ASSERT(false);
|
||||
|
@ -58,15 +58,15 @@ namespace libtorrent
|
|||
int ip_filter::access(address const& addr) const
|
||||
{
|
||||
if (addr.is_v4())
|
||||
return m_filter4.access(addr.to_v4());
|
||||
return m_filter4.access(addr.to_v4().to_bytes());
|
||||
TORRENT_ASSERT(addr.is_v6());
|
||||
return m_filter6.access(addr.to_v6());
|
||||
return m_filter6.access(addr.to_v6().to_bytes());
|
||||
}
|
||||
|
||||
ip_filter::filter_tuple_t ip_filter::export_filter() const
|
||||
{
|
||||
return boost::make_tuple(m_filter4.export_filter()
|
||||
, m_filter6.export_filter());
|
||||
return boost::make_tuple(m_filter4.export_filter<address_v4>()
|
||||
, m_filter6.export_filter<address_v6>());
|
||||
}
|
||||
|
||||
void port_filter::add_rule(boost::uint16_t first, boost::uint16_t last, int flags)
|
||||
|
|
|
@ -95,7 +95,6 @@ namespace libtorrent { namespace
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct metadata_plugin : torrent_plugin
|
||||
{
|
||||
metadata_plugin(torrent& t)
|
||||
|
@ -217,7 +216,7 @@ namespace libtorrent { namespace
|
|||
m_metadata_size = total_size;
|
||||
}
|
||||
|
||||
void piece_pass(int)
|
||||
void on_piece_pass(int)
|
||||
{
|
||||
// if we became a seed, copy the metadata from
|
||||
// the torrent before it is deallocated
|
||||
|
|
|
@ -52,11 +52,11 @@ namespace libtorrent {
|
|||
m_DH->g = BN_bin2bn (m_dh_generator, sizeof(m_dh_generator), NULL);
|
||||
m_DH->length = 160l;
|
||||
|
||||
assert (sizeof(m_dh_prime) == DH_size(m_DH));
|
||||
TORRENT_ASSERT(sizeof(m_dh_prime) == DH_size(m_DH));
|
||||
|
||||
DH_generate_key (m_DH); // TODO Check != 0
|
||||
|
||||
assert (m_DH->pub_key);
|
||||
TORRENT_ASSERT(m_DH->pub_key);
|
||||
|
||||
// DH can generate key sizes that are smaller than the size of
|
||||
// P with exponentially decreasing probability, in which case
|
||||
|
@ -78,7 +78,7 @@ namespace libtorrent {
|
|||
|
||||
DH_key_exchange::~DH_key_exchange ()
|
||||
{
|
||||
assert (m_DH);
|
||||
TORRENT_ASSERT(m_DH);
|
||||
DH_free (m_DH);
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ namespace libtorrent {
|
|||
// compute shared secret given remote public key
|
||||
void DH_key_exchange::compute_secret (char const* remote_pubkey)
|
||||
{
|
||||
assert (remote_pubkey);
|
||||
TORRENT_ASSERT(remote_pubkey);
|
||||
BIGNUM* bn_remote_pubkey = BN_bin2bn ((unsigned char*)remote_pubkey, 96, NULL);
|
||||
char dh_secret[96];
|
||||
|
||||
|
|
|
@ -759,7 +759,7 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
// -----------------------------
|
||||
// -------- REJECT PIECE -------
|
||||
// ------- SUGGEST PIECE -------
|
||||
// -----------------------------
|
||||
|
||||
void peer_connection::incoming_suggest(int index)
|
||||
|
@ -1127,6 +1127,18 @@ namespace libtorrent
|
|||
"i: " << m_peer_interested << " | "
|
||||
"t: " << (int)t->torrent_file().piece_size(r.piece) << " | "
|
||||
"n: " << t->torrent_file().num_pieces() << " ]\n";
|
||||
|
||||
(*m_logger) << time_now_string()
|
||||
<< " ==> REJECT_PIECE [ "
|
||||
"piece: " << r.piece << " | "
|
||||
"s: " << r.start << " | "
|
||||
"l: " << r.length << " ]\n";
|
||||
|
||||
(*m_logger) << time_now_string()
|
||||
<< " ==> REJECT_PIECE [ "
|
||||
"piece: " << r.piece << " | "
|
||||
"s: " << r.start << " | "
|
||||
"l: " << r.length << " ]\n";
|
||||
#endif
|
||||
write_reject_request(r);
|
||||
return;
|
||||
|
@ -1157,6 +1169,11 @@ namespace libtorrent
|
|||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string()
|
||||
<< " *** REJECTING REQUEST [ peer choked and piece not in allowed fast set ]\n";
|
||||
(*m_logger) << time_now_string()
|
||||
<< " ==> REJECT_PIECE [ "
|
||||
"piece: " << r.piece << " | "
|
||||
"s: " << r.start << " | "
|
||||
"l: " << r.length << " ]\n";
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
@ -1179,6 +1196,12 @@ namespace libtorrent
|
|||
"n: " << t->torrent_file().num_pieces() << " | "
|
||||
"h: " << t->have_piece(r.piece) << " | "
|
||||
"block_limit: " << t->block_size() << " ]\n";
|
||||
|
||||
(*m_logger) << time_now_string()
|
||||
<< " ==> REJECT_PIECE [ "
|
||||
"piece: " << r.piece << " | "
|
||||
"s: " << r.start << " | "
|
||||
"l: " << r.length << " ]\n";
|
||||
#endif
|
||||
|
||||
write_reject_request(r);
|
||||
|
@ -1365,6 +1388,9 @@ namespace libtorrent
|
|||
m_outstanding_writing_bytes += p.length;
|
||||
TORRENT_ASSERT(!m_reading);
|
||||
picker.mark_as_writing(block_finished, peer_info_struct());
|
||||
#ifndef NDEBUG
|
||||
t->check_invariant();
|
||||
#endif
|
||||
}
|
||||
|
||||
void peer_connection::on_disk_write_complete(int ret, disk_io_job const& j
|
||||
|
@ -1479,6 +1505,14 @@ namespace libtorrent
|
|||
if (i != m_requests.end())
|
||||
{
|
||||
m_requests.erase(i);
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string()
|
||||
<< " ==> REJECT_PIECE [ "
|
||||
"piece: " << r.piece << " | "
|
||||
"s: " << r.start << " | "
|
||||
"l: " << r.length << " ]\n";
|
||||
#endif
|
||||
write_reject_request(r);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1612,12 +1646,6 @@ namespace libtorrent
|
|||
}
|
||||
#endif
|
||||
|
||||
// if we already have the piece, we can
|
||||
// ignore this message
|
||||
if (t->valid_metadata()
|
||||
&& t->have_piece(index))
|
||||
return;
|
||||
|
||||
if (index < 0 || index >= int(m_have_piece.size()))
|
||||
{
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
|
@ -1627,6 +1655,12 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
// if we already have the piece, we can
|
||||
// ignore this message
|
||||
if (t->valid_metadata()
|
||||
&& t->have_piece(index))
|
||||
return;
|
||||
|
||||
m_allowed_fast.push_back(index);
|
||||
|
||||
// if the peer has the piece and we want
|
||||
|
@ -1735,11 +1769,6 @@ namespace libtorrent
|
|||
// sent yet, so we don't have to send a cancel.
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_download_queue.erase(it);
|
||||
t->picker().abort_download(block);
|
||||
}
|
||||
|
||||
int block_offset = block.block_index * t->block_size();
|
||||
int block_size
|
||||
|
@ -1753,13 +1782,12 @@ namespace libtorrent
|
|||
r.start = block_offset;
|
||||
r.length = block_size;
|
||||
|
||||
write_cancel(r);
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string()
|
||||
<< " ==> CANCEL [ piece: " << block.piece_index << " | s: "
|
||||
<< block_offset << " | l: " << block_size << " | " << block.block_index << " ]\n";
|
||||
#endif
|
||||
write_cancel(r);
|
||||
}
|
||||
|
||||
void peer_connection::send_choke()
|
||||
|
@ -1783,6 +1811,19 @@ namespace libtorrent
|
|||
// reject the requests we have in the queue
|
||||
std::for_each(m_requests.begin(), m_requests.end()
|
||||
, bind(&peer_connection::write_reject_request, this, _1));
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
for (std::deque<peer_request>::iterator i = m_requests.begin()
|
||||
, end(m_requests.end()); i != end; ++i)
|
||||
{
|
||||
peer_request const& r = *i;
|
||||
(*m_logger) << time_now_string()
|
||||
<< " ==> REJECT_PIECE [ "
|
||||
"piece: " << r.piece << " | "
|
||||
"s: " << r.start << " | "
|
||||
"l: " << r.length << " ]\n";
|
||||
}
|
||||
#endif
|
||||
m_requests.clear();
|
||||
}
|
||||
|
||||
|
@ -2206,18 +2247,24 @@ namespace libtorrent
|
|||
else
|
||||
{
|
||||
piece_picker& picker = t->picker();
|
||||
while (!m_download_queue.empty())
|
||||
|
||||
std::deque<piece_block> dl(m_download_queue);
|
||||
for (std::deque<piece_block>::iterator i = dl.begin()
|
||||
, end(dl.end()); i != end; ++i)
|
||||
{
|
||||
piece_block const& r = m_download_queue.back();
|
||||
picker.abort_download(r);
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string()
|
||||
<< " ==> CANCEL [ piece: " << r.piece_index
|
||||
<< " | block: " << r.block_index
|
||||
<< " ]\n";
|
||||
#endif
|
||||
write_cancel(t->to_req(r));
|
||||
m_download_queue.pop_back();
|
||||
}
|
||||
while (!m_request_queue.empty())
|
||||
{
|
||||
piece_block const& r = m_request_queue.back();
|
||||
picker.abort_download(r);
|
||||
write_cancel(t->to_req(r));
|
||||
m_request_queue.pop_back();
|
||||
}
|
||||
|
||||
|
@ -2562,6 +2609,7 @@ namespace libtorrent
|
|||
// return value is destructed
|
||||
buffer::interval peer_connection::allocate_send_buffer(int size)
|
||||
{
|
||||
TORRENT_ASSERT(size > 0);
|
||||
char* insert = m_send_buffer.allocate_appendix(size);
|
||||
if (insert == 0)
|
||||
{
|
||||
|
@ -2618,6 +2666,7 @@ namespace libtorrent
|
|||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << "**ERROR**: " << error.message() << "[in peer_connection::on_receive_data]\n";
|
||||
#endif
|
||||
set_failed();
|
||||
on_receive(error, bytes_transferred);
|
||||
throw std::runtime_error(error.message());
|
||||
}
|
||||
|
@ -2778,6 +2827,7 @@ namespace libtorrent
|
|||
(*m_ses.m_logger) << "CONNECTION FAILED: " << m_remote.address().to_string()
|
||||
<< ": " << e.message() << "\n";
|
||||
#endif
|
||||
set_failed();
|
||||
m_ses.connection_failed(self(), m_remote, e.message().c_str());
|
||||
return;
|
||||
}
|
||||
|
@ -2838,6 +2888,7 @@ namespace libtorrent
|
|||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << "**ERROR**: " << error.message() << " [in peer_connection::on_send_data]\n";
|
||||
#endif
|
||||
set_failed();
|
||||
throw std::runtime_error(error.message());
|
||||
}
|
||||
if (m_disconnecting) return;
|
||||
|
@ -2869,6 +2920,17 @@ namespace libtorrent
|
|||
#ifndef NDEBUG
|
||||
void peer_connection::check_invariant() const
|
||||
{
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
// this peer is in the bandwidth history iff max_assignable < limit
|
||||
TORRENT_ASSERT((m_bandwidth_limit[i].max_assignable() < m_bandwidth_limit[i].throttle())
|
||||
== m_ses.m_bandwidth_manager[i]->is_in_history(this)
|
||||
|| m_bandwidth_limit[i].throttle() == bandwidth_limit::inf);
|
||||
}
|
||||
std::set<piece_block> unique;
|
||||
std::copy(m_download_queue.begin(), m_download_queue.end(), std::inserter(unique, unique.begin()));
|
||||
std::copy(m_request_queue.begin(), m_request_queue.end(), std::inserter(unique, unique.begin()));
|
||||
TORRENT_ASSERT(unique.size() == m_download_queue.size() + m_request_queue.size());
|
||||
if (m_peer_info)
|
||||
{
|
||||
TORRENT_ASSERT(m_peer_info->connection == this
|
||||
|
|
|
@ -533,6 +533,12 @@ namespace libtorrent
|
|||
if (i->second.type == peer::not_connectable) continue;
|
||||
if (i->second.seed && finished) continue;
|
||||
if (i->second.failcount >= max_failcount) continue;
|
||||
|
||||
// prefer peers with lower failcount
|
||||
if (candidate != m_peers.end()
|
||||
&& candidate->second.failcount < i->second.failcount)
|
||||
continue;
|
||||
|
||||
if (now - i->second.connected < seconds(i->second.failcount * min_reconnect_time))
|
||||
continue;
|
||||
if (ses.m_port_filter.access(i->second.ip.port()) & port_filter::blocked)
|
||||
|
|
|
@ -2198,6 +2198,11 @@ namespace detail
|
|||
#endif
|
||||
m_checker_thread->join();
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_logger) << time_now_string() << " waiting for disk io thread\n";
|
||||
#endif
|
||||
m_disk_thread.join();
|
||||
|
||||
TORRENT_ASSERT(m_torrents.empty());
|
||||
TORRENT_ASSERT(m_connections.empty());
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
|
@ -2345,8 +2350,10 @@ namespace detail
|
|||
, m_listen_interface.address()
|
||||
, m_settings.user_agent
|
||||
, bind(&session_impl::on_port_mapping
|
||||
, this, _1, _2, _3));
|
||||
, this, _1, _2, _3)
|
||||
, m_settings.upnp_ignore_nonrouters);
|
||||
|
||||
m_upnp->discover_device();
|
||||
m_upnp->set_mappings(m_listen_interface.port(),
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
m_dht ? m_dht_settings.service_port :
|
||||
|
@ -2385,7 +2392,11 @@ namespace detail
|
|||
|
||||
std::pair<char*, int> session_impl::allocate_buffer(int size)
|
||||
{
|
||||
TORRENT_ASSERT(size > 0);
|
||||
int num_buffers = (size + send_buffer_size - 1) / send_buffer_size;
|
||||
TORRENT_ASSERT(num_buffers > 0);
|
||||
|
||||
boost::mutex::scoped_lock l(m_send_buffer_mutex);
|
||||
#ifdef TORRENT_STATS
|
||||
m_buffer_allocations += num_buffers;
|
||||
m_buffer_usage_logger << log_time() << " protocol_buffer: "
|
||||
|
@ -2397,8 +2408,12 @@ namespace detail
|
|||
|
||||
void session_impl::free_buffer(char* buf, int size)
|
||||
{
|
||||
TORRENT_ASSERT(size > 0);
|
||||
TORRENT_ASSERT(size % send_buffer_size == 0);
|
||||
int num_buffers = size / send_buffer_size;
|
||||
TORRENT_ASSERT(num_buffers > 0);
|
||||
|
||||
boost::mutex::scoped_lock l(m_send_buffer_mutex);
|
||||
#ifdef TORRENT_STATS
|
||||
m_buffer_allocations -= num_buffers;
|
||||
TORRENT_ASSERT(m_buffer_allocations >= 0);
|
||||
|
|
|
@ -1589,6 +1589,18 @@ namespace libtorrent
|
|||
p->set_peer_info(0);
|
||||
TORRENT_ASSERT(i != m_connections.end());
|
||||
m_connections.erase(i);
|
||||
|
||||
// remove from bandwidth request-queue
|
||||
for (int c = 0; c < 2; ++c)
|
||||
{
|
||||
for (queue_t::iterator i = m_bandwidth_queue[c].begin()
|
||||
, end(m_bandwidth_queue[c].end()); i != end; ++i)
|
||||
{
|
||||
if (i->peer != p) continue;
|
||||
m_bandwidth_queue[c].erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
|
@ -2147,6 +2159,11 @@ namespace libtorrent
|
|||
throw protocol_error("session is closing");
|
||||
}
|
||||
|
||||
if (int(m_connections.size()) >= m_max_connections)
|
||||
{
|
||||
throw protocol_error("reached connection limit");
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(m_connections.find(p) == m_connections.end());
|
||||
peer_iterator ci = m_connections.insert(p).first;
|
||||
try
|
||||
|
@ -2220,6 +2237,7 @@ namespace libtorrent
|
|||
, bool non_prioritized)
|
||||
{
|
||||
TORRENT_ASSERT(m_bandwidth_limit[channel].throttle() > 0);
|
||||
TORRENT_ASSERT(p->max_assignable_bandwidth(channel) > 0);
|
||||
int block_size = m_bandwidth_limit[channel].throttle() / 10;
|
||||
if (block_size <= 0) block_size = 1;
|
||||
|
||||
|
@ -2244,16 +2262,23 @@ namespace libtorrent
|
|||
|
||||
TORRENT_ASSERT(amount > 0);
|
||||
m_bandwidth_limit[channel].expire(amount);
|
||||
|
||||
queue_t tmp;
|
||||
while (!m_bandwidth_queue[channel].empty())
|
||||
{
|
||||
bw_queue_entry<peer_connection> qe = m_bandwidth_queue[channel].front();
|
||||
if (m_bandwidth_limit[channel].max_assignable() == 0)
|
||||
break;
|
||||
m_bandwidth_queue[channel].pop_front();
|
||||
if (qe.peer->max_assignable_bandwidth(channel) <= 0)
|
||||
{
|
||||
TORRENT_ASSERT(m_ses.m_bandwidth_manager[channel]->is_in_history(qe.peer.get()));
|
||||
if (!qe.peer->is_disconnecting()) tmp.push_back(qe);
|
||||
continue;
|
||||
}
|
||||
perform_bandwidth_request(channel, qe.peer
|
||||
, qe.max_block_size, qe.non_prioritized);
|
||||
}
|
||||
m_bandwidth_queue[channel].insert(m_bandwidth_queue[channel].begin(), tmp.begin(), tmp.end());
|
||||
}
|
||||
|
||||
void torrent::perform_bandwidth_request(int channel
|
||||
|
@ -2592,6 +2617,9 @@ namespace libtorrent
|
|||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||
|
||||
TORRENT_ASSERT(m_bandwidth_queue[0].size() <= m_connections.size());
|
||||
TORRENT_ASSERT(m_bandwidth_queue[1].size() <= m_connections.size());
|
||||
|
||||
int num_uploads = 0;
|
||||
std::map<piece_block, int> num_requests;
|
||||
for (const_peer_iterator i = begin(); i != end(); ++i)
|
||||
|
@ -2615,6 +2643,7 @@ namespace libtorrent
|
|||
for (std::map<piece_block, int>::iterator i = num_requests.begin()
|
||||
, end(num_requests.end()); i != end; ++i)
|
||||
{
|
||||
if (!m_picker->is_downloaded(i->first))
|
||||
TORRENT_ASSERT(m_picker->num_peers(i->first) == i->second);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -350,10 +350,23 @@ namespace libtorrent
|
|||
{ m_name = info["name"].string(); }
|
||||
|
||||
fs::path tmp = m_name;
|
||||
if (tmp.is_complete()) throw std::runtime_error("torrent contains "
|
||||
"a file with an absolute path: '" + m_name + "'");
|
||||
if (tmp.has_branch_path()) throw std::runtime_error(
|
||||
"torrent contains name with directories: '" + m_name + "'");
|
||||
if (tmp.is_complete())
|
||||
{
|
||||
m_name = tmp.leaf();
|
||||
}
|
||||
else if (tmp.has_branch_path())
|
||||
{
|
||||
fs::path p;
|
||||
for (fs::path::iterator i = tmp.begin()
|
||||
, end(tmp.end()); i != end; ++i)
|
||||
{
|
||||
if (*i == "." || *i == "..") continue;
|
||||
p /= *i;
|
||||
}
|
||||
m_name = p.string();
|
||||
}
|
||||
if (m_name == ".." || m_name == ".")
|
||||
throw std::runtime_error("invalid 'name' of torrent (possible exploit attempt)");
|
||||
|
||||
// extract file list
|
||||
entry const* i = info.find_key("files");
|
||||
|
|
|
@ -106,7 +106,6 @@ namespace libtorrent
|
|||
, udp::resolver::iterator i) try
|
||||
{
|
||||
if (error == asio::error::operation_aborted) return;
|
||||
if (!m_socket.is_open()) return; // the operation was aborted
|
||||
if (error || i == udp::resolver::iterator())
|
||||
{
|
||||
fail(-1, error.message().c_str());
|
||||
|
|
|
@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/http_tracker_connection.hpp"
|
||||
#include "libtorrent/xml_parse.hpp"
|
||||
#include "libtorrent/connection_queue.hpp"
|
||||
#include "libtorrent/enum_net.hpp"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
@ -61,7 +62,7 @@ namespace libtorrent
|
|||
|
||||
upnp::upnp(io_service& ios, connection_queue& cc
|
||||
, address const& listen_interface, std::string const& user_agent
|
||||
, portmap_callback_t const& cb)
|
||||
, portmap_callback_t const& cb, bool ignore_nonrouters)
|
||||
: m_udp_local_port(0)
|
||||
, m_tcp_local_port(0)
|
||||
, m_user_agent(user_agent)
|
||||
|
@ -81,7 +82,21 @@ upnp::upnp(io_service& ios, connection_queue& cc
|
|||
m_log.open("upnp.log", std::ios::in | std::ios::out | std::ios::trunc);
|
||||
#endif
|
||||
m_retry_count = 0;
|
||||
discover_device();
|
||||
|
||||
if (ignore_nonrouters)
|
||||
{
|
||||
asio::error_code ec;
|
||||
std::vector<address> const& net = enum_net_interfaces(m_io_service, ec);
|
||||
m_filter.reserve(net.size());
|
||||
for (std::vector<address>::const_iterator i = net.begin()
|
||||
, end(net.end()); i != end; ++i)
|
||||
{
|
||||
asio::error_code e;
|
||||
address a = router_for_interface(*i, e);
|
||||
if (e || is_loopback(a)) continue;
|
||||
m_filter.push_back(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
upnp::~upnp()
|
||||
|
@ -266,6 +281,18 @@ try
|
|||
Server:Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0
|
||||
|
||||
*/
|
||||
if (!m_filter.empty() && std::find(m_filter.begin(), m_filter.end()
|
||||
, from.address()) == m_filter.end())
|
||||
{
|
||||
// this upnp device is filtered because it's not in the
|
||||
// list of configured routers
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
m_log << time_now_string() << " <== (" << from << ") Rootdevice "
|
||||
"ignored because it's not out router" << std::endl;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
http_parser p;
|
||||
try
|
||||
{
|
||||
|
@ -663,7 +690,7 @@ void upnp::on_upnp_xml(asio::error_code const& e
|
|||
parse_state s;
|
||||
s.reset("urn:schemas-upnp-org:service:WANIPConnection:1");
|
||||
xml_parse((char*)p.get_body().begin, (char*)p.get_body().end
|
||||
, m_strand.wrap(bind(&find_control_url, _1, _2, boost::ref(s))));
|
||||
, bind(&find_control_url, _1, _2, boost::ref(s)));
|
||||
if (s.found_service)
|
||||
{
|
||||
d.service_namespace = s.service_type;
|
||||
|
@ -674,7 +701,7 @@ void upnp::on_upnp_xml(asio::error_code const& e
|
|||
// a PPP connection
|
||||
s.reset("urn:schemas-upnp-org:service:WANPPPConnection:1");
|
||||
xml_parse((char*)p.get_body().begin, (char*)p.get_body().end
|
||||
, m_strand.wrap(bind(&find_control_url, _1, _2, boost::ref(s))));
|
||||
, bind(&find_control_url, _1, _2, boost::ref(s)));
|
||||
if (s.found_service)
|
||||
{
|
||||
d.service_namespace = s.service_type;
|
||||
|
@ -821,7 +848,7 @@ void upnp::on_upnp_map_response(asio::error_code const& e
|
|||
|
||||
error_code_parse_state s;
|
||||
xml_parse((char*)p.get_body().begin, (char*)p.get_body().end
|
||||
, m_strand.wrap(bind(&find_error_code, _1, _2, boost::ref(s))));
|
||||
, bind(&find_error_code, _1, _2, boost::ref(s)));
|
||||
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
if (s.error_code != -1)
|
||||
|
|
Loading…
Reference in New Issue