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:
parent
c398bd26f3
commit
1054ba4ab6
5 changed files with 98 additions and 14 deletions
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue