fix: abort handshake if the torrent is stopped (#6947)

* fix: abort handshake if torrent isn't running

* fix: check if torrent is running in all cases

* fix: don't penalise peer if handshake failed because of us

* fix: tests

* perf: ensure copy-elision in `HandshakeMediator::torrent()`

* code review: more accurate log wording
This commit is contained in:
Yat Ho
2025-03-10 14:05:16 +08:00
committed by GitHub
parent 1232f558a6
commit 088232f69c
4 changed files with 27 additions and 18 deletions

View File

@@ -290,14 +290,14 @@ ReadState tr_handshake::read_handshake(tr_peerIo* peer_io)
auto hash = tr_sha1_digest_t{}; auto hash = tr_sha1_digest_t{};
peer_io->read_bytes(std::data(hash), std::size(hash)); peer_io->read_bytes(std::data(hash), std::size(hash));
if (auto const& info = mediator_->torrent(hash); !info || !info->is_running)
{
tr_logAddTraceHand(this, "peer is trying to connect to us for a torrent we aren't running.");
return done(false);
}
if (is_incoming() && peer_io->torrent_hash() == tr_sha1_digest_t{}) // incoming plain handshake if (is_incoming() && peer_io->torrent_hash() == tr_sha1_digest_t{}) // incoming plain handshake
{ {
if (!mediator_->torrent(hash))
{
tr_logAddTraceHand(this, "peer is trying to connect to us for a torrent we don't have.");
return done(false);
}
peer_io->set_torrent_hash(hash); peer_io->set_torrent_hash(hash);
} }
else // outgoing, or incoming MSE handshake else // outgoing, or incoming MSE handshake
@@ -458,14 +458,14 @@ ReadState tr_handshake::read_crypto_provide(tr_peerIo* peer_io)
obfuscated_hash[i] = x_or[i] ^ req3[i]; obfuscated_hash[i] = x_or[i] ^ req3[i];
} }
if (auto const info = mediator_->torrent_from_obfuscated(obfuscated_hash); info) if (auto const info = mediator_->torrent_from_obfuscated(obfuscated_hash); info && info->is_running)
{ {
tr_logAddTraceHand(this, fmt::format("got INCOMING connection's MSE handshake for torrent [{}]", info->id)); tr_logAddTraceHand(this, fmt::format("got INCOMING connection's MSE handshake for torrent [{}]", info->id));
peer_io->set_torrent_hash(info->info_hash); peer_io->set_torrent_hash(info->info_hash);
} }
else else
{ {
tr_logAddTraceHand(this, "can't find that torrent..."); tr_logAddTraceHand(this, "we are not running that torrent...");
return done(false); return done(false);
} }
@@ -714,7 +714,7 @@ bool tr_handshake::build_handshake_message(tr_peerIo* io, libtransmission::Buffe
TR_ASSERT_MSG(info_hash != tr_sha1_digest_t{}, "build_handshake_message requires an info_hash"); TR_ASSERT_MSG(info_hash != tr_sha1_digest_t{}, "build_handshake_message requires an info_hash");
auto const info = mediator_->torrent(info_hash); auto const info = mediator_->torrent(info_hash);
if (!info) if (!info || !info->is_running)
{ {
return false; return false;
} }

View File

@@ -64,6 +64,7 @@ public:
tr_peer_id_t client_peer_id; tr_peer_id_t client_peer_id;
tr_torrent_id_t id; tr_torrent_id_t id;
bool is_done; bool is_done;
bool is_running;
}; };
virtual ~Mediator() = default; virtual ~Mediator() = default;

View File

@@ -75,12 +75,13 @@ private:
return {}; return {};
} }
auto info = TorrentInfo{}; return TorrentInfo{
info.info_hash = tor->info_hash(); tor->info_hash(), // info_hash
info.client_peer_id = tor->peer_id(); tor->peer_id(), // client_peer_id
info.id = tor->id(); tor->id(), // id
info.is_done = tor->is_done(); tor->is_done(), // is_done
return info; tor->is_running() // is_running
};
} }
public: public:
@@ -1289,7 +1290,12 @@ void create_bit_torrent_peer(
info->destroy_handshake(); info->destroy_handshake();
} }
if (!result.is_connected || swarm == nullptr || !swarm->is_running) if (swarm == nullptr || !swarm->is_running)
{
return false;
}
if (!result.is_connected)
{ {
if (info && !info->is_connected()) if (info && !info->is_connected())
{ {

View File

@@ -155,11 +155,13 @@ public:
tr_handshake::Mediator::TorrentInfo const TorrentWeAreSeeding{ tr_sha1::digest("abcde"sv), tr_handshake::Mediator::TorrentInfo const TorrentWeAreSeeding{ tr_sha1::digest("abcde"sv),
tr_peerIdInit(), tr_peerIdInit(),
tr_torrent_id_t{ 100 }, tr_torrent_id_t{ 100 },
true /*is_done*/ }; true /*is_done*/,
true /*is_running*/ };
tr_handshake::Mediator::TorrentInfo const UbuntuTorrent{ *tr_sha1_from_string("2c6b6858d61da9543d4231a71db4b1c9264b0685"sv), tr_handshake::Mediator::TorrentInfo const UbuntuTorrent{ *tr_sha1_from_string("2c6b6858d61da9543d4231a71db4b1c9264b0685"sv),
tr_peerIdInit(), tr_peerIdInit(),
tr_torrent_id_t{ 101 }, tr_torrent_id_t{ 101 },
false /*is_done*/ }; false /*is_done*/,
true /*is_running*/ };
auto createIncomingIo(tr_session* session) auto createIncomingIo(tr_session* session)
{ {