mirror of
https://github.com/transmission/transmission
synced 2025-03-13 07:33:02 +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:
parent
5296570476
commit
18ea8c429a
10 changed files with 197 additions and 187 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
21
gtk/main.c
21
gtk/main.c
|
@ -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*
|
||||
|
|
|
@ -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,
|
||||
void * unused UNUSED)
|
||||
core_read_rpc_response (tr_session * session UNUSED,
|
||||
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);
|
||||
}
|
||||
|
||||
/***
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
@ -516,19 +509,21 @@ struct rpc_response_data
|
|||
};
|
||||
|
||||
static void
|
||||
rpc_response_func (tr_session * session UNUSED,
|
||||
struct evbuffer * response,
|
||||
void * user_data)
|
||||
rpc_response_func (tr_session * session UNUSED,
|
||||
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
|
||||
|
|
|
@ -7,10 +7,6 @@
|
|||
* $Id$
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <event2/buffer.h>
|
||||
|
||||
#include "transmission.h"
|
||||
#include "rpcimpl.h"
|
||||
#include "utils.h"
|
||||
|
@ -75,18 +71,19 @@ test_list (void)
|
|||
***/
|
||||
|
||||
static void
|
||||
rpc_response_func (tr_session * session UNUSED,
|
||||
struct evbuffer * response,
|
||||
void * setme)
|
||||
rpc_response_func (tr_session * session UNUSED,
|
||||
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);
|
||||
|
|
|
@ -84,29 +84,25 @@ notify (tr_session * session,
|
|||
* when the task is complete */
|
||||
struct tr_rpc_idle_data
|
||||
{
|
||||
tr_session * session;
|
||||
tr_variant * response;
|
||||
tr_variant * args_out;
|
||||
tr_rpc_response_func callback;
|
||||
void * callback_user_data;
|
||||
tr_session * session;
|
||||
tr_variant * response;
|
||||
tr_variant * args_out;
|
||||
tr_rpc_response_func callback;
|
||||
void * callback_user_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);
|
||||
|
||||
if (result == NULL)
|
||||
result = "success";
|
||||
tr_variantDictAddStr (data->response, TR_KEY_result, result);
|
||||
(*data->callback)(data->session, data->response, data->callback_user_data);
|
||||
|
||||
buf = tr_variantToBuf (data->response, TR_VARIANT_FMT_JSON_LEAN);
|
||||
(*data->callback)(data->session, buf, data->callback_user_data);
|
||||
evbuffer_free (buf);
|
||||
|
||||
tr_variantFree (data->response);
|
||||
tr_free (data->response);
|
||||
tr_free (data);
|
||||
tr_variantFree (data->response);
|
||||
tr_free (data->response);
|
||||
tr_free (data);
|
||||
}
|
||||
|
||||
/***
|
||||
|
@ -1450,7 +1446,7 @@ portTested (tr_session * session UNUSED,
|
|||
tr_snprintf (result, sizeof (result), "success");
|
||||
}
|
||||
|
||||
tr_idle_function_done (data, result);
|
||||
tr_idle_function_done (data, result);
|
||||
}
|
||||
|
||||
static const char*
|
||||
|
@ -2177,28 +2173,29 @@ methods[] =
|
|||
};
|
||||
|
||||
static void
|
||||
noop_response_callback (tr_session * session UNUSED,
|
||||
struct evbuffer * response UNUSED,
|
||||
void * user_data UNUSED)
|
||||
noop_response_callback (tr_session * session UNUSED,
|
||||
tr_variant * response UNUSED,
|
||||
void * user_data UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
request_exec (tr_session * session,
|
||||
tr_variant * request,
|
||||
tr_rpc_response_func callback,
|
||||
void * callback_user_data)
|
||||
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);
|
||||
|
|
|
@ -21,15 +21,13 @@ extern "C" {
|
|||
**** RPC processing
|
||||
***/
|
||||
|
||||
struct evbuffer;
|
||||
typedef void (*tr_rpc_response_func)(tr_session * session,
|
||||
tr_variant * response,
|
||||
void * user_data);
|
||||
|
||||
typedef void (*tr_rpc_response_func)(tr_session * session,
|
||||
struct evbuffer * 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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue