refactor: move tr_pex/tr_variant converters to serializer.cc (#8655)

This commit is contained in:
Yat Ho
2026-03-09 01:22:30 +08:00
committed by GitHub
parent 105224de1d
commit 282f085e30
5 changed files with 92 additions and 76 deletions

View File

@@ -1441,64 +1441,6 @@ 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

@@ -629,21 +629,6 @@ 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

@@ -25,6 +25,7 @@
#include "libtransmission/quark.h"
#include "libtransmission/resume.h"
#include "libtransmission/session.h"
#include "libtransmission/serializer.h"
#include "libtransmission/string-utils.h"
#include "libtransmission/torrent-ctor.h"
#include "libtransmission/torrent-metainfo.h"
@@ -49,19 +50,27 @@ void save_peers(tr_variant::Map& map, tr_torrent const* tor)
{
if (auto const pex = tr_peerMgrGetPeers(tor, TR_AF_INET, TR_PEERS_INTERESTING, MaxRememberedPeers); !std::empty(pex))
{
map.insert_or_assign(TR_KEY_peers2, tr_pex::to_variant(std::data(pex), std::size(pex)));
map.insert_or_assign(TR_KEY_peers2, tr::serializer::to_variant(pex));
}
if (auto const pex = tr_peerMgrGetPeers(tor, TR_AF_INET6, TR_PEERS_INTERESTING, MaxRememberedPeers); !std::empty(pex))
{
map.insert_or_assign(TR_KEY_peers2_6, tr_pex::to_variant(std::data(pex), std::size(pex)));
map.insert_or_assign(TR_KEY_peers2_6, tr::serializer::to_variant(pex));
}
}
size_t add_peers(tr_torrent* tor, tr_variant::Vector const& l)
{
auto const n_pex = std::min(std::size(l), size_t{ MaxRememberedPeers });
auto const pex = tr_pex::from_variant(std::data(l), n_pex);
auto pex = std::vector<tr_pex>{};
pex.reserve(n_pex);
for (size_t i = 0; i < n_pex; ++i)
{
if (auto p = tr::serializer::to_value<tr_pex>(l[i]))
{
pex.emplace_back(std::move(*p));
}
}
return tr_peerMgrAddPex(tor, TR_PEER_FROM_RESUME, std::data(pex), std::size(pex));
}

View File

@@ -26,6 +26,7 @@
#include "libtransmission/net.h" // for tr_port
#include "libtransmission/open-files.h" // for tr_open_files::Preallocation
#include "libtransmission/peer-io.h" // tr_preferred_transport
#include "libtransmission/peer-mgr.h" // tr_pex
#include "libtransmission/serializer.h"
#include "libtransmission/string-utils.h"
#include "libtransmission/utils.h" // for tr_strv_strip(), tr_strlower()
@@ -505,6 +506,59 @@ tr_variant from_fs_path(std::filesystem::path const& path)
{
return from_u8string(path.u8string());
}
// ---
bool to_pex(tr_variant const& src, tr_pex* tgt)
{
auto* const map = src.get_if<tr_variant::Map>();
if (map == nullptr)
{
return false;
}
auto const sockaddr = map->value_if<std::string_view>(TR_KEY_socket_address);
if (!sockaddr)
{
return false;
}
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:
return false;
}
pex.flags = static_cast<uint8_t>(map->value_if<int64_t>(TR_KEY_flags).value_or(0));
*tgt = std::move(pex);
return true;
}
tr_variant from_pex(tr_pex const& val)
{
auto pex = tr_variant::Map{ 2U };
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* const end = val.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, val.flags);
return pex;
}
} // unnamed namespace
void Converters::ensure_default_converters()
@@ -523,6 +577,7 @@ void Converters::ensure_default_converters()
Converters::add(to_log_level, from_log_level);
Converters::add(to_mode_t, from_mode_t);
Converters::add(to_msec, from_msec);
Converters::add(to_pex, from_pex);
Converters::add(to_port, from_port);
Converters::add(to_preallocation_mode, from_preallocation_mode);
Converters::add(to_preferred_transport, from_preferred_transport);

View File

@@ -178,6 +178,31 @@ TEST_F(SerializerTest, usesFsPath)
EXPECT_EQ(toString(actual.u8string()), toString(expected.u8string()));
}
TEST_F(SerializerTest, usesTrPex)
{
static auto constexpr CompactIp = std::array{ '\x7F', '\0', '\0', '\1', '\x73', '\x1A' }; // 127.0.0.1:6771
static_assert(CompactIp.size() == tr_socket_address::CompactSockAddrBytes[TR_AF_INET]);
auto const expected_flags = static_cast<uint8_t>(tr_rand_int(0x100U));
auto const expected_sockaddr = tr_socket_address::from_compact_ipv4(reinterpret_cast<std::byte const*>(CompactIp.data()))
.first;
auto const var = Converters::serialize(tr_pex{ expected_sockaddr, expected_flags });
auto* const map = var.get_if<tr_variant::Map>();
ASSERT_NE(map, nullptr);
auto const compact_ip = map->value_if<std::string_view>(TR_KEY_socket_address);
ASSERT_TRUE(compact_ip);
EXPECT_EQ(
std::lexicographical_compare_three_way(compact_ip->begin(), compact_ip->end(), CompactIp.begin(), CompactIp.end()),
std::strong_ordering::equivalent);
EXPECT_EQ(map->value_if<int64_t>(TR_KEY_flags), expected_flags);
auto actual = tr_pex{};
EXPECT_TRUE(Converters::deserialize(var, &actual));
EXPECT_EQ(actual.socket_address, expected_sockaddr);
EXPECT_EQ(actual.flags, expected_flags);
}
TEST_F(SerializerTest, u8StringWarnsOnInvalidUtf8)
{
auto const bad = std::string{ static_cast<char>(0xC3), static_cast<char>(0x28) };