1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2025-03-13 07:33:02 +00:00

fix: use message id to check for pex and metadata xfer support (#7177)

* refactor: use metadata id to check for ut metadata support

* refactor: use pex id to check for ut pex support

* refactor: start pex timer after ltep handshake

* refactor: harden metadata xfer sanity checks

* code review: constexpr

* code review: don't save peer ut_pex_id and ut_metadata_id if on private torrent
This commit is contained in:
Yat Ho 2025-03-05 08:42:26 +08:00 committed by GitHub
parent 0518a2269e
commit 8c18cf4245
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -308,12 +308,6 @@ public:
, callback_{ callback }
, callback_data_{ callback_data }
{
if (tor_.allows_pex())
{
pex_timer_ = session->timerMaker().create([this]() { send_ut_pex(); });
pex_timer_->start_repeating(SendPexInterval);
}
if (io_->supports_ltep())
{
send_ltep_handshake();
@ -591,6 +585,11 @@ private:
// ---
[[nodiscard]] constexpr bool can_xfer_metadata() const noexcept
{
return tor_.is_public() && ut_metadata_id_ != 0U;
}
[[nodiscard]] std::optional<int64_t> pop_next_metadata_request()
{
auto& reqs = peer_requested_metadata_pieces_;
@ -618,6 +617,12 @@ private:
void parse_ut_pex(MessageReader& payload);
void parse_ltep(MessageReader& payload);
[[nodiscard]] constexpr bool can_send_ut_pex() const noexcept
{
// only send pex if both the torrent and peer support it
return tor_.allows_pex() && ut_pex_id_ != 0U;
}
void send_ut_pex();
int client_got_block(std::unique_ptr<Cache::BlockData> block_data, tr_block_index_t block);
@ -689,8 +694,6 @@ private:
// ---
bool peer_supports_pex_ = false;
bool peer_supports_metadata_xfer_ = false;
bool client_sent_ltep_handshake_ = false;
size_t desired_request_count_ = 0;
@ -933,19 +936,19 @@ void tr_peerMsgsImpl::parse_ltep(MessageReader& payload)
// in the reserved bytes of the BT handshake.
send_ltep_handshake();
if (io_->supports_ltep())
if (can_send_ut_pex())
{
pex_timer_ = session->timerMaker().create([this]() { send_ut_pex(); });
pex_timer_->start_repeating(SendPexInterval);
send_ut_pex();
}
}
else if (ltep_msgid == UT_PEX_ID)
{
peer_supports_pex_ = true;
parse_ut_pex(payload);
}
else if (ltep_msgid == UT_METADATA_ID)
{
peer_supports_metadata_xfer_ = true;
parse_ut_metadata(payload);
}
else
@ -1005,8 +1008,7 @@ void tr_peerMsgsImpl::parse_ut_pex(MessageReader& payload)
void tr_peerMsgsImpl::send_ut_pex()
{
// only send pex if both the torrent and peer support it
if (!peer_supports_pex_ || !tor_.allows_pex())
if (!can_send_ut_pex())
{
return;
}
@ -1232,22 +1234,20 @@ void tr_peerMsgsImpl::parse_ltep_handshake(MessageReader& payload)
}
// check supported messages for utorrent pex
peer_supports_pex_ = false;
peer_supports_metadata_xfer_ = false;
auto holepunch_supported = false;
if (tr_variant* sub = nullptr; tr_variantDictFindDict(&*var, TR_KEY_m, &sub))
{
if (auto ut_pex = int64_t{}; tr_variantDictFindInt(sub, TR_KEY_ut_pex, &ut_pex))
auto const tor_is_public = tor_.is_public();
if (auto ut_pex = int64_t{}; tor_is_public && tr_variantDictFindInt(sub, TR_KEY_ut_pex, &ut_pex))
{
peer_supports_pex_ = ut_pex != 0;
ut_pex_id_ = static_cast<uint8_t>(ut_pex);
logtrace(this, fmt::format("msgs->ut_pex is {:d}", ut_pex_id_));
}
if (auto ut_metadata = int64_t{}; tr_variantDictFindInt(sub, TR_KEY_ut_metadata, &ut_metadata))
if (auto ut_metadata = int64_t{}; tor_is_public && tr_variantDictFindInt(sub, TR_KEY_ut_metadata, &ut_metadata))
{
peer_supports_metadata_xfer_ = ut_metadata != 0;
ut_metadata_id_ = static_cast<uint8_t>(ut_metadata);
logtrace(this, fmt::format("msgs->ut_metadata_id_ is {:d}", ut_metadata_id_));
}
@ -1271,11 +1271,11 @@ void tr_peerMsgsImpl::parse_ltep_handshake(MessageReader& payload)
// look for metainfo size (BEP 9)
if (auto metadata_size = int64_t{};
peer_supports_metadata_xfer_ && tr_variantDictFindInt(&*var, TR_KEY_metadata_size, &metadata_size))
can_xfer_metadata() && tr_variantDictFindInt(&*var, TR_KEY_metadata_size, &metadata_size))
{
if (!tr_metadata_download::is_valid_metadata_size(metadata_size))
{
peer_supports_metadata_xfer_ = false;
ut_metadata_id_ = 0U;
}
else
{
@ -1366,9 +1366,10 @@ void tr_peerMsgsImpl::parse_ut_metadata(MessageReader& payload_in)
if (msg_type == MetadataMsgType::Request)
{
if (piece >= 0 && tor_.has_metainfo() && tor_.is_public() && std::size(peer_requested_metadata_pieces_) < MetadataReqQ)
auto& reqs = peer_requested_metadata_pieces_;
if (piece >= 0 && tor_.has_metainfo() && can_xfer_metadata() && std::size(reqs) < MetadataReqQ)
{
peer_requested_metadata_pieces_.push(piece);
reqs.push(piece);
}
else
{
@ -1845,7 +1846,7 @@ void tr_peerMsgsImpl::pulse()
void tr_peerMsgsImpl::maybe_send_metadata_requests(time_t now) const
{
if (!peer_supports_metadata_xfer_)
if (!can_xfer_metadata())
{
return;
}