Files
transmission/qt/RpcClient.h
Yat Ho 62c8edc039 refactor: use api_compat for rpc (#7995)
* fix: legacy RPC tag should ignore non-integers

* refactor: delegate legacy RPC callback to api-compat

* refactor: move `TR_KEY_alt_speed_down_kebab` handling

* refactor: move `TR_KEY_alt_speed_enabled_kebab` handling

* refactor: move `TR_KEY_alt_speed_time_begin_kebab` handling

* refactor: move `TR_KEY_alt_speed_time_day_kebab` handling

* refactor: move `TR_KEY_alt_speed_time_enabled_kebab` handling

* refactor: move `TR_KEY_alt_speed_time_end_kebab` handling

* refactor: move `TR_KEY_alt_speed_up_kebab` handling

* refactor: move `TR_KEY_anti_brute_force_enabled_kebab` handling

* refactor: move `TR_KEY_anti_brute_force_threshold_kebab` handling

* refactor: move `TR_KEY_blocklist_enabled_kebab` handling

* refactor: move `TR_KEY_blocklist_size_kebab` handling

* refactor: move `TR_KEY_blocklist_url_kebab` handling

* refactor: move `TR_KEY_cache_size_mb_kebab` handling

* refactor: move `TR_KEY_config_dir_kebab` handling

* refactor: move `TR_KEY_default_trackers_kebab` handling

* refactor: move `TR_KEY_dht_enabled_kebab` handling

* refactor: move `TR_KEY_download_dir_kebab` handling

* refactor: move `TR_KEY_download_dir_free_space_kebab` handling

* refactor: move `TR_KEY_download_queue_enabled_kebab` handling

* refactor: move `TR_KEY_download_queue_size_kebab` handling

* refactor: move `TR_KEY_idle_seeding_limit_kebab` handling

* refactor: move `TR_KEY_idle_seeding_limit_enabled_kebab` handling

* refactor: move `TR_KEY_incomplete_dir_kebab` handling

* refactor: move `TR_KEY_incomplete_dir_enabled_kebab` handling

* refactor: move `TR_KEY_lpd_enabled_kebab` handling

* refactor: move `TR_KEY_peer_limit_global_kebab` handling

* refactor: move `TR_KEY_peer_limit_per_torrent_kebab` handling

* refactor: move `TR_KEY_peer_port_kebab` handling

* refactor: move `TR_KEY_peer_port_random_on_start_kebab` handling

* refactor: move `TR_KEY_pex_enabled_kebab` handling

* refactor: move `TR_KEY_port_forwarding_enabled_kebab` handling

* refactor: move `TR_KEY_queue_stalled_enabled_kebab` handling

* refactor: move `TR_KEY_queue_stalled_minutes_kebab` handling

* refactor: move `TR_KEY_rename_partial_files_kebab` handling

* refactor: move `TR_KEY_rpc_version_kebab` handling

* refactor: move `TR_KEY_rpc_version_minimum_kebab` handling

* refactor: move `TR_KEY_rpc_version_semver_kebab` handling

* refactor: move `TR_KEY_script_torrent_added_enabled_kebab` handling

* refactor: move `TR_KEY_script_torrent_added_filename_kebab` handling

* refactor: move `TR_KEY_script_torrent_done_enabled_kebab` handling

* refactor: move `TR_KEY_script_torrent_done_filename_kebab` handling

* refactor: move `TR_KEY_script_torrent_done_seeding_enabled_kebab` handling

* refactor: move `TR_KEY_script_torrent_done_seeding_filename_kebab` handling

* refactor: remove `tr_quark_convert` usage for `tr_session::Scripts`

* refactor: move `TR_KEY_seed_ratio_limit_camel` handling

* refactor: move `TR_KEY_seed_ratio_limited_camel` handling

* refactor: move `TR_KEY_seed_queue_enabled_kebab` handling

* refactor: move `TR_KEY_seed_queue_size_kebab` handling

* refactor: move `TR_KEY_session_id_kebab` handling

* refactor: move `TR_KEY_speed_limit_down_kebab` handling

* refactor: move `TR_KEY_speed_limit_down_enabled_kebab` handling

* refactor: move `TR_KEY_speed_limit_up_kebab` handling

* refactor: move `TR_KEY_speed_limit_up_enabled_kebab` handling

* refactor: move `TR_KEY_start_added_torrents_kebab` handling

* refactor: move `TR_KEY_tcp_enabled_kebab` handling

* refactor: move `TR_KEY_trash_original_torrent_files_kebab` handling

* refactor: move `TR_KEY_utp_enabled_kebab` handling

* refactor: move `TR_KEY_recently_active_kebab` handling

* refactor: move `TR_KEY_delete_local_data_kebab` handling

* refactor: move `TR_KEY_activity_date_camel` handling

* refactor: move `TR_KEY_added_date_camel` handling

* refactor: move `TR_KEY_bandwidth_priority_camel` handling

* refactor: move `TR_KEY_bytes_completed_camel` handling

* refactor: move `TR_KEY_corrupt_ever_camel` handling

* refactor: move `TR_KEY_date_created_camel` handling

* refactor: move `TR_KEY_desired_available_camel` handling

* refactor: move `TR_KEY_done_date_camel` handling

* refactor: move `TR_KEY_download_dir_camel` handling

* refactor: move `TR_KEY_download_limit_camel` handling

* refactor: move `TR_KEY_download_limited_camel` handling

* refactor: move `TR_KEY_downloaded_ever_camel` handling

* refactor: move `TR_KEY_edit_date_camel` handling

* refactor: move `TR_KEY_error_string_camel` handling

* refactor: move `TR_KEY_eta_idle_camel` handling

* refactor: move `TR_KEY_file_stats_camel` handling

* refactor: move `TR_KEY_file_count_kebab` handling

* refactor: move `TR_KEY_hash_string_camel` handling

* refactor: move `TR_KEY_have_unchecked_camel` handling

* refactor: move `TR_KEY_have_valid_camel` handling

* refactor: move `TR_KEY_honors_session_limits_camel` handling

* refactor: move `TR_KEY_is_finished_camel` handling

* refactor: move `TR_KEY_is_private_camel` handling

* refactor: move `TR_KEY_is_stalled_camel` handling

* refactor: move `TR_KEY_left_until_done_camel` handling

* refactor: move `TR_KEY_magnet_link_camel` handling

* refactor: move `TR_KEY_manual_announce_time_camel` handling

* refactor: move `TR_KEY_max_connected_peers_camel` handling

* refactor: move `TR_KEY_metadata_percent_complete_camel` handling

* refactor: move `TR_KEY_peer_limit_kebab` handling

* refactor: move `TR_KEY_peers_connected_camel` handling

* refactor: move `TR_KEY_peers_from_camel` handling

* refactor: move `TR_KEY_peers_getting_from_us_camel` handling

* refactor: move `TR_KEY_peers_sending_to_us_camel` handling

* refactor: move `TR_KEY_percent_complete_camel` handling

* refactor: move `TR_KEY_percent_done_camel` handling

* refactor: move `TR_KEY_piece_count_camel` handling

* refactor: move `TR_KEY_piece_size_camel` handling

* refactor: move `TR_KEY_primary_mime_type_kebab` handling

* refactor: move `TR_KEY_queue_position_camel` handling

* refactor: move `TR_KEY_rate_download_camel` handling

* refactor: move `TR_KEY_rate_upload_camel` handling

* refactor: move `TR_KEY_recheck_progress_camel` handling

* refactor: move `TR_KEY_seconds_downloading_camel` handling

* refactor: move `TR_KEY_seconds_seeding_camel` handling

* refactor: move `TR_KEY_seed_idle_limit_camel` handling

* refactor: move `TR_KEY_seed_idle_mode_camel` handling

* refactor: move `TR_KEY_seed_ratio_mode_camel` handling

* refactor: move `TR_KEY_size_when_done_camel` handling

* refactor: move `TR_KEY_start_date_camel` handling

* refactor: move `TR_KEY_torrent_file_camel` handling

* refactor: move `TR_KEY_total_size_camel` handling

* refactor: move `TR_KEY_tracker_list_camel` handling

* refactor: move `TR_KEY_tracker_stats_camel` handling

* refactor: move `TR_KEY_upload_limit_camel` handling

* refactor: move `TR_KEY_upload_limited_camel` handling

* refactor: move `TR_KEY_upload_ratio_camel` handling

* refactor: move `TR_KEY_uploaded_ever_camel` handling

* refactor: move `TR_KEY_webseeds_sending_to_us_camel` handling

* refactor: move `TR_KEY_announce_state_camel` handling

* refactor: move `TR_KEY_download_count_camel` handling

* refactor: move `TR_KEY_has_announced_camel` handling

* refactor: move `TR_KEY_has_scraped_camel` handling

* refactor: move `TR_KEY_is_backup_camel` handling

* refactor: move `TR_KEY_last_announce_peer_count_camel` handling

* refactor: move `TR_KEY_last_announce_result_camel` handling

* refactor: move `TR_KEY_last_announce_start_time_camel` handling

* refactor: move `TR_KEY_last_announce_succeeded_camel` handling

* refactor: move `TR_KEY_last_announce_time_camel` handling

* refactor: move `TR_KEY_last_announce_timed_out_camel` handling

* refactor: move `TR_KEY_last_scrape_result_camel` handling

* refactor: move `TR_KEY_last_scrape_start_time_camel` handling

* refactor: move `TR_KEY_last_scrape_succeeded_camel` handling

* refactor: move `TR_KEY_last_scrape_time_camel` handling

* refactor: move `TR_KEY_last_scrape_timed_out_camel` handling

* refactor: move `TR_KEY_leecher_count_camel` handling

* refactor: move `TR_KEY_next_announce_time_camel` handling

* refactor: move `TR_KEY_next_scrape_time_camel` handling

* refactor: move `TR_KEY_scrape_state_camel` handling

* refactor: move `TR_KEY_seeder_count_camel` handling

* refactor: move `TR_KEY_client_is_choked_camel` handling

* refactor: move `TR_KEY_client_is_interested_camel` handling

* refactor: move `TR_KEY_client_name_camel` handling

* refactor: move `TR_KEY_flag_str_camel` handling

* refactor: move `TR_KEY_is_downloading_from_camel` handling

* refactor: move `TR_KEY_is_encrypted_camel` handling

* refactor: move `TR_KEY_is_incoming_camel` handling

* refactor: move `TR_KEY_is_utp_camel` handling

* refactor: move `TR_KEY_is_uploading_to_camel` handling

* refactor: move `TR_KEY_peer_is_choked_camel` handling

* refactor: move `TR_KEY_peer_is_interested_camel` handling

* refactor: move `TR_KEY_rate_to_client_camel` handling

* refactor: move `TR_KEY_rate_to_peer_camel` handling

* refactor: move `TR_KEY_from_cache_camel` handling

* refactor: move `TR_KEY_from_dht_camel` handling

* refactor: move `TR_KEY_from_incoming_camel` handling

* refactor: move `TR_KEY_from_lpd_camel` handling

* refactor: move `TR_KEY_from_ltep_camel` handling

* refactor: move `TR_KEY_from_pex_camel` handling

* refactor: move `TR_KEY_from_pex_camel` handling

* refactor: move `TR_KEY_tracker_add_camel` handling

* refactor: move `TR_KEY_tracker_remove_camel` handling

* refactor: move `TR_KEY_tracker_replace_camel` handling

* refactor: move `TR_KEY_downloaded_bytes_camel` handling

* refactor: move `TR_KEY_files_added_camel` handling

* refactor: move `TR_KEY_seconds_active_camel` handling

* refactor: move `TR_KEY_session_count_camel` handling

* refactor: move `TR_KEY_uploaded_bytes_camel` handling

* refactor: move `TR_KEY_active_torrent_count_camel` handling

* refactor: move `TR_KEY_cumulative_stats_kebab` handling

* refactor: move `TR_KEY_cumulative_stats_kebab` handling

* refactor: move `TR_KEY_download_speed_camel` handling

* refactor: move `TR_KEY_paused_torrent_count_camel` handling

* refactor: move `TR_KEY_torrent_count_camel` handling

* refactor: move `TR_KEY_upload_speed_camel` handling

* refactor: move `TR_KEY_files_unwanted_kebab` handling

* refactor: move `TR_KEY_files_wanted_kebab` handling

* refactor: move `TR_KEY_priority_high_kebab` handling

* refactor: move `TR_KEY_priority_low_kebab` handling

* refactor: move `TR_KEY_priority_normal_kebab` handling

* refactor: move `TR_KEY_port_is_open_kebab` handling

* refactor: move `TR_KEY_torrent_duplicate_kebab` handling

* refactor: move `TR_KEY_torrent_added_kebab` handling

* refactor: move `TR_KEY_memory_bytes_kebab` handling

* refactor: move `TR_KEY_memory_units_kebab` handling

* refactor: move `TR_KEY_size_bytes_kebab` handling

* refactor: move `TR_KEY_size_units_kebab` handling

* refactor: move `TR_KEY_speed_bytes_kebab` handling

* refactor: move `TR_KEY_speed_units_kebab` handling

* refactor: remove DoneCb

* perf: adjust reserve capacity
2025-12-24 13:29:59 -06:00

108 lines
3.0 KiB
C++

// 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 <cstdint> // int64_t
#include <memory>
#include <optional>
#include <string_view>
#include <unordered_map>
#include <QFuture>
#include <QFutureInterface>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QObject>
#include <QString>
#include <QUrl>
#include <libtransmission/transmission.h>
#include <libtransmission/api-compat.h>
#include <libtransmission/quark.h>
#include <libtransmission/variant.h>
class QNetworkAccessManager;
using TrVariantPtr = std::shared_ptr<tr_variant>;
Q_DECLARE_METATYPE(TrVariantPtr)
extern "C"
{
struct tr_session;
}
struct RpcResponse
{
QString errmsg;
TrVariantPtr args;
bool success = false;
QNetworkReply::NetworkError networkError = QNetworkReply::NoError;
};
Q_DECLARE_METATYPE(QFutureInterface<RpcResponse>)
// The response future -- the RPC engine returns one for each request made.
using RpcResponseFuture = QFuture<RpcResponse>;
class RpcClient : public QObject
{
Q_OBJECT
public:
explicit RpcClient(QObject* parent = nullptr);
RpcClient(RpcClient&&) = delete;
RpcClient(RpcClient const&) = delete;
RpcClient& operator=(RpcClient&&) = delete;
RpcClient& operator=(RpcClient const&) = delete;
[[nodiscard]] constexpr auto const& url() const noexcept
{
return url_;
}
[[nodiscard]] constexpr auto isLocal() const noexcept
{
return session_ != nullptr || url_is_loopback_;
}
void stop();
void start(tr_session* session);
void start(QUrl const& url);
RpcResponseFuture exec(tr_quark method, tr_variant* args);
signals:
void httpAuthenticationRequired();
void dataReadProgress();
void dataSendProgress();
void networkResponse(QNetworkReply::NetworkError code, QString const& message);
private slots:
void networkRequestFinished(QNetworkReply* reply);
void localRequestFinished(TrVariantPtr response);
private:
QNetworkAccessManager* networkAccessManager();
void sendNetworkRequest(QByteArray const& body, QFutureInterface<RpcResponse> const& promise);
void sendLocalRequest(tr_variant& req, QFutureInterface<RpcResponse> const& promise, int64_t id);
[[nodiscard]] int64_t parseResponseId(tr_variant& response) const;
[[nodiscard]] RpcResponse parseResponseData(tr_variant& response) const;
// TODO: change this default in 5.0.0-beta.1
static auto constexpr DefaultNetworkStyle = libtransmission::api_compat::Style::Tr4;
libtransmission::api_compat::Style network_style_ = DefaultNetworkStyle;
tr_session* session_ = {};
QByteArray session_id_;
QUrl url_;
QNetworkAccessManager* nam_ = {};
std::unordered_map<int64_t, QFutureInterface<RpcResponse>> local_requests_;
bool const verbose_ = qEnvironmentVariableIsSet("TR_RPC_VERBOSE");
bool url_is_loopback_ = false;
};