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