added support for lazy bitfields
This commit is contained in:
parent
ea965431bf
commit
9fe77101ed
|
@ -101,6 +101,7 @@ namespace libtorrent
|
|||
, ignore_limits_on_local_network(true)
|
||||
, connection_speed(20)
|
||||
, send_redundant_have(false)
|
||||
, lazy_bitfields(true)
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
, use_dht_as_fallback(true)
|
||||
#endif
|
||||
|
@ -219,6 +220,12 @@ namespace libtorrent
|
|||
// for collecting statistics in some cases. Default is false.
|
||||
bool send_redundant_have;
|
||||
|
||||
// if this is true, outgoing bitfields will never be fuil. If the
|
||||
// client is seed, a few bits will be set to 0, and later filled
|
||||
// in with have messages. This is to prevent certain ISPs
|
||||
// from stopping people from seeding.
|
||||
bool lazy_bitfields;
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
// while this is true, the dht will note be used unless the
|
||||
// tracker is online
|
||||
|
|
|
@ -775,19 +775,46 @@ namespace libtorrent
|
|||
assert(m_sent_bitfield == false);
|
||||
assert(t->valid_metadata());
|
||||
|
||||
int num_pieces = bitfield.size();
|
||||
int lazy_pieces[50];
|
||||
int num_lazy_pieces = 0;
|
||||
int lazy_piece = 0;
|
||||
|
||||
assert(t->is_seed() == (std::count(bitfield.begin(), bitfield.end(), true) == num_pieces));
|
||||
if (t->is_seed() && m_ses.settings().lazy_bitfields)
|
||||
{
|
||||
num_lazy_pieces = std::min(50, num_pieces / 10);
|
||||
if (num_lazy_pieces < 1) num_lazy_pieces = 1;
|
||||
for (int i = 0; i < num_pieces; ++i)
|
||||
{
|
||||
if (rand() % (num_pieces - i) >= num_lazy_pieces - lazy_piece) continue;
|
||||
lazy_pieces[lazy_piece++] = i;
|
||||
}
|
||||
assert(lazy_piece == num_lazy_pieces);
|
||||
lazy_piece = 0;
|
||||
}
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string() << " ==> BITFIELD ";
|
||||
|
||||
std::stringstream bitfield_string;
|
||||
for (int i = 0; i < (int)get_bitfield().size(); ++i)
|
||||
{
|
||||
if (lazy_piece < num_lazy_pieces
|
||||
&& lazy_pieces[lazy_piece] == i)
|
||||
{
|
||||
bitfield_string << "0";
|
||||
++lazy_piece;
|
||||
continue;
|
||||
}
|
||||
if (bitfield[i]) bitfield_string << "1";
|
||||
else bitfield_string << "0";
|
||||
}
|
||||
bitfield_string << "\n";
|
||||
(*m_logger) << bitfield_string.str();
|
||||
lazy_piece = 0;
|
||||
#endif
|
||||
const int packet_size = ((int)bitfield.size() + 7) / 8 + 5;
|
||||
const int packet_size = (num_pieces + 7) / 8 + 5;
|
||||
|
||||
buffer::interval i = allocate_send_buffer(packet_size);
|
||||
|
||||
|
@ -795,12 +822,31 @@ namespace libtorrent
|
|||
detail::write_uint8(msg_bitfield, i.begin);
|
||||
|
||||
std::fill(i.begin, i.end, 0);
|
||||
for (int c = 0; c < (int)bitfield.size(); ++c)
|
||||
for (int c = 0; c < num_pieces; ++c)
|
||||
{
|
||||
if (lazy_piece < num_lazy_pieces
|
||||
&& lazy_pieces[lazy_piece])
|
||||
{
|
||||
++lazy_piece;
|
||||
continue;
|
||||
}
|
||||
if (bitfield[c])
|
||||
i.begin[c >> 3] |= 1 << (7 - (c & 7));
|
||||
}
|
||||
assert(i.end - i.begin == ((int)bitfield.size() + 7) / 8);
|
||||
assert(i.end - i.begin == (num_pieces + 7) / 8);
|
||||
|
||||
if (num_lazy_pieces > 0)
|
||||
{
|
||||
for (int i = 0; i < num_lazy_pieces; ++i)
|
||||
{
|
||||
write_have(lazy_pieces[i]);
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string()
|
||||
<< " ==> HAVE [ piece: " << lazy_pieces[i] << "]\n";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
m_sent_bitfield = true;
|
||||
#endif
|
||||
|
|
|
@ -2581,6 +2581,10 @@ namespace libtorrent
|
|||
d = time_now() - m_last_receive;
|
||||
if (d > seconds(m_timeout)) return true;
|
||||
|
||||
// TODO: as long as we have less than 95% of the
|
||||
// global (or local) connection limit, connections should
|
||||
// never time out for another reason
|
||||
|
||||
// if the peer hasn't become interested and we haven't
|
||||
// become interested in the peer for 10 minutes, it
|
||||
// has also timed out.
|
||||
|
@ -2636,7 +2640,7 @@ namespace libtorrent
|
|||
bool peer_connection::is_seed() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
// if m_num_pieces == 0, we probably doesn't have the
|
||||
// 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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue