Ignore:
Timestamp:
May 12, 2008, 1:05:06 PM (14 years ago)
Author:
charles
Message:

json ipc: implement torrent-add, torrent-set-file, torrent-get-file

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/ipc.c

    r5813 r5817  
    1111 */
    1212
     13#include <assert.h>
     14#include <string.h> /* strcmp */
     15
    1316#include "transmission.h"
    1417#include "bencode.h"
     
    1619#include "torrent.h"
    1720#include "utils.h"
     21
     22#define TR_N_ELEMENTS( ary ) ( sizeof( ary ) / sizeof( (ary)[0] ) )
    1823
    1924/***
     
    6166    return torrents;
    6267}
    63            
    64 static const char*
    65 torrentStart( tr_handle * handle, tr_benc * args_in, tr_benc * args_out UNUSED )
    66 {
    67     int i, torrentCount;
    68     tr_torrent ** torrents = getTorrents( handle, args_in, &torrentCount );
    69     for( i=0; i<torrentCount; ++i )
    70         tr_torrentStart( torrents[i] );
    71     tr_free( torrents );
    72     return NULL;
    73 }
    74 
    75 static const char*
    76 torrentStop( tr_handle * handle, tr_benc * args_in, tr_benc * args_out UNUSED )
    77 {
    78     int i, torrentCount;
    79     tr_torrent ** torrents = getTorrents( handle, args_in, &torrentCount );
    80     for( i=0; i<torrentCount; ++i )
    81         tr_torrentStop( torrents[i] );
    82     tr_free( torrents );
    83     return NULL;
    84 }
    85 
    86 static const char*
    87 torrentClose( tr_handle * handle, tr_benc * args_in, tr_benc * args_out UNUSED )
    88 {
    89     int i, torrentCount;
    90     tr_torrent ** torrents = getTorrents( handle, args_in, &torrentCount );
    91     for( i=0; i<torrentCount; ++i )
    92         tr_torrentClose( torrents[i] );
    93     tr_free( torrents );
    94     return NULL;
    95 }
    96 
    97 static const char*
    98 torrentVerify( tr_handle * handle, tr_benc * args_in, tr_benc * args_out UNUSED )
    99 {
    100     int i, torrentCount;
    101     tr_torrent ** torrents = getTorrents( handle, args_in, &torrentCount );
    102     for( i=0; i<torrentCount; ++i )
    103         tr_torrentVerify( torrents[i] );
    104     tr_free( torrents );
     68
     69typedef void( *tor_func )( tr_torrent * tor );
     70
     71static void callTorrentFunc( tr_handle * h, tr_benc * args_in, tor_func func )
     72{
     73    int i, torrentCount;
     74    tr_torrent ** torrents = getTorrents( h, args_in, &torrentCount );
     75    for( i=0; i<torrentCount; ++i )
     76        ( *func )( torrents[i] );
     77    tr_free( torrents );
     78}
     79
     80static const char*
     81torrentStart( tr_handle * h, tr_benc * args_in, tr_benc * args_out UNUSED )
     82{
     83    callTorrentFunc( h, args_in, tr_torrentStart );
     84    return NULL;
     85}
     86
     87static const char*
     88torrentStop( tr_handle * h, tr_benc * args_in, tr_benc * args_out UNUSED )
     89{
     90    callTorrentFunc( h, args_in, tr_torrentStop );
     91    return NULL;
     92}
     93
     94static const char*
     95torrentClose( tr_handle * h, tr_benc * args_in, tr_benc * args_out UNUSED )
     96{
     97    callTorrentFunc( h, args_in, tr_torrentClose );
     98    return NULL;
     99}
     100
     101static const char*
     102torrentVerify( tr_handle * h, tr_benc * args_in, tr_benc * args_out UNUSED )
     103{
     104    callTorrentFunc( h, args_in, tr_torrentVerify );
    105105    return NULL;
    106106}
     
    119119        tr_benc * d = tr_bencListAddDict( list, 32 );
    120120        tr_benc * t;
     121        const int * f = st->peersFrom;
     122        const struct tr_tracker_stat * s = &st->tracker_stat;
    121123
    122124        tr_bencDictAddInt( d, "id", tor->uniqueId );
     
    151153        tr_bencDictAddInt( d, "activityDate", st->activityDate );
    152154        t = tr_bencDictAddDict( d, "peersFrom", 4 );
    153             tr_bencDictAddInt( t, "cache",    st->peersFrom[TR_PEER_FROM_CACHE] );
    154             tr_bencDictAddInt( t, "incoming", st->peersFrom[TR_PEER_FROM_INCOMING] );
    155             tr_bencDictAddInt( t, "pex",      st->peersFrom[TR_PEER_FROM_PEX] );
    156             tr_bencDictAddInt( t, "tracker",  st->peersFrom[TR_PEER_FROM_TRACKER] );
     155            tr_bencDictAddInt( t, "cache",    f[TR_PEER_FROM_CACHE] );
     156            tr_bencDictAddInt( t, "incoming", f[TR_PEER_FROM_INCOMING] );
     157            tr_bencDictAddInt( t, "pex",      f[TR_PEER_FROM_PEX] );
     158            tr_bencDictAddInt( t, "tracker",  f[TR_PEER_FROM_TRACKER] );
    157159        t = tr_bencDictAddDict( d, "tracker_stat", 7 );
    158             tr_bencDictAddStr( t, "scrapeResponse", st->tracker_stat.scrapeResponse );
    159             tr_bencDictAddStr( t, "announceResponse", st->tracker_stat.announceResponse );
    160             tr_bencDictAddInt( t, "lastScrapeTime", st->tracker_stat.lastScrapeTime );
    161             tr_bencDictAddInt( t, "nextScrapeTime", st->tracker_stat.nextScrapeTime );
    162             tr_bencDictAddInt( t, "lastAnnounceTime", st->tracker_stat.lastAnnounceTime );
    163             tr_bencDictAddInt( t, "nextAnnounceTime", st->tracker_stat.nextAnnounceTime );
    164             tr_bencDictAddInt( t, "nextManualAnnounceTime", st->tracker_stat.nextManualAnnounceTime );
     160            tr_bencDictAddStr( t, "scrapeResponse", s->scrapeResponse );
     161            tr_bencDictAddStr( t, "announceResponse", s->announceResponse );
     162            tr_bencDictAddInt( t, "lastScrapeTime", s->lastScrapeTime );
     163            tr_bencDictAddInt( t, "nextScrapeTime", s->nextScrapeTime );
     164            tr_bencDictAddInt( t, "lastAnnounceTime", s->lastAnnounceTime );
     165            tr_bencDictAddInt( t, "nextAnnounceTime", s->nextAnnounceTime );
     166            tr_bencDictAddInt( t, "nextManualAnnounceTime", s->nextManualAnnounceTime );
    165167    }
    166168
     
    199201}
    200202
     203static void
     204serializeInfo( const tr_torrent * tor, tr_benc * d )
     205{
     206    const tr_info * inf = tr_torrentInfo( tor );
     207    tr_bencInitDict( d, 14 );
     208    tr_bencDictAddInt( d, "id", tor->uniqueId );
     209    tr_bencDictAddStr( d, "torrent", inf->torrent );
     210    tr_bencDictAddStr( d, "hashString", inf->hashString );
     211    tr_bencDictAddStr( d, "name", inf->name );
     212    tr_bencDictAddStr( d, "comment", inf->comment ? inf->comment : "" );
     213    tr_bencDictAddStr( d, "creator", inf->creator ? inf->creator : "" );
     214    tr_bencDictAddInt( d, "isPrivate", inf->isPrivate );
     215    tr_bencDictAddInt( d, "isMultifile", inf->isMultifile );
     216    tr_bencDictAddInt( d, "dateCreated", inf->dateCreated );
     217    tr_bencDictAddInt( d, "pieceSize", inf->pieceSize );
     218    tr_bencDictAddInt( d, "pieceCount", inf->pieceCount );
     219    tr_bencDictAddInt( d, "totalSize", inf->totalSize );
     220    addFiles   ( inf, tr_bencDictAddList( d, "files", inf->fileCount ) );
     221    addTrackers( inf, tr_bencDictAddList( d, "files", inf->trackerCount ) );
     222}
     223
    201224static const char*
    202225torrentInfo( tr_handle * handle, tr_benc * args_in, tr_benc * args_out )
     
    207230
    208231    for( i=0; i<torrentCount; ++i )
    209     {
    210         tr_torrent * tor = torrents[i];
    211         const tr_info * inf = tr_torrentInfo( tor );
    212         tr_benc * d = tr_bencListAddDict( list, 13 );
    213         tr_bencDictAddStr( d, "torrent", inf->torrent );
    214         tr_bencDictAddStr( d, "hashString", inf->hashString );
    215         tr_bencDictAddStr( d, "name", inf->name );
    216         tr_bencDictAddStr( d, "comment", inf->comment ? inf->comment : "" );
    217         tr_bencDictAddStr( d, "creator", inf->creator ? inf->creator : "" );
    218         tr_bencDictAddInt( d, "isPrivate", inf->isPrivate );
    219         tr_bencDictAddInt( d, "isMultifile", inf->isMultifile );
    220         tr_bencDictAddInt( d, "dateCreated", inf->dateCreated );
    221         tr_bencDictAddInt( d, "pieceSize", inf->pieceSize );
    222         tr_bencDictAddInt( d, "pieceCount", inf->pieceCount );
    223         tr_bencDictAddInt( d, "totalSize", inf->totalSize );
    224         addFiles   ( inf, tr_bencDictAddList( d, "files", inf->fileCount ) );
    225         addTrackers( inf, tr_bencDictAddList( d, "files", inf->trackerCount ) );
    226     }
    227 
    228     /* cleanup */
     232        serializeInfo( torrents[i], tr_bencListAdd( list ) );
     233
    229234    tr_free( torrents );
    230235    return NULL;
     
    241246    {
    242247        tr_torrent * tor = torrents[i];
    243         tr_benc * d = tr_bencListAddDict( list, 3 );
    244         tr_bencDictAddInt( d, "max-peers", tr_torrentGetMaxConnectedPeers( tor ) );
    245         tr_bencDictAddInt( d, "speed-limit-down", tr_torrentGetSpeedLimit( tor, TR_DOWN ) );
    246         tr_bencDictAddInt( d, "speed-limit-up", tr_torrentGetSpeedLimit( tor, TR_UP ) );
     248        tr_benc * d = tr_bencListAddDict( list, 4 );
     249        tr_bencDictAddInt( d, "id",
     250                           tor->uniqueId );
     251        tr_bencDictAddInt( d, "max-peers",
     252                           tr_torrentGetMaxConnectedPeers( tor ) );
     253        tr_bencDictAddInt( d, "speed-limit-down",
     254                           tr_torrentGetSpeedLimit( tor, TR_DOWN ) );
     255        tr_bencDictAddInt( d, "speed-limit-up",
     256                           tr_torrentGetSpeedLimit( tor, TR_UP ) );
    247257    }
    248258
     
    273283}
    274284
    275 static const char*
    276 torrentGetFile( tr_handle * handle UNUSED, tr_benc * args_in UNUSED, tr_benc * args_out UNUSED )
    277 {
    278     return NULL;
    279 }
    280 
    281 static const char*
    282 torrentSetFile( tr_handle * handle UNUSED, tr_benc * args_in UNUSED, tr_benc * args_out UNUSED )
    283 {
    284     return NULL;
    285 }
    286 
    287 static const char*
    288 sessionSet( tr_handle * handle UNUSED, tr_benc * args_in UNUSED, tr_benc * args_out UNUSED )
    289 {
    290     return NULL;
    291 }
    292 
    293 static const char*
    294 sessionGet( tr_handle * handle UNUSED, tr_benc * args_in UNUSED, tr_benc * args_out UNUSED )
    295 {
    296     return NULL;
    297 }
    298 
    299 static const char*
    300 torrentAdd( tr_handle * handle UNUSED, tr_benc * args_in UNUSED, tr_benc * args_out UNUSED )
    301 {
     285typedef int( *fileTestFunc )( const tr_torrent * tor, int i );
     286
     287static int
     288testFileHigh( const tr_torrent * tor, int i )
     289{
     290    return tor->info.files[i].priority == TR_PRI_HIGH;
     291}
     292static int
     293testFileLow( const tr_torrent * tor, int i )
     294{
     295    return tor->info.files[i].priority == TR_PRI_LOW;
     296}
     297static int
     298testFileNormal( const tr_torrent * tor, int i )
     299{
     300    return tor->info.files[i].priority == TR_PRI_NORMAL;
     301}
     302static int
     303testFileDND( const tr_torrent * tor, int i )
     304{
     305    return tor->info.files[i].dnd != 0;
     306}
     307static int
     308testFileDownload( const tr_torrent * tor, int i )
     309{
     310    return tor->info.files[i].dnd == 0;
     311}
     312
     313static void
     314buildFileList( const tr_torrent * tor, tr_benc * dict,
     315               const char * key, fileTestFunc func )
     316{
     317    int i;
     318    const int n = tor->info.fileCount;
     319    tr_benc * list;
     320    int * files = tr_new0( int, n );
     321    int fileCount = 0;
     322   
     323    for( i=0; i<n; ++i )
     324        if( func( tor, i ) )
     325            files[fileCount++] = i;
     326
     327    list = tr_bencDictAddList( dict, key, fileCount );
     328
     329    for( i=0; i<fileCount; ++i )
     330        tr_bencListAddInt( list, files[i] );
     331
     332    tr_free( files );
     333}
     334
     335static const char*
     336torrentGetFile( tr_handle * handle, tr_benc * args_in, tr_benc * args_out )
     337{
     338    int i, torrentCount;
     339    tr_torrent ** torrents = getTorrents( handle, args_in, &torrentCount );
     340    tr_benc * list = tr_bencDictAddList( args_out, "torrents", torrentCount );
     341
     342    for( i=0; i<torrentCount; ++i )
     343    {
     344        const tr_torrent * tor = torrents[i];
     345        tr_benc * d = tr_bencListAddDict( list, 6 );
     346        tr_bencDictAddInt( d, "id", tor->uniqueId );
     347        buildFileList( tor, d, "priority-high", testFileHigh );
     348        buildFileList( tor, d, "priority-low", testFileLow );
     349        buildFileList( tor, d, "priority-normal", testFileNormal );
     350        buildFileList( tor, d, "download", testFileDownload );
     351        buildFileList( tor, d, "no-download", testFileDND );
     352    }
     353
     354    tr_free( torrents );
     355    return NULL;
     356}
     357
     358static void
     359setFilePriorities( tr_torrent * tor, int priority, tr_benc * list )
     360{
     361    const int n = tr_bencListSize( list );
     362    int i;
     363    int64_t tmp;
     364    int fileCount = 0;
     365    tr_file_index_t * files = tr_new0( tr_file_index_t, n );
     366
     367    for( i=0; i<n; ++i )
     368        if( tr_bencGetInt( tr_bencListChild(list,i), &tmp ) )
     369            files[fileCount++] = tmp;
     370
     371    if( fileCount )
     372        tr_torrentSetFilePriorities( tor, files, fileCount, priority );
     373
     374    tr_free( files );
     375}
     376
     377static void
     378setFileDLs( tr_torrent * tor, int do_download, tr_benc * list )
     379{
     380    const int n = tr_bencListSize( list );
     381    int i;
     382    int64_t tmp;
     383    int fileCount = 0;
     384    tr_file_index_t * files = tr_new0( tr_file_index_t, n );
     385
     386    for( i=0; i<n; ++i )
     387        if( tr_bencGetInt( tr_bencListChild(list,i), &tmp ) )
     388            files[fileCount++] = tmp;
     389
     390    if( fileCount )
     391        tr_torrentSetFileDLs( tor, files, fileCount, do_download );
     392
     393    tr_free( files );
     394}
     395
     396static const char*
     397torrentSetFile( tr_handle * h, tr_benc * args_in, tr_benc * args_out UNUSED )
     398{
     399    int i, torrentCount;
     400    tr_torrent ** torrents = getTorrents( h, args_in, &torrentCount );
     401
     402    for( i=0; i<torrentCount; ++i )
     403    {
     404        tr_benc * files;
     405        tr_torrent * tor = torrents[i];
     406
     407        if( tr_bencDictFindList( args_in, "priority-high", &files ) )
     408            setFilePriorities( tor, TR_PRI_HIGH, files );
     409        if( tr_bencDictFindList( args_in, "priority-low", &files ) )
     410            setFilePriorities( tor, TR_PRI_LOW, files );
     411        if( tr_bencDictFindList( args_in, "priority-normal", &files ) )
     412            setFilePriorities( tor, TR_PRI_NORMAL, files );
     413        if( tr_bencDictFindList( args_in, "download", &files ) )
     414            setFileDLs( tor, TRUE, files );
     415        if( tr_bencDictFindList( args_in, "no-download", &files ) )
     416            setFileDLs( tor, FALSE, files );
     417    }
     418
     419    tr_free( torrents );
    302420    return NULL;
    303421}
     
    306424****
    307425***/
     426
     427static const char*
     428torrentAdd( tr_handle * h, tr_benc * args_in, tr_benc * args_out )
     429{
     430    const char * filename;
     431    if( !tr_bencDictFindStr( args_in, "filename", &filename ) )
     432        return "no filename specified";
     433    else {
     434        int64_t i;
     435        int err = 0;
     436        const char * str;
     437        tr_ctor * ctor;
     438        tr_torrent * tor;
     439
     440        ctor = tr_ctorNew( h );
     441        tr_ctorSetMetainfoFromFile( ctor, filename );
     442        if( tr_bencDictFindInt( args_in, "autostart", &i ) )
     443            tr_ctorSetPaused( ctor, TR_FORCE, !i );
     444        if( tr_bencDictFindInt( args_in, "max-peers", &i ) )
     445            tr_ctorSetMaxConnectedPeers( ctor, TR_FORCE, i );
     446        if( tr_bencDictFindStr( args_in, "destination", &str ) )
     447            tr_ctorSetDestination( ctor, TR_FORCE, str );
     448        tor = tr_torrentNew( h, ctor, &err );
     449        tr_ctorFree( ctor );
     450
     451        if( tor )
     452            serializeInfo( tor, tr_bencDictAdd( args_out, "torrent-added" ) );
     453        else if( err == TR_EDUPLICATE )
     454            return "duplicate torrent";
     455        else if( err == TR_EINVALID )
     456            return "invalid or corrupt torrent file";
     457    }
     458
     459    return NULL;
     460}
     461
     462/***
     463****
     464***/
     465
     466static const char*
     467sessionSet( tr_handle * handle UNUSED, tr_benc * args_in UNUSED, tr_benc * args_out UNUSED )
     468{
     469    /* TODO */
     470    return NULL;
     471}
     472
     473static const char*
     474sessionGet( tr_handle * handle UNUSED, tr_benc * args_in UNUSED, tr_benc * args_out UNUSED )
     475{
     476    /* TODO */
     477    return NULL;
     478}
     479
     480/***
     481****
     482***/
     483
     484typedef const char* (handler)( tr_handle*, tr_benc*, tr_benc* );
     485
     486struct request_handler
     487{
     488    const char * name;
     489    handler * func;
     490} request_handlers[] = {
     491    { "torrent-start", torrentStart },
     492    { "torrent-stop", torrentStop },
     493    { "torrent-close", torrentClose },
     494    { "torrent-verify", torrentVerify },
     495    { "torrent-status", torrentStatus },
     496    { "torrent-info", torrentInfo },
     497    { "torrent-add", torrentAdd },
     498    { "torrent-set", torrentSet },
     499    { "torrent-get", torrentGet },
     500    { "torrent-set-file", torrentSetFile },
     501    { "torrent-get-file", torrentGetFile },
     502    { "session-set", sessionSet },
     503    { "session-get", sessionGet }
     504};
    308505
    309506static char*
     
    341538        result = "no request name given";
    342539    else {
    343              if( !strcmp( str, "torrent-start" ) )    result = torrentStart  ( handle, args_in, args_out );
    344         else if( !strcmp( str, "torrent-stop" ) )     result = torrentStop   ( handle, args_in, args_out );
    345         else if( !strcmp( str, "torrent-close" ) )    result = torrentClose  ( handle, args_in, args_out );
    346         else if( !strcmp( str, "torrent-verify" ) )   result = torrentVerify ( handle, args_in, args_out );
    347         else if( !strcmp( str, "torrent-status" ) )   result = torrentStatus ( handle, args_in, args_out );
    348 
    349         else if( !strcmp( str, "torrent-info" ) )     result = torrentInfo ( handle, args_in, args_out );
    350         else if( !strcmp( str, "torrent-add" ) )      result = torrentAdd    ( handle, args_in, args_out );
    351         else if( !strcmp( str, "torrent-set" ) )      result = torrentSet    ( handle, args_in, args_out );
    352         else if( !strcmp( str, "torrent-get" ) )      result = torrentGet    ( handle, args_in, args_out );
    353         else if( !strcmp( str, "torrent-set-file" ) ) result = torrentSetFile( handle, args_in, args_out );
    354         else if( !strcmp( str, "torrent-get-file" ) ) result = torrentGetFile( handle, args_in, args_out );
    355         else if( !strcmp( str, "session-set" ) )      result = sessionSet    ( handle, args_in, args_out );
    356         else if( !strcmp( str, "session-get" ) )      result = sessionGet    ( handle, args_in, args_out );
    357         else                                          result = "request name not recognized";
    358     }
    359 
     540        const int n = TR_N_ELEMENTS( request_handlers );
     541        for( i=0; i<n; ++i )
     542            if( !strcmp( str, request_handlers[i].name ) )
     543                break;
     544        result = i==n
     545            ? "request name not recognized"
     546            : (*request_handlers[i].func)( handle, args_in, args_out );
     547    }
     548
     549    /* serialize & return the response */
    360550    if( !result )
    361551        result = "success";
Note: See TracChangeset for help on using the changeset viewer.