forked from premiere/premiere-libtorrent
fixed metadata extension issues
This commit is contained in:
parent
d4dd2d2a31
commit
92ed7fb364
|
@ -168,7 +168,9 @@ namespace libtorrent
|
|||
|
||||
// this is called when the metadata is retrieved
|
||||
// and the files has been checked
|
||||
virtual void on_metadata() {}
|
||||
virtual void on_metadata() {};
|
||||
|
||||
void on_metadata_impl();
|
||||
|
||||
void set_upload_limit(int limit);
|
||||
void set_download_limit(int limit);
|
||||
|
@ -363,7 +365,7 @@ namespace libtorrent
|
|||
// the following functions appends messages
|
||||
// to the send buffer
|
||||
void send_choke();
|
||||
void send_unchoke();
|
||||
bool send_unchoke();
|
||||
void send_interested();
|
||||
void send_not_interested();
|
||||
|
||||
|
@ -865,6 +867,7 @@ namespace libtorrent
|
|||
public:
|
||||
bool m_in_constructor:1;
|
||||
bool m_disconnect_started:1;
|
||||
bool m_initialized:1;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
|
|
@ -245,6 +245,10 @@ namespace libtorrent
|
|||
|
||||
void bt_peer_connection::on_metadata()
|
||||
{
|
||||
// connections that are still in the handshake
|
||||
// will send their bitfield when the handshake
|
||||
// is done
|
||||
if (m_state < read_packet_size) return;
|
||||
boost::shared_ptr<torrent> t = associated_torrent().lock();
|
||||
TORRENT_ASSERT(t);
|
||||
write_bitfield();
|
||||
|
@ -252,7 +256,6 @@ namespace libtorrent
|
|||
if (m_supports_dht_port && m_ses.m_dht)
|
||||
write_dht_port(m_ses.get_dht_settings().service_port);
|
||||
#endif
|
||||
if (is_interesting()) write_interested();
|
||||
}
|
||||
|
||||
void bt_peer_connection::write_dht_port(int listen_port)
|
||||
|
@ -938,9 +941,13 @@ namespace libtorrent
|
|||
// if we don't have the metedata, we cannot
|
||||
// verify the bitfield size
|
||||
if (t->valid_metadata()
|
||||
&& packet_size() - 1 != ((int)get_bitfield().size() + 7) / 8)
|
||||
&& packet_size() - 1 != (t->torrent_file().num_pieces() + 7) / 8)
|
||||
{
|
||||
disconnect("bitfield with invalid size", 2);
|
||||
std::stringstream msg;
|
||||
msg << "got bitfield with invalid size: " << (packet_size() - 1)
|
||||
<< "bytes. expected: " << ((t->torrent_file().num_pieces() + 7) / 8)
|
||||
<< " bytes";
|
||||
disconnect(msg.str().c_str(), 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2500,7 +2507,7 @@ namespace libtorrent
|
|||
|
||||
m_state = read_packet_size;
|
||||
reset_recv_buffer(5);
|
||||
if (t->valid_metadata())
|
||||
if (t->ready_for_connections())
|
||||
{
|
||||
write_bitfield();
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
|
|
|
@ -133,6 +133,7 @@ namespace libtorrent
|
|||
#ifndef NDEBUG
|
||||
, m_in_constructor(true)
|
||||
, m_disconnect_started(false)
|
||||
, m_initialized(false)
|
||||
#endif
|
||||
{
|
||||
m_channel_state[upload_channel] = peer_info::bw_idle;
|
||||
|
@ -238,6 +239,7 @@ namespace libtorrent
|
|||
#ifndef NDEBUG
|
||||
, m_in_constructor(true)
|
||||
, m_disconnect_started(false)
|
||||
, m_initialized(false)
|
||||
#endif
|
||||
{
|
||||
m_channel_state[upload_channel] = peer_info::bw_idle;
|
||||
|
@ -430,6 +432,60 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
void peer_connection::on_metadata_impl()
|
||||
{
|
||||
boost::shared_ptr<torrent> t = associated_torrent().lock();
|
||||
m_have_piece.resize(t->torrent_file().num_pieces(), m_have_all);
|
||||
m_num_pieces = m_have_piece.count();
|
||||
if (m_num_pieces == int(m_have_piece.size()))
|
||||
{
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string()
|
||||
<< " *** on_metadata(): THIS IS A SEED ***\n";
|
||||
#endif
|
||||
// if this is a web seed. we don't have a peer_info struct
|
||||
if (m_peer_info) m_peer_info->seed = true;
|
||||
m_upload_only = true;
|
||||
|
||||
t->peer_has_all();
|
||||
disconnect_if_redundant();
|
||||
if (m_disconnecting) return;
|
||||
|
||||
on_metadata();
|
||||
if (m_disconnecting) return;
|
||||
|
||||
if (!t->is_finished())
|
||||
t->get_policy().peer_is_interesting(*this);
|
||||
|
||||
return;
|
||||
}
|
||||
TORRENT_ASSERT(!m_have_all);
|
||||
|
||||
on_metadata();
|
||||
if (m_disconnecting) return;
|
||||
|
||||
// let the torrent know which pieces the
|
||||
// peer has
|
||||
// if we're a seed, we don't keep track of piece availability
|
||||
bool interesting = false;
|
||||
if (!t->is_seed())
|
||||
{
|
||||
t->peer_has(m_have_piece);
|
||||
|
||||
for (int i = 0; i < (int)m_have_piece.size(); ++i)
|
||||
{
|
||||
if (m_have_piece[i])
|
||||
{
|
||||
if (!t->have_piece(i) && t->picker().piece_priority(i) != 0)
|
||||
interesting = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (interesting) t->get_policy().peer_is_interesting(*this);
|
||||
else if (upload_only()) disconnect("upload to upload connections");
|
||||
}
|
||||
|
||||
void peer_connection::init()
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
@ -440,13 +496,15 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(t->ready_for_connections());
|
||||
|
||||
m_have_piece.resize(t->torrent_file().num_pieces(), m_have_all);
|
||||
if (m_have_all) m_num_pieces = t->torrent_file().num_pieces();
|
||||
|
||||
if (m_have_all) m_num_pieces = t->torrent_file().num_pieces();
|
||||
#ifndef NDEBUG
|
||||
m_initialized = true;
|
||||
#endif
|
||||
// now that we have a piece_picker,
|
||||
// update it with this peer's pieces
|
||||
|
||||
TORRENT_ASSERT(m_num_pieces == std::count(m_have_piece.begin()
|
||||
, m_have_piece.end(), true));
|
||||
TORRENT_ASSERT(m_num_pieces == m_have_piece.count());
|
||||
|
||||
if (m_num_pieces == int(m_have_piece.size()))
|
||||
{
|
||||
|
@ -1105,6 +1163,7 @@ namespace libtorrent
|
|||
else
|
||||
{
|
||||
m_have_piece.set_bit(index);
|
||||
++m_num_pieces;
|
||||
|
||||
// only update the piece_picker if
|
||||
// we have the metadata and if
|
||||
|
@ -1112,7 +1171,6 @@ namespace libtorrent
|
|||
// we won't have a piece picker)
|
||||
if (t->valid_metadata())
|
||||
{
|
||||
++m_num_pieces;
|
||||
t->peer_has(index);
|
||||
|
||||
if (!t->have_piece(index)
|
||||
|
@ -1177,11 +1235,11 @@ namespace libtorrent
|
|||
// if we don't have the metedata, we cannot
|
||||
// verify the bitfield size
|
||||
if (t->valid_metadata()
|
||||
&& (bits.size() / 8) != (m_have_piece.size() / 8))
|
||||
&& (bits.size() + 7) / 8 != (m_have_piece.size() + 7) / 8)
|
||||
{
|
||||
std::stringstream msg;
|
||||
msg << "got bitfield with invalid size: " << (bits.size() / 8)
|
||||
<< "bytes. expected: " << (m_have_piece.size() / 8)
|
||||
msg << "got bitfield with invalid size: " << ((bits.size() + 7) / 8)
|
||||
<< "bytes. expected: " << ((m_have_piece.size() + 7) / 8)
|
||||
<< " bytes";
|
||||
disconnect(msg.str().c_str(), 2);
|
||||
return;
|
||||
|
@ -1928,20 +1986,22 @@ namespace libtorrent
|
|||
#endif
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
if (index < 0 || index >= int(m_have_piece.size()))
|
||||
if (t->valid_metadata())
|
||||
{
|
||||
if (index < 0 || index >= int(m_have_piece.size()))
|
||||
{
|
||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||
(*m_logger) << time_now_string() << " <== INVALID_ALLOWED_FAST [ " << index << " | s: "
|
||||
<< int(m_have_piece.size()) << " ]\n";
|
||||
(*m_logger) << time_now_string() << " <== INVALID_ALLOWED_FAST [ " << index << " | s: "
|
||||
<< int(m_have_piece.size()) << " ]\n";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// if we already have the piece, we can
|
||||
// ignore this message
|
||||
if (t->valid_metadata()
|
||||
&& t->have_piece(index))
|
||||
return;
|
||||
// if we already have the piece, we can
|
||||
// ignore this message
|
||||
if (t->have_piece(index))
|
||||
return;
|
||||
}
|
||||
|
||||
m_allowed_fast.push_back(index);
|
||||
|
||||
|
@ -1949,6 +2009,7 @@ namespace libtorrent
|
|||
// to download it, request it
|
||||
if (int(m_have_piece.size()) > index
|
||||
&& m_have_piece[index]
|
||||
&& t->valid_metadata()
|
||||
&& t->has_picker()
|
||||
&& t->picker().piece_priority(index) > 0)
|
||||
{
|
||||
|
@ -2120,11 +2181,13 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
void peer_connection::send_unchoke()
|
||||
bool peer_connection::send_unchoke()
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (!m_choked) return;
|
||||
if (!m_choked) return false;
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
if (!t->ready_for_connections()) return false;
|
||||
m_last_unchoke = time_now();
|
||||
write_unchoke();
|
||||
m_choked = false;
|
||||
|
@ -2132,14 +2195,15 @@ namespace libtorrent
|
|||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string() << " ==> UNCHOKE\n";
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void peer_connection::send_interested()
|
||||
{
|
||||
if (m_interesting) return;
|
||||
m_interesting = true;
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
if (!t->valid_metadata()) return;
|
||||
if (!t->ready_for_connections()) return;
|
||||
m_interesting = true;
|
||||
write_interested();
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
|
@ -2150,9 +2214,9 @@ namespace libtorrent
|
|||
void peer_connection::send_not_interested()
|
||||
{
|
||||
if (!m_interesting) return;
|
||||
m_interesting = false;
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
if (!t->valid_metadata()) return;
|
||||
if (!t->ready_for_connections()) return;
|
||||
m_interesting = false;
|
||||
write_not_interested();
|
||||
|
||||
m_became_uninteresting = time_now();
|
||||
|
@ -2744,7 +2808,7 @@ namespace libtorrent
|
|||
}
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
if (!t->valid_metadata()) return;
|
||||
if (!t->ready_for_connections()) return;
|
||||
|
||||
// calculate the desired download queue size
|
||||
const float queue_time = m_ses.settings().request_queue_time;
|
||||
|
@ -2946,7 +3010,7 @@ namespace libtorrent
|
|||
while (!m_requests.empty()
|
||||
&& (send_buffer_size() + m_reading_bytes < buffer_size_watermark))
|
||||
{
|
||||
TORRENT_ASSERT(t->valid_metadata());
|
||||
TORRENT_ASSERT(t->ready_for_connections());
|
||||
peer_request& r = m_requests.front();
|
||||
|
||||
TORRENT_ASSERT(r.piece >= 0);
|
||||
|
@ -3679,6 +3743,8 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(!is_choked());
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(m_have_piece.count() == m_num_pieces);
|
||||
|
||||
if (!t)
|
||||
{
|
||||
#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS
|
||||
|
@ -3691,6 +3757,9 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
if (t->ready_for_connections() && m_initialized)
|
||||
TORRENT_ASSERT(t->torrent_file().num_pieces() == m_have_piece.size());
|
||||
|
||||
if (m_ses.settings().close_redundant_connections)
|
||||
{
|
||||
// make sure upload only peers are disconnected
|
||||
|
@ -3703,10 +3772,14 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(m_disconnect_started);
|
||||
}
|
||||
|
||||
if (t->is_finished())
|
||||
TORRENT_ASSERT(!m_interesting);
|
||||
if (is_seed())
|
||||
TORRENT_ASSERT(m_upload_only);
|
||||
if (!m_disconnect_started)
|
||||
{
|
||||
// none of this matters if we're disconnecting anyway
|
||||
if (t->is_finished())
|
||||
TORRENT_ASSERT(!m_interesting);
|
||||
if (is_seed())
|
||||
TORRENT_ASSERT(m_upload_only);
|
||||
}
|
||||
|
||||
if (t->has_picker())
|
||||
{
|
||||
|
@ -3777,18 +3850,6 @@ namespace libtorrent
|
|||
*/
|
||||
}
|
||||
}
|
||||
// expensive when using checked iterators
|
||||
/*
|
||||
if (t->valid_metadata())
|
||||
{
|
||||
int piece_count = std::count(m_have_piece.begin()
|
||||
, m_have_piece.end(), true);
|
||||
if (m_num_pieces != piece_count)
|
||||
{
|
||||
TORRENT_ASSERT(false);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// extremely expensive invariant check
|
||||
/*
|
||||
|
@ -3870,7 +3931,8 @@ namespace libtorrent
|
|||
{
|
||||
// if m_num_pieces == 0, we probably don't have the
|
||||
// metadata yet.
|
||||
return m_num_pieces == (int)m_have_piece.size() && m_num_pieces > 0;
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
return m_num_pieces == (int)m_have_piece.size() && m_num_pieces > 0 && t && t->valid_metadata();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1058,6 +1058,7 @@ namespace libtorrent
|
|||
{
|
||||
// INVARIANT_CHECK;
|
||||
|
||||
if (c.in_handshake()) return;
|
||||
c.send_interested();
|
||||
if (c.has_peer_choked()
|
||||
&& c.allowed_fast().empty())
|
||||
|
|
|
@ -333,7 +333,11 @@ namespace libtorrent
|
|||
// we need to start announcing since we don't have any
|
||||
// metadata. To receive peers to ask for it.
|
||||
if (m_torrent_file->is_valid()) init();
|
||||
else if (!m_trackers.empty()) start_announcing();
|
||||
else
|
||||
{
|
||||
set_state(torrent_status::downloading_metadata);
|
||||
if (!m_trackers.empty()) start_announcing();
|
||||
}
|
||||
|
||||
if (m_abort) return;
|
||||
}
|
||||
|
@ -2001,7 +2005,7 @@ namespace libtorrent
|
|||
|
||||
TORRENT_ASSERT(c.is_choked());
|
||||
if (m_num_uploads >= m_max_uploads) return false;
|
||||
c.send_unchoke();
|
||||
if (!c.send_unchoke()) return false;
|
||||
++m_num_uploads;
|
||||
return true;
|
||||
}
|
||||
|
@ -3334,7 +3338,9 @@ namespace libtorrent
|
|||
{
|
||||
peer_connection* pc = *i;
|
||||
++i;
|
||||
pc->on_metadata();
|
||||
if (pc->is_disconnecting()) continue;
|
||||
pc->on_metadata_impl();
|
||||
if (pc->is_disconnecting()) continue;
|
||||
pc->init();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue