mirror of
https://github.com/transmission/transmission.git
synced 2025-12-19 18:08:31 +00:00
refactor: use the new jsonrpc API for RPC calls in tr-gtk (#7938)
* feat: copy TR_RPC_VERBOSE env var feature from tr-qt
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#include "Utils.h"
|
||||
|
||||
#include <libtransmission/transmission.h>
|
||||
#include <libtransmission/api-compat.h>
|
||||
#include <libtransmission/log.h>
|
||||
#include <libtransmission/quark.h>
|
||||
#include <libtransmission/rpcimpl.h>
|
||||
@@ -198,7 +199,7 @@ private:
|
||||
void start_all_torrents();
|
||||
void pause_all_torrents();
|
||||
void copy_magnet_link_to_clipboard(Glib::RefPtr<Torrent> const& torrent) const;
|
||||
bool call_rpc_for_selected_torrents(std::string const& method);
|
||||
bool call_rpc_for_selected_torrents(tr_quark method);
|
||||
void remove_selected(bool delete_files);
|
||||
|
||||
static tr_rpc_callback_status on_rpc_changed(
|
||||
@@ -1416,25 +1417,18 @@ void Application::Impl::show_about_dialog()
|
||||
d->show();
|
||||
}
|
||||
|
||||
bool Application::Impl::call_rpc_for_selected_torrents(std::string const& method)
|
||||
bool Application::Impl::call_rpc_for_selected_torrents(tr_quark const method)
|
||||
{
|
||||
tr_variant top;
|
||||
bool invoked = false;
|
||||
auto* session = core_->get_session();
|
||||
|
||||
tr_variantInitDict(&top, 2);
|
||||
tr_variantDictAddStrView(&top, TR_KEY_method, method);
|
||||
auto* const args = tr_variantDictAddDict(&top, TR_KEY_arguments, 1);
|
||||
auto* const ids = tr_variantDictAddList(args, TR_KEY_ids, 0);
|
||||
wind_->for_each_selected_torrent([ids](auto const& torrent) { tr_variantListAddInt(ids, torrent->get_id()); });
|
||||
|
||||
if (tr_variantListSize(ids) != 0)
|
||||
auto const ids = get_selected_torrent_ids();
|
||||
if (std::empty(ids))
|
||||
{
|
||||
tr_rpc_request_exec(session, top, {});
|
||||
invoked = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return invoked;
|
||||
auto params = tr_variant::Map{ 1U };
|
||||
params.try_emplace(TR_KEY_ids, Session::to_variant(ids));
|
||||
core_->exec(method, std::move(params));
|
||||
return true;
|
||||
}
|
||||
|
||||
void Application::Impl::remove_selected(bool delete_files)
|
||||
@@ -1447,22 +1441,12 @@ void Application::Impl::remove_selected(bool delete_files)
|
||||
|
||||
void Application::Impl::start_all_torrents()
|
||||
{
|
||||
auto* session = core_->get_session();
|
||||
tr_variant request;
|
||||
|
||||
tr_variantInitDict(&request, 1);
|
||||
tr_variantDictAddStrView(&request, TR_KEY_method, tr_quark_get_string_view(TR_KEY_torrent_start_kebab));
|
||||
tr_rpc_request_exec(session, request, {});
|
||||
core_->exec(TR_KEY_torrent_start, {});
|
||||
}
|
||||
|
||||
void Application::Impl::pause_all_torrents()
|
||||
{
|
||||
auto* session = core_->get_session();
|
||||
tr_variant request;
|
||||
|
||||
tr_variantInitDict(&request, 1);
|
||||
tr_variantDictAddStrView(&request, TR_KEY_method, tr_quark_get_string_view(TR_KEY_torrent_stop_kebab));
|
||||
tr_rpc_request_exec(session, request, {});
|
||||
core_->exec(TR_KEY_torrent_stop, {});
|
||||
}
|
||||
|
||||
void Application::Impl::copy_magnet_link_to_clipboard(Glib::RefPtr<Torrent> const& torrent) const
|
||||
@@ -1483,6 +1467,38 @@ void gtr_actions_handler(Glib::ustring const& action_name, gpointer user_data)
|
||||
static_cast<Application::Impl*>(user_data)->actions_handler(action_name);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
[[nodiscard]] std::optional<tr_quark> get_rpc_method(std::string_view const str)
|
||||
{
|
||||
if (auto quark = tr_quark_lookup(str)) // method-name, methodName, method_name
|
||||
{
|
||||
quark = tr_quark_convert(*quark); // method_name
|
||||
switch (*quark)
|
||||
{
|
||||
// method_name
|
||||
case TR_KEY_queue_move_bottom:
|
||||
case TR_KEY_queue_move_down:
|
||||
case TR_KEY_queue_move_top:
|
||||
case TR_KEY_queue_move_up:
|
||||
case TR_KEY_torrent_reannounce:
|
||||
case TR_KEY_torrent_start:
|
||||
case TR_KEY_torrent_start_now:
|
||||
case TR_KEY_torrent_stop:
|
||||
case TR_KEY_torrent_verify:
|
||||
return quark;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Application::Impl::actions_handler(Glib::ustring const& action_name)
|
||||
{
|
||||
bool changed = false;
|
||||
@@ -1533,13 +1549,9 @@ void Application::Impl::actions_handler(Glib::ustring const& action_name)
|
||||
w->show();
|
||||
}
|
||||
}
|
||||
else if (
|
||||
// TODO: migrate from _kebab
|
||||
action_name == "torrent-start" || action_name == "torrent-start-now" || action_name == "torrent-stop" ||
|
||||
action_name == "torrent-reannounce" || action_name == "torrent-verify" || action_name == "queue-move-top" ||
|
||||
action_name == "queue-move-up" || action_name == "queue-move-down" || action_name == "queue-move-bottom")
|
||||
else if (auto const method = get_rpc_method(action_name.raw()))
|
||||
{
|
||||
changed = call_rpc_for_selected_torrents(action_name);
|
||||
changed = call_rpc_for_selected_torrents(*method);
|
||||
}
|
||||
else if (action_name == "open-torrent-folder")
|
||||
{
|
||||
|
||||
@@ -109,9 +109,14 @@ private:
|
||||
void onScrapeToggled();
|
||||
void onBackupToggled();
|
||||
|
||||
void torrent_set_bool(tr_quark key, bool value);
|
||||
void torrent_set_int(tr_quark key, int value);
|
||||
void torrent_set_real(tr_quark key, double value);
|
||||
template<typename T>
|
||||
void torrent_set_field(tr_quark const key, T value)
|
||||
{
|
||||
auto params = tr_variant::Map{ 2U };
|
||||
params.try_emplace(key, std::forward<T>(value));
|
||||
params.try_emplace(TR_KEY_ids, Session::to_variant(ids_));
|
||||
core_->exec(TR_KEY_torrent_set, std::move(params));
|
||||
}
|
||||
|
||||
void refreshInfo(std::vector<tr_torrent*> const& torrents);
|
||||
void refreshPeers(std::vector<tr_torrent*> const& torrents);
|
||||
@@ -436,88 +441,34 @@ void DetailsDialog::Impl::refreshOptions(std::vector<tr_torrent*> const& torrent
|
||||
}
|
||||
}
|
||||
|
||||
void DetailsDialog::Impl::torrent_set_bool(tr_quark key, bool value)
|
||||
{
|
||||
tr_variant top;
|
||||
|
||||
tr_variantInitDict(&top, 2);
|
||||
tr_variantDictAddStrView(&top, TR_KEY_method, tr_quark_get_string_view(TR_KEY_torrent_set_kebab));
|
||||
tr_variant* const args = tr_variantDictAddDict(&top, TR_KEY_arguments, 2);
|
||||
tr_variantDictAddBool(args, key, value);
|
||||
tr_variant* const ids = tr_variantDictAddList(args, TR_KEY_ids, ids_.size());
|
||||
|
||||
for (auto const id : ids_)
|
||||
{
|
||||
tr_variantListAddInt(ids, id);
|
||||
}
|
||||
|
||||
core_->exec(top);
|
||||
}
|
||||
|
||||
void DetailsDialog::Impl::torrent_set_int(tr_quark key, int value)
|
||||
{
|
||||
tr_variant top;
|
||||
|
||||
tr_variantInitDict(&top, 2);
|
||||
tr_variantDictAddStrView(&top, TR_KEY_method, tr_quark_get_string_view(TR_KEY_torrent_set_kebab));
|
||||
tr_variant* const args = tr_variantDictAddDict(&top, TR_KEY_arguments, 2);
|
||||
tr_variantDictAddInt(args, key, value);
|
||||
tr_variant* const ids = tr_variantDictAddList(args, TR_KEY_ids, ids_.size());
|
||||
|
||||
for (auto const id : ids_)
|
||||
{
|
||||
tr_variantListAddInt(ids, id);
|
||||
}
|
||||
|
||||
core_->exec(top);
|
||||
}
|
||||
|
||||
void DetailsDialog::Impl::torrent_set_real(tr_quark key, double value)
|
||||
{
|
||||
tr_variant top;
|
||||
|
||||
tr_variantInitDict(&top, 2);
|
||||
tr_variantDictAddStrView(&top, TR_KEY_method, tr_quark_get_string_view(TR_KEY_torrent_set_kebab));
|
||||
tr_variant* const args = tr_variantDictAddDict(&top, TR_KEY_arguments, 2);
|
||||
tr_variantDictAddReal(args, key, value);
|
||||
tr_variant* const ids = tr_variantDictAddList(args, TR_KEY_ids, ids_.size());
|
||||
|
||||
for (auto const id : ids_)
|
||||
{
|
||||
tr_variantListAddInt(ids, id);
|
||||
}
|
||||
|
||||
core_->exec(top);
|
||||
}
|
||||
|
||||
void DetailsDialog::Impl::options_page_init(Glib::RefPtr<Gtk::Builder> const& /*builder*/)
|
||||
{
|
||||
auto const speed_units_kbyps_str = Speed::units().display_name(Speed::Units::KByps);
|
||||
|
||||
honor_limits_check_tag_ = honor_limits_check_->signal_toggled().connect(
|
||||
[this]() { torrent_set_bool(TR_KEY_honors_session_limits_camel, honor_limits_check_->get_active()); });
|
||||
[this]() { torrent_set_field(TR_KEY_honors_session_limits, honor_limits_check_->get_active()); });
|
||||
|
||||
down_limited_check_->set_label(
|
||||
fmt::format(fmt::runtime(down_limited_check_->get_label().raw()), fmt::arg("speed_units", speed_units_kbyps_str)));
|
||||
down_limited_check_tag_ = down_limited_check_->signal_toggled().connect(
|
||||
[this]() { torrent_set_bool(TR_KEY_download_limited_camel, down_limited_check_->get_active()); });
|
||||
[this]() { torrent_set_field(TR_KEY_download_limited, down_limited_check_->get_active()); });
|
||||
|
||||
down_limit_spin_->set_adjustment(Gtk::Adjustment::create(0, 0, std::numeric_limits<int>::max(), 5));
|
||||
down_limit_spin_tag_ = down_limit_spin_->signal_value_changed().connect(
|
||||
[this]() { torrent_set_int(TR_KEY_download_limit_camel, down_limit_spin_->get_value_as_int()); });
|
||||
[this]() { torrent_set_field(TR_KEY_download_limit, down_limit_spin_->get_value_as_int()); });
|
||||
|
||||
up_limited_check_->set_label(
|
||||
fmt::format(fmt::runtime(up_limited_check_->get_label().raw()), fmt::arg("speed_units", speed_units_kbyps_str)));
|
||||
up_limited_check_tag_ = up_limited_check_->signal_toggled().connect(
|
||||
[this]() { torrent_set_bool(TR_KEY_upload_limited_camel, up_limited_check_->get_active()); });
|
||||
[this]() { torrent_set_field(TR_KEY_upload_limited, up_limited_check_->get_active()); });
|
||||
|
||||
up_limit_sping_->set_adjustment(Gtk::Adjustment::create(0, 0, std::numeric_limits<int>::max(), 5));
|
||||
up_limit_spin_tag_ = up_limit_sping_->signal_value_changed().connect(
|
||||
[this]() { torrent_set_int(TR_KEY_upload_limit_camel, up_limit_sping_->get_value_as_int()); });
|
||||
[this]() { torrent_set_field(TR_KEY_upload_limit, up_limit_sping_->get_value_as_int()); });
|
||||
|
||||
gtr_priority_combo_init(*bandwidth_combo_);
|
||||
bandwidth_combo_tag_ = bandwidth_combo_->signal_changed().connect(
|
||||
[this]() { torrent_set_int(TR_KEY_bandwidth_priority_camel, gtr_combo_box_get_active_enum(*bandwidth_combo_)); });
|
||||
[this]() { torrent_set_field(TR_KEY_bandwidth_priority, gtr_combo_box_get_active_enum(*bandwidth_combo_)); });
|
||||
|
||||
gtr_combo_box_set_enum(
|
||||
*ratio_combo_,
|
||||
@@ -529,13 +480,13 @@ void DetailsDialog::Impl::options_page_init(Glib::RefPtr<Gtk::Builder> const& /*
|
||||
ratio_combo_tag_ = ratio_combo_->signal_changed().connect(
|
||||
[this]()
|
||||
{
|
||||
torrent_set_int(TR_KEY_seed_ratio_mode_camel, gtr_combo_box_get_active_enum(*ratio_combo_));
|
||||
torrent_set_field(TR_KEY_seed_ratio_mode, gtr_combo_box_get_active_enum(*ratio_combo_));
|
||||
refresh();
|
||||
});
|
||||
ratio_spin_->set_adjustment(Gtk::Adjustment::create(0, 0, 1000, .05));
|
||||
ratio_spin_->set_width_chars(7);
|
||||
ratio_spin_tag_ = ratio_spin_->signal_value_changed().connect(
|
||||
[this]() { torrent_set_real(TR_KEY_seed_ratio_limit_camel, ratio_spin_->get_value()); });
|
||||
[this]() { torrent_set_field(TR_KEY_seed_ratio_limit, ratio_spin_->get_value()); });
|
||||
|
||||
gtr_combo_box_set_enum(
|
||||
*idle_combo_,
|
||||
@@ -547,16 +498,16 @@ void DetailsDialog::Impl::options_page_init(Glib::RefPtr<Gtk::Builder> const& /*
|
||||
idle_combo_tag_ = idle_combo_->signal_changed().connect(
|
||||
[this]()
|
||||
{
|
||||
torrent_set_int(TR_KEY_seed_idle_mode_camel, gtr_combo_box_get_active_enum(*idle_combo_));
|
||||
torrent_set_field(TR_KEY_seed_idle_mode, gtr_combo_box_get_active_enum(*idle_combo_));
|
||||
refresh();
|
||||
});
|
||||
idle_spin_->set_adjustment(Gtk::Adjustment::create(1, 1, 40320, 5));
|
||||
idle_spin_tag_ = idle_spin_->signal_value_changed().connect(
|
||||
[this]() { torrent_set_int(TR_KEY_seed_idle_limit_camel, idle_spin_->get_value_as_int()); });
|
||||
[this]() { torrent_set_field(TR_KEY_seed_idle_limit, idle_spin_->get_value_as_int()); });
|
||||
|
||||
max_peers_spin_->set_adjustment(Gtk::Adjustment::create(1, 1, 3000, 5));
|
||||
max_peers_spin_tag_ = max_peers_spin_->signal_value_changed().connect(
|
||||
[this]() { torrent_set_int(TR_KEY_peer_limit_kebab, max_peers_spin_->get_value_as_int()); });
|
||||
[this]() { torrent_set_field(TR_KEY_peer_limit, max_peers_spin_->get_value_as_int()); });
|
||||
}
|
||||
|
||||
/****
|
||||
@@ -2388,16 +2339,11 @@ void AddTrackerDialog::on_response(int response)
|
||||
{
|
||||
if (tr_urlIsValidTracker(url.c_str()))
|
||||
{
|
||||
tr_variant top;
|
||||
|
||||
tr_variantInitDict(&top, 2);
|
||||
tr_variantDictAddStrView(&top, TR_KEY_method, tr_quark_get_string_view(TR_KEY_torrent_set_kebab));
|
||||
auto* const args = tr_variantDictAddDict(&top, TR_KEY_arguments, 2);
|
||||
tr_variantDictAddInt(args, TR_KEY_id, torrent_id_);
|
||||
auto* const trackers = tr_variantDictAddList(args, TR_KEY_tracker_add_camel, 1);
|
||||
tr_variantListAddStr(trackers, url.raw());
|
||||
|
||||
core_->exec(top);
|
||||
// TODO(ckerr) migrate to `TR_KEY_tracker_list`
|
||||
auto params = tr_variant::Map{ 2U };
|
||||
params.try_emplace(TR_KEY_ids, Session::to_variant({ torrent_id_ }));
|
||||
params.try_emplace(TR_KEY_tracker_add, Session::to_variant({ url.raw() }));
|
||||
core_->exec(TR_KEY_torrent_set, std::move(params));
|
||||
parent_.refresh();
|
||||
}
|
||||
else
|
||||
@@ -2435,16 +2381,12 @@ void DetailsDialog::Impl::on_tracker_list_remove_button_clicked()
|
||||
{
|
||||
auto const torrent_id = iter->get_value(tracker_cols.torrent_id);
|
||||
auto const tracker_id = iter->get_value(tracker_cols.tracker_id);
|
||||
tr_variant top;
|
||||
|
||||
tr_variantInitDict(&top, 2);
|
||||
tr_variantDictAddStrView(&top, TR_KEY_method, tr_quark_get_string_view(TR_KEY_torrent_set_kebab));
|
||||
auto* const args = tr_variantDictAddDict(&top, TR_KEY_arguments, 2);
|
||||
tr_variantDictAddInt(args, TR_KEY_id, torrent_id);
|
||||
auto* const trackers = tr_variantDictAddList(args, TR_KEY_tracker_remove_camel, 1);
|
||||
tr_variantListAddInt(trackers, tracker_id);
|
||||
|
||||
core_->exec(top);
|
||||
// TODO(ckerr): migrate to `TR_KEY_tracker_list`
|
||||
auto params = tr_variant::Map{ 2U };
|
||||
params.try_emplace(TR_KEY_ids, Session::to_variant({ torrent_id }));
|
||||
params.try_emplace(TR_KEY_tracker_remove, Session::to_variant({ tracker_id }));
|
||||
core_->exec(TR_KEY_torrent_set, std::move(params));
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
156
gtk/Session.cc
156
gtk/Session.cc
@@ -91,7 +91,7 @@ public:
|
||||
|
||||
void remove_torrent(tr_torrent_id_t id, bool delete_files);
|
||||
|
||||
void send_rpc_request(tr_variant const& request, int64_t tag, std::function<void(tr_variant&)> const& response_func);
|
||||
void send_rpc_request(tr_quark method, tr_variant const& params, std::function<void(tr_variant&)> on_response);
|
||||
|
||||
void commit_prefs_change(tr_quark key);
|
||||
|
||||
@@ -1008,16 +1008,11 @@ void Session::update()
|
||||
impl_->update();
|
||||
}
|
||||
|
||||
void Session::start_now(tr_torrent_id_t id)
|
||||
void Session::start_now(tr_torrent_id_t const id)
|
||||
{
|
||||
tr_variant top;
|
||||
tr_variantInitDict(&top, 2);
|
||||
tr_variantDictAddStrView(&top, TR_KEY_method, "torrent-start-now");
|
||||
|
||||
auto* args = tr_variantDictAddDict(&top, TR_KEY_arguments, 1);
|
||||
auto* ids = tr_variantDictAddList(args, TR_KEY_ids, 1);
|
||||
tr_variantListAddInt(ids, id);
|
||||
exec(top);
|
||||
auto params = tr_variant::Map{ 1U };
|
||||
params.try_emplace(TR_KEY_ids, to_variant({ id }));
|
||||
exec(TR_KEY_torrent_start_now, std::move(params));
|
||||
}
|
||||
|
||||
void Session::Impl::update()
|
||||
@@ -1208,31 +1203,34 @@ void Session::set_pref(tr_quark const key, double newval)
|
||||
****
|
||||
***/
|
||||
|
||||
/* #define DEBUG_RPC */
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
int64_t nextTag = 1;
|
||||
int64_t nextId = 1;
|
||||
|
||||
bool const verbose_ = tr_env_key_exists("TR_RPC_VERBOSE");
|
||||
|
||||
std::map<int64_t, std::function<void(tr_variant&)>> pendingRequests;
|
||||
|
||||
bool core_read_rpc_response_idle(tr_variant& response)
|
||||
{
|
||||
if (int64_t tag = 0; tr_variantDictFindInt(&response, TR_KEY_tag, &tag))
|
||||
if (verbose_)
|
||||
{
|
||||
if (auto const data_it = pendingRequests.find(tag); data_it != pendingRequests.end())
|
||||
{
|
||||
if (auto const& response_func = data_it->second; response_func)
|
||||
{
|
||||
response_func(response);
|
||||
}
|
||||
fmt::print("{:s}:{:d} got response:\n{:s}\n", __FILE__, __LINE__, tr_variant_serde::json().to_string(response));
|
||||
}
|
||||
|
||||
pendingRequests.erase(data_it);
|
||||
}
|
||||
else
|
||||
if (auto const* resmap = response.get_if<tr_variant::Map>())
|
||||
{
|
||||
if (auto const id = resmap->value_if<int64_t>(TR_KEY_id))
|
||||
{
|
||||
gtr_warning(fmt::format(fmt::runtime(_("Couldn't find pending RPC request for tag {tag}")), fmt::arg("tag", tag)));
|
||||
if (auto const nh = pendingRequests.extract(*id))
|
||||
{
|
||||
nh.mapped()(response);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtr_warning(fmt::format(fmt::runtime(_("Couldn't find pending RPC request for id {id}")), fmt::arg("id", *id)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1248,26 +1246,45 @@ void core_read_rpc_response(tr_session* /*session*/, tr_variant&& response)
|
||||
} // namespace
|
||||
|
||||
void Session::Impl::send_rpc_request(
|
||||
tr_variant const& request,
|
||||
int64_t tag,
|
||||
std::function<void(tr_variant&)> const& response_func)
|
||||
tr_quark const method,
|
||||
tr_variant const& params,
|
||||
std::function<void(tr_variant&)> on_response)
|
||||
{
|
||||
if (session_ == nullptr)
|
||||
{
|
||||
gtr_error("GTK+ client doesn't support connections to remote servers yet.");
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
// build the jsonrpc request
|
||||
auto reqmap = tr_variant::Map{ 4U };
|
||||
reqmap.try_emplace(TR_KEY_jsonrpc, tr_variant::unmanaged_string(JsonRpc::Version));
|
||||
reqmap.try_emplace(TR_KEY_method, tr_variant::unmanaged_string(method));
|
||||
|
||||
// add params if there are any
|
||||
if (params.has_value())
|
||||
{
|
||||
/* remember this request */
|
||||
pendingRequests.try_emplace(tag, response_func);
|
||||
|
||||
/* make the request */
|
||||
#ifdef DEBUG_RPC
|
||||
gtr_message(fmt::format("request: [{}]", tr_variantToStr(request, TR_VARIANT_FMT_JSON_LEAN)));
|
||||
#endif
|
||||
|
||||
tr_rpc_request_exec(session_, request, core_read_rpc_response);
|
||||
reqmap.try_emplace(TR_KEY_params, params.clone());
|
||||
}
|
||||
|
||||
// add id if we want a response
|
||||
auto callback = std::function<void(tr_session*, tr_variant&&)>{};
|
||||
if (on_response)
|
||||
{
|
||||
auto const id = nextId++;
|
||||
pendingRequests.try_emplace(id, std::move(on_response));
|
||||
reqmap.try_emplace(TR_KEY_id, id);
|
||||
callback = core_read_rpc_response;
|
||||
}
|
||||
|
||||
auto req = tr_variant{ std::move(reqmap) };
|
||||
|
||||
if (verbose_)
|
||||
{
|
||||
fmt::print("{:s}:{:d} sending req:\n{:s}\n", __FILE__, __LINE__, tr_variant_serde::json().to_string(req));
|
||||
}
|
||||
|
||||
tr_rpc_request_exec(session_, req, std::move(callback));
|
||||
}
|
||||
|
||||
/***
|
||||
@@ -1284,36 +1301,30 @@ void Session::port_test(PortTestIpProtocol const ip_protocol)
|
||||
}
|
||||
impl_->set_port_test_pending(true, ip_protocol);
|
||||
|
||||
auto const tag = nextTag++;
|
||||
|
||||
auto arguments_map = tr_variant::Map{ 1U };
|
||||
arguments_map.try_emplace(TR_KEY_ip_protocol, tr_variant::unmanaged_string(IpStr[ip_protocol]));
|
||||
|
||||
auto request_map = tr_variant::Map{ 3U };
|
||||
request_map.try_emplace(TR_KEY_method, tr_variant::unmanaged_string("port-test"sv));
|
||||
request_map.try_emplace(TR_KEY_tag, tag);
|
||||
request_map.try_emplace(TR_KEY_arguments, std::move(arguments_map));
|
||||
auto params = tr_variant::Map{ 1U };
|
||||
params.try_emplace(TR_KEY_ip_protocol, tr_variant::unmanaged_string(IpStr[ip_protocol]));
|
||||
|
||||
impl_->send_rpc_request(
|
||||
tr_variant{ std::move(request_map) },
|
||||
tag,
|
||||
TR_KEY_port_test,
|
||||
std::move(params),
|
||||
[this, ip_protocol](tr_variant& response)
|
||||
{
|
||||
impl_->set_port_test_pending(false, ip_protocol);
|
||||
|
||||
auto status = std::optional<bool>{};
|
||||
if (tr_variant* args = nullptr; tr_variantDictFindDict(&response, TR_KEY_arguments, &args))
|
||||
auto is_open = std::optional<bool>();
|
||||
|
||||
if (auto const* resmap = response.get_if<tr_variant::Map>())
|
||||
{
|
||||
if (auto result = bool{}; tr_variantDictFindBool(args, TR_KEY_port_is_open_kebab, &result))
|
||||
if (auto const* result = resmap->find_if<tr_variant::Map>(TR_KEY_result))
|
||||
{
|
||||
status = result;
|
||||
is_open = result->value_if<bool>(TR_KEY_port_is_open);
|
||||
}
|
||||
}
|
||||
|
||||
// If for whatever reason the status optional is empty here,
|
||||
// then something must have gone wrong with the port test,
|
||||
// so the UI should show the "error" state
|
||||
impl_->signal_port_tested().emit(status, ip_protocol);
|
||||
impl_->signal_port_tested().emit(is_open, ip_protocol);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1341,46 +1352,35 @@ void Session::Impl::set_port_test_pending(bool pending, Session::PortTestIpProto
|
||||
|
||||
void Session::blocklist_update()
|
||||
{
|
||||
auto const tag = nextTag;
|
||||
++nextTag;
|
||||
|
||||
tr_variant request;
|
||||
tr_variantInitDict(&request, 2);
|
||||
tr_variantDictAddStrView(&request, TR_KEY_method, "blocklist-update");
|
||||
tr_variantDictAddInt(&request, TR_KEY_tag, tag);
|
||||
impl_->send_rpc_request(
|
||||
request,
|
||||
tag,
|
||||
[this](auto& response)
|
||||
TR_KEY_blocklist_update,
|
||||
tr_variant{}, // no params
|
||||
[this](tr_variant& response)
|
||||
{
|
||||
tr_variant* args = nullptr;
|
||||
int64_t ruleCount = 0;
|
||||
std::optional<int64_t> n_rules;
|
||||
|
||||
if (!tr_variantDictFindDict(&response, TR_KEY_arguments, &args) ||
|
||||
!tr_variantDictFindInt(args, TR_KEY_blocklist_size_kebab, &ruleCount))
|
||||
if (auto const* resmap = response.get_if<tr_variant::Map>())
|
||||
{
|
||||
ruleCount = -1;
|
||||
if (auto const* result = resmap->find_if<tr_variant::Map>(TR_KEY_result))
|
||||
{
|
||||
n_rules = result->value_if<int64_t>(TR_KEY_blocklist_size);
|
||||
}
|
||||
}
|
||||
|
||||
if (ruleCount > 0)
|
||||
if (n_rules.has_value())
|
||||
{
|
||||
gtr_pref_int_set(TR_KEY_blocklist_date, tr_time());
|
||||
}
|
||||
|
||||
impl_->signal_blocklist_updated().emit(ruleCount >= 0);
|
||||
impl_->signal_blocklist_updated().emit(*n_rules >= 0);
|
||||
});
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
// ---
|
||||
|
||||
void Session::exec(tr_variant const& request)
|
||||
void Session::exec(tr_quark method, tr_variant const& params)
|
||||
{
|
||||
auto const tag = nextTag;
|
||||
++nextTag;
|
||||
|
||||
impl_->send_rpc_request(request, tag, {});
|
||||
impl_->send_rpc_request(method, params, {});
|
||||
}
|
||||
|
||||
/***
|
||||
|
||||
@@ -134,16 +134,35 @@ public:
|
||||
void set_pref(tr_quark key, int val);
|
||||
void set_pref(tr_quark key, double val);
|
||||
|
||||
/**
|
||||
***
|
||||
**/
|
||||
// ---
|
||||
|
||||
// Helper for building RPC payloads.
|
||||
// TODO(C++20): fold these two into a single std::span method
|
||||
template<typename T>
|
||||
[[nodiscard]] static auto to_variant(std::vector<T> const& items)
|
||||
{
|
||||
auto vec = tr_variant::Vector{};
|
||||
vec.reserve(std::size(items));
|
||||
for (auto const& item : items)
|
||||
{
|
||||
vec.emplace_back(item);
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
template<typename T>
|
||||
[[nodiscard]] static auto to_variant(std::initializer_list<T> items)
|
||||
{
|
||||
return to_variant(std::vector<T>{ std::move(items) });
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
void port_test(PortTestIpProtocol ip_protocol);
|
||||
bool port_test_pending(PortTestIpProtocol ip_protocol) const noexcept;
|
||||
|
||||
void blocklist_update();
|
||||
|
||||
void exec(tr_variant const& request);
|
||||
void exec(tr_quark method, tr_variant const& params);
|
||||
|
||||
void open_folder(tr_torrent_id_t torrent_id) const;
|
||||
|
||||
|
||||
@@ -691,7 +691,7 @@ uint64_t tr_ntohll(uint64_t netlonglong)
|
||||
|
||||
// --- ENVIRONMENT
|
||||
|
||||
bool tr_env_key_exists(char const* key)
|
||||
bool tr_env_key_exists(char const* key) noexcept
|
||||
{
|
||||
TR_ASSERT(key != nullptr);
|
||||
|
||||
|
||||
@@ -286,7 +286,7 @@ constexpr void tr_timeUpdate(time_t now) noexcept
|
||||
// ---
|
||||
|
||||
/** @brief Check if environment variable exists. */
|
||||
[[nodiscard]] bool tr_env_key_exists(char const* key);
|
||||
[[nodiscard]] bool tr_env_key_exists(char const* key) noexcept;
|
||||
|
||||
/** @brief Get environment variable value as string. */
|
||||
[[nodiscard]] std::string tr_env_get_string(std::string_view key, std::string_view default_value = {});
|
||||
|
||||
@@ -230,7 +230,7 @@ public:
|
||||
return it->second.value_if<Type>();
|
||||
}
|
||||
|
||||
return {};
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
@@ -241,7 +241,7 @@ public:
|
||||
return it->second.value_if<Type>();
|
||||
}
|
||||
|
||||
return {};
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user