1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2025-03-13 15:39:01 +00:00

Improve RPC performance for local sessions

Don't unnecessarily de-/serialize JSON data if local session is used.
This commit is contained in:
Mike Gelfand 2015-07-13 00:32:48 +00:00
parent 5296570476
commit 18ea8c429a
10 changed files with 197 additions and 187 deletions

View file

@ -2442,15 +2442,19 @@ on_add_tracker_response (GtkDialog * dialog, int response, gpointer gdi)
{
if (tr_urlIsValidTracker (url))
{
char * json = g_strdup_printf (
"{\n"
" \"method\": \"torrent-set\",\n"
" \"arguments\": { \"id\": %d, \"trackerAdd\": [ \"%s\" ] }\n"
"}\n",
torrent_id, url);
gtr_core_exec_json (di->core, json);
tr_variant top, * args, * trackers;
tr_variantInitDict (&top, 2);
tr_variantDictAddStr (&top, TR_KEY_method, "torrent-set");
args = tr_variantDictAddDict (&top, TR_KEY_arguments, 2);
tr_variantDictAddInt (args, TR_KEY_id, torrent_id);
trackers = tr_variantDictAddList (args, TR_KEY_trackerAdd, 1);
tr_variantListAddStr (trackers, url);
gtr_core_exec (di->core, &top);
refresh (di);
g_free (json);
tr_variantFree (&top);
}
else
{
@ -2518,20 +2522,25 @@ on_tracker_list_remove_button_clicked (GtkButton * button UNUSED, gpointer gdi)
if (gtk_tree_selection_get_selected (sel, &model, &iter))
{
char * json;
int torrent_id;
int tracker_id;
tr_variant top, * args, * trackers;
gtk_tree_model_get (model, &iter, TRACKER_COL_TRACKER_ID, &tracker_id,
TRACKER_COL_TORRENT_ID, &torrent_id,
-1);
json = g_strdup_printf ("{\n"
" \"method\": \"torrent-set\",\n"
" \"arguments\": { \"id\": %d, \"trackerRemove\": [ %d ] }\n"
"}\n",
torrent_id, tracker_id);
gtr_core_exec_json (di->core, json);
tr_variantInitDict (&top, 2);
tr_variantDictAddStr (&top, TR_KEY_method, "torrent-set");
args = tr_variantDictAddDict (&top, TR_KEY_arguments, 2);
tr_variantDictAddInt (args, TR_KEY_id, torrent_id);
trackers = tr_variantDictAddList (args, TR_KEY_trackerRemove, 1);
tr_variantListAddInt (trackers, tracker_id);
gtr_core_exec (di->core, &top);
refresh (di);
g_free (json);
tr_variantFree (&top);
}
}

View file

@ -1414,10 +1414,7 @@ call_rpc_for_selected_torrents (struct cbdata * data, const char * method)
if (tr_variantListSize (ids) != 0)
{
int json_len;
char * json = tr_variantToStr (&top, TR_VARIANT_FMT_JSON_LEAN, &json_len);
tr_rpc_request_exec_json (session, json, json_len, NULL, NULL);
g_free (json);
tr_rpc_request_exec_json (session, &top, NULL, NULL);
invoked = TRUE;
}
@ -1467,16 +1464,24 @@ static void
start_all_torrents (struct cbdata * data)
{
tr_session * session = gtr_core_session (data->core);
const char * cmd = "{ \"method\": \"torrent-start\" }";
tr_rpc_request_exec_json (session, cmd, strlen (cmd), NULL, NULL);
tr_variant request;
tr_variantInitDict (&request, 1);
tr_variantDictAddStr (&request, TR_KEY_method, "torrent-start");
tr_rpc_request_exec_json (session, &request, NULL, NULL);
tr_variantFree (&request);
}
static void
pause_all_torrents (struct cbdata * data)
{
tr_session * session = gtr_core_session (data->core);
const char * cmd = "{ \"method\": \"torrent-stop\" }";
tr_rpc_request_exec_json (session, cmd, strlen (cmd), NULL, NULL);
tr_variant request;
tr_variantInitDict (&request, 1);
tr_variantDictAddStr (&request, TR_KEY_method, "torrent-stop");
tr_rpc_request_exec_json (session, &request, NULL, NULL);
tr_variantFree (&request);
}
static tr_torrent*

View file

@ -1726,41 +1726,41 @@ static GHashTable * pendingRequests = NULL;
static gboolean
core_read_rpc_response_idle (void * vresponse)
{
tr_variant top;
int64_t intVal;
struct evbuffer * response = vresponse;
tr_variant * response = vresponse;
tr_variantFromJson (&top, evbuffer_pullup (response, -1), evbuffer_get_length (response));
if (tr_variantDictFindInt (&top, TR_KEY_tag, &intVal))
if (tr_variantDictFindInt (response, TR_KEY_tag, &intVal))
{
const int tag = (int)intVal;
struct pending_request_data * data = g_hash_table_lookup (pendingRequests, &tag);
if (data)
{
if (data->response_func)
(*data->response_func)(data->core, &top, data->response_func_user_data);
(*data->response_func)(data->core, response, data->response_func_user_data);
g_hash_table_remove (pendingRequests, &tag);
}
}
tr_variantFree (&top);
evbuffer_free (response);
tr_variantFree (response);
tr_free (response);
return G_SOURCE_REMOVE;
}
static void
core_read_rpc_response (tr_session * session UNUSED,
struct evbuffer * response,
tr_variant * response,
void * unused UNUSED)
{
struct evbuffer * buf = evbuffer_new ();
evbuffer_add_buffer (buf, response);
gdk_threads_add_idle (core_read_rpc_response_idle, buf);
tr_variant * response_copy = tr_new (tr_variant, 1);
*response_copy = *response;
tr_variantInitBool (response, false);
gdk_threads_add_idle (core_read_rpc_response_idle, response_copy);
}
static void
core_send_rpc_request (TrCore * core, const char * json, int tag,
core_send_rpc_request (TrCore * core, const tr_variant * request, int tag,
server_response_func * response_func,
void * response_func_user_data)
{
@ -1787,9 +1787,15 @@ core_send_rpc_request (TrCore * core, const char * json, int tag,
/* make the request */
#ifdef DEBUG_RPC
g_message ("request: [%s]", json);
{
struct evbuffer * buf = tr_variantToBuf (request, TR_VARIANT_FMT_JSON_LEAN);
const size_t buf_len = evbuffer_get_length (buf);
g_message ("request: [%*.*s]", (int) buf_len, (int) buf_len, evbuffer_pullup (buf, -1));
evbuffer_free (buf);
}
#endif
tr_rpc_request_exec_json (session, json, strlen (json), core_read_rpc_response, GINT_TO_POINTER (tag));
tr_rpc_request_exec_json (session, request, core_read_rpc_response, GINT_TO_POINTER (tag));
}
}
@ -1813,10 +1819,14 @@ on_port_test_response (TrCore * core, tr_variant * response, gpointer u UNUSED)
void
gtr_core_port_test (TrCore * core)
{
char buf[64];
const int tag = nextTag++;
g_snprintf (buf, sizeof (buf), "{ \"method\": \"port-test\", \"tag\": %d }", tag);
core_send_rpc_request (core, buf, tag, on_port_test_response, NULL);
tr_variant request;
tr_variantInitDict (&request, 2);
tr_variantDictAddStr (&request, TR_KEY_method, "port-test");
tr_variantDictAddInt (&request, TR_KEY_tag, tag);
core_send_rpc_request (core, &request, tag, on_port_test_response, NULL);
tr_variantFree (&request);
}
/***
@ -1842,29 +1852,25 @@ on_blocklist_response (TrCore * core, tr_variant * response, gpointer data UNUSE
void
gtr_core_blocklist_update (TrCore * core)
{
char buf[64];
const int tag = nextTag++;
g_snprintf (buf, sizeof (buf), "{ \"method\": \"blocklist-update\", \"tag\": %d }", tag);
core_send_rpc_request (core, buf, tag, on_blocklist_response, NULL);
tr_variant request;
tr_variantInitDict (&request, 2);
tr_variantDictAddStr (&request, TR_KEY_method, "blocklist-update");
tr_variantDictAddInt (&request, TR_KEY_tag, tag);
core_send_rpc_request (core, &request, tag, on_blocklist_response, NULL);
tr_variantFree (&request);
}
/***
****
***/
void
gtr_core_exec_json (TrCore * core, const char * json)
{
const int tag = nextTag++;
core_send_rpc_request (core, json, tag, NULL, NULL);
}
void
gtr_core_exec (TrCore * core, const tr_variant * top)
{
char * json = tr_variantToStr (top, TR_VARIANT_FMT_JSON_LEAN, NULL);
gtr_core_exec_json (core, json);
tr_free (json);
const int tag = nextTag++;
core_send_rpc_request (core, top, tag, NULL, NULL);
}
/***

View file

@ -155,8 +155,6 @@ void gtr_core_blocklist_update (TrCore * core);
void gtr_core_exec (TrCore * core, const tr_variant * benc);
void gtr_core_exec_json (TrCore * core, const char * json);
void gtr_core_open_folder (TrCore * core, int torrent_id);

View file

@ -265,14 +265,7 @@ handle_upload (struct evhttp_request * req,
}
if (have_source)
{
struct evbuffer * json = tr_variantToBuf (&top, TR_VARIANT_FMT_JSON);
tr_rpc_request_exec_json (server->session,
evbuffer_pullup (json, -1),
evbuffer_get_length (json),
NULL, NULL);
evbuffer_free (json);
}
tr_rpc_request_exec_json (server->session, &top, NULL, NULL);
tr_variantFree (&top);
}
@ -517,18 +510,20 @@ struct rpc_response_data
static void
rpc_response_func (tr_session * session UNUSED,
struct evbuffer * response,
tr_variant * response,
void * user_data)
{
struct rpc_response_data * data = user_data;
struct evbuffer * response_buf = tr_variantToBuf (response, TR_VARIANT_FMT_JSON_LEAN);
struct evbuffer * buf = evbuffer_new ();
add_response (data->req, data->server, buf, response);
add_response (data->req, data->server, buf, response_buf);
evhttp_add_header (data->req->output_headers,
"Content-Type", "application/json; charset=UTF-8");
evhttp_send_reply (data->req, HTTP_OK, "OK", buf);
evbuffer_free (buf);
evbuffer_free (response_buf);
tr_free (data);
}
@ -538,13 +533,18 @@ handle_rpc_from_json (struct evhttp_request * req,
const char * json,
size_t json_len)
{
tr_variant top;
bool have_content = tr_variantFromJson (&top, json, json_len) == 0;
struct rpc_response_data * data;
data = tr_new0 (struct rpc_response_data, 1);
data->req = req;
data->server = server;
tr_rpc_request_exec_json (server->session, json, json_len, rpc_response_func, data);
tr_rpc_request_exec_json (server->session, have_content ? &top : NULL, rpc_response_func, data);
if (have_content)
tr_variantFree (&top);
}
static void

View file

@ -7,10 +7,6 @@
* $Id$
*/
#include <string.h>
#include <event2/buffer.h>
#include "transmission.h"
#include "rpcimpl.h"
#include "utils.h"
@ -76,17 +72,18 @@ test_list (void)
static void
rpc_response_func (tr_session * session UNUSED,
struct evbuffer * response,
tr_variant * response,
void * setme)
{
tr_variantFromBuf (setme, TR_VARIANT_FMT_JSON, evbuffer_pullup(response,-1), evbuffer_get_length(response), NULL, NULL);
*(tr_variant *) setme = *response;
tr_variantInitBool (response, false);
}
static int
test_session_get_and_set (void)
{
tr_session * session;
const char * json;
tr_variant request;
tr_variant response;
tr_variant * args;
tr_torrent * tor;
@ -95,10 +92,11 @@ test_session_get_and_set (void)
tor= libttest_zero_torrent_init (session);
check (tor != NULL);
json = "{\"method\":\"session-get\"}";
tr_rpc_request_exec_json (session, json, strlen(json), rpc_response_func, &response);
tr_variantInitDict (&request, 1);
tr_variantDictAddStr (&request, TR_KEY_method, "session-get");
tr_rpc_request_exec_json (session, &request, rpc_response_func, &response);
tr_variantFree (&request);
check (tr_variantIsDict(&response));
check (tr_variantIsDict(&response));
check (tr_variantDictFindDict (&response, TR_KEY_arguments, &args));
check (tr_variantDictFind (args, TR_KEY_alt_speed_down) != NULL);

View file

@ -94,15 +94,11 @@ struct tr_rpc_idle_data
static void
tr_idle_function_done (struct tr_rpc_idle_data * data, const char * result)
{
struct evbuffer * buf;
if (result == NULL)
result = "success";
tr_variantDictAddStr (data->response, TR_KEY_result, result);
buf = tr_variantToBuf (data->response, TR_VARIANT_FMT_JSON_LEAN);
(*data->callback)(data->session, buf, data->callback_user_data);
evbuffer_free (buf);
(*data->callback)(data->session, data->response, data->callback_user_data);
tr_variantFree (data->response);
tr_free (data->response);
@ -2178,27 +2174,28 @@ methods[] =
static void
noop_response_callback (tr_session * session UNUSED,
struct evbuffer * response UNUSED,
tr_variant * response UNUSED,
void * user_data UNUSED)
{
}
static void
request_exec (tr_session * session,
tr_variant * request,
void
tr_rpc_request_exec_json (tr_session * session,
const tr_variant * request,
tr_rpc_response_func callback,
void * callback_user_data)
{
int i;
const char * str;
tr_variant * args_in = tr_variantDictFind (request, TR_KEY_arguments);
tr_variant * const mutable_request = (tr_variant *) request;
tr_variant * args_in = tr_variantDictFind (mutable_request, TR_KEY_arguments);
const char * result = NULL;
if (callback == NULL)
callback = noop_response_callback;
/* parse the request */
if (!tr_variantDictFindStr (request, TR_KEY_method, &str, NULL))
if (!tr_variantDictFindStr (mutable_request, TR_KEY_method, &str, NULL))
{
result = "no method name";
}
@ -2219,17 +2216,14 @@ request_exec (tr_session * session,
{
int64_t tag;
tr_variant response;
struct evbuffer * buf;
tr_variantInitDict (&response, 3);
tr_variantDictAddDict (&response, TR_KEY_arguments, 0);
tr_variantDictAddStr (&response, TR_KEY_result, result);
if (tr_variantDictFindInt (request, TR_KEY_tag, &tag))
if (tr_variantDictFindInt (mutable_request, TR_KEY_tag, &tag))
tr_variantDictAddInt (&response, TR_KEY_tag, tag);
buf = tr_variantToBuf (&response, TR_VARIANT_FMT_JSON_LEAN);
(*callback)(session, buf, callback_user_data);
evbuffer_free (buf);
(*callback)(session, &response, callback_user_data);
tr_variantFree (&response);
}
@ -2238,7 +2232,6 @@ request_exec (tr_session * session,
int64_t tag;
tr_variant response;
tr_variant * args_out;
struct evbuffer * buf;
tr_variantInitDict (&response, 3);
args_out = tr_variantDictAddDict (&response, TR_KEY_arguments, 0);
@ -2246,12 +2239,10 @@ request_exec (tr_session * session,
if (result == NULL)
result = "success";
tr_variantDictAddStr (&response, TR_KEY_result, result);
if (tr_variantDictFindInt (request, TR_KEY_tag, &tag))
if (tr_variantDictFindInt (mutable_request, TR_KEY_tag, &tag))
tr_variantDictAddInt (&response, TR_KEY_tag, tag);
buf = tr_variantToBuf (&response, TR_VARIANT_FMT_JSON_LEAN);
(*callback)(session, buf, callback_user_data);
evbuffer_free (buf);
(*callback)(session, &response, callback_user_data);
tr_variantFree (&response);
}
@ -2262,7 +2253,7 @@ request_exec (tr_session * session,
data->session = session;
data->response = tr_new0 (tr_variant, 1);
tr_variantInitDict (data->response, 3);
if (tr_variantDictFindInt (request, TR_KEY_tag, &tag))
if (tr_variantDictFindInt (mutable_request, TR_KEY_tag, &tag))
tr_variantDictAddInt (data->response, TR_KEY_tag, tag);
data->args_out = tr_variantDictAddDict (data->response, TR_KEY_arguments, 0);
data->callback = callback;
@ -2271,26 +2262,6 @@ request_exec (tr_session * session,
}
}
void
tr_rpc_request_exec_json (tr_session * session,
const void * request_json,
int request_len,
tr_rpc_response_func callback,
void * callback_user_data)
{
tr_variant top;
int have_content;
if (request_len < 0)
request_len = strlen (request_json);
have_content = !tr_variantFromJson (&top, request_json, request_len);
request_exec (session, have_content ? &top : NULL, callback, callback_user_data);
if (have_content)
tr_variantFree (&top);
}
/**
* Munge the URI into a usable form.
*
@ -2366,7 +2337,7 @@ tr_rpc_request_exec_uri (tr_session * session,
pch = next ? next + 1 : NULL;
}
request_exec (session, &top, callback, callback_user_data);
tr_rpc_request_exec_json (session, &top, callback, callback_user_data);
/* cleanup */
tr_variantFree (&top);

View file

@ -21,15 +21,13 @@ extern "C" {
**** RPC processing
***/
struct evbuffer;
typedef void (*tr_rpc_response_func)(tr_session * session,
struct evbuffer * response,
tr_variant * response,
void * user_data);
/* http://www.json.org/ */
void tr_rpc_request_exec_json (tr_session * session,
const void * request_json,
int request_len,
const tr_variant * request,
tr_rpc_response_func callback,
void * callback_user_data);

View file

@ -28,13 +28,31 @@
#define REQUEST_DATA_PROPERTY_KEY "requestData"
namespace
{
void
destroyVariant (tr_variant * json)
{
tr_variantFree (json);
tr_free (json);
}
TrVariantPtr
createVariant ()
{
return TrVariantPtr (tr_new0 (tr_variant, 1), &destroyVariant);
}
}
RpcClient::RpcClient (QObject * parent):
QObject (parent),
mySession (nullptr),
myNAM (nullptr)
{
connect (this, SIGNAL (responseReceived (QByteArray)),
this, SLOT (parseResponse (QByteArray)));
qRegisterMetaType<TrVariantPtr> ("TrVariantPtr");
connect (this, SIGNAL (responseReceived (TrVariantPtr)),
this, SLOT (parseResponse (TrVariantPtr)));
}
void
@ -96,28 +114,23 @@ RpcClient::exec (tr_quark method, tr_variant * args, int64_t tag)
void
RpcClient::exec (const char* method, tr_variant * args, int64_t tag)
{
tr_variant top;
tr_variantInitDict (&top, 3);
tr_variantDictAddStr (&top, TR_KEY_method, method);
TrVariantPtr json = createVariant ();
tr_variantInitDict (json.get (), 3);
tr_variantDictAddStr (json.get (), TR_KEY_method, method);
if (tag >= 0)
tr_variantDictAddInt (&top, TR_KEY_tag, tag);
tr_variantDictAddInt (json.get (), TR_KEY_tag, tag);
if (args != nullptr)
tr_variantDictSteal (&top, TR_KEY_arguments, args);
tr_variantDictSteal (json.get (), TR_KEY_arguments, args);
int length;
char * str = tr_variantToStr (&top, TR_VARIANT_FMT_JSON_LEAN, &length);
sendRequest (QByteArray (str, length));
tr_free (str);
tr_variantFree (&top);
sendRequest (json);
}
void
RpcClient::sendRequest (const QByteArray& json)
RpcClient::sendRequest (TrVariantPtr json)
{
if (mySession != nullptr)
{
tr_rpc_request_exec_json (mySession, json.constData (), json.size (), localSessionCallback, this);
tr_rpc_request_exec_json (mySession, json.get (), localSessionCallback, this);
}
else if (!myUrl.isEmpty ())
{
@ -129,8 +142,13 @@ RpcClient::sendRequest (const QByteArray& json)
if (!mySessionId.isEmpty ())
request.setRawHeader (TR_RPC_SESSION_ID_HEADER, mySessionId.toUtf8 ());
QNetworkReply * reply = networkAccessManager ()->post (request, json);
reply->setProperty (REQUEST_DATA_PROPERTY_KEY, json);
int rawJsonDataLength;
char * rawJsonData = tr_variantToStr (json.get (), TR_VARIANT_FMT_JSON_LEAN, &rawJsonDataLength);
QByteArray jsonData (rawJsonData, rawJsonDataLength);
tr_free (rawJsonData);
QNetworkReply * reply = networkAccessManager ()->post (request, jsonData);
reply->setProperty (REQUEST_DATA_PROPERTY_KEY, QVariant::fromValue (json));
connect (reply, SIGNAL (downloadProgress (qint64, qint64)), this, SIGNAL (dataReadProgress ()));
connect (reply, SIGNAL (uploadProgress (qint64, qint64)), this, SIGNAL (dataSendProgress ()));
connect (reply, SIGNAL (error (QNetworkReply::NetworkError)), this, SIGNAL (error (QNetworkReply::NetworkError)));
@ -142,7 +160,7 @@ RpcClient::sendRequest (const QByteArray& json)
<< ": "
<< request.rawHeader (b).constData ()
<< std::endl;
std::cerr << "Body:\n" << json.constData () << std::endl;
std::cerr << "Body:\n" << jsonData.constData () << std::endl;
#endif
}
}
@ -165,16 +183,19 @@ RpcClient::networkAccessManager ()
}
void
RpcClient::localSessionCallback (tr_session * s, evbuffer * json, void * vself)
RpcClient::localSessionCallback (tr_session * s, tr_variant * response, void * vself)
{
Q_UNUSED (s);
RpcClient * self = static_cast<RpcClient*> (vself);
TrVariantPtr json = createVariant ();
*json = *response;
tr_variantInitBool (response, false);
// this callback is invoked in the libtransmission thread, so we don't want
// to process the response here... let's push it over to the Qt thread.
self->responseReceived (QByteArray (reinterpret_cast<const char*> (evbuffer_pullup (json, -1)),
static_cast<int> (evbuffer_get_length (json))).trimmed ());
self->responseReceived (json);
}
void
@ -196,7 +217,7 @@ RpcClient::onFinished (QNetworkReply * reply)
// we got a 409 telling us our session id has expired.
// update it and resubmit the request.
mySessionId = QString::fromUtf8 (reply->rawHeader (TR_RPC_SESSION_ID_HEADER));
sendRequest (reply->property (REQUEST_DATA_PROPERTY_KEY).toByteArray ());
sendRequest (reply->property (REQUEST_DATA_PROPERTY_KEY).value<TrVariantPtr> ());
}
else if (reply->error () != QNetworkReply::NoError)
{
@ -204,7 +225,12 @@ RpcClient::onFinished (QNetworkReply * reply)
}
else
{
parseResponse (reply->readAll ().trimmed ());
const QByteArray jsonData = reply->readAll ().trimmed ();
TrVariantPtr json = createVariant ();
if (tr_variantFromJson (json.get (), jsonData.constData (), jsonData.size ()) == 0)
parseResponse (json);
emit error (QNetworkReply::NoError);
}
@ -212,25 +238,19 @@ RpcClient::onFinished (QNetworkReply * reply)
}
void
RpcClient::parseResponse (const QByteArray& json)
RpcClient::parseResponse (TrVariantPtr json)
{
tr_variant top;
if (tr_variantFromJson (&top, json.constData (), json.size ()) != 0)
return;
int64_t tag;
if (!tr_variantDictFindInt (&top, TR_KEY_tag, &tag))
if (!tr_variantDictFindInt (json.get (), TR_KEY_tag, &tag))
tag = -1;
const char * result;
if (!tr_variantDictFindStr (&top, TR_KEY_result, &result, nullptr))
if (!tr_variantDictFindStr (json.get (), TR_KEY_result, &result, nullptr))
result = nullptr;
tr_variant * args;
if (!tr_variantDictFindDict (&top, TR_KEY_arguments, &args))
if (!tr_variantDictFindDict (json.get (), TR_KEY_arguments, &args))
args = nullptr;
emit executed (tag, result == nullptr ? QString () : QString::fromUtf8 (result), args);
tr_variantFree (&top);
}

View file

@ -10,6 +10,8 @@
#ifndef QTR_RPC_CLIENT_H
#define QTR_RPC_CLIENT_H
#include <memory>
#include <QNetworkReply>
#include <QObject>
#include <QString>
@ -17,15 +19,18 @@
#include <libtransmission/transmission.h>
#include <libtransmission/quark.h>
#include <libtransmission/variant.h>
class QByteArray;
class QNetworkAccessManager;
typedef std::shared_ptr<tr_variant> TrVariantPtr;
Q_DECLARE_METATYPE (TrVariantPtr);
extern "C"
{
struct evbuffer;
struct tr_session;
struct tr_variant;
}
class RpcClient: public QObject
@ -55,17 +60,17 @@ class RpcClient: public QObject
void executed (int64_t tag, const QString& result, tr_variant * args);
// private
void responseReceived (const QByteArray& json);
void responseReceived (TrVariantPtr json);
private:
void sendRequest (const QByteArray& json);
void sendRequest (TrVariantPtr json);
QNetworkAccessManager * networkAccessManager ();
static void localSessionCallback (tr_session * s, evbuffer * json, void * vself);
static void localSessionCallback (tr_session * s, tr_variant * response, void * vself);
private slots:
void onFinished (QNetworkReply * reply);
void parseResponse (const QByteArray& json);
void parseResponse (TrVariantPtr json);
private:
tr_session * mySession;