mirror of
https://github.com/transmission/transmission
synced 2024-12-24 08:43:27 +00:00
make the request/response messages a little terser. add per-torrent speed limit toggles. rename ipc -> rpc.
This commit is contained in:
parent
48874c0619
commit
17b9dc7462
4 changed files with 96 additions and 104 deletions
|
@ -18,46 +18,45 @@
|
|||
floating-point numbers are represented as strings.
|
||||
booleans are represented as integers where 0 is false and 1 is true.
|
||||
|
||||
There are only two message types: request and response. Both
|
||||
are JSON objects with two members: "headers" (described in 2.1)
|
||||
and "body" (described in 2.2 - 2.3).
|
||||
Messages are represented as a JSON objects. There are two types:
|
||||
requests (described in 2.1) and responses (described in 2.2).
|
||||
|
||||
2.1. Headers
|
||||
2.1. Requests
|
||||
|
||||
Message headers support two members:
|
||||
(1) A required "type" string whose value must be "request" or "response".
|
||||
(2) An optional "tag" integer supplied by requests for their own use.
|
||||
Responses MUST include the request tag's verbatim.
|
||||
Requests supports three keys:
|
||||
|
||||
2.2. Request Body
|
||||
(1) A required "method" string telling the name of the method to invoke
|
||||
(2) An optional "arguments" object of name/value pairs
|
||||
(3) An optional "tag" integer used for clients to track responses.
|
||||
If provided by a request, the response MUST include the same tag.
|
||||
|
||||
Request bodies support two members:
|
||||
(1) A required "name" string telling the name of the request.
|
||||
(2) An optional "arguments" object of name/value pairs.
|
||||
2.2. Responses
|
||||
|
||||
2.3. Response Body
|
||||
Reponses support three keys:
|
||||
|
||||
All response bodies support two members:
|
||||
(1) A required "result" string whose value must be "success" on success,
|
||||
and may be "no-permission", "bad-format", or "error" on failure.
|
||||
(2) An optional "arguments" object of name/value pairs.
|
||||
The contents of these arguments depend on the request's name.
|
||||
or an error string on failure.
|
||||
(2) An optional "arguments" object of name/value pairs
|
||||
(3) An optional "tag" integer as described in 2.1.
|
||||
|
||||
3. Torrent Requests
|
||||
|
||||
3.1. Torrent Action Requests
|
||||
|
||||
Request names: "torrent-start", "torrent-stop",
|
||||
"torrent-remove", "torrent-verify"
|
||||
Method names: "torrent-start", "torrent-stop",
|
||||
"torrent-remove", "torrent-verify"
|
||||
|
||||
Request arguments: "ids", a list of unique torrent ids, sha1 hash strings,
|
||||
or both. These are the torrents that the request will
|
||||
be applied to. If "ids" is ommitted, the request is
|
||||
applied to all torrents.
|
||||
|
||||
Response arguments: none.
|
||||
|
||||
3.2. Torrent Info Requests
|
||||
|
||||
Request name: "torrent-info".
|
||||
Method name: "torrent-info".
|
||||
|
||||
Request arguments: 3.1's optional "ids" argument.
|
||||
|
||||
Response arguments: "info", an array of objects based on libtransmission's
|
||||
|
@ -70,53 +69,42 @@
|
|||
Example Request:
|
||||
|
||||
{
|
||||
"headers": {
|
||||
"type": "request",
|
||||
"tag": 666
|
||||
},
|
||||
"body": {
|
||||
"name": "torrent-info",
|
||||
"arguments": {
|
||||
"ids": [ 7, 10 ]
|
||||
}
|
||||
}
|
||||
"arguments": { "ids": [ 7, 10 ] }
|
||||
"method": "torrent-info",
|
||||
"tag": 666
|
||||
}
|
||||
|
||||
Example Response:
|
||||
|
||||
{
|
||||
"headers": {
|
||||
"type": "response",
|
||||
"tag": 666
|
||||
}
|
||||
"body": {
|
||||
"result": "success",
|
||||
"arguments": {
|
||||
"info": [
|
||||
{
|
||||
"id": 7,
|
||||
"totalSize": 9803930483,
|
||||
"pieceCount": 1209233,
|
||||
"pieceSize": 4096,
|
||||
"name": "Ubuntu x86_64 DVD",
|
||||
...
|
||||
}
|
||||
{
|
||||
"id": 10,
|
||||
"totalSize": 2398480394,
|
||||
"pieceCount": 83943,
|
||||
"pieceSize": 12345,
|
||||
"name": "Ubuntu i386 DVD",
|
||||
...
|
||||
}
|
||||
]
|
||||
}
|
||||
"tag": 666
|
||||
"result": "success",
|
||||
"arguments": {
|
||||
"info": [
|
||||
{
|
||||
"id": 7,
|
||||
"totalSize": 9803930483,
|
||||
"pieceCount": 1209233,
|
||||
"pieceSize": 4096,
|
||||
"name": "Ubuntu x86_64 DVD",
|
||||
...
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"totalSize": 2398480394,
|
||||
"pieceCount": 83943,
|
||||
"pieceSize": 12345,
|
||||
"name": "Ubuntu i386 DVD",
|
||||
...
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
3.3. Torrent Status Requests
|
||||
|
||||
Request name is "torrent-status".
|
||||
Method name: "torrent-status"
|
||||
|
||||
Request arguments: 3.1's optional "ids" argument.
|
||||
|
||||
Response arguments: "status", an array of objects based on
|
||||
|
@ -128,12 +116,13 @@
|
|||
|
||||
3.4. Adding a Torrent
|
||||
|
||||
Request name: "torrent-add"
|
||||
Method name: "torrent-add"
|
||||
|
||||
Request arguments:
|
||||
|
||||
string | value type & description
|
||||
-------------------+-------------------------------------------------
|
||||
"autostart" | boolean true means to auto-start torrents
|
||||
"paused" | boolean if true, don't start the torrent
|
||||
"destination" | string path to download the torrent to
|
||||
"filename" | string location of the .torrent file
|
||||
"peer-limit" | int maximum number of peers
|
||||
|
@ -147,21 +136,23 @@
|
|||
|
||||
Common arguments:
|
||||
|
||||
string | value type & description
|
||||
-------------------+-------------------------------------------------
|
||||
"peer-limit" | int maximum number of peers
|
||||
"speed-limit-down" | int maximum download speed (in KiB/s)
|
||||
"speed-limit-up" | int maximum upload speed (in KiB/s)
|
||||
string | value type & description
|
||||
---------------------------+-------------------------------------------------
|
||||
"peer-limit" | int maximum number of peers
|
||||
"speed-limit-down" | int maximum download speed (in KiB/s)
|
||||
"speed-limit-down-enabled" | boolean true if the download speed is limited
|
||||
"speed-limit-up" | int maximum upload speed (in KiB/s)
|
||||
"speed-limit-up-enabled" | boolean true if the upload speed is limited
|
||||
|
||||
3.5.1. Mutators
|
||||
|
||||
Request name: "torrent-set"
|
||||
Method name: "torrent-set"
|
||||
Request arguments: 3.1's "ids", plus one or more of 3.5's arguments
|
||||
Response arguments: none
|
||||
|
||||
3.5.2. Accessors
|
||||
|
||||
Request name: "torrent-get"
|
||||
Method name: "torrent-get"
|
||||
Request arguments: none
|
||||
Response arguments: A "torrents" list of objects containing all
|
||||
of 3.5's arguments plus the torrent's "id" int.
|
||||
|
@ -181,13 +172,13 @@
|
|||
|
||||
3.6.1. Mutators
|
||||
|
||||
Request name: "torrent-set-file"
|
||||
Method name: "torrent-set-file"
|
||||
Request arguments: 3.1's "ids", plus one or more of 3.6's arguments
|
||||
Response arguments: none
|
||||
|
||||
3.6.2. Accessors
|
||||
|
||||
Request name: "torrent-get-file"
|
||||
Method name: "torrent-get-file"
|
||||
Request arguments: none
|
||||
Response arguments: A "torrents" list of objects containing all
|
||||
of 3.6's arguments plus the torrent's "id" int.
|
||||
|
@ -210,13 +201,13 @@
|
|||
|
||||
4.2. Mutators
|
||||
|
||||
Request name: "session-set"
|
||||
Method name: "session-set"
|
||||
Request arguments: one or more of 4.1's arguments
|
||||
Response arguments: none
|
||||
|
||||
4.2. Accessors
|
||||
|
||||
Request name: "session-get"
|
||||
Method name: "session-get"
|
||||
Request arguments: none
|
||||
Response arguments: all of 4.1's arguments
|
||||
|
|
@ -16,7 +16,6 @@ libtransmission_a_SOURCES = \
|
|||
ggets.c \
|
||||
handshake.c \
|
||||
inout.c \
|
||||
ipc.c \
|
||||
ipcparse.c \
|
||||
json.c \
|
||||
list.c \
|
||||
|
@ -33,6 +32,7 @@ libtransmission_a_SOURCES = \
|
|||
publish.c \
|
||||
ratecontrol.c \
|
||||
resume.c \
|
||||
rpc.c \
|
||||
session.c \
|
||||
stats.c \
|
||||
torrent.c \
|
||||
|
@ -57,7 +57,6 @@ noinst_HEADERS = \
|
|||
ggets.h \
|
||||
handshake.h \
|
||||
inout.h \
|
||||
ipc.h \
|
||||
ipcparse.h \
|
||||
list.h \
|
||||
makemeta.h \
|
||||
|
@ -74,6 +73,7 @@ noinst_HEADERS = \
|
|||
publish.h \
|
||||
ratecontrol.h \
|
||||
resume.h \
|
||||
rpc.h \
|
||||
session.h \
|
||||
stats.h \
|
||||
torrent.h \
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
#include "transmission.h"
|
||||
#include "bencode.h"
|
||||
#include "ipc.h"
|
||||
#include "rpc.h"
|
||||
#include "torrent.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
@ -245,14 +245,20 @@ torrentGet( tr_handle * handle, tr_benc * args_in, tr_benc * args_out )
|
|||
for( i=0; i<torrentCount; ++i )
|
||||
{
|
||||
tr_torrent * tor = torrents[i];
|
||||
tr_benc * d = tr_bencListAddDict( list, 4 );
|
||||
tr_benc * d = tr_bencListAddDict( list, 6 );
|
||||
tr_bencDictAddInt( d, "id", tor->uniqueId );
|
||||
tr_bencDictAddInt( d, "peer-limit",
|
||||
tr_torrentGetPeerLimit( tor ) );
|
||||
tr_bencDictAddInt( d, "speed-limit-down",
|
||||
tr_torrentGetSpeedLimit( tor, TR_DOWN ) );
|
||||
tr_bencDictAddInt( d, "speed-limit-down-enabled",
|
||||
tr_torrentGetSpeedMode( tor, TR_DOWN )
|
||||
== TR_SPEEDLIMIT_SINGLE );
|
||||
tr_bencDictAddInt( d, "speed-limit-up",
|
||||
tr_torrentGetSpeedLimit( tor, TR_UP ) );
|
||||
tr_bencDictAddInt( d, "speed-limit-up-enabled",
|
||||
tr_torrentGetSpeedMode( tor, TR_UP )
|
||||
== TR_SPEEDLIMIT_SINGLE );
|
||||
}
|
||||
|
||||
tr_free( torrents );
|
||||
|
@ -273,8 +279,14 @@ torrentSet( tr_handle * handle, tr_benc * args_in, tr_benc * args_out UNUSED )
|
|||
tr_torrentSetPeerLimit( tor, tmp );
|
||||
if( tr_bencDictFindInt( args_in, "speed-limit-down", &tmp ) )
|
||||
tr_torrentSetSpeedLimit( tor, TR_DOWN, tmp );
|
||||
if( tr_bencDictFindInt( args_in, "speed-limit-down-enabled", &tmp ) )
|
||||
tr_torrentSetSpeedMode( tor, TR_DOWN, tmp ? TR_SPEEDLIMIT_SINGLE
|
||||
: TR_SPEEDLIMIT_GLOBAL );
|
||||
if( tr_bencDictFindInt( args_in, "speed-limit-up", &tmp ) )
|
||||
tr_torrentSetSpeedLimit( tor, TR_UP, tmp );
|
||||
if( tr_bencDictFindInt( args_in, "speed-limit-up-enabled", &tmp ) )
|
||||
tr_torrentSetSpeedMode( tor, TR_UP, tmp ? TR_SPEEDLIMIT_SINGLE
|
||||
: TR_SPEEDLIMIT_GLOBAL );
|
||||
}
|
||||
|
||||
tr_free( torrents );
|
||||
|
@ -438,8 +450,8 @@ torrentAdd( tr_handle * h, tr_benc * args_in, tr_benc * args_out )
|
|||
|
||||
ctor = tr_ctorNew( h );
|
||||
tr_ctorSetMetainfoFromFile( ctor, filename );
|
||||
if( tr_bencDictFindInt( args_in, "autostart", &i ) )
|
||||
tr_ctorSetPaused( ctor, TR_FORCE, !i );
|
||||
if( tr_bencDictFindInt( args_in, "paused", &i ) )
|
||||
tr_ctorSetPaused( ctor, TR_FORCE, i );
|
||||
if( tr_bencDictFindInt( args_in, "peer-limit", &i ) )
|
||||
tr_ctorSetPeerLimit( ctor, TR_FORCE, i );
|
||||
if( tr_bencDictFindStr( args_in, "destination", &str ) )
|
||||
|
@ -538,7 +550,7 @@ typedef const char* (handler)( tr_handle*, tr_benc*, tr_benc* );
|
|||
|
||||
struct request_handler
|
||||
{
|
||||
const char * name;
|
||||
const char * method;
|
||||
handler * func;
|
||||
} request_handlers[] = {
|
||||
{ "torrent-start", torrentStart },
|
||||
|
@ -565,51 +577,40 @@ request_exec( struct tr_handle * handle,
|
|||
const char * str;
|
||||
char * out;
|
||||
tr_benc response;
|
||||
tr_benc * headers_in = NULL;
|
||||
tr_benc * body_in = NULL;
|
||||
tr_benc * args_in = NULL;
|
||||
tr_benc * headers_out = NULL;
|
||||
tr_benc * body_out = NULL;
|
||||
tr_benc * args_in = tr_bencDictFind( request, "args" );
|
||||
tr_benc * args_out = NULL;
|
||||
const char * result = NULL;
|
||||
|
||||
headers_in = tr_bencDictFind( request, "headers" );
|
||||
body_in = tr_bencDictFind( request, "body" );
|
||||
args_in = tr_bencDictFind( body_in, "args" );
|
||||
|
||||
/* build the response skeleton */
|
||||
tr_bencInitDict( &response, 2 );
|
||||
headers_out = tr_bencDictAddDict( &response, "headers", 2 );
|
||||
tr_bencDictAddStr( headers_out, "type", "response" );
|
||||
if( tr_bencDictFindInt( headers_in, "tag", &i ) )
|
||||
tr_bencDictAddInt( headers_out, "tag", i );
|
||||
body_out = tr_bencDictAddDict( &response, "body", 2 );
|
||||
args_out = tr_bencDictAddDict( body_out, "args", 0 );
|
||||
tr_bencInitDict( &response, 3 );
|
||||
if( tr_bencDictFindInt( request, "tag", &i ) )
|
||||
tr_bencDictAddInt( request, "tag", i );
|
||||
args_out = tr_bencDictAddDict( &response, "args", 0 );
|
||||
|
||||
/* parse the request */
|
||||
if( !tr_bencDictFindStr( body_in, "name", &str ) )
|
||||
result = "no request name given";
|
||||
if( !tr_bencDictFindStr( request, "method", &str ) )
|
||||
result = "no method name";
|
||||
else {
|
||||
const int n = TR_N_ELEMENTS( request_handlers );
|
||||
for( i=0; i<n; ++i )
|
||||
if( !strcmp( str, request_handlers[i].name ) )
|
||||
if( !strcmp( str, request_handlers[i].method ) )
|
||||
break;
|
||||
result = i==n
|
||||
? "request name not recognized"
|
||||
? "method name not recognized"
|
||||
: (*request_handlers[i].func)( handle, args_in, args_out );
|
||||
}
|
||||
|
||||
/* serialize & return the response */
|
||||
if( !result )
|
||||
result = "success";
|
||||
tr_bencDictAddStr( body_out, "result", result );
|
||||
out = tr_bencSave( &response, response_len ); /* TODO: json, not benc */
|
||||
result = "success";
|
||||
tr_bencDictAddStr( &response, "result", result );
|
||||
out = tr_bencSaveAsJSON( &response, response_len );
|
||||
tr_bencFree( &response );
|
||||
return out;
|
||||
}
|
||||
|
||||
char*
|
||||
tr_ipc_request_exec( struct tr_handle * handle,
|
||||
tr_rpc_request_exec( struct tr_handle * handle,
|
||||
const void * request_json,
|
||||
int request_len,
|
||||
int * response_len )
|
|
@ -10,13 +10,13 @@
|
|||
* $Id:$
|
||||
*/
|
||||
|
||||
#ifndef TR_IPC_H
|
||||
#define TR_IPC_H
|
||||
#ifndef TR_RPC_H
|
||||
#define TR_RPC_H
|
||||
|
||||
struct tr_handle;
|
||||
|
||||
char*
|
||||
tr_ipc_request_exec( struct tr_handle * handle,
|
||||
tr_rpc_request_exec( struct tr_handle * handle,
|
||||
const void * request_json,
|
||||
int request_len,
|
||||
int * response_len );
|
Loading…
Reference in a new issue