fix: use both address + port together as a key for peer lookup (#5619)

This commit is contained in:
tearfur 2023-06-20 09:26:39 +08:00 committed by GitHub
parent 4b9b9920bf
commit 64261685d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 43 additions and 31 deletions

View File

@ -66,13 +66,19 @@ if ! find_cfiles -exec "${clang_format_exe}" $clang_format_args '{}' '+'; then
fi
# enforce east const
matches="$(find_cfiles -exec perl -ne 'print "west const:",$ARGV,":",$_ if /((?:^|[(<,;]|\bstatic\s+)\s*)\b(const)\b(?!\s+\w+\s*\[)/' '{}' '+')"
# look for 'const'
# - as the first token in the line
# - or preceded by 'static'
# - or following any of (<,;
# - but not if 'const' is followed by ` override` (const virtual function)
# - but not if 'const' is followed by ` = 0` (const virtual function)
matches="$(find_cfiles -exec perl -ne 'print "west const:",$ARGV,":",$_ if /((?:^|[(<,;]|\bstatic\s+)\s*)\b(const)\b(?!\s+((\w+\s*\[)|(override)|(\=\ 0)))/' '{}' '+')"
if [ -n "$matches" ]; then
echo "$matches"
exitcode=1
fi
if [ -n "$fix" ]; then
find_cfiles -exec perl -pi -e 's/((?:^|[(<,;]|\bstatic\s+)\s*)\b(const)\b(?!\s+\w+\s*\[)/\1>\2</g' '{}' '+'
find_cfiles -exec perl -pi -e 's/((?:^|[(<,;]|\bstatic\s+)\s*)\b(const)\b(?!\s+((\w+\s*\[)|(override)|(\=\ 0)))/\1>\2</g' '{}' '+'
fi
# format JS

View File

@ -521,8 +521,9 @@ ReadState tr_handshake::read_crypto_provide(tr_peerIo* peer_io)
if (auto const info = mediator_->torrent_from_obfuscated(obfuscated_hash); info)
{
auto const& [addr, port] = peer_io->socket_address();
bool const client_is_seed = info->is_done;
bool const peer_is_seed = mediator_->is_peer_known_seed(info->id, peer_io->address());
bool const peer_is_seed = mediator_->is_peer_known_seed(info->id, addr, port);
tr_logAddTraceHand(this, fmt::format("got INCOMING connection's encrypted handshake for torrent [{}]", info->id));
peer_io->set_torrent_hash(info->info_hash);
@ -788,7 +789,8 @@ void tr_handshake::on_error(tr_peerIo* io, tr_error const& error, void* vhandsha
/* Don't mark a peer as non-µTP unless it's really a connect failure. */
if ((error.code == ETIMEDOUT || error.code == ECONNREFUSED) && info)
{
handshake->mediator_->set_utp_failed(info_hash, io->address());
auto const& [addr, port] = io->socket_address();
handshake->mediator_->set_utp_failed(info_hash, addr, port);
}
if (handshake->mediator_->allows_tcp() && io->reconnect())

View File

@ -61,14 +61,15 @@ public:
[[nodiscard]] virtual libtransmission::TimerMaker& timer_maker() = 0;
[[nodiscard]] virtual bool allows_dht() const = 0;
[[nodiscard]] virtual bool allows_tcp() const = 0;
[[nodiscard]] virtual bool is_peer_known_seed(tr_torrent_id_t tor_id, tr_address const& addr) const = 0;
[[nodiscard]] virtual bool is_peer_known_seed(tr_torrent_id_t tor_id, tr_address const& addr, tr_port const& port)
const = 0;
[[nodiscard]] virtual size_t pad(void* setme, size_t max_bytes) const = 0;
[[nodiscard]] virtual DH::private_key_bigend_t private_key() const
{
return DH::randomPrivateKey();
}
virtual void set_utp_failed(tr_sha1_digest_t const& info_hash, tr_address const&) = 0;
virtual void set_utp_failed(tr_sha1_digest_t const& info_hash, tr_address const&, tr_port const&) = 0;
};
tr_handshake(Mediator* mediator, std::shared_ptr<tr_peerIo> peer_io, tr_encryption_mode mode_in, DoneFunc on_done);

View File

@ -107,15 +107,15 @@ public:
return session_.allowsTCP();
}
void set_utp_failed(tr_sha1_digest_t const& info_hash, tr_address const& addr) override
void set_utp_failed(tr_sha1_digest_t const& info_hash, tr_address const& addr, tr_port const& port) override
{
if (auto* const tor = session_.torrents().get(info_hash); tor != nullptr)
{
tr_peerMgrSetUtpFailed(tor, addr, true);
tr_peerMgrSetUtpFailed(tor, addr, port, true);
}
}
[[nodiscard]] bool is_peer_known_seed(tr_torrent_id_t tor_id, tr_address const& addr) const override;
[[nodiscard]] bool is_peer_known_seed(tr_torrent_id_t tor_id, tr_address const& addr, tr_port const& port) const override;
[[nodiscard]] libtransmission::TimerMaker& timer_maker() override
{
@ -473,36 +473,36 @@ public:
pool_is_all_seeds_.reset();
}
[[nodiscard]] peer_atom* get_existing_atom(tr_address const& addr) noexcept
[[nodiscard]] peer_atom* get_existing_atom(tr_address const& addr, tr_port const& port) noexcept
{
auto const iter = std::find_if(
std::begin(pool),
std::end(pool),
[&addr](auto const& atom) { return atom.addr == addr; });
[&addr, &port](auto const& atom) { return atom.addr == addr && atom.port == port; });
return iter != std::end(pool) ? &*iter : nullptr;
}
[[nodiscard]] peer_atom const* get_existing_atom(tr_address const& addr) const noexcept
[[nodiscard]] peer_atom const* get_existing_atom(tr_address const& addr, tr_port const& port) const noexcept
{
auto const iter = std::find_if(
std::begin(pool),
std::end(pool),
[&addr](auto const& atom) { return atom.addr == addr; });
[&addr, &port](auto const& atom) { return atom.addr == addr && atom.port == port; });
return iter != std::end(pool) ? &*iter : nullptr;
}
[[nodiscard]] bool peer_is_a_seed(tr_address const& addr) const noexcept
[[nodiscard]] bool peer_is_a_seed(tr_address const& addr, tr_port const& port) const noexcept
{
auto const* const atom = get_existing_atom(addr);
auto const* const atom = get_existing_atom(addr, port);
return atom != nullptr && atom->isSeed();
}
peer_atom* ensure_atom_exists(tr_address const& addr, tr_port const port, uint8_t const flags, uint8_t const from)
peer_atom* ensure_atom_exists(tr_address const& addr, tr_port const& port, uint8_t const flags, uint8_t const from)
{
TR_ASSERT(addr.is_valid());
TR_ASSERT(from < TR_PEER_FROM__MAX);
peer_atom* atom = get_existing_atom(addr);
peer_atom* atom = get_existing_atom(addr, port);
if (atom == nullptr)
{
@ -808,17 +808,17 @@ void tr_peerMgrOnBlocklistChanged(tr_peerMgr* mgr)
// ---
void tr_peerMgrSetUtpSupported(tr_torrent* tor, tr_address const& addr)
void tr_peerMgrSetUtpSupported(tr_torrent* tor, tr_address const& addr, tr_port const& port)
{
if (auto* const atom = tor->swarm->get_existing_atom(addr); atom != nullptr)
if (auto* const atom = tor->swarm->get_existing_atom(addr, port); atom != nullptr)
{
atom->flags |= ADDED_F_UTP_FLAGS;
}
}
void tr_peerMgrSetUtpFailed(tr_torrent* tor, tr_address const& addr, bool failed)
void tr_peerMgrSetUtpFailed(tr_torrent* tor, tr_address const& addr, tr_port const& port, bool failed)
{
if (auto* const atom = tor->swarm->get_existing_atom(addr); atom != nullptr)
if (auto* const atom = tor->swarm->get_existing_atom(addr, port); atom != nullptr)
{
atom->utp_failed = failed;
}
@ -1024,7 +1024,7 @@ void create_bit_torrent_peer(tr_torrent* tor, std::shared_ptr<tr_peerIo> io, str
{
if (s != nullptr)
{
struct peer_atom* atom = s->get_existing_atom(addr);
struct peer_atom* atom = s->get_existing_atom(addr, port);
if (atom != nullptr)
{
@ -2493,8 +2493,8 @@ void tr_peerMgr::makeNewPeerConnections(size_t max)
// ---
bool HandshakeMediator::is_peer_known_seed(tr_torrent_id_t tor_id, tr_address const& addr) const
bool HandshakeMediator::is_peer_known_seed(tr_torrent_id_t tor_id, tr_address const& addr, tr_port const& port) const
{
auto const* const tor = session_.torrents().get(tor_id);
return tor != nullptr && tor->swarm != nullptr && tor->swarm->peer_is_a_seed(addr);
return tor != nullptr && tor->swarm != nullptr && tor->swarm->peer_is_a_seed(addr, port);
}

View File

@ -163,9 +163,9 @@ constexpr bool tr_isPex(tr_pex const* pex)
void tr_peerMgrFree(tr_peerMgr* manager);
void tr_peerMgrSetUtpSupported(tr_torrent* tor, tr_address const& addr);
void tr_peerMgrSetUtpSupported(tr_torrent* tor, tr_address const& addr, tr_port const& port);
void tr_peerMgrSetUtpFailed(tr_torrent* tor, tr_address const& addr, bool failed);
void tr_peerMgrSetUtpFailed(tr_torrent* tor, tr_address const& addr, tr_port const& port, bool failed);
[[nodiscard]] std::vector<tr_block_span_t> tr_peerMgrGetNextRequests(tr_torrent* torrent, tr_peer const* peer, size_t numwant);

View File

@ -336,8 +336,9 @@ public:
if (io->supports_utp())
{
tr_peerMgrSetUtpSupported(torrent, io->address());
tr_peerMgrSetUtpFailed(torrent, io->address(), false);
auto const& [addr, port] = socketAddress();
tr_peerMgrSetUtpSupported(torrent, addr, port);
tr_peerMgrSetUtpFailed(torrent, addr, port, false);
}
if (io->supports_ltep())
@ -1090,7 +1091,8 @@ void parseLtepHandshake(tr_peerMsgsImpl* msgs, MessageReader& payload)
{
/* Mysterious µTorrent extension that we don't grok. However,
it implies support for µTP, so use it to indicate that. */
tr_peerMgrSetUtpFailed(msgs->torrent, msgs->io->address(), false);
auto const& [addr, port] = msgs->socketAddress();
tr_peerMgrSetUtpFailed(msgs->torrent, addr, port, false);
}
}

View File

@ -81,7 +81,8 @@ public:
return true;
}
[[nodiscard]] bool is_peer_known_seed(tr_torrent_id_t /*tor_id*/, tr_address const& /*addr*/) const override
[[nodiscard]] bool is_peer_known_seed(tr_torrent_id_t /*tor_id*/, tr_address const& /*addr*/, tr_port const& /*port*/)
const override
{
return false;
}
@ -99,7 +100,7 @@ public:
return private_key_;
}
void set_utp_failed(tr_sha1_digest_t const& /*info_hash*/, tr_address const& /*addr*/) override
void set_utp_failed(tr_sha1_digest_t const& /*info_hash*/, tr_address const& /*addr*/, tr_port const& /*port*/) override
{
}