refactor: libtransmission Settings (#6592)

* refactor: make tr_session_settings a libtransmission::Settings

* refactor: make VariantConverter private in settings.cc
This commit is contained in:
Charles Kerr 2024-02-15 11:31:09 -06:00 committed by GitHub
parent eeea3c540f
commit c14d445cf5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 774 additions and 811 deletions

View File

@ -437,9 +437,6 @@
CAB35C64252F6F5E00552A55 /* mime-types.h in Headers */ = {isa = PBXBuildFile; fileRef = CAB35C62252F6F5E00552A55 /* mime-types.h */; };
CCEBA596277340F6DF9F4480 /* session-alt-speeds.cc in Sources */ = {isa = PBXBuildFile; fileRef = CCEBA596277340F6DF9F4481 /* session-alt-speeds.cc */; };
CCEBA596277340F6DF9F4482 /* session-alt-speeds.h in Headers */ = {isa = PBXBuildFile; fileRef = CCEBA596277340F6DF9F4483 /* session-alt-speeds.h */; };
D5C306568A7346FFFB8EFAD0 /* session-settings.cc in Sources */ = {isa = PBXBuildFile; fileRef = D5C306568A7346FFFB8EFAD1 /* session-settings.cc */; };
D5C306568A7346FFFB8EFAD2 /* session-settings.h in Headers */ = {isa = PBXBuildFile; fileRef = D5C306568A7346FFFB8EFAD3 /* session-settings.h */; };
D9057D68C13B75636539B680 /* variant-converters.cc in Sources */ = {isa = PBXBuildFile; fileRef = D9057D68C13B75636539B681 /* variant-converters.cc */; };
E138A9780C04D88F00C5426C /* ProgressGradients.mm in Sources */ = {isa = PBXBuildFile; fileRef = E138A9760C04D88F00C5426C /* ProgressGradients.mm */; };
E23B55A5FC3B557F7746D510 /* interned-string.h in Headers */ = {isa = PBXBuildFile; fileRef = E23B55A5FC3B557F7746D511 /* interned-string.h */; settings = {ATTRIBUTES = (Project, ); }; };
E975121263DD973CAF4AEBA0 /* timer.h in Headers */ = {isa = PBXBuildFile; fileRef = E975121263DD973CAF4AEBA1 /* timer.h */; };
@ -1352,9 +1349,6 @@
CAB35C62252F6F5E00552A55 /* mime-types.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = "mime-types.h"; sourceTree = "<group>"; };
CCEBA596277340F6DF9F4481 /* session-alt-speeds.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "session-alt-speeds.cc"; sourceTree = "<group>"; };
CCEBA596277340F6DF9F4483 /* session-alt-speeds.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; path = "session-alt-speeds.h"; sourceTree = "<group>"; };
D5C306568A7346FFFB8EFAD1 /* session-settings.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "session-settings.cc"; sourceTree = "<group>"; };
D5C306568A7346FFFB8EFAD3 /* session-settings.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; path = "session-settings.h"; sourceTree = "<group>"; };
D9057D68C13B75636539B681 /* variant-converters.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "variant-converters.cc"; sourceTree = "<group>"; };
E138A9750C04D88F00C5426C /* ProgressGradients.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ProgressGradients.h; sourceTree = "<group>"; };
E138A9760C04D88F00C5426C /* ProgressGradients.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ProgressGradients.mm; sourceTree = "<group>"; };
E23B55A5FC3B557F7746D511 /* interned-string.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; path = "interned-string.h"; sourceTree = "<group>"; };
@ -1885,11 +1879,8 @@
BEFC1E140C07861A00B0BB3C /* session.h */,
CCEBA596277340F6DF9F4481 /* session-alt-speeds.cc */,
CCEBA596277340F6DF9F4483 /* session-alt-speeds.h */,
D5C306568A7346FFFB8EFAD1 /* session-settings.cc */,
D5C306568A7346FFFB8EFAD3 /* session-settings.h */,
ED67FB402B70FCE400D8A037 /* settings.cc */,
ED67FB412B70FCE400D8A037 /* settings.h */,
D9057D68C13B75636539B681 /* variant-converters.cc */,
A25D2CBB0CF4C7190096A262 /* stats.cc */,
A25D2CBA0CF4C7190096A262 /* stats.h */,
C11DEA141FCD31C0009E22B9 /* subprocess-posix.cc */,
@ -2377,7 +2368,6 @@
BEFC1E450C07861A00B0BB3C /* net.h in Headers */,
BEFC1E4D0C07861A00B0BB3C /* session.h in Headers */,
CCEBA596277340F6DF9F4482 /* session-alt-speeds.h in Headers */,
D5C306568A7346FFFB8EFAD2 /* session-settings.h in Headers */,
BEFC1E4E0C07861A00B0BB3C /* inout.h in Headers */,
BEFC1E520C07861A00B0BB3C /* open-files.h in Headers */,
ED8A163F2735A8AA000D61F9 /* peer-mgr-active-requests.h in Headers */,
@ -3134,8 +3124,6 @@
ED8A16402735A8AA000D61F9 /* peer-mgr-active-requests.cc in Sources */,
BEFC1E2F0C07861A00B0BB3C /* session.cc in Sources */,
CCEBA596277340F6DF9F4480 /* session-alt-speeds.cc in Sources */,
D5C306568A7346FFFB8EFAD0 /* session-settings.cc in Sources */,
D9057D68C13B75636539B680 /* variant-converters.cc in Sources */,
BEFC1E320C07861A00B0BB3C /* torrent.cc in Sources */,
2B9BA6C508B488FE586A0AB0 /* torrents.cc in Sources */,
BE7AA337F6752914B0C416B2 /* utils-ev.cc in Sources */,

View File

@ -9,6 +9,7 @@ Checks: >
cert-*,
-cert-err58-cpp,
clang-analyzer-*,
-clang-analyzer-optin.core.EnumCastOutOfRange,
cppcoreguidelines-avoid-do-while,
cppcoreguidelines-avoid-goto,
cppcoreguidelines-avoid-reference-coroutine-parameters,
@ -29,6 +30,7 @@ Checks: >
modernize-*,
-modernize-use-trailing-return-type,
performance-*,
-performance-move-const-arg,
portability-*,
readability-*,
-readability-function-cognitive-complexity,

View File

@ -113,7 +113,6 @@ target_sources(${TR_NAME}
session-alt-speeds.h
session-id.cc
session-id.h
session-settings.cc
session-thread.cc
session-thread.h
session.cc
@ -161,7 +160,6 @@ target_sources(${TR_NAME}
utils.h
utils.mm
variant-benc.cc
variant-converters.cc
variant-json.cc
variant.cc
variant.h

View File

@ -831,7 +831,7 @@ void tr_rpc_server::set_anti_brute_force_enabled(bool enabled) noexcept
// --- LIFECYCLE
tr_rpc_server::tr_rpc_server(tr_session* session_in, Settings settings)
tr_rpc_server::tr_rpc_server(tr_session* session_in, Settings&& settings)
: compressor{ libdeflate_alloc_compressor(DeflateLevel), libdeflate_free_compressor }
, web_client_dir_{ tr_getWebClientDir(session_in) }
, bind_address_{ std::make_unique<class tr_rpc_address>() }
@ -840,7 +840,7 @@ tr_rpc_server::tr_rpc_server(tr_session* session_in, Settings settings)
load(std::move(settings));
}
void tr_rpc_server::load(Settings settings)
void tr_rpc_server::load(Settings&& settings)
{
settings_ = std::move(settings);

View File

@ -39,6 +39,7 @@ public:
{
public:
Settings() = default;
virtual ~Settings() = default;
explicit Settings(tr_variant const& src)
{
@ -47,20 +48,20 @@ public:
// NB: When adding a field here, you must also add it to
// fields() if you want it to be in session-settings.json
size_t anti_brute_force_limit = 100U;
bool authentication_required = false;
std::string bind_address_str = "0.0.0.0";
std::string host_whitelist_str = "";
bool is_anti_brute_force_enabled = false;
bool is_enabled = false;
bool is_host_whitelist_enabled = true;
bool is_whitelist_enabled = true;
tr_port port = tr_port::from_host(TR_DEFAULT_RPC_PORT);
size_t anti_brute_force_limit = 100U;
std::string bind_address_str = "0.0.0.0";
std::string host_whitelist_str = "";
std::string salted_password = "";
tr_mode_t socket_mode = 0750;
std::string url = TR_DEFAULT_RPC_URL_STR;
std::string username = "";
std::string whitelist_str = TR_DEFAULT_RPC_WHITELIST;
tr_mode_t socket_mode = 0750;
tr_port port = tr_port::from_host(TR_DEFAULT_RPC_PORT);
private:
[[nodiscard]] Fields fields() override
@ -84,7 +85,7 @@ public:
}
};
tr_rpc_server(tr_session* session, Settings settings);
tr_rpc_server(tr_session* session, Settings&& settings);
~tr_rpc_server();
tr_rpc_server(tr_rpc_server&) = delete;
@ -92,7 +93,7 @@ public:
tr_rpc_server& operator=(tr_rpc_server&) = delete;
tr_rpc_server& operator=(tr_rpc_server&&) = delete;
void load(Settings settings);
void load(Settings&& settings);
[[nodiscard]] constexpr Settings const& settings() const
{

View File

@ -18,58 +18,23 @@
using namespace std::literals;
void tr_session_alt_speeds::load(tr_variant const& src)
void tr_session_alt_speeds::load(Settings&& settings)
{
auto const* const src_map = src.get_if<tr_variant::Map>();
if (src_map != nullptr)
{
#define V(key, field, type, default_value, comment) \
if (auto const iter = src_map->find(key); iter != std::end(*src_map)) \
{ \
if (auto val = libtransmission::VariantConverter::load<decltype(field)>(iter->second); val) \
{ \
this->field = *val; \
} \
}
ALT_SPEEDS_FIELDS(V)
#undef V
}
settings_ = std::move(settings);
update_scheduler();
}
tr_variant tr_session_alt_speeds::settings() const
{
auto settings = tr_variant::Map{};
#define V(key, field, type, default_value, comment) \
settings.try_emplace(key, libtransmission::VariantConverter::save<decltype(field)>(field));
ALT_SPEEDS_FIELDS(V)
#undef V
return tr_variant{ std::move(settings) };
}
tr_variant tr_session_alt_speeds::default_settings()
{
auto settings = tr_variant::Map{};
#define V(key, field, type, default_value, comment) \
settings.try_emplace(key, libtransmission::VariantConverter::save<decltype(field)>(static_cast<type>(default_value)));
ALT_SPEEDS_FIELDS(V)
#undef V
return tr_variant{ std::move(settings) };
}
// --- minutes
void tr_session_alt_speeds::update_minutes()
{
minutes_.reset();
for (int day = 0; day < 7; ++day)
{
if ((static_cast<tr_sched_day>(use_on_these_weekdays_) & (1 << day)) != 0)
if ((static_cast<tr_sched_day>(settings_.use_on_these_weekdays) & (1 << day)) != 0)
{
auto const begin = minute_begin_;
auto const end = minute_end_ > minute_begin_ ? minute_end_ : minute_end_ + MinutesPerDay;
auto const begin = settings_.minute_begin;
auto const end = settings_.minute_end > settings_.minute_begin ? settings_.minute_end :
settings_.minute_end + MinutesPerDay;
for (auto i = begin; i < end; ++i)
{
minutes_.set((i + day * MinutesPerDay) % MinutesPerWeek);
@ -103,10 +68,10 @@ void tr_session_alt_speeds::check_scheduler()
void tr_session_alt_speeds::set_active(bool active, ChangeReason reason)
{
if (is_active_ != active)
if (auto& tgt = settings_.is_active; tgt != active)
{
is_active_ = active;
mediator_.is_active_changed(is_active_, reason);
tgt = active;
mediator_.is_active_changed(tgt, reason);
}
}

View File

@ -17,25 +17,53 @@
#include "libtransmission/transmission.h" // for TR_SCHED_ALL
#include "libtransmission/quark.h"
#include "libtransmission/settings.h"
#include "libtransmission/values.h"
struct tr_variant;
#define ALT_SPEEDS_FIELDS(V) \
V(TR_KEY_alt_speed_enabled, is_active_, bool, false, "") \
V(TR_KEY_alt_speed_up, speed_up_kbyps_, size_t, 50U, "") \
V(TR_KEY_alt_speed_down, speed_down_kbyps_, size_t, 50U, "") \
V(TR_KEY_alt_speed_time_enabled, scheduler_enabled_, bool, false, "whether alt speeds toggle on and off on schedule") \
V(TR_KEY_alt_speed_time_day, use_on_these_weekdays_, size_t, TR_SCHED_ALL, "days of the week") \
V(TR_KEY_alt_speed_time_begin, minute_begin_, size_t, 540U, "minutes past midnight; 9AM") \
V(TR_KEY_alt_speed_time_end, minute_end_, size_t, 1020U, "minutes past midnight; 5PM")
/** Manages alternate speed limits and a scheduler to auto-toggle them. */
class tr_session_alt_speeds
{
using Speed = libtransmission::Values::Speed;
public:
class Settings final : public libtransmission::Settings
{
public:
Settings() = default;
virtual ~Settings() = default;
explicit Settings(tr_variant const& src)
{
load(src);
}
// NB: When adding a field here, you must also add it to
// fields() if you want it to be in session-settings.json
bool is_active = false;
bool scheduler_enabled = false; // whether alt speeds toggle on and off on schedule
size_t minute_begin = 540U; // minutes past midnight; 9AM
size_t minute_end = 1020U; // minutes past midnight; 5PM
size_t speed_down_kbyps = 50U;
size_t speed_up_kbyps = 50U;
size_t use_on_these_weekdays = TR_SCHED_ALL;
private:
[[nodiscard]] Fields fields() override
{
return {
{ TR_KEY_alt_speed_enabled, &is_active },
{ TR_KEY_alt_speed_up, &speed_up_kbyps },
{ TR_KEY_alt_speed_down, &speed_down_kbyps },
{ TR_KEY_alt_speed_time_enabled, &scheduler_enabled },
{ TR_KEY_alt_speed_time_day, &use_on_these_weekdays },
{ TR_KEY_alt_speed_time_begin, &minute_begin },
{ TR_KEY_alt_speed_time_end, &minute_end },
};
}
};
enum class ChangeReason
{
User,
@ -58,65 +86,68 @@ public:
{
}
void load(tr_variant const& src);
[[nodiscard]] tr_variant settings() const;
[[nodiscard]] static tr_variant default_settings();
void load(Settings&& settings);
[[nodiscard]] constexpr auto const& settings() const noexcept
{
return settings_;
}
[[nodiscard]] constexpr bool is_active() const noexcept
{
return is_active_;
return settings().is_active;
}
void check_scheduler();
void set_scheduler_enabled(bool enabled)
{
scheduler_enabled_ = enabled;
settings_.scheduler_enabled = enabled;
update_scheduler();
}
// return true iff the scheduler will turn alt speeds on/off
[[nodiscard]] constexpr auto is_scheduler_enabled() const noexcept
{
return scheduler_enabled_;
return settings().scheduler_enabled;
}
void set_start_minute(size_t minute)
{
minute_begin_ = minute;
settings_.minute_begin = minute;
update_scheduler();
}
[[nodiscard]] constexpr auto start_minute() const noexcept
{
return minute_begin_;
return settings().minute_begin;
}
void set_end_minute(size_t minute)
{
minute_end_ = minute;
settings_.minute_end = minute;
update_scheduler();
}
[[nodiscard]] constexpr auto end_minute() const noexcept
{
return minute_end_;
return settings().minute_end;
}
void set_weekdays(tr_sched_day days)
{
use_on_these_weekdays_ = days;
settings_.use_on_these_weekdays = days;
update_scheduler();
}
[[nodiscard]] constexpr tr_sched_day weekdays() const noexcept
{
return static_cast<tr_sched_day>(use_on_these_weekdays_);
return static_cast<tr_sched_day>(settings().use_on_these_weekdays);
}
[[nodiscard]] auto speed_limit(tr_direction const dir) const noexcept
{
auto const kbyps = dir == TR_DOWN ? speed_down_kbyps_ : speed_up_kbyps_;
auto const kbyps = dir == TR_DOWN ? settings().speed_down_kbyps : settings().speed_up_kbyps;
return Speed{ kbyps, Speed::Units::KByps };
}
@ -124,11 +155,11 @@ public:
{
if (dir == TR_DOWN)
{
speed_down_kbyps_ = limit.count(Speed::Units::KByps);
settings_.speed_down_kbyps = limit.count(Speed::Units::KByps);
}
else
{
speed_up_kbyps_ = limit.count(Speed::Units::KByps);
settings_.speed_up_kbyps = limit.count(Speed::Units::KByps);
}
}
@ -137,6 +168,8 @@ public:
private:
Mediator& mediator_;
Settings settings_;
void update_scheduler();
void update_minutes();
@ -154,8 +187,4 @@ private:
// recent change that was made by the scheduler
std::optional<bool> scheduler_set_is_active_to_;
#define V(key, name, type, default_value, comment) type name = type{ default_value };
ALT_SPEEDS_FIELDS(V)
#undef V
};

View File

@ -1,44 +0,0 @@
// This file Copyright © Mnemosyne LLC.
// It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
// or any future license endorsed by Mnemosyne LLC.
// License text can be found in the licenses/ folder.
#include <utility> // std::move()
#include "libtransmission/session-settings.h"
#include "libtransmission/variant.h"
void tr_session_settings::load(tr_variant const& src)
{
auto const* map = src.get_if<tr_variant::Map>();
if (map == nullptr)
{
return;
}
#define V(key, field, type, default_value, comment) \
if (auto const iter = map->find(key); iter != std::end(*map)) \
{ \
if (auto val = libtransmission::VariantConverter::load<decltype(field)>(iter->second); val) \
{ \
this->field = *val; \
} \
}
SESSION_SETTINGS_FIELDS(V)
#undef V
}
tr_variant tr_session_settings::settings() const
{
auto map = tr_variant::Map{};
#define V(key, field, type, default_value, comment) \
map.try_emplace(key, libtransmission::VariantConverter::save<decltype(field)>(field));
SESSION_SETTINGS_FIELDS(V)
#undef V
return tr_variant{ std::move(map) };
}
tr_variant tr_session_settings::default_settings()
{
return tr_session_settings{}.settings();
}

View File

@ -1,101 +0,0 @@
// This file Copyright © Mnemosyne LLC.
// It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
// or any future license endorsed by Mnemosyne LLC.
// License text can be found in the licenses/ folder.
#pragma once
#include <chrono> // for tr_sleep_per_seconds_during_verify
#include <cstddef> // for size_t
#include <string>
#include "libtransmission/transmission.h"
#include "libtransmission/log.h" // for tr_log_level
#include "libtransmission/net.h" // for tr_port, tr_tos_t
#include "libtransmission/open-files.h" // for tr_open_files::Preallocation
#include "libtransmission/peer-io.h" // tr_preferred_transport
#include "libtransmission/quark.h"
struct tr_variant;
#define SESSION_SETTINGS_FIELDS(V) \
V(TR_KEY_announce_ip, announce_ip, std::string, "", "") \
V(TR_KEY_announce_ip_enabled, announce_ip_enabled, bool, false, "") \
V(TR_KEY_bind_address_ipv4, bind_address_ipv4, std::string, "", "") \
V(TR_KEY_bind_address_ipv6, bind_address_ipv6, std::string, "", "") \
V(TR_KEY_blocklist_enabled, blocklist_enabled, bool, false, "") \
V(TR_KEY_blocklist_url, blocklist_url, std::string, "http://www.example.com/blocklist", "") \
V(TR_KEY_cache_size_mb, cache_size_mbytes, size_t, 4U, "") \
V(TR_KEY_default_trackers, default_trackers_str, std::string, "", "") \
V(TR_KEY_dht_enabled, dht_enabled, bool, true, "") \
V(TR_KEY_download_dir, download_dir, std::string, tr_getDefaultDownloadDir(), "") \
V(TR_KEY_download_queue_enabled, download_queue_enabled, bool, true, "") \
V(TR_KEY_download_queue_size, download_queue_size, size_t, 5U, "") \
V(TR_KEY_encryption, encryption_mode, tr_encryption_mode, TR_ENCRYPTION_PREFERRED, "") \
V(TR_KEY_idle_seeding_limit, idle_seeding_limit_minutes, size_t, 30U, "") \
V(TR_KEY_idle_seeding_limit_enabled, idle_seeding_limit_enabled, bool, false, "") \
V(TR_KEY_incomplete_dir, incomplete_dir, std::string, tr_getDefaultDownloadDir(), "") \
V(TR_KEY_incomplete_dir_enabled, incomplete_dir_enabled, bool, false, "") \
V(TR_KEY_lpd_enabled, lpd_enabled, bool, true, "") \
V(TR_KEY_message_level, log_level, tr_log_level, TR_LOG_INFO, "") \
V(TR_KEY_peer_congestion_algorithm, peer_congestion_algorithm, std::string, "", "") \
V(TR_KEY_peer_limit_global, peer_limit_global, size_t, TR_DEFAULT_PEER_LIMIT_GLOBAL, "") \
V(TR_KEY_peer_limit_per_torrent, peer_limit_per_torrent, size_t, TR_DEFAULT_PEER_LIMIT_TORRENT, "") \
V(TR_KEY_peer_port, \
peer_port, \
tr_port, \
tr_port::from_host(TR_DEFAULT_PEER_PORT), \
"The local machine's incoming peer port") \
V(TR_KEY_peer_port_random_high, peer_port_random_high, tr_port, tr_port::from_host(65535), "") \
V(TR_KEY_peer_port_random_low, peer_port_random_low, tr_port, tr_port::from_host(49152), "") \
V(TR_KEY_peer_port_random_on_start, peer_port_random_on_start, bool, false, "") \
V(TR_KEY_peer_socket_tos, peer_socket_tos, tr_tos_t, 0x04, "") \
V(TR_KEY_pex_enabled, pex_enabled, bool, true, "") \
V(TR_KEY_port_forwarding_enabled, port_forwarding_enabled, bool, true, "") \
V(TR_KEY_preallocation, preallocation_mode, tr_open_files::Preallocation, tr_open_files::Preallocation::Sparse, "") \
V(TR_KEY_queue_stalled_enabled, queue_stalled_enabled, bool, true, "") \
V(TR_KEY_queue_stalled_minutes, queue_stalled_minutes, size_t, 30U, "") \
V(TR_KEY_ratio_limit, ratio_limit, double, 2.0, "") \
V(TR_KEY_ratio_limit_enabled, ratio_limit_enabled, bool, false, "") \
V(TR_KEY_rename_partial_files, is_incomplete_file_naming_enabled, bool, false, "") \
V(TR_KEY_scrape_paused_torrents_enabled, should_scrape_paused_torrents, bool, true, "") \
V(TR_KEY_script_torrent_added_enabled, script_torrent_added_enabled, bool, false, "") \
V(TR_KEY_script_torrent_added_filename, script_torrent_added_filename, std::string, "", "") \
V(TR_KEY_script_torrent_done_enabled, script_torrent_done_enabled, bool, false, "") \
V(TR_KEY_script_torrent_done_filename, script_torrent_done_filename, std::string, "", "") \
V(TR_KEY_script_torrent_done_seeding_enabled, script_torrent_done_seeding_enabled, bool, false, "") \
V(TR_KEY_script_torrent_done_seeding_filename, script_torrent_done_seeding_filename, std::string, "", "") \
V(TR_KEY_seed_queue_enabled, seed_queue_enabled, bool, false, "") \
V(TR_KEY_seed_queue_size, seed_queue_size, size_t, 10U, "") \
V(TR_KEY_sleep_per_seconds_during_verify, sleep_per_seconds_during_verify, std::chrono::milliseconds, 100, "") \
V(TR_KEY_speed_limit_down, speed_limit_down, size_t, 100U, "") \
V(TR_KEY_speed_limit_down_enabled, speed_limit_down_enabled, bool, false, "") \
V(TR_KEY_speed_limit_up, speed_limit_up, size_t, 100U, "") \
V(TR_KEY_speed_limit_up_enabled, speed_limit_up_enabled, bool, false, "") \
V(TR_KEY_start_added_torrents, should_start_added_torrents, bool, true, "") \
V(TR_KEY_tcp_enabled, tcp_enabled, bool, true, "") \
V(TR_KEY_trash_original_torrent_files, should_delete_source_torrents, bool, false, "") \
V(TR_KEY_umask, umask, tr_mode_t, 022, "") \
V(TR_KEY_upload_slots_per_torrent, upload_slots_per_torrent, size_t, 8U, "") \
V(TR_KEY_utp_enabled, utp_enabled, bool, true, "") \
V(TR_KEY_preferred_transport, preferred_transport, tr_preferred_transport, TR_PREFER_UTP, "") \
V(TR_KEY_torrent_added_verify_mode, torrent_added_verify_mode, tr_verify_added_mode, TR_VERIFY_ADDED_FAST, "")
struct tr_session_settings
{
tr_session_settings() = default;
explicit tr_session_settings(tr_variant const& src)
{
load(src);
}
void load(tr_variant const& src);
[[nodiscard]] tr_variant settings() const;
[[nodiscard]] static tr_variant default_settings();
#define V(key, name, type, default_value, comment) type name = type{ default_value };
SESSION_SETTINGS_FIELDS(V)
#undef V
};

View File

@ -46,7 +46,6 @@
#include "libtransmission/rpc-server.h"
#include "libtransmission/session.h"
#include "libtransmission/session-alt-speeds.h"
#include "libtransmission/session-settings.h"
#include "libtransmission/timer-ev.h"
#include "libtransmission/torrent.h"
#include "libtransmission/torrent-ctor.h"
@ -461,17 +460,17 @@ tr_variant tr_sessionGetDefaultSettings()
{
auto ret = tr_variant::make_map();
ret.merge(tr_rpc_server::Settings{}.save());
ret.merge(tr_session_alt_speeds::default_settings());
ret.merge(tr_session_settings::default_settings());
ret.merge(tr_session_alt_speeds::Settings{}.save());
ret.merge(tr_session::Settings{}.save());
return ret;
}
tr_variant tr_sessionGetSettings(tr_session const* session)
{
auto settings = tr_variant::make_map();
settings.merge(session->alt_speeds_.settings());
settings.merge(session->alt_speeds_.settings().save());
settings.merge(session->rpc_server_->settings().save());
settings.merge(session->settings_.settings());
settings.merge(session->settings_.save());
tr_variantDictAddInt(&settings, TR_KEY_message_level, tr_logGetLevel());
return settings;
}
@ -748,14 +747,14 @@ void tr_session::setSettings(tr_variant const& settings, bool force)
TR_ASSERT(am_in_session_thread());
TR_ASSERT(settings.holds_alternative<tr_variant::Map>());
setSettings(tr_session_settings{ settings }, force);
setSettings(tr_session::Settings{ settings }, force);
// delegate loading out the other settings
alt_speeds_.load(settings);
alt_speeds_.load(tr_session_alt_speeds::Settings{ settings });
rpc_server_->load(tr_rpc_server::Settings{ settings });
}
void tr_session::setSettings(tr_session_settings&& settings_in, bool force)
void tr_session::setSettings(tr_session::Settings&& settings_in, bool force)
{
auto const lock = unique_lock();

View File

@ -45,15 +45,17 @@
#include "libtransmission/cache.h"
#include "libtransmission/global-ip-cache.h"
#include "libtransmission/interned-string.h"
#include "libtransmission/net.h" // tr_socket_t
#include "libtransmission/log.h" // for tr_log_level
#include "libtransmission/net.h" // for tr_port, tr_tos_t
#include "libtransmission/open-files.h"
#include "libtransmission/peer-io.h" // tr_preferred_transport
#include "libtransmission/port-forwarding.h"
#include "libtransmission/quark.h"
#include "libtransmission/rpc-server.h"
#include "libtransmission/session-alt-speeds.h"
#include "libtransmission/session-id.h"
#include "libtransmission/session-settings.h"
#include "libtransmission/session-thread.h"
#include "libtransmission/settings.h"
#include "libtransmission/stats.h"
#include "libtransmission/timer.h"
#include "libtransmission/torrents.h"
@ -349,6 +351,142 @@ private:
};
public:
struct Settings : public libtransmission::Settings
{
public:
Settings() = default;
virtual ~Settings() = default;
explicit Settings(tr_variant const& src)
{
load(src);
}
// NB: When adding a field here, you must also add it to
// fields() if you want it to be in session-settings.json
bool announce_ip_enabled = false;
bool blocklist_enabled = false;
bool dht_enabled = true;
bool download_queue_enabled = true;
bool idle_seeding_limit_enabled = false;
bool incomplete_dir_enabled = false;
bool is_incomplete_file_naming_enabled = false;
bool lpd_enabled = true;
bool peer_port_random_on_start = false;
bool pex_enabled = true;
bool port_forwarding_enabled = true;
bool queue_stalled_enabled = true;
bool ratio_limit_enabled = false;
bool script_torrent_added_enabled = false;
bool script_torrent_done_enabled = false;
bool script_torrent_done_seeding_enabled = false;
bool seed_queue_enabled = false;
bool should_delete_source_torrents = false;
bool should_scrape_paused_torrents = true;
bool should_start_added_torrents = true;
bool speed_limit_down_enabled = false;
bool speed_limit_up_enabled = false;
bool tcp_enabled = true;
bool utp_enabled = true;
double ratio_limit = 2.0;
size_t cache_size_mbytes = 4U;
size_t download_queue_size = 5U;
size_t idle_seeding_limit_minutes = 30U;
size_t peer_limit_global = TR_DEFAULT_PEER_LIMIT_GLOBAL;
size_t peer_limit_per_torrent = TR_DEFAULT_PEER_LIMIT_TORRENT;
size_t queue_stalled_minutes = 30U;
size_t seed_queue_size = 10U;
size_t speed_limit_down = 100U;
size_t speed_limit_up = 100U;
size_t upload_slots_per_torrent = 8U;
std::chrono::milliseconds sleep_per_seconds_during_verify = std::chrono::milliseconds{ 100 };
std::string announce_ip;
std::string bind_address_ipv4;
std::string bind_address_ipv6;
std::string blocklist_url = "http://www.example.com/blocklist";
std::string default_trackers_str;
std::string download_dir = tr_getDefaultDownloadDir();
std::string incomplete_dir = tr_getDefaultDownloadDir();
std::string peer_congestion_algorithm;
std::string script_torrent_added_filename;
std::string script_torrent_done_filename;
std::string script_torrent_done_seeding_filename;
tr_encryption_mode encryption_mode = TR_ENCRYPTION_PREFERRED;
tr_log_level log_level = TR_LOG_INFO;
tr_mode_t umask = 022;
tr_open_files::Preallocation preallocation_mode = tr_open_files::Preallocation::Sparse;
tr_port peer_port_random_high = tr_port::from_host(65535);
tr_port peer_port_random_low = tr_port::from_host(49152);
tr_port peer_port = tr_port::from_host(TR_DEFAULT_PEER_PORT);
tr_preferred_transport preferred_transport = TR_PREFER_UTP;
tr_tos_t peer_socket_tos{ 0x04 };
tr_verify_added_mode torrent_added_verify_mode = TR_VERIFY_ADDED_FAST;
private:
[[nodiscard]] Fields fields() override
{
return {
{ TR_KEY_announce_ip, &announce_ip },
{ TR_KEY_announce_ip_enabled, &announce_ip_enabled },
{ TR_KEY_bind_address_ipv4, &bind_address_ipv4 },
{ TR_KEY_bind_address_ipv6, &bind_address_ipv6 },
{ TR_KEY_blocklist_enabled, &blocklist_enabled },
{ TR_KEY_blocklist_url, &blocklist_url },
{ TR_KEY_cache_size_mb, &cache_size_mbytes },
{ TR_KEY_default_trackers, &default_trackers_str },
{ TR_KEY_dht_enabled, &dht_enabled },
{ TR_KEY_download_dir, &download_dir },
{ TR_KEY_download_queue_enabled, &download_queue_enabled },
{ TR_KEY_download_queue_size, &download_queue_size },
{ TR_KEY_encryption, &encryption_mode },
{ TR_KEY_idle_seeding_limit, &idle_seeding_limit_minutes },
{ TR_KEY_idle_seeding_limit_enabled, &idle_seeding_limit_enabled },
{ TR_KEY_incomplete_dir, &incomplete_dir },
{ TR_KEY_incomplete_dir_enabled, &incomplete_dir_enabled },
{ TR_KEY_lpd_enabled, &lpd_enabled },
{ TR_KEY_message_level, &log_level },
{ TR_KEY_peer_congestion_algorithm, &peer_congestion_algorithm },
{ TR_KEY_peer_limit_global, &peer_limit_global },
{ TR_KEY_peer_limit_per_torrent, &peer_limit_per_torrent },
{ TR_KEY_peer_port, &peer_port },
{ TR_KEY_peer_port_random_high, &peer_port_random_high },
{ TR_KEY_peer_port_random_low, &peer_port_random_low },
{ TR_KEY_peer_port_random_on_start, &peer_port_random_on_start },
{ TR_KEY_peer_socket_tos, &peer_socket_tos },
{ TR_KEY_pex_enabled, &pex_enabled },
{ TR_KEY_port_forwarding_enabled, &port_forwarding_enabled },
{ TR_KEY_preallocation, &preallocation_mode },
{ TR_KEY_preferred_transport, &preferred_transport },
{ TR_KEY_queue_stalled_enabled, &queue_stalled_enabled },
{ TR_KEY_queue_stalled_minutes, &queue_stalled_minutes },
{ TR_KEY_ratio_limit, &ratio_limit },
{ TR_KEY_ratio_limit_enabled, &ratio_limit_enabled },
{ TR_KEY_rename_partial_files, &is_incomplete_file_naming_enabled },
{ TR_KEY_scrape_paused_torrents_enabled, &should_scrape_paused_torrents },
{ TR_KEY_script_torrent_added_enabled, &script_torrent_added_enabled },
{ TR_KEY_script_torrent_added_filename, &script_torrent_added_filename },
{ TR_KEY_script_torrent_done_enabled, &script_torrent_done_enabled },
{ TR_KEY_script_torrent_done_filename, &script_torrent_done_filename },
{ TR_KEY_script_torrent_done_seeding_enabled, &script_torrent_done_seeding_enabled },
{ TR_KEY_script_torrent_done_seeding_filename, &script_torrent_done_seeding_filename },
{ TR_KEY_seed_queue_enabled, &seed_queue_enabled },
{ TR_KEY_seed_queue_size, &seed_queue_size },
{ TR_KEY_sleep_per_seconds_during_verify, &sleep_per_seconds_during_verify },
{ TR_KEY_speed_limit_down, &speed_limit_down },
{ TR_KEY_speed_limit_down_enabled, &speed_limit_down_enabled },
{ TR_KEY_speed_limit_up, &speed_limit_up },
{ TR_KEY_speed_limit_up_enabled, &speed_limit_up_enabled },
{ TR_KEY_start_added_torrents, &should_start_added_torrents },
{ TR_KEY_tcp_enabled, &tcp_enabled },
{ TR_KEY_torrent_added_verify_mode, &torrent_added_verify_mode },
{ TR_KEY_trash_original_torrent_files, &should_delete_source_torrents },
{ TR_KEY_umask, &umask },
{ TR_KEY_upload_slots_per_torrent, &upload_slots_per_torrent },
{ TR_KEY_utp_enabled, &utp_enabled },
};
}
};
explicit tr_session(std::string_view config_dir, tr_variant const& settings_dict);
[[nodiscard]] std::string_view sessionId() const noexcept
@ -398,6 +536,11 @@ public:
return std::unique_lock(session_mutex_);
}
[[nodiscard]] constexpr auto const& settings() const noexcept
{
return settings_;
}
// paths
[[nodiscard]] constexpr auto const& configDir() const noexcept
@ -417,7 +560,7 @@ public:
[[nodiscard]] constexpr auto const& downloadDir() const noexcept
{
return settings_.download_dir;
return settings().download_dir;
}
void setDownloadDir(std::string_view dir)
@ -430,7 +573,7 @@ public:
[[nodiscard]] constexpr auto const& defaultTrackersStr() const noexcept
{
return settings_.default_trackers_str;
return settings().default_trackers_str;
}
[[nodiscard]] constexpr auto const& defaultTrackers() const noexcept
@ -444,7 +587,7 @@ public:
[[nodiscard]] constexpr auto const& incompleteDir() const noexcept
{
return settings_.incomplete_dir;
return settings().incomplete_dir;
}
void setIncompleteDir(std::string_view dir)
@ -454,7 +597,7 @@ public:
[[nodiscard]] constexpr auto useIncompleteDir() const noexcept
{
return settings_.incomplete_dir_enabled;
return settings().incomplete_dir_enabled;
}
constexpr void useIncompleteDir(bool enabled) noexcept
@ -499,12 +642,12 @@ public:
[[nodiscard]] auto blocklist_enabled() const noexcept
{
return settings_.blocklist_enabled;
return settings().blocklist_enabled;
}
[[nodiscard]] constexpr auto const& blocklistUrl() const noexcept
{
return settings_.blocklist_url;
return settings().blocklist_url;
}
void setBlocklistUrl(std::string_view url)
@ -524,7 +667,7 @@ public:
[[nodiscard]] constexpr auto const& peerCongestionAlgorithm() const noexcept
{
return settings_.peer_congestion_algorithm;
return settings().peer_congestion_algorithm;
}
void setPeerCongestionAlgorithm(std::string_view algorithm)
@ -539,12 +682,12 @@ public:
[[nodiscard]] constexpr auto peerLimit() const noexcept
{
return settings_.peer_limit_global;
return settings().peer_limit_global;
}
[[nodiscard]] constexpr auto peerLimitPerTorrent() const noexcept
{
return settings_.peer_limit_per_torrent;
return settings().peer_limit_per_torrent;
}
// bandwidth
@ -565,7 +708,7 @@ public:
[[nodiscard]] constexpr std::string const& announceIP() const noexcept
{
return settings_.announce_ip;
return settings().announce_ip;
}
void setAnnounceIP(std::string_view ip)
@ -575,7 +718,7 @@ public:
[[nodiscard]] constexpr bool useAnnounceIP() const noexcept
{
return settings_.announce_ip_enabled;
return settings().announce_ip_enabled;
}
constexpr void useAnnounceIP(bool enabled) noexcept
@ -712,17 +855,17 @@ public:
[[nodiscard]] constexpr auto queueStalledEnabled() const noexcept
{
return settings_.queue_stalled_enabled;
return settings().queue_stalled_enabled;
}
[[nodiscard]] constexpr auto queueStalledMinutes() const noexcept
{
return settings_.queue_stalled_minutes;
return settings().queue_stalled_minutes;
}
[[nodiscard]] constexpr auto uploadSlotsPerTorrent() const noexcept
{
return settings_.upload_slots_per_torrent;
return settings().upload_slots_per_torrent;
}
[[nodiscard]] constexpr auto isClosing() const noexcept
@ -732,17 +875,17 @@ public:
[[nodiscard]] constexpr auto encryptionMode() const noexcept
{
return settings_.encryption_mode;
return settings().encryption_mode;
}
[[nodiscard]] constexpr auto preallocationMode() const noexcept
{
return settings_.preallocation_mode;
return settings().preallocation_mode;
}
[[nodiscard]] constexpr auto shouldScrapePausedTorrents() const noexcept
{
return settings_.should_scrape_paused_torrents;
return settings().should_scrape_paused_torrents;
}
[[nodiscard]] constexpr auto shouldPauseAddedTorrents() const noexcept
@ -752,49 +895,49 @@ public:
[[nodiscard]] constexpr auto shouldFullyVerifyAddedTorrents() const noexcept
{
return settings_.torrent_added_verify_mode == TR_VERIFY_ADDED_FULL;
return settings().torrent_added_verify_mode == TR_VERIFY_ADDED_FULL;
}
[[nodiscard]] constexpr auto shouldDeleteSource() const noexcept
{
return settings_.should_delete_source_torrents;
return settings().should_delete_source_torrents;
}
[[nodiscard]] constexpr auto allowsDHT() const noexcept
{
return settings_.dht_enabled;
return settings().dht_enabled;
}
[[nodiscard]] constexpr bool allowsLPD() const noexcept
{
return settings_.lpd_enabled;
return settings().lpd_enabled;
}
[[nodiscard]] constexpr auto allows_pex() const noexcept
{
return settings_.pex_enabled;
return settings().pex_enabled;
}
[[nodiscard]] constexpr auto allowsTCP() const noexcept
{
return settings_.tcp_enabled;
return settings().tcp_enabled;
}
[[nodiscard]] bool allowsUTP() const noexcept;
[[nodiscard]] constexpr auto preferred_transport() const noexcept
{
return settings_.preferred_transport;
return settings().preferred_transport;
}
[[nodiscard]] constexpr auto isIdleLimited() const noexcept
{
return settings_.idle_seeding_limit_enabled;
return settings().idle_seeding_limit_enabled;
}
[[nodiscard]] constexpr auto idleLimitMinutes() const noexcept
{
return settings_.idle_seeding_limit_minutes;
return settings().idle_seeding_limit_minutes;
}
/*module_visible*/
@ -863,22 +1006,22 @@ public:
[[nodiscard]] constexpr auto isIncompleteFileNamingEnabled() const noexcept
{
return settings_.is_incomplete_file_naming_enabled;
return settings().is_incomplete_file_naming_enabled;
}
[[nodiscard]] constexpr auto isPortRandom() const noexcept
{
return settings_.peer_port_random_on_start;
return settings().peer_port_random_on_start;
}
[[nodiscard]] constexpr auto isRatioLimited() const noexcept
{
return settings_.ratio_limit_enabled;
return settings().ratio_limit_enabled;
}
[[nodiscard]] constexpr auto desiredRatio() const noexcept
{
return settings_.ratio_limit;
return settings().ratio_limit;
}
void verify_add(tr_torrent* tor);
@ -949,7 +1092,7 @@ private:
struct init_data;
void initImpl(init_data&);
void setSettings(tr_variant const& settings_map, bool force);
void setSettings(tr_session_settings&& settings, bool force);
void setSettings(Settings&& settings, bool force);
void closeImplPart1(std::promise<void>* closed_promise, std::chrono::time_point<std::chrono::steady_clock> deadline);
void closeImplPart2(std::promise<void>* closed_promise, std::chrono::time_point<std::chrono::steady_clock> deadline);
@ -1054,7 +1197,7 @@ private:
/// trivial type fields
tr_session_settings settings_;
Settings settings_;
queue_start_callback_t queue_start_callback_ = nullptr;
void* queue_start_user_data_ = nullptr;

View File

@ -3,15 +3,460 @@
// or any future license endorsed by Mnemosyne LLC.
// License text can be found in the licenses/ folder.
#include <array>
#include <cstddef> // size_t
#include <cstdint> // int64_t, uint32_t
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <variant>
#include <fmt/core.h>
#include "libtransmission/transmission.h"
#include "libtransmission/log.h" // for tr_log_level
#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/settings.h"
#include "libtransmission/utils.h" // for tr_strv_strip(), tr_strlower()
#include "libtransmission/variant.h"
using namespace std::literals;
namespace libtransmission
{
namespace
{
struct VariantConverter
{
public:
template<typename T>
static std::optional<T> load(tr_variant const& src);
template<typename T>
static tr_variant save(T const& val);
private:
template<typename T, size_t N>
using Lookup = std::array<std::pair<std::string_view, T>, N>;
static auto constexpr EncryptionKeys = Lookup<tr_encryption_mode, 3U>{ {
{ "required", TR_ENCRYPTION_REQUIRED },
{ "preferred", TR_ENCRYPTION_PREFERRED },
{ "allowed", TR_CLEAR_PREFERRED },
} };
static auto constexpr LogKeys = Lookup<tr_log_level, 7U>{ {
{ "critical", TR_LOG_CRITICAL },
{ "debug", TR_LOG_DEBUG },
{ "error", TR_LOG_ERROR },
{ "info", TR_LOG_INFO },
{ "off", TR_LOG_OFF },
{ "trace", TR_LOG_TRACE },
{ "warn", TR_LOG_WARN },
} };
static auto constexpr PreallocationKeys = Lookup<tr_open_files::Preallocation, 5U>{ {
{ "off", tr_open_files::Preallocation::None },
{ "none", tr_open_files::Preallocation::None },
{ "fast", tr_open_files::Preallocation::Sparse },
{ "sparse", tr_open_files::Preallocation::Sparse },
{ "full", tr_open_files::Preallocation::Full },
} };
static auto constexpr VerifyModeKeys = Lookup<tr_verify_added_mode, 2U>{ {
{ "fast", TR_VERIFY_ADDED_FAST },
{ "full", TR_VERIFY_ADDED_FULL },
} };
static auto constexpr PreferredTransportKeys = Lookup<tr_preferred_transport, TR_NUM_PREFERRED_TRANSPORT>{ {
{ "utp", TR_PREFER_UTP },
{ "tcp", TR_PREFER_TCP },
} };
};
template<>
std::optional<bool> VariantConverter::load(tr_variant const& src)
{
if (auto val = src.get_if<bool>(); val != nullptr)
{
return *val;
}
return {};
}
template<>
tr_variant VariantConverter::save(bool const& val)
{
return val;
}
// ---
template<>
std::optional<std::chrono::milliseconds> VariantConverter::load(tr_variant const& src)
{
if (auto val = src.get_if<int64_t>(); val != nullptr)
{
return std::chrono::milliseconds(*val);
}
return {};
}
template<>
tr_variant VariantConverter::save(std::chrono::milliseconds const& val)
{
return val.count();
}
// ---
template<>
std::optional<double> VariantConverter::load(tr_variant const& src)
{
if (auto val = src.get_if<double>(); val != nullptr)
{
return *val;
}
return {};
}
template<>
tr_variant VariantConverter::save(double const& val)
{
return val;
}
// ---
template<>
std::optional<tr_encryption_mode> VariantConverter::load(tr_variant const& src)
{
static constexpr auto Keys = EncryptionKeys;
if (auto const* val = src.get_if<std::string_view>(); val != nullptr)
{
auto const needle = tr_strlower(tr_strv_strip(*val));
for (auto const& [key, encryption] : Keys)
{
if (key == needle)
{
return encryption;
}
}
}
if (auto const* val = src.get_if<int64_t>(); val != nullptr)
{
for (auto const& [key, encryption] : Keys)
{
if (encryption == *val)
{
return encryption;
}
}
}
return {};
}
template<>
tr_variant VariantConverter::save(tr_encryption_mode const& val)
{
return static_cast<int64_t>(val);
}
// ---
template<>
std::optional<tr_log_level> VariantConverter::load(tr_variant const& src)
{
static constexpr auto Keys = LogKeys;
if (auto const* val = src.get_if<std::string_view>(); val != nullptr)
{
auto const needle = tr_strlower(tr_strv_strip(*val));
for (auto const& [name, log_level] : Keys)
{
if (needle == name)
{
return log_level;
}
}
}
if (auto const* val = src.get_if<int64_t>(); val != nullptr)
{
for (auto const& [name, log_level] : Keys)
{
if (log_level == *val)
{
return log_level;
}
}
}
return {};
}
template<>
tr_variant VariantConverter::save(tr_log_level const& val)
{
return static_cast<int64_t>(val);
}
// ---
template<>
std::optional<tr_mode_t> VariantConverter::load(tr_variant const& src)
{
if (auto const* val = src.get_if<std::string_view>(); val != nullptr)
{
if (auto const mode = tr_num_parse<uint32_t>(*val, nullptr, 8); mode)
{
return static_cast<tr_mode_t>(*mode);
}
}
if (auto const* val = src.get_if<int64_t>(); val != nullptr)
{
return static_cast<tr_mode_t>(*val);
}
return {};
}
template<>
tr_variant VariantConverter::save(tr_mode_t const& val)
{
return fmt::format("{:#03o}", val);
}
// ---
template<>
std::optional<tr_port> VariantConverter::load(tr_variant const& src)
{
if (auto const* val = src.get_if<int64_t>(); val != nullptr)
{
return tr_port::from_host(*val);
}
return {};
}
template<>
tr_variant VariantConverter::save(tr_port const& val)
{
return int64_t{ val.host() };
}
// ---
template<>
std::optional<tr_open_files::Preallocation> VariantConverter::load(tr_variant const& src)
{
static constexpr auto Keys = PreallocationKeys;
if (auto const* val = src.get_if<std::string_view>(); val != nullptr)
{
auto const needle = tr_strlower(tr_strv_strip(*val));
for (auto const& [name, value] : Keys)
{
if (name == needle)
{
return value;
}
}
}
if (auto const* val = src.get_if<int64_t>(); val != nullptr)
{
for (auto const& [name, value] : Keys)
{
if (value == static_cast<tr_open_files::Preallocation>(*val))
{
return value;
}
}
}
return {};
}
template<>
tr_variant VariantConverter::save(tr_open_files::Preallocation const& val)
{
return static_cast<int64_t>(val);
}
// ---
template<>
std::optional<tr_preferred_transport> VariantConverter::load(tr_variant const& src)
{
static constexpr auto Keys = PreferredTransportKeys;
if (auto const* val = src.get_if<std::string_view>(); val != nullptr)
{
auto const needle = tr_strlower(tr_strv_strip(*val));
for (auto const& [name, value] : Keys)
{
if (name == needle)
{
return value;
}
}
}
if (auto const* val = src.get_if<int64_t>(); val != nullptr)
{
for (auto const& [name, value] : Keys)
{
if (value == *val)
{
return value;
}
}
}
return {};
}
template<>
tr_variant VariantConverter::save(tr_preferred_transport const& val)
{
for (auto const& [key, value] : PreferredTransportKeys)
{
if (value == val)
{
return key;
}
}
return static_cast<int64_t>(val);
}
// ---
template<>
std::optional<size_t> VariantConverter::load(tr_variant const& src)
{
if (auto const* val = src.get_if<int64_t>(); val != nullptr)
{
return static_cast<size_t>(*val);
}
return {};
}
template<>
tr_variant VariantConverter::save(size_t const& val)
{
return uint64_t{ val };
}
// ---
template<>
std::optional<std::string> VariantConverter::load(tr_variant const& src)
{
if (auto const* val = src.get_if<std::string_view>(); val != nullptr)
{
return std::string{ *val };
}
return {};
}
template<>
tr_variant VariantConverter::save(std::string const& val)
{
return val;
}
// ---
template<>
std::optional<tr_tos_t> VariantConverter::load(tr_variant const& src)
{
if (auto const* val = src.get_if<std::string_view>(); val != nullptr)
{
return tr_tos_t::from_string(*val);
}
if (auto const* val = src.get_if<int64_t>(); val != nullptr)
{
return tr_tos_t{ static_cast<int>(*val) };
}
return {};
}
template<>
tr_variant VariantConverter::save(tr_tos_t const& val)
{
return val.toString();
}
// ---
template<>
std::optional<tr_verify_added_mode> VariantConverter::load(tr_variant const& src)
{
static constexpr auto& Keys = VerifyModeKeys;
if (auto const* val = src.get_if<std::string_view>(); val != nullptr)
{
auto const needle = tr_strlower(tr_strv_strip(*val));
for (auto const& [name, value] : Keys)
{
if (name == needle)
{
return value;
}
}
}
if (auto const* val = src.get_if<int64_t>(); val != nullptr)
{
for (auto const& [name, value] : Keys)
{
if (value == *val)
{
return value;
}
}
}
return {};
}
template<>
tr_variant VariantConverter::save(tr_verify_added_mode const& val)
{
for (auto const& [key, value] : VerifyModeKeys)
{
if (value == val)
{
return key;
}
}
return static_cast<int64_t>(val);
}
struct LoadVisitor
{
explicit constexpr LoadVisitor(tr_variant const& src)
@ -43,7 +488,7 @@ struct SaveVisitor
template<typename T>
void operator()(T const* const src)
{
tgt_.try_emplace(key_, VariantConverter::save<T>(*src));
tgt_.try_emplace(key_, VariantConverter::save(*src));
}
private:
@ -73,8 +518,7 @@ tr_variant Settings::save() const
{
auto const fields = const_cast<Settings*>(this)->fields();
auto map = tr_variant::Map{};
map.reserve(std::size(fields));
auto map = tr_variant::Map{ std::size(fields) };
for (auto const& [key, prop_vptr] : fields)
{

View File

@ -5,6 +5,7 @@
#pragma once
#include <chrono>
#include <cstddef> // for size_t
#include <string>
#include <utility>
@ -36,6 +37,7 @@ protected:
bool*,
double*,
size_t*,
std::chrono::milliseconds*,
std::string*,
tr_encryption_mode*,
tr_log_level*,

View File

@ -1,445 +0,0 @@
// This file Copyright © Mnemosyne LLC.
// It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
// or any future license endorsed by Mnemosyne LLC.
// License text can be found in the licenses/ folder.
#include <array>
#include <cstddef> // size_t
#include <cstdint> // int64_t, uint32_t
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <chrono> //std::chrono::milliseconds
#include <fmt/core.h>
#include "libtransmission/transmission.h"
#include "libtransmission/log.h" // for tr_log_level
#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/utils.h" // for tr_strv_strip(), tr_strlower()
#include "libtransmission/variant.h"
using namespace std::literals;
namespace
{
auto constexpr EncryptionKeys = std::array<std::pair<std::string_view, tr_encryption_mode>, 3>{ {
{ "required", TR_ENCRYPTION_REQUIRED },
{ "preferred", TR_ENCRYPTION_PREFERRED },
{ "allowed", TR_CLEAR_PREFERRED },
} };
auto constexpr LogKeys = std::array<std::pair<std::string_view, tr_log_level>, 7>{ {
{ "critical", TR_LOG_CRITICAL },
{ "debug", TR_LOG_DEBUG },
{ "error", TR_LOG_ERROR },
{ "info", TR_LOG_INFO },
{ "off", TR_LOG_OFF },
{ "trace", TR_LOG_TRACE },
{ "warn", TR_LOG_WARN },
} };
auto constexpr PreallocationKeys = std::array<std::pair<std::string_view, tr_open_files::Preallocation>, 5>{ {
{ "off", tr_open_files::Preallocation::None },
{ "none", tr_open_files::Preallocation::None },
{ "fast", tr_open_files::Preallocation::Sparse },
{ "sparse", tr_open_files::Preallocation::Sparse },
{ "full", tr_open_files::Preallocation::Full },
} };
auto constexpr VerifyModeKeys = std::array<std::pair<std::string_view, tr_verify_added_mode>, 2>{ {
{ "fast", TR_VERIFY_ADDED_FAST },
{ "full", TR_VERIFY_ADDED_FULL },
} };
auto constexpr PreferredTransportKeys = std::
array<std::pair<std::string_view, tr_preferred_transport>, TR_NUM_PREFERRED_TRANSPORT>{ {
{ "utp", TR_PREFER_UTP },
{ "tcp", TR_PREFER_TCP },
} };
} // namespace
namespace libtransmission
{
template<>
std::optional<bool> VariantConverter::load<bool>(tr_variant const& src)
{
if (auto val = src.get_if<bool>(); val != nullptr)
{
return *val;
}
return {};
}
template<>
tr_variant VariantConverter::save<bool>(bool const& val)
{
return val;
}
// ---
template<>
std::optional<double> VariantConverter::load<double>(tr_variant const& src)
{
if (auto val = src.get_if<double>(); val != nullptr)
{
return *val;
}
return {};
}
template<>
tr_variant VariantConverter::save<double>(double const& val)
{
return val;
}
// ---
template<>
std::optional<tr_encryption_mode> VariantConverter::load<tr_encryption_mode>(tr_variant const& src)
{
static constexpr auto Keys = EncryptionKeys;
if (auto const* val = src.get_if<std::string_view>(); val != nullptr)
{
auto const needle = tr_strlower(tr_strv_strip(*val));
for (auto const& [key, encryption] : Keys)
{
if (key == needle)
{
return encryption;
}
}
}
if (auto const* val = src.get_if<int64_t>(); val != nullptr)
{
for (auto const& [key, encryption] : Keys)
{
if (encryption == *val)
{
return encryption;
}
}
}
return {};
}
template<>
tr_variant VariantConverter::save<tr_encryption_mode>(tr_encryption_mode const& val)
{
return static_cast<int64_t>(val);
}
// ---
template<>
std::optional<tr_log_level> VariantConverter::load<tr_log_level>(tr_variant const& src)
{
static constexpr auto Keys = LogKeys;
if (auto const* val = src.get_if<std::string_view>(); val != nullptr)
{
auto const needle = tr_strlower(tr_strv_strip(*val));
for (auto const& [name, log_level] : Keys)
{
if (needle == name)
{
return log_level;
}
}
}
if (auto const* val = src.get_if<int64_t>(); val != nullptr)
{
for (auto const& [name, log_level] : Keys)
{
if (log_level == *val)
{
return log_level;
}
}
}
return {};
}
template<>
tr_variant VariantConverter::save<tr_log_level>(tr_log_level const& val)
{
return static_cast<int64_t>(val);
}
// ---
template<>
std::optional<tr_mode_t> VariantConverter::load<tr_mode_t>(tr_variant const& src)
{
if (auto const* val = src.get_if<std::string_view>(); val != nullptr)
{
if (auto const mode = tr_num_parse<uint32_t>(*val, nullptr, 8); mode)
{
return static_cast<tr_mode_t>(*mode);
}
}
if (auto const* val = src.get_if<int64_t>(); val != nullptr)
{
return static_cast<tr_mode_t>(*val);
}
return {};
}
template<>
tr_variant VariantConverter::save<tr_mode_t>(tr_mode_t const& val)
{
return fmt::format("{:#03o}", val);
}
// ---
template<>
std::optional<tr_port> VariantConverter::load<tr_port>(tr_variant const& src)
{
if (auto const* val = src.get_if<int64_t>(); val != nullptr)
{
return tr_port::from_host(*val);
}
return {};
}
template<>
tr_variant VariantConverter::save<tr_port>(tr_port const& val)
{
return int64_t{ val.host() };
}
// ---
template<>
std::optional<tr_open_files::Preallocation> VariantConverter::load<tr_open_files::Preallocation>(tr_variant const& src)
{
static constexpr auto Keys = PreallocationKeys;
if (auto const* val = src.get_if<std::string_view>(); val != nullptr)
{
auto const needle = tr_strlower(tr_strv_strip(*val));
for (auto const& [name, value] : Keys)
{
if (name == needle)
{
return value;
}
}
}
if (auto const* val = src.get_if<int64_t>(); val != nullptr)
{
for (auto const& [name, value] : Keys)
{
if (value == static_cast<tr_open_files::Preallocation>(*val))
{
return value;
}
}
}
return {};
}
template<>
tr_variant VariantConverter::save<tr_open_files::Preallocation>(tr_open_files::Preallocation const& val)
{
return static_cast<int64_t>(val);
}
// ---
template<>
std::optional<tr_preferred_transport> VariantConverter::load<tr_preferred_transport>(tr_variant const& src)
{
static constexpr auto Keys = PreferredTransportKeys;
if (auto const* val = src.get_if<std::string_view>(); val != nullptr)
{
auto const needle = tr_strlower(tr_strv_strip(*val));
for (auto const& [name, value] : Keys)
{
if (name == needle)
{
return value;
}
}
}
if (auto const* val = src.get_if<int64_t>(); val != nullptr)
{
for (auto const& [name, value] : Keys)
{
if (value == *val)
{
return value;
}
}
}
return {};
}
template<>
tr_variant VariantConverter::save<tr_preferred_transport>(tr_preferred_transport const& val)
{
for (auto const& [key, value] : PreferredTransportKeys)
{
if (value == val)
{
return key;
}
}
return static_cast<int64_t>(val);
}
// ---
template<>
std::optional<size_t> VariantConverter::load<size_t>(tr_variant const& src)
{
if (auto const* val = src.get_if<int64_t>(); val != nullptr)
{
return static_cast<size_t>(*val);
}
return {};
}
template<>
tr_variant VariantConverter::save<size_t>(size_t const& val)
{
return uint64_t{ val };
}
// ---
template<>
std::optional<std::string> VariantConverter::load<std::string>(tr_variant const& src)
{
if (auto const* val = src.get_if<std::string_view>(); val != nullptr)
{
return std::string{ *val };
}
return {};
}
template<>
tr_variant VariantConverter::save<std::string>(std::string const& val)
{
return val;
}
// ---
template<>
std::optional<tr_tos_t> VariantConverter::load<tr_tos_t>(tr_variant const& src)
{
if (auto const* val = src.get_if<std::string_view>(); val != nullptr)
{
return tr_tos_t::from_string(*val);
}
if (auto const* val = src.get_if<int64_t>(); val != nullptr)
{
return tr_tos_t{ static_cast<int>(*val) };
}
return {};
}
template<>
tr_variant VariantConverter::save<tr_tos_t>(tr_tos_t const& val)
{
return val.toString();
}
// ---
template<>
std::optional<tr_verify_added_mode> VariantConverter::load<tr_verify_added_mode>(tr_variant const& src)
{
static constexpr auto& Keys = VerifyModeKeys;
if (auto const* val = src.get_if<std::string_view>(); val != nullptr)
{
auto const needle = tr_strlower(tr_strv_strip(*val));
for (auto const& [name, value] : Keys)
{
if (name == needle)
{
return value;
}
}
}
if (auto const* val = src.get_if<int64_t>(); val != nullptr)
{
for (auto const& [name, value] : Keys)
{
if (value == *val)
{
return value;
}
}
}
return {};
}
template<>
tr_variant VariantConverter::save<tr_verify_added_mode>(tr_verify_added_mode const& val)
{
for (auto const& [key, value] : VerifyModeKeys)
{
if (value == val)
{
return key;
}
}
return static_cast<int64_t>(val);
}
template<>
std::optional<std::chrono::milliseconds> VariantConverter::load<std::chrono::milliseconds>(tr_variant const& src)
{
if (auto val = src.get_if<int64_t>(); val != nullptr)
{
return std::chrono::milliseconds(*val);
}
return {};
}
template<>
tr_variant VariantConverter::save<std::chrono::milliseconds>(std::chrono::milliseconds const& val)
{
return val.count();
}
} // namespace libtransmission

View File

@ -46,7 +46,9 @@ public:
class Map
{
public:
Map(size_t const n_reserve = 0U)
Map() = default;
Map(size_t const n_reserve)
{
vec_.reserve(n_reserve);
}
@ -555,19 +557,4 @@ private:
char const* end_ = nullptr;
};
namespace libtransmission
{
struct VariantConverter
{
public:
template<typename T>
static std::optional<T> load(tr_variant const& src);
template<typename T>
static tr_variant save(T const& val);
};
} // namespace libtransmission
/* @} */

View File

@ -173,9 +173,9 @@ TEST_F(AnnounceListTest, canSetUnsortedWithBackupsInTiers)
// confirm that each has a unique id
auto ids = std::set<tr_tracker_id_t>{};
for (size_t i = 0, n = std::size(announce_list); i < n; ++i)
for (auto const& tracker : announce_list)
{
ids.insert(announce_list.at(i).id);
ids.insert(tracker.id);
}
EXPECT_EQ(std::size(announce_list), std::size(ids));
}

View File

@ -859,13 +859,12 @@ TEST_F(FileTest, pathDirname)
for (auto const& [input, expected] : DirnameTests)
{
EXPECT_EQ(expected, tr_sys_path_dirname(input)) << "input[" << input << "] expected [" << expected << "] actual ["
<< tr_sys_path_dirname(input) << ']' << std::endl;
EXPECT_EQ(expected, tr_sys_path_dirname(input))
<< "input[" << input << "] expected [" << expected << "] actual [" << tr_sys_path_dirname(input) << "]\n";
auto path = tr_pathbuf{ input };
path.popdir();
EXPECT_EQ(expected, path) << "input[" << input << "] expected [" << expected << "] actual [" << path << ']'
<< std::endl;
EXPECT_EQ(expected, path) << "input[" << input << "] expected [" << expected << "] actual [" << path << "]\n";
}
/* TODO: is_same(dirname(x) + '/' + basename(x), x) */

View File

@ -15,24 +15,20 @@
#include <libtransmission/open-files.h>
#include <libtransmission/peer-io.h>
#include <libtransmission/quark.h>
#include <libtransmission/session-settings.h>
#include <libtransmission/session.h>
#include <libtransmission/variant.h>
#include "gtest/gtest.h"
using namespace std::literals;
class SettingsTest : public ::testing::Test
{
protected:
using SessionSettings = tr_session_settings;
};
using SettingsTest = ::testing::Test;
TEST_F(SettingsTest, canInstantiate)
{
auto settings = tr_session_settings{};
auto settings = tr_session::Settings{};
auto var = settings.settings();
auto var = settings.save();
EXPECT_TRUE(var.has_value());
}
@ -40,7 +36,7 @@ TEST_F(SettingsTest, canLoadBools)
{
static auto constexpr Key = TR_KEY_seed_queue_enabled;
auto settings = tr_session_settings{};
auto settings = tr_session::Settings{};
auto const expected_value = !settings.seed_queue_enabled;
auto var = tr_variant{};
@ -55,11 +51,11 @@ TEST_F(SettingsTest, canSaveBools)
{
static auto constexpr Key = TR_KEY_seed_queue_enabled;
auto settings = tr_session_settings{};
auto settings = tr_session::Settings{};
auto const expected_value = !settings.seed_queue_enabled;
settings.seed_queue_enabled = expected_value;
auto var = settings.settings();
auto var = settings.save();
auto val = bool{};
EXPECT_TRUE(tr_variantDictFindBool(&var, Key, &val));
EXPECT_EQ(expected_value, val);
@ -69,7 +65,7 @@ TEST_F(SettingsTest, canLoadDoubles)
{
static auto constexpr Key = TR_KEY_ratio_limit;
auto settings = tr_session_settings{};
auto settings = tr_session::Settings{};
auto const expected_value = settings.ratio_limit + 1.0;
auto var = tr_variant{};
@ -83,12 +79,12 @@ TEST_F(SettingsTest, canSaveDoubles)
{
static auto constexpr Key = TR_KEY_seed_queue_enabled;
auto settings = tr_session_settings{};
auto settings = tr_session::Settings{};
auto const default_value = settings.seed_queue_enabled;
auto const expected_value = !default_value;
settings.seed_queue_enabled = expected_value;
auto var = settings.settings();
auto var = settings.save();
auto val = bool{};
EXPECT_TRUE(tr_variantDictFindBool(&var, Key, &val));
EXPECT_EQ(expected_value, val);
@ -99,7 +95,7 @@ TEST_F(SettingsTest, canLoadEncryptionMode)
static auto constexpr Key = TR_KEY_encryption;
static auto constexpr ExpectedValue = TR_ENCRYPTION_REQUIRED;
auto settings = std::make_unique<tr_session_settings>();
auto settings = std::make_unique<tr_session::Settings>();
ASSERT_NE(ExpectedValue, settings->encryption_mode);
auto var = tr_variant{};
@ -109,7 +105,7 @@ TEST_F(SettingsTest, canLoadEncryptionMode)
EXPECT_EQ(ExpectedValue, settings->encryption_mode);
var.clear();
settings = std::make_unique<tr_session_settings>();
settings = std::make_unique<tr_session::Settings>();
tr_variantInitDict(&var, 1);
tr_variantDictAddStrView(&var, Key, "required");
settings->load(var);
@ -121,11 +117,11 @@ TEST_F(SettingsTest, canSaveEncryptionMode)
static auto constexpr Key = TR_KEY_encryption;
static auto constexpr ExpectedValue = TR_ENCRYPTION_REQUIRED;
auto settings = tr_session_settings{};
auto settings = tr_session::Settings{};
EXPECT_NE(ExpectedValue, settings.seed_queue_enabled);
settings.encryption_mode = ExpectedValue;
auto var = settings.settings();
auto var = settings.save();
auto val = int64_t{};
EXPECT_TRUE(tr_variantDictFindInt(&var, Key, &val));
EXPECT_EQ(ExpectedValue, val);
@ -135,7 +131,7 @@ TEST_F(SettingsTest, canLoadLogLevel)
{
static auto constexpr Key = TR_KEY_message_level;
auto settings = std::make_unique<tr_session_settings>();
auto settings = std::make_unique<tr_session::Settings>();
auto const default_value = settings->log_level;
auto constexpr ExpectedValue = TR_LOG_DEBUG;
ASSERT_NE(ExpectedValue, default_value);
@ -147,7 +143,7 @@ TEST_F(SettingsTest, canLoadLogLevel)
EXPECT_EQ(ExpectedValue, settings->log_level);
var.clear();
settings = std::make_unique<tr_session_settings>();
settings = std::make_unique<tr_session::Settings>();
tr_variantInitDict(&var, 1);
tr_variantDictAddStrView(&var, Key, "debug");
settings->load(var);
@ -158,13 +154,13 @@ TEST_F(SettingsTest, canSaveLogLevel)
{
static auto constexpr Key = TR_KEY_message_level;
auto settings = tr_session_settings{};
auto settings = tr_session::Settings{};
auto const default_value = settings.log_level;
auto constexpr ExpectedValue = TR_LOG_DEBUG;
ASSERT_NE(ExpectedValue, default_value);
settings.log_level = ExpectedValue;
auto var = settings.settings();
auto var = settings.save();
auto val = int64_t{};
EXPECT_TRUE(tr_variantDictFindInt(&var, Key, &val));
EXPECT_EQ(ExpectedValue, val);
@ -174,7 +170,7 @@ TEST_F(SettingsTest, canLoadMode)
{
static auto constexpr Key = TR_KEY_umask;
auto settings = std::make_unique<tr_session_settings>();
auto settings = std::make_unique<tr_session::Settings>();
auto const default_value = settings->umask;
auto constexpr ExpectedValue = tr_mode_t{ 0777 };
ASSERT_NE(ExpectedValue, default_value);
@ -186,7 +182,7 @@ TEST_F(SettingsTest, canLoadMode)
EXPECT_EQ(ExpectedValue, settings->umask);
var.clear();
settings = std::make_unique<tr_session_settings>();
settings = std::make_unique<tr_session::Settings>();
tr_variantInitDict(&var, 1);
tr_variantDictAddStrView(&var, Key, "0777");
settings->load(var);
@ -197,13 +193,13 @@ TEST_F(SettingsTest, canSaveMode)
{
static auto constexpr Key = TR_KEY_umask;
auto settings = tr_session_settings{};
auto settings = tr_session::Settings{};
auto const default_value = settings.log_level;
auto constexpr ExpectedValue = tr_mode_t{ 0777 };
ASSERT_NE(ExpectedValue, default_value);
settings.umask = ExpectedValue;
auto var = settings.settings();
auto var = settings.save();
auto val = std::string_view{};
EXPECT_TRUE(tr_variantDictFindStrView(&var, Key, &val));
EXPECT_EQ("0777", val);
@ -213,7 +209,7 @@ TEST_F(SettingsTest, canLoadPort)
{
static auto constexpr Key = TR_KEY_peer_port;
auto settings = tr_session_settings{};
auto settings = tr_session::Settings{};
auto const default_value = settings.peer_port;
auto constexpr ExpectedValue = tr_port::from_host(8080);
ASSERT_NE(ExpectedValue, default_value);
@ -229,13 +225,13 @@ TEST_F(SettingsTest, canSavePort)
{
static auto constexpr Key = TR_KEY_peer_port;
auto settings = tr_session_settings{};
auto settings = tr_session::Settings{};
auto const default_value = settings.peer_port;
auto constexpr ExpectedValue = tr_port::from_host(8080);
ASSERT_NE(ExpectedValue, default_value);
settings.peer_port = ExpectedValue;
auto var = settings.settings();
auto var = settings.save();
auto val = int64_t{};
EXPECT_TRUE(tr_variantDictFindInt(&var, Key, &val));
EXPECT_EQ(ExpectedValue.host(), val);
@ -245,7 +241,7 @@ TEST_F(SettingsTest, canLoadPreallocation)
{
static auto constexpr Key = TR_KEY_preallocation;
auto settings = std::make_unique<tr_session_settings>();
auto settings = std::make_unique<tr_session::Settings>();
auto const default_value = settings->preallocation_mode;
auto constexpr ExpectedValue = tr_open_files::Preallocation::Full;
ASSERT_NE(ExpectedValue, default_value);
@ -257,7 +253,7 @@ TEST_F(SettingsTest, canLoadPreallocation)
EXPECT_EQ(ExpectedValue, settings->preallocation_mode);
var.clear();
settings = std::make_unique<tr_session_settings>();
settings = std::make_unique<tr_session::Settings>();
tr_variantInitDict(&var, 1);
tr_variantDictAddStrView(&var, Key, "full");
settings->load(var);
@ -268,13 +264,13 @@ TEST_F(SettingsTest, canSavePreallocation)
{
static auto constexpr Key = TR_KEY_preallocation;
auto settings = tr_session_settings{};
auto settings = tr_session::Settings{};
auto const default_value = settings.preallocation_mode;
auto constexpr ExpectedValue = tr_open_files::Preallocation::Full;
ASSERT_NE(ExpectedValue, default_value);
settings.preallocation_mode = ExpectedValue;
auto var = settings.settings();
auto var = settings.save();
auto val = int64_t{};
EXPECT_TRUE(tr_variantDictFindInt(&var, Key, &val));
EXPECT_EQ(static_cast<int64_t>(ExpectedValue), val);
@ -284,7 +280,7 @@ TEST_F(SettingsTest, canLoadSizeT)
{
static auto constexpr Key = TR_KEY_queue_stalled_minutes;
auto settings = tr_session_settings{};
auto settings = tr_session::Settings{};
auto const expected_value = settings.queue_stalled_minutes + 5U;
auto var = tr_variant{};
@ -298,11 +294,11 @@ TEST_F(SettingsTest, canSaveSizeT)
{
static auto constexpr Key = TR_KEY_queue_stalled_minutes;
auto settings = tr_session_settings{};
auto settings = tr_session::Settings{};
auto const expected_value = settings.queue_stalled_minutes + 5U;
settings.queue_stalled_minutes = expected_value;
auto var = settings.settings();
auto var = settings.save();
auto val = int64_t{};
EXPECT_TRUE(tr_variantDictFindInt(&var, Key, &val));
EXPECT_EQ(expected_value, static_cast<size_t>(val));
@ -313,8 +309,8 @@ TEST_F(SettingsTest, canLoadString)
static auto constexpr Key = TR_KEY_bind_address_ipv4;
static auto constexpr ChangedValue = std::string_view{ "127.0.0.1" };
auto settings = tr_session_settings{};
EXPECT_NE(ChangedValue, tr_session_settings{}.bind_address_ipv4);
auto settings = tr_session::Settings{};
EXPECT_NE(ChangedValue, tr_session::Settings{}.bind_address_ipv4);
auto var = tr_variant{};
tr_variantInitDict(&var, 1);
@ -328,11 +324,11 @@ TEST_F(SettingsTest, canSaveString)
static auto constexpr Key = TR_KEY_bind_address_ipv4;
static auto constexpr ChangedValue = std::string_view{ "127.0.0.1" };
auto settings = tr_session_settings{};
EXPECT_NE(ChangedValue, tr_session_settings{}.bind_address_ipv4);
auto settings = tr_session::Settings{};
EXPECT_NE(ChangedValue, tr_session::Settings{}.bind_address_ipv4);
settings.bind_address_ipv4 = ChangedValue;
auto var = settings.settings();
auto var = settings.save();
auto val = std::string_view{};
EXPECT_TRUE(tr_variantDictFindStrView(&var, Key, &val));
EXPECT_EQ(ChangedValue, val);
@ -343,7 +339,7 @@ TEST_F(SettingsTest, canLoadTos)
static auto constexpr Key = TR_KEY_peer_socket_tos;
static auto constexpr ChangedValue = tr_tos_t{ 0x20 };
auto settings = std::make_unique<tr_session_settings>();
auto settings = std::make_unique<tr_session::Settings>();
auto const default_value = settings->peer_socket_tos;
ASSERT_NE(ChangedValue, default_value);
@ -354,7 +350,7 @@ TEST_F(SettingsTest, canLoadTos)
EXPECT_EQ(ChangedValue, settings->peer_socket_tos);
var.clear();
settings = std::make_unique<tr_session_settings>();
settings = std::make_unique<tr_session::Settings>();
tr_variantInitDict(&var, 1);
tr_variantDictAddStrView(&var, Key, "cs1");
settings->load(var);
@ -366,11 +362,11 @@ TEST_F(SettingsTest, canSaveTos)
static auto constexpr Key = TR_KEY_peer_socket_tos;
static auto constexpr ChangedValue = tr_tos_t{ 0x20 };
auto settings = tr_session_settings{};
auto settings = tr_session::Settings{};
ASSERT_NE(ChangedValue, settings.peer_socket_tos);
settings.peer_socket_tos = tr_tos_t(0x20);
auto var = settings.settings();
auto var = settings.save();
auto val = std::string_view{};
EXPECT_TRUE(tr_variantDictFindStrView(&var, Key, &val));
EXPECT_EQ(ChangedValue.toString(), val);
@ -381,7 +377,7 @@ TEST_F(SettingsTest, canLoadVerify)
static auto constexpr Key = TR_KEY_torrent_added_verify_mode;
static auto constexpr ChangedValue = TR_VERIFY_ADDED_FULL;
auto settings = std::make_unique<tr_session_settings>();
auto settings = std::make_unique<tr_session::Settings>();
auto const default_value = settings->torrent_added_verify_mode;
ASSERT_NE(ChangedValue, default_value);
@ -392,7 +388,7 @@ TEST_F(SettingsTest, canLoadVerify)
EXPECT_EQ(ChangedValue, settings->torrent_added_verify_mode);
var.clear();
settings = std::make_unique<tr_session_settings>();
settings = std::make_unique<tr_session::Settings>();
tr_variantInitDict(&var, 1);
tr_variantDictAddInt(&var, Key, ChangedValue);
settings->load(var);
@ -404,11 +400,11 @@ TEST_F(SettingsTest, canSaveVerify)
static auto constexpr Key = TR_KEY_torrent_added_verify_mode;
static auto constexpr ChangedValue = TR_VERIFY_ADDED_FULL;
auto settings = tr_session_settings{};
auto settings = tr_session::Settings{};
ASSERT_NE(ChangedValue, settings.torrent_added_verify_mode);
settings.torrent_added_verify_mode = ChangedValue;
auto var = settings.settings();
auto var = settings.save();
auto val = std::string_view{};
EXPECT_TRUE(tr_variantDictFindStrView(&var, Key, &val));
EXPECT_EQ("full", val);
@ -419,7 +415,7 @@ TEST_F(SettingsTest, canLoadPreferredTransport)
static auto constexpr Key = TR_KEY_preferred_transport;
auto constexpr ExpectedValue = TR_PREFER_TCP;
auto settings = std::make_unique<tr_session_settings>();
auto settings = std::make_unique<tr_session::Settings>();
auto const default_value = settings->preferred_transport;
ASSERT_NE(ExpectedValue, default_value);
@ -430,7 +426,7 @@ TEST_F(SettingsTest, canLoadPreferredTransport)
EXPECT_EQ(ExpectedValue, settings->preferred_transport);
var.clear();
settings = std::make_unique<tr_session_settings>();
settings = std::make_unique<tr_session::Settings>();
tr_variantInitDict(&var, 1);
tr_variantDictAddStrView(&var, Key, "tcp");
settings->load(var);
@ -442,14 +438,14 @@ TEST_F(SettingsTest, canSavePreferredTransport)
static auto constexpr Key = TR_KEY_preferred_transport;
static auto constexpr ExpectedValue = TR_PREFER_TCP;
auto settings = tr_session_settings{};
auto settings = tr_session::Settings{};
auto const default_value = settings.preferred_transport;
ASSERT_NE(ExpectedValue, default_value);
auto var = tr_variant{};
tr_variantInitDict(&var, 100);
settings.preferred_transport = ExpectedValue;
var = settings.settings();
var = settings.save();
auto val = std::string_view{};
EXPECT_TRUE(tr_variantDictFindStrView(&var, Key, &val));
EXPECT_EQ("tcp", val);
@ -460,7 +456,7 @@ TEST_F(SettingsTest, canLoadSleepPerSecondsDuringVerify)
static auto constexpr Key = TR_KEY_sleep_per_seconds_during_verify;
auto constexpr ExpectedValue = 90ms;
auto settings = std::make_unique<tr_session_settings>();
auto settings = std::make_unique<tr_session::Settings>();
auto const default_value = settings->sleep_per_seconds_during_verify;
ASSERT_NE(ExpectedValue, default_value);
@ -471,7 +467,7 @@ TEST_F(SettingsTest, canLoadSleepPerSecondsDuringVerify)
EXPECT_EQ(ExpectedValue, settings->sleep_per_seconds_during_verify);
var.clear();
settings = std::make_unique<tr_session_settings>();
settings = std::make_unique<tr_session::Settings>();
tr_variantInitDict(&var, 1);
tr_variantDictAddInt(&var, Key, 90);
settings->load(var);
@ -483,16 +479,16 @@ TEST_F(SettingsTest, canSaveSleepPerSecondsDuringVerify)
static auto constexpr Key = TR_KEY_sleep_per_seconds_during_verify;
static auto constexpr ExpectedValue = 90ms;
auto settings = tr_session_settings{};
auto settings = tr_session::Settings{};
auto const default_value = settings.sleep_per_seconds_during_verify;
ASSERT_NE(ExpectedValue, default_value);
auto var = tr_variant{};
tr_variantInitDict(&var, 100);
settings.sleep_per_seconds_during_verify = ExpectedValue;
var = settings.settings();
var = settings.save();
int64_t val_raw;
auto val_raw = int64_t{};
EXPECT_TRUE(tr_variantDictFindInt(&var, Key, &val_raw));
EXPECT_EQ(ExpectedValue, std::chrono::milliseconds{ val_raw });
}
}