// 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 // int64_t #include #include #include #include #include #include #include #include #include #include #include #include #include #include class QNetworkAccessManager; using TrVariantPtr = std::shared_ptr; 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) // The response future -- the RPC engine returns one for each request made. using RpcResponseFuture = QFuture; 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 const& promise); void sendLocalRequest(tr_variant const& req, QFutureInterface const& promise, int64_t id); [[nodiscard]] int64_t parseResponseId(tr_variant& response) const; [[nodiscard]] RpcResponse parseResponseData(tr_variant& response) const; std::optional request_; tr_session* session_ = {}; QString session_id_; QUrl url_; QNetworkAccessManager* nam_ = {}; std::unordered_map> local_requests_; bool const verbose_ = qEnvironmentVariableIsSet("TR_RPC_VERBOSE"); bool url_is_loopback_ = false; };