Skip to content

Commit aa59c7c

Browse files
committed
fix to_req() to not request pad-space for v2-only torrents
1 parent bf2f338 commit aa59c7c

8 files changed

Lines changed: 85 additions & 112 deletions

File tree

ChangeLog

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
2.0.13
22

3+
* optimize v2 request sizes
34
* fix socks5 issues
45
* fix issue in loading v2 resume data merkle trees
56

include/libtorrent/torrent_handle.hpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -289,11 +289,13 @@ namespace aux {
289289
// The overload taking a raw pointer to the data is a blocking call. It
290290
// won't return until the libtorrent thread has copied the data into its
291291
// disk write buffer. ``data`` is expected to point to a buffer of as
292-
// many bytes as the size of the specified piece. See
293-
// file_storage::piece_size().
292+
// many bytes as the size of the specified piece.
293+
// For v2 torrents, pieces at the end of files may not be full sized.
294+
// For backwards compatibility, it's OK to pass a full sized piece as
295+
// well.
294296
//
295297
// The data in the buffer is copied and passed on to the disk IO thread
296-
// to be written at a later point.
298+
// to be written at some later point in time.
297299
//
298300
// The overload taking a ``std::vector<char>`` is not blocking, it will
299301
// send the buffer to the main thread and return immediately.
@@ -308,8 +310,12 @@ namespace aux {
308310
// alert, read_piece_alert. Since this alert is a response to an explicit
309311
// call, it will always be posted, regardless of the alert mask.
310312
//
311-
// Note that if you read multiple pieces, the read operations are not
312-
// guaranteed to finish in the same order as you initiated them.
313+
// .. note:: that if you read multiple pieces, the read operations are not
314+
// guaranteed to finish in the same order as you initiated them.
315+
//
316+
// .. note:: the size of the buffer passed back in the alert is not
317+
// necessarily piece_length() long. The last piece or pieces at the end
318+
// of files (in v2 and hybrid torrents) are not full size.
313319
void read_piece(piece_index_t piece) const;
314320

315321
// Returns true if this piece has been completely downloaded and written

include/libtorrent/torrent_info.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,16 @@ TORRENT_VERSION_NAMESPACE_3
505505
// except for the last piece, which may be shorter.
506506
int piece_size(piece_index_t index) const { return m_files.piece_size(index); }
507507

508+
// returns the piece size appropriate for computing request lengths.
509+
// for v2 torrents, pieces at the end of files may be shorter than
510+
// the main piece size. This is the case for hybrid torrents as well.
511+
int piece_size_for_req(piece_index_t index) const
512+
{
513+
return v2()
514+
? m_files.piece_size2(index)
515+
: m_files.piece_size(index);
516+
}
517+
508518
// ``hash_for_piece()`` takes a piece-index and returns the 20-bytes
509519
// sha1-hash for that piece and ``info_hash()`` returns the 20-bytes
510520
// sha1-hash for the info-section of the torrent file.

src/bt_peer_connection.cpp

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -879,23 +879,7 @@ namespace {
879879
TORRENT_ASSERT(t);
880880
auto const dlq = download_queue();
881881
for (pending_block const& pb : dlq)
882-
{
883-
peer_request r;
884-
r.piece = pb.block.piece_index;
885-
r.start = pb.block.block_index * t->block_size();
886-
r.length = t->block_size();
887-
// if it's the last piece, make sure to
888-
// set the length of the request to not
889-
// exceed the end of the torrent. This is
890-
// necessary in order to maintain a correct
891-
// m_outstanding_bytes
892-
if (r.piece == t->torrent_file().last_piece())
893-
{
894-
r.length = std::min(t->torrent_file().piece_size(
895-
r.piece) - r.start, r.length);
896-
}
897-
incoming_reject_request(r);
898-
}
882+
incoming_reject_request(t->to_req(pb.block));
899883
}
900884
}
901885

src/http_seed_connection.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,7 @@ namespace libtorrent {
150150
// would otherwise point to one past the end
151151
int const correction = ret.bytes_downloaded ? -1 : 0;
152152
ret.block_index = (pr.start + ret.bytes_downloaded + correction) / t->block_size();
153-
ret.full_block_bytes = t->block_size();
154-
piece_index_t const last_piece = t->torrent_file().last_piece();
155-
if (ret.piece_index == last_piece && ret.block_index
156-
== t->torrent_file().piece_size(last_piece) / t->block_size())
157-
ret.full_block_bytes = t->torrent_file().piece_size(last_piece) % t->block_size();
153+
ret.full_block_bytes = std::min(t->block_size(), t->torrent_file().piece_size_for_req(ret.piece_index) - pr.start);
158154
return ret;
159155
}
160156

src/peer_connection.cpp

Lines changed: 19 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,7 +1271,7 @@ namespace libtorrent {
12711271
return p.piece >= piece_index_t(0)
12721272
&& p.piece < ti.end_piece()
12731273
&& p.start >= 0
1274-
&& p.start < ti.piece_length()
1274+
&& p.start < ti.piece_size_for_req(p.piece)
12751275
&& t->to_req(piece_block(p.piece, p.start / t->block_size())) == p;
12761276
}
12771277

@@ -1599,9 +1599,9 @@ namespace libtorrent {
15991599
if (r.piece < piece_index_t{}
16001600
|| r.piece >= t->torrent_file().files().end_piece()
16011601
|| r.start < 0
1602-
|| r.start >= t->torrent_file().piece_length()
1602+
|| r.start >= t->torrent_file().piece_size_for_req(r.piece)
16031603
|| (r.start % block_size) != 0
1604-
|| r.length != std::min(t->torrent_file().piece_size(r.piece) - r.start, block_size))
1604+
|| r.length != std::min(t->torrent_file().piece_size_for_req(r.piece) - r.start, block_size))
16051605
{
16061606
#ifndef TORRENT_DISABLE_LOGGING
16071607
peer_log(peer_log_alert::info, "REJECT_PIECE", "invalid reject message (%d, %d, %d)"
@@ -3717,25 +3717,15 @@ namespace libtorrent {
37173717
{
37183718
piece_block const b = pb.block;
37193719

3720-
int const block_offset = b.block_index * t->block_size();
3721-
int const block_size
3722-
= std::min(t->torrent_file().piece_size(b.piece_index)-block_offset,
3723-
t->block_size());
3724-
TORRENT_ASSERT(block_size > 0);
3725-
TORRENT_ASSERT(block_size <= t->block_size());
3726-
37273720
// we can't cancel the piece if we've started receiving it
37283721
if (m_receiving_block == b) continue;
37293722

3730-
peer_request r;
3731-
r.piece = b.piece_index;
3732-
r.start = block_offset;
3733-
r.length = block_size;
3723+
peer_request const r = t->to_req(b);
37343724

37353725
#ifndef TORRENT_DISABLE_LOGGING
37363726
peer_log(peer_log_alert::outgoing_message, "CANCEL"
37373727
, "piece: %d s: %d l: %d b: %d"
3738-
, static_cast<int>(b.piece_index), block_offset, block_size, b.block_index);
3728+
, static_cast<int>(r.piece), r.start, r.length, b.block_index);
37393729
#endif
37403730
write_cancel(r);
37413731
}
@@ -3784,28 +3774,18 @@ namespace libtorrent {
37843774
return;
37853775
}
37863776

3787-
int const block_offset = block.block_index * t->block_size();
3788-
int const block_size
3789-
= std::min(t->torrent_file().piece_size(block.piece_index) - block_offset,
3790-
t->block_size());
3791-
TORRENT_ASSERT(block_size > 0);
3792-
TORRENT_ASSERT(block_size <= t->block_size());
3793-
37943777
it->not_wanted = true;
37953778

37963779
if (force) t->picker().abort_download(block, peer_info_struct());
37973780

3798-
if (m_outstanding_bytes < block_size) return;
3781+
peer_request const r = t->to_req(block);
37993782

3800-
peer_request r;
3801-
r.piece = block.piece_index;
3802-
r.start = block_offset;
3803-
r.length = block_size;
3783+
if (m_outstanding_bytes < r.length) return;
38043784

38053785
#ifndef TORRENT_DISABLE_LOGGING
38063786
peer_log(peer_log_alert::outgoing_message, "CANCEL"
38073787
, "piece: %d s: %d l: %d b: %d"
3808-
, static_cast<int>(block.piece_index), block_offset, block_size, block.block_index);
3788+
, static_cast<int>(r.piece), r.start, r.length, block.block_index);
38093789
#endif
38103790
write_cancel(r);
38113791
}
@@ -4081,24 +4061,14 @@ namespace libtorrent {
40814061
continue;
40824062
}
40834063

4084-
int block_offset = block.block.block_index * t->block_size();
4085-
int bs = std::min(t->torrent_file().piece_size(
4086-
block.block.piece_index) - block_offset, t->block_size());
4087-
TORRENT_ASSERT(bs > 0);
4088-
TORRENT_ASSERT(bs <= t->block_size());
4089-
4090-
peer_request r;
4091-
r.piece = block.block.piece_index;
4092-
r.start = block_offset;
4093-
r.length = bs;
4094-
4064+
peer_request r = t->to_req(block.block);
40954065
if (m_download_queue.empty())
40964066
m_counters.inc_stats_counter(counters::num_peers_down_requests);
40974067

40984068
TORRENT_ASSERT(validate_piece_request(t->to_req(block.block)));
40994069
block.send_buffer_offset = aux::numeric_cast<std::uint32_t>(m_send_buffer.size());
41004070
m_download_queue.push_back(block);
4101-
m_outstanding_bytes += bs;
4071+
m_outstanding_bytes += r.length;
41024072
#if TORRENT_USE_INVARIANT_CHECKS
41034073
check_invariant();
41044074
#endif
@@ -4128,9 +4098,10 @@ namespace libtorrent {
41284098
m_download_queue.push_back(block);
41294099
if (m_queued_time_critical) --m_queued_time_critical;
41304100

4131-
block_offset = block.block.block_index * t->block_size();
4132-
bs = std::min(t->torrent_file().piece_size(
4133-
block.block.piece_index) - block_offset, t->block_size());
4101+
int const block_offset = block.block.block_index * t->block_size();
4102+
int const bs =
4103+
std::min(t->torrent_file().piece_size_for_req(block.block.piece_index)
4104+
- block_offset, t->block_size());
41344105
TORRENT_ASSERT(bs > 0);
41354106
TORRENT_ASSERT(bs <= t->block_size());
41364107

@@ -6607,28 +6578,20 @@ namespace libtorrent {
66076578
// if the piece is fully downloaded, we might have popped it from the
66086579
// download queue already
66096580
int outstanding_bytes = 0;
6610-
// bool in_download_queue = false;
66116581
int const bs = t->block_size();
66126582
piece_block last_block(ti.last_piece()
6613-
, (ti.piece_size(ti.last_piece()) + bs - 1) / bs);
6583+
, (ti.piece_size_for_req(ti.last_piece()) + bs - 1) / bs);
6584+
66146585
for (std::vector<pending_block>::const_iterator i = m_download_queue.begin()
66156586
, end(m_download_queue.end()); i != end; ++i)
66166587
{
66176588
TORRENT_ASSERT(i->block.piece_index <= last_block.piece_index);
66186589
TORRENT_ASSERT(i->block.piece_index < last_block.piece_index
66196590
|| i->block.block_index <= last_block.block_index);
6591+
6592+
outstanding_bytes += t->to_req(i->block).length;
66206593
if (m_received_in_piece && i == m_download_queue.begin())
6621-
{
6622-
// in_download_queue = true;
6623-
// this assert is not correct since block may have different sizes
6624-
// and may not be returned in the order they were requested
6625-
// TORRENT_ASSERT(t->to_req(i->block).length >= m_received_in_piece);
6626-
outstanding_bytes += t->to_req(i->block).length - m_received_in_piece;
6627-
}
6628-
else
6629-
{
6630-
outstanding_bytes += t->to_req(i->block).length;
6631-
}
6594+
outstanding_bytes -= m_received_in_piece;
66326595
}
66336596
//if (p && p->bytes_downloaded < p->full_block_bytes) TORRENT_ASSERT(in_download_queue);
66346597

src/torrent.cpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,7 @@ aux::vector<download_priority_t, piece_index_t> file_to_piece_prio(
807807
return;
808808
}
809809

810-
const int piece_size = m_torrent_file->piece_size(piece);
810+
const int piece_size = m_torrent_file->piece_size_for_req(piece);
811811
const int blocks_in_piece = (piece_size + block_size() - 1) / block_size();
812812

813813
TORRENT_ASSERT(blocks_in_piece > 0);
@@ -1254,7 +1254,7 @@ aux::vector<download_priority_t, piece_index_t> file_to_piece_prio(
12541254

12551255
if (rp->blocks_left == 0)
12561256
{
1257-
int size = m_torrent_file->piece_size(r.piece);
1257+
int size = m_torrent_file->piece_size_for_req(r.piece);
12581258
if (rp->fail)
12591259
{
12601260
m_ses.alerts().emplace_alert<read_piece_alert>(
@@ -1376,10 +1376,13 @@ aux::vector<download_priority_t, piece_index_t> file_to_piece_prio(
13761376
return;
13771377

13781378
// make sure the piece size is correct
1379-
if (data.size() != std::size_t(m_torrent_file->piece_size(piece)))
1380-
return;
1381-
1382-
add_piece(piece, data.data(), flags);
1379+
// we check against the v1 piece size as well, for backwards compatibility
1380+
if (data.size() == std::size_t(m_torrent_file->piece_size_for_req(piece))
1381+
|| data.size() == std::size_t(m_torrent_file->piece_size(piece)))
1382+
{
1383+
data.resize(std::size_t(m_torrent_file->piece_size_for_req(piece)));
1384+
add_piece(piece, data.data(), flags);
1385+
}
13831386
}
13841387

13851388
// TODO: 3 there's some duplication between this function and
@@ -1393,7 +1396,7 @@ aux::vector<download_priority_t, piece_index_t> file_to_piece_prio(
13931396
if (piece >= torrent_file().end_piece())
13941397
return;
13951398

1396-
int const piece_size = m_torrent_file->piece_size(piece);
1399+
int const piece_size = m_torrent_file->piece_size_for_req(piece);
13971400
int const blocks_in_piece = (piece_size + block_size() - 1) / block_size();
13981401

13991402
if (m_deleted) return;
@@ -1519,8 +1522,8 @@ aux::vector<download_priority_t, piece_index_t> file_to_piece_prio(
15191522
peer_request torrent::to_req(piece_block const& p) const
15201523
{
15211524
int const block_offset = p.block_index * block_size();
1522-
int const block = std::min(torrent_file().piece_size(
1523-
p.piece_index) - block_offset, block_size());
1525+
int const piece_sz = torrent_file().piece_size_for_req(p.piece_index);
1526+
int const block = std::min(piece_sz - block_offset, block_size());
15241527
TORRENT_ASSERT(block > 0);
15251528
TORRENT_ASSERT(block <= block_size());
15261529

@@ -7391,7 +7394,7 @@ namespace {
73917394
TORRENT_ASSERT(counter * blocks_per_piece + pi.blocks_in_piece <= int(blk.size()));
73927395
block_info* blocks = &blk[std::size_t(counter * blocks_per_piece)];
73937396
pi.blocks = blocks;
7394-
int const piece_size = ti.piece_size(i->index);
7397+
int const piece_size = ti.piece_size_for_req(i->index);
73957398
int idx = -1;
73967399
for (auto const& info : p.blocks_for_piece(*i))
73977400
{

0 commit comments

Comments
 (0)