forked from premiere/premiere-libtorrent
keep track of interest more tightly. better support for upload_only
This commit is contained in:
parent
84406e2064
commit
429a118dd2
|
@ -323,6 +323,10 @@ namespace libtorrent
|
|||
// the number of bytes transferred within unchoke cycles
|
||||
void reset_choke_counters();
|
||||
|
||||
// if this peer connection is useless (neither party is
|
||||
// interested in the other), disconnect it
|
||||
void disconnect_if_redundant();
|
||||
|
||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||
boost::shared_ptr<logger> m_logger;
|
||||
#endif
|
||||
|
@ -854,9 +858,13 @@ namespace libtorrent
|
|||
// is set to 1
|
||||
bool m_snubbed:1;
|
||||
|
||||
// this is set to true once the bitfield is received
|
||||
bool m_bitfield_received:1;
|
||||
|
||||
#ifndef NDEBUG
|
||||
public:
|
||||
bool m_in_constructor:1;
|
||||
bool m_disconnect_started:1;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
|
|
@ -610,6 +610,8 @@ namespace libtorrent
|
|||
{ return m_connections_initialized; }
|
||||
bool valid_metadata() const
|
||||
{ return m_torrent_file->is_valid(); }
|
||||
bool are_files_checked() const
|
||||
{ return m_files_checked; }
|
||||
|
||||
// parses the info section from the given
|
||||
// bencoded tree and moves the torrent
|
||||
|
|
|
@ -2647,9 +2647,6 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(m_sent_handshake);
|
||||
}
|
||||
|
||||
if (!m_in_constructor)
|
||||
peer_connection::check_invariant();
|
||||
|
||||
if (!m_payloads.empty())
|
||||
{
|
||||
for (std::deque<range>::const_iterator i = m_payloads.begin();
|
||||
|
|
|
@ -129,8 +129,10 @@ namespace libtorrent
|
|||
, m_request_large_blocks(false)
|
||||
, m_upload_only(false)
|
||||
, m_snubbed(false)
|
||||
, m_bitfield_received(false)
|
||||
#ifndef NDEBUG
|
||||
, m_in_constructor(true)
|
||||
, m_disconnect_started(false)
|
||||
#endif
|
||||
{
|
||||
m_channel_state[upload_channel] = peer_info::bw_idle;
|
||||
|
@ -232,8 +234,10 @@ namespace libtorrent
|
|||
, m_request_large_blocks(false)
|
||||
, m_upload_only(false)
|
||||
, m_snubbed(false)
|
||||
, m_bitfield_received(false)
|
||||
#ifndef NDEBUG
|
||||
, m_in_constructor(true)
|
||||
, m_disconnect_started(false)
|
||||
#endif
|
||||
{
|
||||
m_channel_state[upload_channel] = peer_info::bw_idle;
|
||||
|
@ -328,8 +332,6 @@ namespace libtorrent
|
|||
|
||||
void peer_connection::update_interest()
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
TORRENT_ASSERT(t);
|
||||
|
||||
|
@ -351,10 +353,8 @@ namespace libtorrent
|
|||
}
|
||||
try
|
||||
{
|
||||
if (!interested)
|
||||
send_not_interested();
|
||||
else
|
||||
t->get_policy().peer_is_interesting(*this);
|
||||
if (!interested) send_not_interested();
|
||||
else t->get_policy().peer_is_interesting(*this);
|
||||
}
|
||||
// may throw an asio error if socket has disconnected
|
||||
catch (std::exception&) {}
|
||||
|
@ -455,15 +455,10 @@ namespace libtorrent
|
|||
#endif
|
||||
// if this is a web seed. we don't have a peer_info struct
|
||||
if (m_peer_info) m_peer_info->seed = true;
|
||||
// if we're a seed too, disconnect
|
||||
if (t->is_finished() && m_ses.settings().close_redundant_connections)
|
||||
{
|
||||
disconnect("seed to seed connection redundant");
|
||||
return;
|
||||
}
|
||||
|
||||
t->peer_has_all();
|
||||
if (!t->is_finished())
|
||||
t->get_policy().peer_is_interesting(*this);
|
||||
if (t->is_finished()) send_not_interested();
|
||||
else t->get_policy().peer_is_interesting(*this);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -482,8 +477,12 @@ namespace libtorrent
|
|||
interesting = true;
|
||||
}
|
||||
}
|
||||
if (interesting)
|
||||
t->get_policy().peer_is_interesting(*this);
|
||||
if (interesting) t->get_policy().peer_is_interesting(*this);
|
||||
else send_not_interested();
|
||||
}
|
||||
else
|
||||
{
|
||||
update_interest();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -492,6 +491,7 @@ namespace libtorrent
|
|||
// INVARIANT_CHECK;
|
||||
TORRENT_ASSERT(!m_in_constructor);
|
||||
TORRENT_ASSERT(m_disconnecting);
|
||||
TORRENT_ASSERT(m_disconnect_started);
|
||||
|
||||
m_disk_recv_buffer_size = 0;
|
||||
|
||||
|
@ -535,16 +535,25 @@ namespace libtorrent
|
|||
m_suggested_pieces.begin(), m_suggested_pieces.end(), index);
|
||||
if (i != m_suggested_pieces.end()) m_suggested_pieces.erase(i);
|
||||
|
||||
// optimization, don't send have messages
|
||||
// to peers that already have the piece
|
||||
if (!m_ses.settings().send_redundant_have
|
||||
&& has_piece(index))
|
||||
if (has_piece(index))
|
||||
{
|
||||
// if we got a piece that this peer has
|
||||
// it might have been the last interesting
|
||||
// piece this peer had. We might not be
|
||||
// interested anymore
|
||||
update_interest();
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
// optimization, don't send have messages
|
||||
// to peers that already have the piece
|
||||
if (!m_ses.settings().send_redundant_have)
|
||||
{
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string()
|
||||
<< " ==> HAVE [ piece: " << index << " ] SUPRESSED\n";
|
||||
(*m_logger) << time_now_string()
|
||||
<< " ==> HAVE [ piece: " << index << " ] SUPRESSED\n";
|
||||
#endif
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
|
@ -561,8 +570,6 @@ namespace libtorrent
|
|||
|
||||
bool peer_connection::has_piece(int i) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
TORRENT_ASSERT(t);
|
||||
TORRENT_ASSERT(t->valid_metadata());
|
||||
|
@ -1055,6 +1062,10 @@ namespace libtorrent
|
|||
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
// if we haven't received a bitfield, it was
|
||||
// probably omitted, which is the same as 'have_none'
|
||||
if (!m_bitfield_received) incoming_have_none();
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string()
|
||||
<< " <== HAVE [ piece: " << index << "]\n";
|
||||
|
@ -1121,15 +1132,12 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
if (upload_only())
|
||||
if (is_seed())
|
||||
{
|
||||
TORRENT_ASSERT(m_peer_info);
|
||||
if (is_seed()) m_peer_info->seed = true;
|
||||
if (t->is_finished() && m_ses.settings().close_redundant_connections)
|
||||
{
|
||||
disconnect("seed to seed connection redundant");
|
||||
return;
|
||||
}
|
||||
m_peer_info->seed = true;
|
||||
m_upload_only = true;
|
||||
disconnect_if_redundant();
|
||||
if (is_disconnecting()) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1179,6 +1187,8 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
m_bitfield_received = true;
|
||||
|
||||
// if we don't have metadata yet
|
||||
// just remember the bitmask
|
||||
// don't update the piecepicker
|
||||
|
@ -1201,12 +1211,9 @@ namespace libtorrent
|
|||
#endif
|
||||
// if this is a web seed. we don't have a peer_info struct
|
||||
if (m_peer_info) m_peer_info->seed = true;
|
||||
// if we're a seed too, disconnect
|
||||
if (t->is_finished() && m_ses.settings().close_redundant_connections)
|
||||
{
|
||||
disconnect("seed to seed connection redundant, disconnecting");
|
||||
return;
|
||||
}
|
||||
m_upload_only = true;
|
||||
disconnect_if_redundant();
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
m_have_piece.set_all();
|
||||
m_num_pieces = num_pieces;
|
||||
|
@ -1247,6 +1254,22 @@ namespace libtorrent
|
|||
else if (upload_only()) disconnect("upload to upload connections");
|
||||
}
|
||||
|
||||
void peer_connection::disconnect_if_redundant()
|
||||
{
|
||||
if (!m_ses.settings().close_redundant_connections) return;
|
||||
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
TORRENT_ASSERT(t);
|
||||
if (m_upload_only && t->is_finished())
|
||||
disconnect("seed to seed");
|
||||
|
||||
if (m_upload_only
|
||||
&& !m_interesting
|
||||
&& m_bitfield_received
|
||||
&& t->are_files_checked())
|
||||
disconnect("uninteresting upload-only peer");
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// ---------- REQUEST ----------
|
||||
// -----------------------------
|
||||
|
@ -1258,6 +1281,10 @@ namespace libtorrent
|
|||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
TORRENT_ASSERT(t);
|
||||
|
||||
// if we haven't received a bitfield, it was
|
||||
// probably omitted, which is the same as 'have_none'
|
||||
if (!m_bitfield_received) incoming_have_none();
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
|
@ -1460,6 +1487,10 @@ namespace libtorrent
|
|||
}
|
||||
#endif
|
||||
|
||||
// if we haven't received a bitfield, it was
|
||||
// probably omitted, which is the same as 'have_none'
|
||||
if (!m_bitfield_received) incoming_have_none();
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
|
@ -1797,6 +1828,12 @@ namespace libtorrent
|
|||
m_have_all = true;
|
||||
|
||||
if (m_peer_info) m_peer_info->seed = true;
|
||||
m_upload_only = true;
|
||||
m_bitfield_received = true;
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << " *** THIS IS A SEED ***\n";
|
||||
#endif
|
||||
|
||||
// if we don't have metadata yet
|
||||
// just remember the bitmask
|
||||
|
@ -1804,30 +1841,24 @@ namespace libtorrent
|
|||
// (since it doesn't exist yet)
|
||||
if (!t->ready_for_connections())
|
||||
{
|
||||
disconnect_if_redundant();
|
||||
// TODO: this might need something more
|
||||
// so that once we have the metadata
|
||||
// we can construct a full bitfield
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << " *** THIS IS A SEED ***\n";
|
||||
#endif
|
||||
|
||||
// if we're a seed too, disconnect
|
||||
if (t->is_finished() && m_ses.settings().close_redundant_connections)
|
||||
{
|
||||
disconnect("seed to seed connection redundant, disconnecting");
|
||||
return;
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(!m_have_piece.empty());
|
||||
m_have_piece.set_all();
|
||||
m_num_pieces = m_have_piece.size();
|
||||
|
||||
t->peer_has_all();
|
||||
if (!t->is_finished())
|
||||
t->get_policy().peer_is_interesting(*this);
|
||||
|
||||
// if we're finished, we're not interested
|
||||
if (t->is_finished()) send_not_interested();
|
||||
else t->get_policy().peer_is_interesting(*this);
|
||||
|
||||
disconnect_if_redundant();
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
|
@ -1854,8 +1885,13 @@ namespace libtorrent
|
|||
#endif
|
||||
if (is_disconnecting()) return;
|
||||
if (m_peer_info) m_peer_info->seed = false;
|
||||
m_bitfield_received = true;
|
||||
|
||||
// we're never interested in a peer that doesn't have anything
|
||||
send_not_interested();
|
||||
|
||||
TORRENT_ASSERT(!m_have_piece.empty() || !t->ready_for_connections());
|
||||
disconnect_if_redundant();
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
|
@ -2090,11 +2126,9 @@ namespace libtorrent
|
|||
|
||||
void peer_connection::send_interested()
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_interesting) return;
|
||||
write_interested();
|
||||
m_interesting = true;
|
||||
write_interested();
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string() << " ==> INTERESTED\n";
|
||||
|
@ -2103,17 +2137,16 @@ namespace libtorrent
|
|||
|
||||
void peer_connection::send_not_interested()
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (!m_interesting) return;
|
||||
write_not_interested();
|
||||
m_interesting = false;
|
||||
write_not_interested();
|
||||
|
||||
m_became_uninteresting = time_now();
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string() << " ==> NOT_INTERESTED\n";
|
||||
#endif
|
||||
disconnect_if_redundant();
|
||||
}
|
||||
|
||||
void peer_connection::send_block_requests()
|
||||
|
@ -2253,6 +2286,10 @@ namespace libtorrent
|
|||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||
|
||||
#ifndef NDEBUG
|
||||
m_disconnect_started = true;
|
||||
#endif
|
||||
|
||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||
switch (error)
|
||||
{
|
||||
|
@ -2979,8 +3016,6 @@ namespace libtorrent
|
|||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_channel_state[upload_channel] != peer_info::bw_idle) return;
|
||||
|
||||
shared_ptr<torrent> t = m_torrent.lock();
|
||||
|
@ -3388,8 +3423,6 @@ namespace libtorrent
|
|||
|
||||
bool peer_connection::can_write() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
// if we have requests or pending data to be sent or announcements to be made
|
||||
// we want to send data
|
||||
return !m_send_buffer.empty()
|
||||
|
@ -3400,8 +3433,6 @@ namespace libtorrent
|
|||
|
||||
bool peer_connection::can_read() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
bool ret = (m_bandwidth_limit[download_channel].quota_left() > 0
|
||||
|| m_ignore_bandwidth_limits)
|
||||
&& !m_connecting
|
||||
|
@ -3585,6 +3616,7 @@ namespace libtorrent
|
|||
if (m_disconnecting)
|
||||
{
|
||||
TORRENT_ASSERT(!t);
|
||||
TORRENT_ASSERT(m_disconnect_started);
|
||||
}
|
||||
else if (!m_in_constructor)
|
||||
{
|
||||
|
@ -3634,6 +3666,23 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
if (m_ses.settings().close_redundant_connections)
|
||||
{
|
||||
// make sure upload only peers are disconnected
|
||||
if (t->is_finished() && m_upload_only)
|
||||
TORRENT_ASSERT(m_disconnect_started);
|
||||
if (m_upload_only
|
||||
&& !m_interesting
|
||||
&& m_bitfield_received
|
||||
&& t->are_files_checked())
|
||||
TORRENT_ASSERT(m_disconnect_started);
|
||||
}
|
||||
|
||||
if (t->is_finished())
|
||||
TORRENT_ASSERT(!m_interesting);
|
||||
if (is_seed())
|
||||
TORRENT_ASSERT(m_upload_only);
|
||||
|
||||
if (t->has_picker())
|
||||
{
|
||||
std::map<piece_block, int> num_requests;
|
||||
|
|
|
@ -1344,8 +1344,12 @@ namespace libtorrent
|
|||
std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin()));
|
||||
|
||||
m_picker->we_have(index);
|
||||
for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i)
|
||||
(*i)->announce_piece(index);
|
||||
for (peer_iterator i = m_connections.begin(); i != m_connections.end();)
|
||||
{
|
||||
peer_connection* p = *i;
|
||||
++i;
|
||||
p->announce_piece(index);
|
||||
}
|
||||
|
||||
for (std::set<void*>::iterator i = peers.begin()
|
||||
, end(peers.end()); i != end; ++i)
|
||||
|
@ -1989,7 +1993,6 @@ namespace libtorrent
|
|||
{
|
||||
if (m_picker.get())
|
||||
{
|
||||
TORRENT_ASSERT(!is_seed());
|
||||
m_picker->dec_refcount_all();
|
||||
}
|
||||
}
|
||||
|
@ -3108,8 +3111,6 @@ namespace libtorrent
|
|||
// called when torrent is complete (all pieces downloaded)
|
||||
void torrent::completed()
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
m_picker.reset();
|
||||
|
||||
set_state(torrent_status::seeding);
|
||||
|
@ -3224,24 +3225,13 @@ namespace libtorrent
|
|||
m_connections_initialized = true;
|
||||
// all peer connections have to initialize themselves now that the metadata
|
||||
// is available
|
||||
for (torrent::peer_iterator i = m_connections.begin()
|
||||
, end(m_connections.end()); i != end;)
|
||||
for (torrent::peer_iterator i = m_connections.begin();
|
||||
i != m_connections.end();)
|
||||
{
|
||||
boost::intrusive_ptr<peer_connection> pc = *i;
|
||||
peer_connection* pc = *i;
|
||||
++i;
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif
|
||||
pc->on_metadata();
|
||||
pc->init();
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
pc->disconnect(e.what());
|
||||
}
|
||||
#endif
|
||||
pc->on_metadata();
|
||||
pc->init();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue