mirror of
https://git.deluge-torrent.org/deluge
synced 2025-08-08 09:28:41 +00:00
lt sync 1958
This commit is contained in:
parent
76a0eb12e8
commit
df29d7d69a
17 changed files with 221 additions and 190 deletions
|
@ -124,6 +124,12 @@ struct bandwidth_manager
|
||||||
bool is_in_history(PeerConnection const* peer) const
|
bool is_in_history(PeerConnection const* peer) const
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
return is_in_history(peer, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_in_history(PeerConnection const* peer, boost::mutex::scoped_lock& l) const
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(l.locked());
|
||||||
for (typename history_t::const_iterator i
|
for (typename history_t::const_iterator i
|
||||||
= m_history.begin(), end(m_history.end()); i != end; ++i)
|
= m_history.begin(), end(m_history.end()); i != end; ++i)
|
||||||
{
|
{
|
||||||
|
@ -133,17 +139,21 @@ struct bandwidth_manager
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int queue_size() const
|
||||||
|
{
|
||||||
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
return m_queue.size();
|
||||||
|
}
|
||||||
|
|
||||||
// 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
|
||||||
void request_bandwidth(intrusive_ptr<PeerConnection> peer
|
void request_bandwidth(intrusive_ptr<PeerConnection> peer
|
||||||
, int blk
|
, int blk, int priority)
|
||||||
, bool non_prioritized) throw()
|
|
||||||
{
|
{
|
||||||
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
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
|
||||||
|
@ -157,38 +167,13 @@ struct bandwidth_manager
|
||||||
#endif
|
#endif
|
||||||
TORRENT_ASSERT(peer->max_assignable_bandwidth(m_channel) > 0);
|
TORRENT_ASSERT(peer->max_assignable_bandwidth(m_channel) > 0);
|
||||||
|
|
||||||
boost::shared_ptr<Torrent> t = peer->associated_torrent().lock();
|
typename queue_t::reverse_iterator i(m_queue.rbegin());
|
||||||
|
while (i != m_queue.rend() && priority > i->priority)
|
||||||
if (peer->max_assignable_bandwidth(m_channel) == 0)
|
|
||||||
{
|
{
|
||||||
t->expire_bandwidth(m_channel, blk);
|
++i->priority;
|
||||||
peer->assign_bandwidth(m_channel, 0);
|
++i;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
m_queue.push_back(bw_queue_entry<PeerConnection>(peer, blk, non_prioritized));
|
m_queue.insert(i.base(), bw_queue_entry<PeerConnection>(peer, blk, priority));
|
||||||
if (!non_prioritized)
|
|
||||||
{
|
|
||||||
typename queue_t::reverse_iterator i = m_queue.rbegin();
|
|
||||||
typename queue_t::reverse_iterator j(i);
|
|
||||||
for (++j; j != m_queue.rend(); ++j)
|
|
||||||
{
|
|
||||||
// if the peer's torrent is not the same one
|
|
||||||
// continue looking for a peer from the same torrent
|
|
||||||
if (j->peer->associated_torrent().lock() != t)
|
|
||||||
continue;
|
|
||||||
// if we found a peer from the same torrent that
|
|
||||||
// is prioritized, there is no point looking
|
|
||||||
// any further.
|
|
||||||
if (!j->non_prioritized) break;
|
|
||||||
|
|
||||||
using std::swap;
|
|
||||||
swap(*i, *j);
|
|
||||||
i = j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#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(l);
|
if (!m_queue.empty()) hand_out_bandwidth(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,18 +186,24 @@ struct bandwidth_manager
|
||||||
{
|
{
|
||||||
current_quota += i->amount;
|
current_quota += i->amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_ASSERT(current_quota == m_current_quota);
|
TORRENT_ASSERT(current_quota == m_current_quota);
|
||||||
|
|
||||||
|
typename queue_t::const_iterator j = m_queue.begin();
|
||||||
|
if (j != m_queue.end())
|
||||||
|
{
|
||||||
|
++j;
|
||||||
|
for (typename queue_t::const_iterator i = m_queue.begin()
|
||||||
|
, end(m_queue.end()); i != end && j != end; ++i, ++j)
|
||||||
|
TORRENT_ASSERT(i->priority >= j->priority);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void add_history_entry(history_entry<PeerConnection, Torrent> const& e) throw()
|
void add_history_entry(history_entry<PeerConnection, Torrent> const& e)
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
|
||||||
try {
|
try {
|
||||||
#endif
|
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
m_history.push_front(e);
|
m_history.push_front(e);
|
||||||
m_current_quota += e.amount;
|
m_current_quota += e.amount;
|
||||||
|
@ -224,24 +215,19 @@ private:
|
||||||
|
|
||||||
m_history_timer.expires_at(e.expires_at);
|
m_history_timer.expires_at(e.expires_at);
|
||||||
m_history_timer.async_wait(bind(&bandwidth_manager::on_history_expire, this, _1));
|
m_history_timer.async_wait(bind(&bandwidth_manager::on_history_expire, this, _1));
|
||||||
#ifndef NDEBUG
|
|
||||||
}
|
}
|
||||||
catch (std::exception&) { TORRENT_ASSERT(false); }
|
catch (std::exception&) {}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_history_expire(asio::error_code const& e) throw()
|
void on_history_expire(asio::error_code const& e)
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
|
||||||
try {
|
try {
|
||||||
#endif
|
|
||||||
INVARIANT_CHECK;
|
|
||||||
|
|
||||||
if (e) return;
|
if (e) return;
|
||||||
|
|
||||||
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
INVARIANT_CHECK;
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
@ -268,24 +254,19 @@ private:
|
||||||
// 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(l);
|
if (!m_queue.empty()) hand_out_bandwidth(l);
|
||||||
#ifndef NDEBUG
|
|
||||||
}
|
}
|
||||||
catch (std::exception&)
|
catch (std::exception&) {}
|
||||||
{
|
|
||||||
TORRENT_ASSERT(false);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hand_out_bandwidth(boost::mutex::scoped_lock& l) throw()
|
void hand_out_bandwidth(boost::mutex::scoped_lock& l) throw()
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(l.locked());
|
||||||
// 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
|
||||||
if (m_in_hand_out_bandwidth) return;
|
if (m_in_hand_out_bandwidth) return;
|
||||||
m_in_hand_out_bandwidth = true;
|
m_in_hand_out_bandwidth = true;
|
||||||
#ifndef NDEBUG
|
|
||||||
try {
|
try {
|
||||||
#endif
|
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
ptime now(time_now());
|
ptime now(time_now());
|
||||||
|
@ -308,24 +289,20 @@ private:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
queue_t q;
|
|
||||||
queue_t tmp;
|
queue_t tmp;
|
||||||
m_queue.swap(q);
|
while (!m_queue.empty() && amount > 0)
|
||||||
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);
|
TORRENT_ASSERT(qe.max_block_size > 0);
|
||||||
q.pop_front();
|
m_queue.pop_front();
|
||||||
|
|
||||||
shared_ptr<Torrent> t = qe.peer->associated_torrent().lock();
|
shared_ptr<Torrent> t = qe.torrent.lock();
|
||||||
if (!t) continue;
|
if (!t) continue;
|
||||||
if (qe.peer->is_disconnecting())
|
if (qe.peer->is_disconnecting())
|
||||||
{
|
{
|
||||||
l.unlock();
|
l.unlock();
|
||||||
t->expire_bandwidth(m_channel, qe.max_block_size);
|
t->expire_bandwidth(m_channel, qe.max_block_size);
|
||||||
l.lock();
|
l.lock();
|
||||||
amount = limit - m_current_quota;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,7 +312,7 @@ private:
|
||||||
int max_assignable = qe.peer->max_assignable_bandwidth(m_channel);
|
int max_assignable = qe.peer->max_assignable_bandwidth(m_channel);
|
||||||
if (max_assignable == 0)
|
if (max_assignable == 0)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(is_in_history(qe.peer.get()));
|
TORRENT_ASSERT(is_in_history(qe.peer.get(), l));
|
||||||
tmp.push_back(qe);
|
tmp.push_back(qe);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -379,11 +356,6 @@ private:
|
||||||
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
|
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
|
||||||
std::cerr << " block_size = " << block_size << " amount = " << amount << std::endl;
|
std::cerr << " block_size = " << block_size << " amount = " << amount << std::endl;
|
||||||
#endif
|
#endif
|
||||||
if (amount < block_size / 2)
|
|
||||||
{
|
|
||||||
tmp.push_back(qe);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// so, hand out max_assignable, but no more than
|
// so, hand out max_assignable, but no more than
|
||||||
// the available bandwidth (amount) and no more
|
// the available bandwidth (amount) and no more
|
||||||
|
@ -391,7 +363,6 @@ private:
|
||||||
int hand_out_amount = (std::min)((std::min)(block_size, max_assignable)
|
int hand_out_amount = (std::min)((std::min)(block_size, max_assignable)
|
||||||
, amount);
|
, amount);
|
||||||
TORRENT_ASSERT(hand_out_amount > 0);
|
TORRENT_ASSERT(hand_out_amount > 0);
|
||||||
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();
|
l.unlock();
|
||||||
|
@ -400,15 +371,14 @@ private:
|
||||||
l.lock();
|
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));
|
||||||
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());
|
if (!tmp.empty()) m_queue.insert(m_queue.begin(), tmp.begin(), tmp.end());
|
||||||
#ifndef NDEBUG
|
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{ TORRENT_ASSERT(false); };
|
{
|
||||||
#endif
|
m_in_hand_out_bandwidth = false;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
m_in_hand_out_bandwidth = false;
|
m_in_hand_out_bandwidth = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,12 +40,15 @@ namespace libtorrent {
|
||||||
template<class PeerConnection>
|
template<class PeerConnection>
|
||||||
struct bw_queue_entry
|
struct bw_queue_entry
|
||||||
{
|
{
|
||||||
|
typedef typename PeerConnection::torrent_type torrent_type;
|
||||||
bw_queue_entry(boost::intrusive_ptr<PeerConnection> const& pe
|
bw_queue_entry(boost::intrusive_ptr<PeerConnection> const& pe
|
||||||
, int blk, bool no_prio)
|
, int blk, int prio)
|
||||||
: peer(pe), max_block_size(blk), non_prioritized(no_prio) {}
|
: peer(pe), torrent(peer->associated_torrent())
|
||||||
|
, max_block_size(blk), priority(prio) {}
|
||||||
boost::intrusive_ptr<PeerConnection> peer;
|
boost::intrusive_ptr<PeerConnection> peer;
|
||||||
|
boost::weak_ptr<torrent_type> torrent;
|
||||||
int max_block_size;
|
int max_block_size;
|
||||||
bool non_prioritized;
|
int priority; // 0 is low prio
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ struct http_connection : boost::enable_shared_from_this<http_connection>, boost:
|
||||||
, m_download_quota(0)
|
, m_download_quota(0)
|
||||||
, m_limiter_timer_active(false)
|
, m_limiter_timer_active(false)
|
||||||
, m_limiter_timer(ios)
|
, m_limiter_timer(ios)
|
||||||
, m_redirect(true)
|
, m_redirects(5)
|
||||||
, m_connection_ticket(-1)
|
, m_connection_ticket(-1)
|
||||||
, m_cc(cc)
|
, m_cc(cc)
|
||||||
{
|
{
|
||||||
|
@ -93,10 +93,10 @@ struct http_connection : boost::enable_shared_from_this<http_connection>, boost:
|
||||||
std::string sendbuffer;
|
std::string sendbuffer;
|
||||||
|
|
||||||
void get(std::string const& url, time_duration timeout = seconds(30)
|
void get(std::string const& url, time_duration timeout = seconds(30)
|
||||||
, bool handle_redirect = true);
|
, int handle_redirects = 5);
|
||||||
|
|
||||||
void start(std::string const& hostname, std::string const& port
|
void start(std::string const& hostname, std::string const& port
|
||||||
, time_duration timeout, bool handle_redirect = true);
|
, time_duration timeout, int handle_redirect = 5);
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
tcp::socket const& socket() const { return m_sock; }
|
tcp::socket const& socket() const { return m_sock; }
|
||||||
|
@ -153,9 +153,8 @@ private:
|
||||||
// as all the quota was used.
|
// as all the quota was used.
|
||||||
deadline_timer m_limiter_timer;
|
deadline_timer m_limiter_timer;
|
||||||
|
|
||||||
// if set to true, the connection should handle
|
// the number of redirects to follow (in sequence)
|
||||||
// HTTP redirects.
|
int m_redirects;
|
||||||
bool m_redirect;
|
|
||||||
|
|
||||||
int m_connection_ticket;
|
int m_connection_ticket;
|
||||||
connection_queue& m_cc;
|
connection_queue& m_cc;
|
||||||
|
|
|
@ -66,7 +66,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#if !defined NDEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS
|
||||||
#define INVARIANT_CHECK \
|
#define INVARIANT_CHECK \
|
||||||
invariant_checker const& _invariant_check = make_invariant_checker(*this); \
|
invariant_checker const& _invariant_check = make_invariant_checker(*this); \
|
||||||
(void)_invariant_check; \
|
(void)_invariant_check; \
|
||||||
|
|
|
@ -98,6 +98,8 @@ namespace libtorrent
|
||||||
friend class invariant_access;
|
friend class invariant_access;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
typedef torrent torrent_type;
|
||||||
|
|
||||||
enum channels
|
enum channels
|
||||||
{
|
{
|
||||||
upload_channel,
|
upload_channel,
|
||||||
|
@ -173,8 +175,8 @@ namespace libtorrent
|
||||||
void request_large_blocks(bool b)
|
void request_large_blocks(bool b)
|
||||||
{ m_request_large_blocks = b; }
|
{ m_request_large_blocks = b; }
|
||||||
|
|
||||||
void set_non_prioritized(bool b)
|
void set_priority(int p)
|
||||||
{ m_non_prioritized = b; }
|
{ m_priority = p; }
|
||||||
|
|
||||||
void fast_reconnect(bool r);
|
void fast_reconnect(bool r);
|
||||||
bool fast_reconnect() const { return m_fast_reconnect; }
|
bool fast_reconnect() const { return m_fast_reconnect; }
|
||||||
|
@ -224,7 +226,7 @@ namespace libtorrent
|
||||||
void add_stat(size_type downloaded, size_type uploaded);
|
void add_stat(size_type downloaded, size_type uploaded);
|
||||||
|
|
||||||
// is called once every second by the main loop
|
// is called once every second by the main loop
|
||||||
void second_tick(float tick_interval) throw();
|
void second_tick(float tick_interval);
|
||||||
|
|
||||||
boost::shared_ptr<socket_type> get_socket() const { return m_socket; }
|
boost::shared_ptr<socket_type> get_socket() const { return m_socket; }
|
||||||
tcp::endpoint const& remote() const { return m_remote; }
|
tcp::endpoint const& remote() const { return m_remote; }
|
||||||
|
@ -683,11 +685,9 @@ namespace libtorrent
|
||||||
// at a time.
|
// at a time.
|
||||||
bool m_request_large_blocks;
|
bool m_request_large_blocks;
|
||||||
|
|
||||||
// if this is true, other (prioritized) peers will
|
// this is the priority with which this peer gets
|
||||||
// skip ahead of it in the queue for bandwidth. The
|
// download bandwidth quota assigned to it.
|
||||||
// effect is that non prioritized peers will only use
|
int m_priority;
|
||||||
// the left-over bandwidth (suitable for web seeds).
|
|
||||||
bool m_non_prioritized;
|
|
||||||
|
|
||||||
int m_upload_limit;
|
int m_upload_limit;
|
||||||
int m_download_limit;
|
int m_download_limit;
|
||||||
|
|
|
@ -96,8 +96,10 @@ namespace libtorrent
|
||||||
// time since last download or upload
|
// time since last download or upload
|
||||||
time_duration last_active;
|
time_duration last_active;
|
||||||
|
|
||||||
// the size of the send buffer for this peer
|
// the size of the send buffer for this peer, in bytes
|
||||||
int send_buffer_size;
|
int send_buffer_size;
|
||||||
|
// the number bytes that's actually used of the send buffer
|
||||||
|
int used_send_buffer;
|
||||||
|
|
||||||
// the number of failed hashes for this peer
|
// the number of failed hashes for this peer
|
||||||
int num_hashfails;
|
int num_hashfails;
|
||||||
|
|
|
@ -55,6 +55,9 @@ namespace libtorrent
|
||||||
|
|
||||||
int num_peers;
|
int num_peers;
|
||||||
|
|
||||||
|
int up_bandwidth_queue;
|
||||||
|
int down_bandwidth_queue;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_DHT
|
#ifndef TORRENT_DISABLE_DHT
|
||||||
int dht_nodes;
|
int dht_nodes;
|
||||||
int dht_node_cache;
|
int dht_node_cache;
|
||||||
|
|
|
@ -229,12 +229,11 @@ namespace libtorrent
|
||||||
|
|
||||||
void request_bandwidth(int channel
|
void request_bandwidth(int channel
|
||||||
, boost::intrusive_ptr<peer_connection> const& p
|
, boost::intrusive_ptr<peer_connection> const& p
|
||||||
, bool non_prioritized);
|
, int priority);
|
||||||
|
|
||||||
void perform_bandwidth_request(int channel
|
void perform_bandwidth_request(int channel
|
||||||
, boost::intrusive_ptr<peer_connection> const& p
|
, boost::intrusive_ptr<peer_connection> const& p
|
||||||
, int block_size
|
, int block_size, int priority);
|
||||||
, bool non_prioritized);
|
|
||||||
|
|
||||||
void expire_bandwidth(int channel, int amount);
|
void expire_bandwidth(int channel, int amount);
|
||||||
void assign_bandwidth(int channel, int amount, int blk);
|
void assign_bandwidth(int channel, int amount, int blk);
|
||||||
|
|
|
@ -112,6 +112,8 @@ namespace libtorrent
|
||||||
, uploads_limit(0)
|
, uploads_limit(0)
|
||||||
, connections_limit(0)
|
, connections_limit(0)
|
||||||
, storage_mode(storage_mode_sparse)
|
, storage_mode(storage_mode_sparse)
|
||||||
|
, up_bandwidth_queue(0)
|
||||||
|
, down_bandwidth_queue(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
enum state_t
|
enum state_t
|
||||||
|
@ -231,6 +233,9 @@ namespace libtorrent
|
||||||
// true if the torrent is saved in compact mode
|
// true if the torrent is saved in compact mode
|
||||||
// false if it is saved in full allocation mode
|
// false if it is saved in full allocation mode
|
||||||
storage_mode_t storage_mode;
|
storage_mode_t storage_mode;
|
||||||
|
|
||||||
|
int up_bandwidth_queue;
|
||||||
|
int down_bandwidth_queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TORRENT_EXPORT block_info
|
struct TORRENT_EXPORT block_info
|
||||||
|
|
|
@ -333,7 +333,11 @@ namespace libtorrent
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
// std::cerr << "DISK THREAD: exception: " << e.what() << std::endl;
|
// std::cerr << "DISK THREAD: exception: " << e.what() << std::endl;
|
||||||
|
try
|
||||||
|
{
|
||||||
j.str = e.what();
|
j.str = e.what();
|
||||||
|
}
|
||||||
|
catch (std::exception&) {}
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,9 +45,8 @@ namespace libtorrent
|
||||||
enum { max_bottled_buffer = 1024 * 1024 };
|
enum { max_bottled_buffer = 1024 * 1024 };
|
||||||
|
|
||||||
void http_connection::get(std::string const& url, time_duration timeout
|
void http_connection::get(std::string const& url, time_duration timeout
|
||||||
, bool handle_redirect)
|
, int handle_redirects)
|
||||||
{
|
{
|
||||||
m_redirect = handle_redirect;
|
|
||||||
std::string protocol;
|
std::string protocol;
|
||||||
std::string auth;
|
std::string auth;
|
||||||
std::string hostname;
|
std::string hostname;
|
||||||
|
@ -62,21 +61,23 @@ void http_connection::get(std::string const& url, time_duration timeout
|
||||||
headers << "Authorization: Basic " << base64encode(auth) << "\r\n";
|
headers << "Authorization: Basic " << base64encode(auth) << "\r\n";
|
||||||
headers << "\r\n";
|
headers << "\r\n";
|
||||||
sendbuffer = headers.str();
|
sendbuffer = headers.str();
|
||||||
start(hostname, boost::lexical_cast<std::string>(port), timeout);
|
start(hostname, boost::lexical_cast<std::string>(port), timeout, handle_redirects);
|
||||||
}
|
}
|
||||||
|
|
||||||
void http_connection::start(std::string const& hostname, std::string const& port
|
void http_connection::start(std::string const& hostname, std::string const& port
|
||||||
, time_duration timeout, bool handle_redirect)
|
, time_duration timeout, int handle_redirects)
|
||||||
{
|
{
|
||||||
m_redirect = handle_redirect;
|
m_redirects = handle_redirects;
|
||||||
m_timeout = timeout;
|
m_timeout = timeout;
|
||||||
m_timer.expires_from_now(m_timeout);
|
m_timer.expires_from_now(m_timeout);
|
||||||
m_timer.async_wait(bind(&http_connection::on_timeout
|
m_timer.async_wait(bind(&http_connection::on_timeout
|
||||||
, boost::weak_ptr<http_connection>(shared_from_this()), _1));
|
, boost::weak_ptr<http_connection>(shared_from_this()), _1));
|
||||||
m_called = false;
|
m_called = false;
|
||||||
|
m_parser.reset();
|
||||||
|
m_recvbuffer.clear();
|
||||||
|
m_read_pos = 0;
|
||||||
if (m_sock.is_open() && m_hostname == hostname && m_port == port)
|
if (m_sock.is_open() && m_hostname == hostname && m_port == port)
|
||||||
{
|
{
|
||||||
m_parser.reset();
|
|
||||||
asio::async_write(m_sock, asio::buffer(sendbuffer)
|
asio::async_write(m_sock, asio::buffer(sendbuffer)
|
||||||
, bind(&http_connection::on_write, shared_from_this(), _1));
|
, bind(&http_connection::on_write, shared_from_this(), _1));
|
||||||
}
|
}
|
||||||
|
@ -233,6 +234,7 @@ void http_connection::on_read(asio::error_code const& e
|
||||||
|
|
||||||
if (e == asio::error::eof)
|
if (e == asio::error::eof)
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(bytes_transferred == 0);
|
||||||
char const* data = 0;
|
char const* data = 0;
|
||||||
std::size_t size = 0;
|
std::size_t size = 0;
|
||||||
if (m_bottled && m_parser.header_finished())
|
if (m_bottled && m_parser.header_finished())
|
||||||
|
@ -247,6 +249,7 @@ void http_connection::on_read(asio::error_code const& e
|
||||||
|
|
||||||
if (e)
|
if (e)
|
||||||
{
|
{
|
||||||
|
TORRENT_ASSERT(bytes_transferred == 0);
|
||||||
callback(e);
|
callback(e);
|
||||||
close();
|
close();
|
||||||
return;
|
return;
|
||||||
|
@ -255,31 +258,6 @@ void http_connection::on_read(asio::error_code const& e
|
||||||
m_read_pos += bytes_transferred;
|
m_read_pos += bytes_transferred;
|
||||||
TORRENT_ASSERT(m_read_pos <= int(m_recvbuffer.size()));
|
TORRENT_ASSERT(m_read_pos <= int(m_recvbuffer.size()));
|
||||||
|
|
||||||
// having a nonempty path means we should handle redirects
|
|
||||||
if (m_redirect && m_parser.header_finished())
|
|
||||||
{
|
|
||||||
int code = m_parser.status_code();
|
|
||||||
if (code >= 300 && code < 400)
|
|
||||||
{
|
|
||||||
// attempt a redirect
|
|
||||||
std::string const& url = m_parser.header("location");
|
|
||||||
if (url.empty())
|
|
||||||
{
|
|
||||||
// missing location header
|
|
||||||
callback(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_limiter_timer_active = false;
|
|
||||||
close();
|
|
||||||
|
|
||||||
get(url, m_timeout);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_redirect = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_bottled || !m_parser.header_finished())
|
if (m_bottled || !m_parser.header_finished())
|
||||||
{
|
{
|
||||||
libtorrent::buffer::const_interval rcv_buf(&m_recvbuffer[0]
|
libtorrent::buffer::const_interval rcv_buf(&m_recvbuffer[0]
|
||||||
|
@ -295,6 +273,32 @@ void http_connection::on_read(asio::error_code const& e
|
||||||
m_handler.clear();
|
m_handler.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// having a nonempty path means we should handle redirects
|
||||||
|
if (m_redirects && m_parser.header_finished())
|
||||||
|
{
|
||||||
|
int code = m_parser.status_code();
|
||||||
|
|
||||||
|
if (code >= 300 && code < 400)
|
||||||
|
{
|
||||||
|
// attempt a redirect
|
||||||
|
std::string const& url = m_parser.header("location");
|
||||||
|
if (url.empty())
|
||||||
|
{
|
||||||
|
// missing location header
|
||||||
|
callback(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
asio::error_code ec;
|
||||||
|
m_sock.close(ec);
|
||||||
|
get(url, m_timeout, m_redirects - 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_redirects = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_bottled && m_parser.header_finished())
|
if (!m_bottled && m_parser.header_finished())
|
||||||
{
|
{
|
||||||
if (m_read_pos > m_parser.body_start())
|
if (m_read_pos > m_parser.body_start())
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Copyright (c) 2007, Un Shyam
|
Copyright (c) 2007, Un Shyam & Arvid Norberg
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -40,23 +40,33 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/pe_crypto.hpp"
|
#include "libtorrent/pe_crypto.hpp"
|
||||||
#include "libtorrent/assert.hpp"
|
#include "libtorrent/assert.hpp"
|
||||||
|
|
||||||
namespace libtorrent {
|
namespace libtorrent
|
||||||
|
{
|
||||||
|
|
||||||
// Set the prime P and the generator, generate local public key
|
// Set the prime P and the generator, generate local public key
|
||||||
DH_key_exchange::DH_key_exchange ()
|
DH_key_exchange::DH_key_exchange()
|
||||||
{
|
{
|
||||||
m_DH = DH_new ();
|
m_DH = DH_new();
|
||||||
|
if (m_DH == 0) throw std::bad_alloc();
|
||||||
|
|
||||||
|
m_DH->p = BN_bin2bn(m_dh_prime, sizeof(m_dh_prime), NULL);
|
||||||
|
m_DH->g = BN_bin2bn(m_dh_generator, sizeof(m_dh_generator), NULL);
|
||||||
|
if (m_DH->p == 0 || m_DH->g == 0)
|
||||||
|
{
|
||||||
|
DH_free(m_DH);
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
|
||||||
m_DH->p = BN_bin2bn (m_dh_prime, sizeof(m_dh_prime), NULL);
|
|
||||||
m_DH->g = BN_bin2bn (m_dh_generator, sizeof(m_dh_generator), NULL);
|
|
||||||
m_DH->length = 160l;
|
m_DH->length = 160l;
|
||||||
|
|
||||||
TORRENT_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);
|
||||||
|
if (m_DH->pub_key == 0)
|
||||||
TORRENT_ASSERT(m_DH->pub_key);
|
{
|
||||||
|
DH_free(m_DH);
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -76,27 +86,29 @@ namespace libtorrent {
|
||||||
BN_bn2bin(m_DH->pub_key, (unsigned char*)m_dh_local_key); // TODO Check return value
|
BN_bn2bin(m_DH->pub_key, (unsigned char*)m_dh_local_key); // TODO Check return value
|
||||||
}
|
}
|
||||||
|
|
||||||
DH_key_exchange::~DH_key_exchange ()
|
DH_key_exchange::~DH_key_exchange()
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(m_DH);
|
TORRENT_ASSERT(m_DH);
|
||||||
DH_free (m_DH);
|
DH_free(m_DH);
|
||||||
}
|
}
|
||||||
|
|
||||||
char const* DH_key_exchange::get_local_key () const
|
char const* DH_key_exchange::get_local_key() const
|
||||||
{
|
{
|
||||||
return m_dh_local_key;
|
return m_dh_local_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 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)
|
||||||
{
|
{
|
||||||
TORRENT_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);
|
||||||
|
if (bn_remote_pubkey == 0) throw std::bad_alloc();
|
||||||
char dh_secret[96];
|
char dh_secret[96];
|
||||||
|
|
||||||
int secret_size = DH_compute_key ( (unsigned char*)dh_secret,
|
int secret_size = DH_compute_key((unsigned char*)dh_secret
|
||||||
bn_remote_pubkey, m_DH); // TODO Check for errors
|
, bn_remote_pubkey, m_DH);
|
||||||
|
if (secret_size < 0 || secret_size > 96) throw std::bad_alloc();
|
||||||
|
|
||||||
if (secret_size != 96)
|
if (secret_size != 96)
|
||||||
{
|
{
|
||||||
|
@ -104,11 +116,10 @@ namespace libtorrent {
|
||||||
std::fill(m_dh_secret, m_dh_secret + 96 - secret_size, 0);
|
std::fill(m_dh_secret, m_dh_secret + 96 - secret_size, 0);
|
||||||
}
|
}
|
||||||
std::copy(dh_secret, dh_secret + secret_size, m_dh_secret + 96 - secret_size);
|
std::copy(dh_secret, dh_secret + secret_size, m_dh_secret + 96 - secret_size);
|
||||||
|
BN_free(bn_remote_pubkey);
|
||||||
BN_free (bn_remote_pubkey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char const* DH_key_exchange::get_secret () const
|
char const* DH_key_exchange::get_secret() const
|
||||||
{
|
{
|
||||||
return m_dh_secret;
|
return m_dh_secret;
|
||||||
}
|
}
|
||||||
|
@ -129,3 +140,4 @@ namespace libtorrent {
|
||||||
} // namespace libtorrent
|
} // namespace libtorrent
|
||||||
|
|
||||||
#endif // #ifndef TORRENT_DISABLE_ENCRYPTION
|
#endif // #ifndef TORRENT_DISABLE_ENCRYPTION
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ namespace libtorrent
|
||||||
, m_reading(false)
|
, m_reading(false)
|
||||||
, m_prefer_whole_pieces(false)
|
, m_prefer_whole_pieces(false)
|
||||||
, m_request_large_blocks(false)
|
, m_request_large_blocks(false)
|
||||||
, m_non_prioritized(false)
|
, m_priority(1)
|
||||||
, m_upload_limit(bandwidth_limit::inf)
|
, m_upload_limit(bandwidth_limit::inf)
|
||||||
, m_download_limit(bandwidth_limit::inf)
|
, m_download_limit(bandwidth_limit::inf)
|
||||||
, m_peer_info(peerinfo)
|
, m_peer_info(peerinfo)
|
||||||
|
@ -186,7 +186,7 @@ namespace libtorrent
|
||||||
, m_reading(false)
|
, m_reading(false)
|
||||||
, m_prefer_whole_pieces(false)
|
, m_prefer_whole_pieces(false)
|
||||||
, m_request_large_blocks(false)
|
, m_request_large_blocks(false)
|
||||||
, m_non_prioritized(false)
|
, m_priority(1)
|
||||||
, m_upload_limit(bandwidth_limit::inf)
|
, m_upload_limit(bandwidth_limit::inf)
|
||||||
, m_download_limit(bandwidth_limit::inf)
|
, m_download_limit(bandwidth_limit::inf)
|
||||||
, m_peer_info(peerinfo)
|
, m_peer_info(peerinfo)
|
||||||
|
@ -376,6 +376,7 @@ namespace libtorrent
|
||||||
peer_connection::~peer_connection()
|
peer_connection::~peer_connection()
|
||||||
{
|
{
|
||||||
// INVARIANT_CHECK;
|
// INVARIANT_CHECK;
|
||||||
|
TORRENT_ASSERT(!m_in_constructor);
|
||||||
TORRENT_ASSERT(m_disconnecting);
|
TORRENT_ASSERT(m_disconnecting);
|
||||||
|
|
||||||
#ifdef TORRENT_VERBOSE_LOGGING
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
|
@ -593,6 +594,7 @@ namespace libtorrent
|
||||||
// check to make sure we don't have another connection with the same
|
// check to make sure we don't have another connection with the same
|
||||||
// info_hash and peer_id. If we do. close this connection.
|
// info_hash and peer_id. If we do. close this connection.
|
||||||
t->attach_peer(this);
|
t->attach_peer(this);
|
||||||
|
if (m_disconnecting) return;
|
||||||
m_torrent = wpt;
|
m_torrent = wpt;
|
||||||
|
|
||||||
TORRENT_ASSERT(!m_torrent.expired());
|
TORRENT_ASSERT(!m_torrent.expired());
|
||||||
|
@ -1740,7 +1742,8 @@ namespace libtorrent
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||||
TORRENT_ASSERT(t);
|
// this peer might be disconnecting
|
||||||
|
if (!t) return;
|
||||||
|
|
||||||
TORRENT_ASSERT(t->valid_metadata());
|
TORRENT_ASSERT(t->valid_metadata());
|
||||||
|
|
||||||
|
@ -1991,16 +1994,17 @@ 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_in_constructor);
|
||||||
boost::intrusive_ptr<peer_connection> me(this);
|
boost::intrusive_ptr<peer_connection> me(this);
|
||||||
|
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
if (m_disconnecting) return;
|
if (m_disconnecting) return;
|
||||||
m_disconnecting = true;
|
if (m_connecting && m_connection_ticket >= 0)
|
||||||
if (m_connecting)
|
{
|
||||||
m_ses.m_half_open.done(m_connection_ticket);
|
m_ses.m_half_open.done(m_connection_ticket);
|
||||||
|
m_connection_ticket = -1;
|
||||||
m_ses.m_io_service.post(boost::bind(&close_socket_ignore_error, m_socket));
|
}
|
||||||
|
|
||||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||||
|
|
||||||
|
@ -2026,7 +2030,9 @@ namespace libtorrent
|
||||||
m_torrent.reset();
|
m_torrent.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_disconnecting = true;
|
||||||
m_ses.close_connection(me);
|
m_ses.close_connection(me);
|
||||||
|
m_ses.m_io_service.post(boost::bind(&close_socket_ignore_error, m_socket));
|
||||||
}
|
}
|
||||||
|
|
||||||
void peer_connection::set_upload_limit(int limit)
|
void peer_connection::set_upload_limit(int limit)
|
||||||
|
@ -2071,7 +2077,8 @@ namespace libtorrent
|
||||||
|
|
||||||
bool peer_connection::on_local_network() const
|
bool peer_connection::on_local_network() const
|
||||||
{
|
{
|
||||||
if (libtorrent::is_local(m_remote.address())) return true;
|
if (libtorrent::is_local(m_remote.address())
|
||||||
|
|| is_loopback(m_remote.address())) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2154,6 +2161,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
p.send_buffer_size = m_send_buffer.capacity();
|
p.send_buffer_size = m_send_buffer.capacity();
|
||||||
|
p.used_send_buffer = m_send_buffer.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void peer_connection::cut_receive_buffer(int size, int packet_size)
|
void peer_connection::cut_receive_buffer(int size, int packet_size)
|
||||||
|
@ -2178,7 +2186,7 @@ namespace libtorrent
|
||||||
if (m_packet_size >= m_recv_pos) m_recv_buffer.resize(m_packet_size);
|
if (m_packet_size >= m_recv_pos) m_recv_buffer.resize(m_packet_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void peer_connection::second_tick(float tick_interval) throw()
|
void peer_connection::second_tick(float tick_interval)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
|
@ -2355,8 +2363,7 @@ namespace libtorrent
|
||||||
else if (buffer_size_watermark > 80 * 1024) buffer_size_watermark = 80 * 1024;
|
else if (buffer_size_watermark > 80 * 1024) buffer_size_watermark = 80 * 1024;
|
||||||
|
|
||||||
while (!m_requests.empty()
|
while (!m_requests.empty()
|
||||||
&& (send_buffer_size() + m_reading_bytes < buffer_size_watermark)
|
&& (send_buffer_size() + m_reading_bytes < buffer_size_watermark))
|
||||||
&& !m_choked)
|
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(t->valid_metadata());
|
TORRENT_ASSERT(t->valid_metadata());
|
||||||
peer_request& r = m_requests.front();
|
peer_request& r = m_requests.front();
|
||||||
|
@ -2482,7 +2489,7 @@ namespace libtorrent
|
||||||
// peers that we are not interested in are non-prioritized
|
// peers that we are not interested in are non-prioritized
|
||||||
m_writing = true;
|
m_writing = true;
|
||||||
t->request_bandwidth(upload_channel, self()
|
t->request_bandwidth(upload_channel, self()
|
||||||
, !(is_interesting() && !has_peer_choked()));
|
, is_interesting() * 2);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2535,7 +2542,7 @@ namespace libtorrent
|
||||||
(*m_logger) << "req bandwidth [ " << download_channel << " ]\n";
|
(*m_logger) << "req bandwidth [ " << download_channel << " ]\n";
|
||||||
#endif
|
#endif
|
||||||
m_reading = true;
|
m_reading = true;
|
||||||
t->request_bandwidth(download_channel, self(), m_non_prioritized);
|
t->request_bandwidth(download_channel, self(), m_priority);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3161,7 +3168,6 @@ namespace libtorrent
|
||||||
|
|
||||||
bool peer_connection::is_seed() const
|
bool peer_connection::is_seed() const
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
|
||||||
// if m_num_pieces == 0, we probably don't have the
|
// if m_num_pieces == 0, we probably don't have the
|
||||||
// metadata yet.
|
// metadata yet.
|
||||||
return m_num_pieces == (int)m_have_piece.size() && m_num_pieces > 0;
|
return m_num_pieces == (int)m_have_piece.size() && m_num_pieces > 0;
|
||||||
|
|
|
@ -1068,7 +1068,7 @@ namespace detail
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't allow more connections than the max setting
|
// don't allow more connections than the max setting
|
||||||
if (num_connections() > max_connections())
|
if (num_connections() >= max_connections())
|
||||||
{
|
{
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
(*m_logger) << "number of connections limit exceeded (conns: "
|
(*m_logger) << "number of connections limit exceeded (conns: "
|
||||||
|
@ -2015,6 +2015,10 @@ namespace detail
|
||||||
// INVARIANT_CHECK;
|
// INVARIANT_CHECK;
|
||||||
|
|
||||||
session_status s;
|
session_status s;
|
||||||
|
|
||||||
|
s.up_bandwidth_queue = m_upload_channel.queue_size();
|
||||||
|
s.down_bandwidth_queue = m_download_channel.queue_size();
|
||||||
|
|
||||||
s.has_incoming_connections = m_incoming_connection;
|
s.has_incoming_connections = m_incoming_connection;
|
||||||
s.num_peers = (int)m_connections.size();
|
s.num_peers = (int)m_connections.size();
|
||||||
|
|
||||||
|
@ -2437,6 +2441,7 @@ namespace detail
|
||||||
boost::shared_ptr<torrent> t = (*i)->associated_torrent().lock();
|
boost::shared_ptr<torrent> t = (*i)->associated_torrent().lock();
|
||||||
|
|
||||||
peer_connection* p = i->get();
|
peer_connection* p = i->get();
|
||||||
|
TORRENT_ASSERT(!p->is_disconnecting());
|
||||||
if (!p->is_choked()) ++unchokes;
|
if (!p->is_choked()) ++unchokes;
|
||||||
if (p->peer_info_struct()
|
if (p->peer_info_struct()
|
||||||
&& p->peer_info_struct()->optimistically_unchoked)
|
&& p->peer_info_struct()->optimistically_unchoked)
|
||||||
|
|
|
@ -452,15 +452,19 @@ namespace libtorrent
|
||||||
// the directory exists.
|
// the directory exists.
|
||||||
if (file_iter->size == 0)
|
if (file_iter->size == 0)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
file(m_save_path / file_iter->path, file::out);
|
file(m_save_path / file_iter->path, file::out);
|
||||||
|
} catch (std::exception&) {}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
if (allocate_files)
|
if (allocate_files)
|
||||||
{
|
{
|
||||||
m_files.open_file(this, m_save_path / file_iter->path, file::in | file::out)
|
m_files.open_file(this, m_save_path / file_iter->path, file::in | file::out)
|
||||||
->set_size(file_iter->size);
|
->set_size(file_iter->size);
|
||||||
}
|
}
|
||||||
|
} catch (std::exception&) {}
|
||||||
}
|
}
|
||||||
// close files that were opened in write mode
|
// close files that were opened in write mode
|
||||||
m_files.release(this);
|
m_files.release(this);
|
||||||
|
|
|
@ -2164,13 +2164,8 @@ namespace libtorrent
|
||||||
throw protocol_error("reached connection limit");
|
throw protocol_error("reached connection limit");
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_ASSERT(m_connections.find(p) == m_connections.end());
|
|
||||||
peer_iterator ci = m_connections.insert(p).first;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// if new_connection throws, we have to remove the
|
|
||||||
// it from the list.
|
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||||
for (extension_list_t::iterator i = m_extensions.begin()
|
for (extension_list_t::iterator i = m_extensions.begin()
|
||||||
, end(m_extensions.end()); i != end; ++i)
|
, end(m_extensions.end()); i != end; ++i)
|
||||||
|
@ -2179,15 +2174,14 @@ namespace libtorrent
|
||||||
if (pp) p->add_extension(pp);
|
if (pp) p->add_extension(pp);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
TORRENT_ASSERT(m_connections.find(p) == ci);
|
m_policy.new_connection(*p);
|
||||||
TORRENT_ASSERT(*ci == p);
|
|
||||||
m_policy.new_connection(**ci);
|
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
m_connections.erase(ci);
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
TORRENT_ASSERT(m_connections.find(p) == m_connections.end());
|
||||||
|
peer_iterator ci = m_connections.insert(p).first;
|
||||||
TORRENT_ASSERT(p->remote() == p->get_socket()->remote_endpoint());
|
TORRENT_ASSERT(p->remote() == p->get_socket()->remote_endpoint());
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
@ -2222,6 +2216,10 @@ namespace libtorrent
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
std::size_t size = m_connections.size();
|
std::size_t size = m_connections.size();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (p->is_disconnecting())
|
||||||
|
m_connections.erase(m_connections.begin());
|
||||||
|
else
|
||||||
p->disconnect();
|
p->disconnect();
|
||||||
TORRENT_ASSERT(m_connections.size() <= size);
|
TORRENT_ASSERT(m_connections.size() <= size);
|
||||||
}
|
}
|
||||||
|
@ -2234,7 +2232,7 @@ namespace libtorrent
|
||||||
|
|
||||||
void torrent::request_bandwidth(int channel
|
void torrent::request_bandwidth(int channel
|
||||||
, boost::intrusive_ptr<peer_connection> const& p
|
, boost::intrusive_ptr<peer_connection> const& p
|
||||||
, bool non_prioritized)
|
, int priority)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(m_bandwidth_limit[channel].throttle() > 0);
|
TORRENT_ASSERT(m_bandwidth_limit[channel].throttle() > 0);
|
||||||
TORRENT_ASSERT(p->max_assignable_bandwidth(channel) > 0);
|
TORRENT_ASSERT(p->max_assignable_bandwidth(channel) > 0);
|
||||||
|
@ -2243,16 +2241,20 @@ namespace libtorrent
|
||||||
|
|
||||||
if (m_bandwidth_limit[channel].max_assignable() > 0)
|
if (m_bandwidth_limit[channel].max_assignable() > 0)
|
||||||
{
|
{
|
||||||
perform_bandwidth_request(channel, p, block_size, non_prioritized);
|
perform_bandwidth_request(channel, p, block_size, priority);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// skip forward in the queue until we find a prioritized peer
|
// skip forward in the queue until we find a prioritized peer
|
||||||
// or hit the front of it.
|
// or hit the front of it.
|
||||||
queue_t::reverse_iterator i = m_bandwidth_queue[channel].rbegin();
|
queue_t::reverse_iterator i = m_bandwidth_queue[channel].rbegin();
|
||||||
while (i != m_bandwidth_queue[channel].rend() && i->non_prioritized) ++i;
|
while (i != m_bandwidth_queue[channel].rend() && priority > i->priority)
|
||||||
|
{
|
||||||
|
++i->priority;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
m_bandwidth_queue[channel].insert(i.base(), bw_queue_entry<peer_connection>(
|
m_bandwidth_queue[channel].insert(i.base(), bw_queue_entry<peer_connection>(
|
||||||
p, block_size, non_prioritized));
|
p, block_size, priority));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2276,7 +2278,7 @@ namespace libtorrent
|
||||||
continue;
|
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.priority);
|
||||||
}
|
}
|
||||||
m_bandwidth_queue[channel].insert(m_bandwidth_queue[channel].begin(), tmp.begin(), tmp.end());
|
m_bandwidth_queue[channel].insert(m_bandwidth_queue[channel].begin(), tmp.begin(), tmp.end());
|
||||||
}
|
}
|
||||||
|
@ -2284,10 +2286,10 @@ namespace libtorrent
|
||||||
void torrent::perform_bandwidth_request(int channel
|
void torrent::perform_bandwidth_request(int channel
|
||||||
, boost::intrusive_ptr<peer_connection> const& p
|
, boost::intrusive_ptr<peer_connection> const& p
|
||||||
, int block_size
|
, int block_size
|
||||||
, bool non_prioritized)
|
, int priority)
|
||||||
{
|
{
|
||||||
m_ses.m_bandwidth_manager[channel]->request_bandwidth(p
|
m_ses.m_bandwidth_manager[channel]->request_bandwidth(p
|
||||||
, block_size, non_prioritized);
|
, block_size, priority);
|
||||||
m_bandwidth_limit[channel].assign(block_size);
|
m_bandwidth_limit[channel].assign(block_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2620,6 +2622,16 @@ namespace libtorrent
|
||||||
TORRENT_ASSERT(m_bandwidth_queue[0].size() <= m_connections.size());
|
TORRENT_ASSERT(m_bandwidth_queue[0].size() <= m_connections.size());
|
||||||
TORRENT_ASSERT(m_bandwidth_queue[1].size() <= m_connections.size());
|
TORRENT_ASSERT(m_bandwidth_queue[1].size() <= m_connections.size());
|
||||||
|
|
||||||
|
for (int c = 0; c < 2; ++c)
|
||||||
|
{
|
||||||
|
queue_t::const_iterator j = m_bandwidth_queue[c].begin();
|
||||||
|
if (j == m_bandwidth_queue[c].end()) continue;
|
||||||
|
++j;
|
||||||
|
for (queue_t::const_iterator i = m_bandwidth_queue[c].begin()
|
||||||
|
, end(m_bandwidth_queue[c].end()); i != end && j != end; ++i, ++j)
|
||||||
|
TORRENT_ASSERT(i->priority >= j->priority);
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
@ -3063,6 +3075,9 @@ namespace libtorrent
|
||||||
|
|
||||||
torrent_status st;
|
torrent_status st;
|
||||||
|
|
||||||
|
st.up_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::upload_channel].size();
|
||||||
|
st.down_bandwidth_queue = (int)m_bandwidth_queue[peer_connection::download_channel].size();
|
||||||
|
|
||||||
st.num_peers = (int)std::count_if(m_connections.begin(), m_connections.end()
|
st.num_peers = (int)std::count_if(m_connections.begin(), m_connections.end()
|
||||||
, !boost::bind(&peer_connection::is_connecting, _1));
|
, !boost::bind(&peer_connection::is_connecting, _1));
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ namespace libtorrent
|
||||||
// we can request more bytes at once
|
// we can request more bytes at once
|
||||||
request_large_blocks(true);
|
request_large_blocks(true);
|
||||||
// we only want left-over bandwidth
|
// we only want left-over bandwidth
|
||||||
set_non_prioritized(true);
|
set_priority(0);
|
||||||
shared_ptr<torrent> tor = t.lock();
|
shared_ptr<torrent> tor = t.lock();
|
||||||
TORRENT_ASSERT(tor);
|
TORRENT_ASSERT(tor);
|
||||||
int blocks_per_piece = tor->torrent_file().piece_length() / tor->block_size();
|
int blocks_per_piece = tor->torrent_file().piece_length() / tor->block_size();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue