lt sync 2650

This commit is contained in:
Andrew Resch 2008-09-01 02:02:04 +00:00
parent 2f6d98693d
commit 3178582312
9 changed files with 194 additions and 60 deletions

View file

@ -187,8 +187,23 @@ namespace libtorrent
void resize(int bits, bool val)
{
int s = m_size;
int b = m_size & 7;
resize(bits);
if (val) set_all(); else clear_all();
if (s >= m_size) return;
int old_size_bytes = (s + 7) / 8;
int new_size_bytes = (m_size + 7) / 8;
if (val)
{
if (old_size_bytes && b) m_bytes[old_size_bytes - 1] |= (0xff >> b);
if (old_size_bytes < new_size_bytes)
memset(m_bytes + old_size_bytes, 0xff, new_size_bytes - old_size_bytes);
}
else
{
if (old_size_bytes < new_size_bytes)
memset(m_bytes + old_size_bytes, 0x00, new_size_bytes - old_size_bytes);
}
}
void set_all()
@ -225,6 +240,8 @@ namespace libtorrent
m_own = true;
}
m_size = bits;
// clear the tail bits in the last byte
if (m_size && (bits & 7)) m_bytes[(m_size + 7) / 8 - 1] &= 0xff << (7 - (bits & 7));
}
private:

View file

@ -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
};
}

View file

@ -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

View file

@ -166,7 +166,7 @@ void rpc_manager::unreachable(udp::endpoint const& ep)
#endif
int num_active = m_oldest_transaction_id < m_next_transaction_id
? m_next_transaction_id - m_oldest_transaction_id
: max_transactions - m_next_transaction_id + m_oldest_transaction_id;
: max_transactions - m_oldest_transaction_id + m_next_transaction_id;
TORRENT_ASSERT((m_oldest_transaction_id + num_active) % max_transactions
== m_next_transaction_id);
int tid = m_oldest_transaction_id;

View file

@ -305,6 +305,11 @@ namespace libtorrent { namespace
// abort if the peer doesn't support the metadata extension
if (m_message_index == 0) return;
#ifdef TORRENT_VERBOSE_LOGGING
(*m_pc.m_logger) << time_now_string()
<< " ==> METADATA_REQUEST [ start: " << start << " | size: " << size << " ]\n";
#endif
buffer::interval i = m_pc.allocate_send_buffer(9);
detail::write_uint32(1 + 1 + 3, i.begin);
@ -335,8 +340,18 @@ namespace libtorrent { namespace
std::pair<int, int> offset
= req_to_offset(req, (int)m_tp.metadata().left());
// TODO: don't allocate send buffer for the metadata part
// just tag it on as a separate buffer like ut_metadata
buffer::interval i = m_pc.allocate_send_buffer(15 + offset.second);
#ifdef TORRENT_VERBOSE_LOGGING
(*m_pc.m_logger) << time_now_string()
<< " ==> METADATA [ start: " << req.first
<< " | size: " << req.second
<< " | offset: " << offset.first
<< " | byte_size: " << offset.second
<< " ]\n";
#endif
// yes, we have metadata, send it
detail::write_uint32(11 + offset.second, i.begin);
detail::write_uint8(bt_peer_connection::msg_extended, i.begin);
@ -353,6 +368,10 @@ namespace libtorrent { namespace
}
else
{
#ifdef TORRENT_VERBOSE_LOGGING
(*m_pc.m_logger) << time_now_string()
<< " ==> DONT HAVE METADATA\n";
#endif
buffer::interval i = m_pc.allocate_send_buffer(4 + 3);
// we don't have the metadata, reply with
// don't have-message
@ -389,6 +408,13 @@ namespace libtorrent { namespace
int start = detail::read_uint8(body.begin);
int size = detail::read_uint8(body.begin) + 1;
#ifdef TORRENT_VERBOSE_LOGGING
(*m_pc.m_logger) << time_now_string()
<< " <== METADATA_REQUEST [ start: " << start
<< " | size: " << size
<< " ]\n";
#endif
if (length != 3)
{
// invalid metadata request
@ -407,6 +433,14 @@ namespace libtorrent { namespace
int offset = detail::read_int32(body.begin);
int data_size = length - 9;
#ifdef TORRENT_VERBOSE_LOGGING
(*m_pc.m_logger) << time_now_string()
<< " <== METADATA [ total_size: " << total_size
<< " | offset: " << offset
<< " | data_size: " << data_size
<< " ]\n";
#endif
if (total_size > 500 * 1024)
{
m_pc.disconnect("metadata size larger than 500 kB");
@ -445,6 +479,10 @@ namespace libtorrent { namespace
if (m_waiting_metadata_request)
m_tp.cancel_metadata_request(m_last_metadata_request);
m_waiting_metadata_request = false;
#ifdef TORRENT_VERBOSE_LOGGING
(*m_pc.m_logger) << time_now_string()
<< " <== DONT HAVE METADATA\n";
#endif
break;
default:
{

View file

@ -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();
}
}

View file

@ -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())

View file

@ -1288,12 +1288,12 @@ namespace aux {
int num_seeds = settings().active_seeds;
int hard_limit = settings().active_limit;
if (num_downloaders == -1)
num_downloaders = (std::numeric_limits<int>::max)();
if (num_seeds == -1)
num_seeds = (std::numeric_limits<int>::max)();
if (hard_limit == -1)
hard_limit = (std::numeric_limits<int>::max)();
if (num_downloaders == -1)
num_downloaders = (std::numeric_limits<int>::max)();
if (num_seeds == -1)
num_seeds = (std::numeric_limits<int>::max)();
if (hard_limit == -1)
hard_limit = (std::numeric_limits<int>::max)();
for (torrent_map::iterator i = m_torrents.begin()
, end(m_torrents.end()); i != end; ++i)

View file

@ -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;
}
@ -344,7 +348,7 @@ namespace libtorrent
if (m_ses.m_listen_sockets.empty()) return false;
if (!m_ses.m_dht) return false;
if (!m_files_checked) return false;
if (m_torrent_file->is_valid() && !m_files_checked) return false;
// don't announce private torrents
if (m_torrent_file->is_valid() && m_torrent_file->priv()) return false;
@ -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();
}
}