From 8c18cf4245263a25bd53ac54183ad2a6d4485014 Mon Sep 17 00:00:00 2001 From: Yat Ho Date: Wed, 5 Mar 2025 08:42:26 +0800 Subject: [PATCH] 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 --- libtransmission/peer-msgs.cc | 49 ++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/libtransmission/peer-msgs.cc b/libtransmission/peer-msgs.cc index be6f5fbc4..58ebbc5ea 100644 --- a/libtransmission/peer-msgs.cc +++ b/libtransmission/peer-msgs.cc @@ -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 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 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(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(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; }