1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2025-03-12 23:23:54 +00:00

refactor: store peers as benc in resume file (#6892)

* refactor: add `tr_pex::to/from_variant()`

* refactor: store peers as benc in resume

* fix: discard invalid pex in `tr_pex::from_variant()`

* fix: limit number of peers loaded from resume
This commit is contained in:
Yat Ho 2025-03-09 02:19:18 +08:00 committed by GitHub
parent c398bd26f3
commit 1054ba4ab6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 98 additions and 14 deletions

View file

@ -1452,6 +1452,64 @@ std::vector<tr_pex> tr_pex::from_compact_ipv6(
return pex;
}
tr_variant::Map tr_pex::to_variant() const
{
auto pex = tr_variant::Map{ 2 };
auto buf = std::array<char, tr_socket_address::CompactSockAddrMaxBytes>{};
auto* const buf_data = std::data(buf);
auto* const begin = reinterpret_cast<std::byte*>(buf_data);
auto* const end = to_compact(begin);
pex.try_emplace(TR_KEY_socket_address, std::string_view{ buf_data, static_cast<size_t>(end - begin) });
pex.try_emplace(TR_KEY_flags, flags);
return pex;
}
std::vector<tr_pex> tr_pex::from_variant(tr_variant const* const var, size_t const n_var)
{
auto pex_vec = std::vector<tr_pex>{};
pex_vec.reserve(n_var);
for (size_t i = 0; i < n_var; ++i)
{
auto* const map = var[i].get_if<tr_variant::Map>();
if (map == nullptr)
{
continue;
}
auto sockaddr = map->value_if<std::string_view>(TR_KEY_socket_address);
if (!sockaddr)
{
continue;
}
auto pex = tr_pex{};
auto* const compact = reinterpret_cast<std::byte const*>(std::data(*sockaddr));
switch (std::size(*sockaddr))
{
case tr_socket_address::CompactSockAddrBytes[TR_AF_INET]:
pex.socket_address = tr_socket_address::from_compact_ipv4(compact).first;
break;
case tr_socket_address::CompactSockAddrBytes[TR_AF_INET6]:
pex.socket_address = tr_socket_address::from_compact_ipv6(compact).first;
break;
default:
TR_ASSERT(false);
continue;
}
pex.flags = static_cast<uint8_t>(map->value_if<int64_t>(TR_KEY_flags).value_or(0));
pex_vec.emplace_back(std::move(pex));
}
return pex_vec;
}
// ---
namespace

View file

@ -24,6 +24,7 @@
#include "libtransmission/net.h" /* tr_address */
#include "libtransmission/tr-assert.h"
#include "libtransmission/utils.h" /* tr_compare_3way */
#include "libtransmission/variant.h"
/**
* @addtogroup peers Peers
@ -587,6 +588,21 @@ struct tr_pex
uint8_t const* added_f,
size_t added_f_len);
[[nodiscard]] tr_variant::Map to_variant() const;
[[nodiscard]] static tr_variant::Vector to_variant(tr_pex const* pex, size_t n_pex)
{
auto ret = tr_variant::Vector{};
ret.reserve(n_pex);
for (size_t i = 0; i < n_pex; ++i)
{
ret.emplace_back(pex[i].to_variant());
}
return ret;
}
[[nodiscard]] static std::vector<tr_pex> from_variant(tr_variant const* var, size_t n_var);
[[nodiscard]] std::string display_name() const
{
return socket_address.display_name();

View file

@ -353,6 +353,7 @@ auto constexpr MyStatic = std::array<std::string_view, TR_N_KEYS>{
"size-units"sv,
"sizeWhenDone"sv,
"sleep-per-seconds-during-verify"sv,
"socket_address"sv,
"sort-mode"sv,
"sort-reversed"sv,
"source"sv,

View file

@ -355,6 +355,7 @@ enum
TR_KEY_size_units,
TR_KEY_sizeWhenDone,
TR_KEY_sleep_per_seconds_during_verify,
TR_KEY_socket_address,
TR_KEY_sort_mode,
TR_KEY_sort_reversed,
TR_KEY_source,

View file

@ -45,43 +45,51 @@ constexpr int MaxRememberedPeers = 200;
void savePeers(tr_variant* dict, tr_torrent const* tor)
{
auto* const map = dict->get_if<tr_variant::Map>();
if (map == nullptr)
{
return;
}
if (auto const pex = tr_peerMgrGetPeers(tor, TR_AF_INET, TR_PEERS_INTERESTING, MaxRememberedPeers); !std::empty(pex))
{
tr_variantDictAddRaw(dict, TR_KEY_peers2, std::data(pex), sizeof(tr_pex) * std::size(pex));
map->try_emplace(TR_KEY_peers2, tr_pex::to_variant(std::data(pex), std::size(pex)));
}
if (auto const pex = tr_peerMgrGetPeers(tor, TR_AF_INET6, TR_PEERS_INTERESTING, MaxRememberedPeers); !std::empty(pex))
{
tr_variantDictAddRaw(dict, TR_KEY_peers2_6, std::data(pex), sizeof(tr_pex) * std::size(pex));
map->try_emplace(TR_KEY_peers2_6, tr_pex::to_variant(std::data(pex), std::size(pex)));
}
}
size_t addPeers(tr_torrent* tor, uint8_t const* buf, size_t buflen)
size_t addPeers(tr_torrent* tor, tr_variant const* l)
{
size_t const n_in = buflen / sizeof(tr_pex);
size_t const n_pex = std::min(n_in, size_t{ MaxRememberedPeers });
auto* const vec = l->get_if<tr_variant::Vector>();
if (vec == nullptr)
{
return {};
}
auto pex = std::array<tr_pex, MaxRememberedPeers>{};
memcpy(std::data(pex), buf, sizeof(tr_pex) * n_pex);
return tr_peerMgrAddPex(tor, TR_PEER_FROM_RESUME, std::data(pex), n_pex);
auto const n_pex = std::min(std::size(*vec), size_t{ MaxRememberedPeers });
auto const pex = tr_pex::from_variant(std::data(*vec), n_pex);
return tr_peerMgrAddPex(tor, TR_PEER_FROM_RESUME, std::data(pex), std::size(pex));
}
auto loadPeers(tr_variant* dict, tr_torrent* tor)
{
auto ret = tr_resume::fields_t{};
uint8_t const* str = nullptr;
auto len = size_t{};
if (tr_variantDictFindRaw(dict, TR_KEY_peers2, &str, &len))
tr_variant* l = nullptr;
if (tr_variantDictFindList(dict, TR_KEY_peers2, &l))
{
size_t const num_added = addPeers(tor, str, len);
size_t const num_added = addPeers(tor, l);
tr_logAddTraceTor(tor, fmt::format("Loaded {} IPv4 peers from resume file", num_added));
ret = tr_resume::Peers;
}
if (tr_variantDictFindRaw(dict, TR_KEY_peers2_6, &str, &len))
if (tr_variantDictFindList(dict, TR_KEY_peers2_6, &l))
{
size_t const num_added = addPeers(tor, str, len);
size_t const num_added = addPeers(tor, l);
tr_logAddTraceTor(tor, fmt::format("Loaded {} IPv6 peers from resume file", num_added));
ret = tr_resume::Peers;
}