fix: check if piece is wanted upon receiving block (#7866)

* fix: check if piece is wanted upon receiving block

* test: block_last_loc
This commit is contained in:
Yat Ho
2025-12-09 05:43:56 +08:00
committed by GitHub
parent 33d6804a76
commit 095bad6568
5 changed files with 59 additions and 6 deletions

View File

@@ -97,6 +97,12 @@ public:
return byte_loc(uint64_t{ block } * BlockSize);
}
// Location of the last byte in `block`.
[[nodiscard]] constexpr auto block_last_loc(tr_block_index_t const block) const noexcept
{
return byte_loc((uint64_t{ block } * BlockSize) + block_size(block) - 1U);
}
// Location of the first byte (+ optional offset and length) in `piece`
[[nodiscard]] constexpr auto piece_loc(tr_piece_index_t piece, uint32_t offset = {}, uint32_t length = {}) const noexcept
{

View File

@@ -1688,18 +1688,22 @@ ReadResult tr_peerMsgsImpl::read_piece_data(MessageReader& payload)
return { ReadState::Err, len };
}
if (!active_requests.test(block))
{
logwarn(this, fmt::format("got unrequested block {:d} ({:d}:{:d}->{:d})", block, piece, offset, len));
return { ReadState::Err, len };
}
if (tor_.has_block(block))
{
logtrace(this, fmt::format("got completed block {:d} ({:d}:{:d}->{:d})", block, piece, offset, len));
return { ReadState::Err, len };
}
if (auto const block_loc = tor_.block_loc(block); !tor_.piece_is_wanted(block_loc.piece))
{
if (auto const block_last_loc = tor_.block_last_loc(block);
block_loc.piece == block_last_loc.piece || !tor_.piece_is_wanted(block_last_loc.piece))
{
logwarn(this, fmt::format("got unwanted block {:d} ({:d}:{:d}->{:d})", block, piece, offset, len));
return { ReadState::Err, len };
}
}
peer_info->set_latest_piece_data_time(tr_time());
bytes_sent_to_client.add(tr_time(), len);
publish(tr_peer_event::GotPieceData(len));

View File

@@ -79,6 +79,10 @@ public:
{
return block_info().block_loc(block);
}
[[nodiscard]] constexpr auto block_last_loc(tr_block_index_t block) const noexcept
{
return block_info().block_last_loc(block);
}
[[nodiscard]] constexpr auto piece_loc(tr_piece_index_t piece, uint32_t offset = 0, uint32_t length = 0) const noexcept
{
return block_info().piece_loc(piece, offset, length);

View File

@@ -267,6 +267,10 @@ struct tr_torrent
{
return metainfo_.block_loc(block);
}
[[nodiscard]] constexpr auto block_last_loc(tr_block_index_t block) const noexcept
{
return metainfo_.block_last_loc(block);
}
[[nodiscard]] constexpr auto piece_loc(tr_piece_index_t piece, uint32_t offset = 0, uint32_t length = 0) const noexcept
{
return metainfo_.piece_loc(piece, offset, length);

View File

@@ -136,6 +136,41 @@ TEST_F(BlockInfoTest, blockLoc)
EXPECT_EQ(0U, loc.piece_offset);
}
TEST_F(BlockInfoTest, blockLastLoc)
{
static auto constexpr ExpectedBlockSize = uint64_t{ 1024U } * 16U;
static auto constexpr ExpectedBlocksPerPiece = uint64_t{ 4U };
static auto constexpr PieceSize = ExpectedBlockSize * ExpectedBlocksPerPiece;
static auto constexpr PieceCount = uint64_t{ 5U };
static auto constexpr TotalSize = (PieceSize * (PieceCount - 1U)) + 1U;
auto const info = tr_block_info{ TotalSize, PieceSize };
// begin
auto loc = info.block_last_loc(0);
EXPECT_EQ(ExpectedBlockSize - 1U, loc.byte);
EXPECT_EQ(0U, loc.block);
EXPECT_EQ(ExpectedBlockSize - 1U, loc.block_offset);
EXPECT_EQ(0U, loc.piece);
EXPECT_EQ(ExpectedBlockSize - 1U, loc.piece_offset);
// third block is halfway through the first piece
loc = info.block_last_loc(2);
EXPECT_EQ((ExpectedBlockSize * 3U) - 1U, loc.byte);
EXPECT_EQ(2U, loc.block);
EXPECT_EQ(ExpectedBlockSize - 1U, loc.block_offset);
EXPECT_EQ(0U, loc.piece);
EXPECT_EQ((ExpectedBlockSize * 3U) - 1U, loc.piece_offset);
// second piece aligns with fifth block
loc = info.block_last_loc(4);
EXPECT_EQ(PieceSize + ExpectedBlockSize - 1U, loc.byte);
EXPECT_EQ(4U, loc.block);
EXPECT_EQ(ExpectedBlockSize - 1U, loc.block_offset);
EXPECT_EQ(1U, loc.piece);
EXPECT_EQ(ExpectedBlockSize - 1U, loc.piece_offset);
}
TEST_F(BlockInfoTest, pieceLoc)
{
static auto constexpr ExpectedBlockSize = uint64_t{ 1024U } * 16U;