From: Daniel Lee Date: Wed, 30 Jun 2010 05:52:24 +0000 (+0000) Subject: (libT) #2581:RPC extended to manage tracker lists X-Git-Tag: 2.10~336 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b99a4a57afa6d90491253d2654f93a2d6f4a4fea;p=transmission (libT) #2581:RPC extended to manage tracker lists --- diff --git a/doc/rpc-spec.txt b/doc/rpc-spec.txt index 741b99523..072e9bd0a 100644 --- a/doc/rpc-spec.txt +++ b/doc/rpc-spec.txt @@ -102,8 +102,31 @@ "priority-normal" | array indices of normal-priority file(s) "seedRatioLimit" | double session seeding ratio "seedRatioMode" | number which ratio to use. See tr_ratiolimit + "trackerAdd" | object (see below) + "trackerEdit" | object (see below) + "trackerRemove" | object (see below) "uploadLimit" | number maximum upload speed (in K/s) "uploadLimited" | boolean true if "uploadLimit" is honored + | + ----------------------+---------------------------------+ + trackerAdd | an object containing: | + +-----------------------+---------+ + | announce | string | announce URL of the tracker + | tier (optional) | number | tier to add the tracker to + ----------------------+---------------------------------+ + trackerEdit | an object containing: | + +-----------------------+---------+ + | announce (or id) | string | announce URL of the tracker to modify + | id (or announce) | number | trackerId of the tracker to modify (see trackerStats) + +-----------------------+---------+ + | announce-new | string | new announce URL for the tracker + | tier | number | tier to change the tracker to + ----------------------+---------------------------------+ + trackerRemove | an object containing: | + +-----------------------+---------+ + | announce (or id) | string | announce URL of the tracker to remove + | id (or announce) | number | trackerId of the tracker to remove (see trackerStats) + +-----------------------+---------+ Just as an empty "ids" value is shorthand for "all ids", using an empty array for "files-wanted", "files-unwanted", "priority-high", "priority-low", or @@ -601,3 +624,7 @@ | 2.00 | yes | session-get | new arg "trash-original-torrent-files" | 2.00 | yes | session-get | new arg "cache-size-MiB" | 2.00 | yes | torrent-get | new arg "isFinished" + ------+---------+-----------+----------------+------------------------------- + 10 | 2.10 | yes | torrent-set | new arg "trackerAdd" + | 2.10 | yes | torrent-set | new arg "trackerEdit" + | 2.10 | yes | torrent-set | new arg "trackerRemove" diff --git a/libtransmission/rpcimpl.c b/libtransmission/rpcimpl.c index 2fb406e94..e35c64507 100644 --- a/libtransmission/rpcimpl.c +++ b/libtransmission/rpcimpl.c @@ -752,6 +752,221 @@ setFileDLs( tr_torrent * tor, return errmsg; } +static tr_bool +findTrackerById( const tr_info * inf, + uint32_t id, + int * index ) +{ + int i; + tr_bool found = FALSE; + + for( i = 0; i < inf->trackerCount; ++i ) + { + const tr_tracker_info * t = &inf->trackers[i]; + if( t->id == id ) + { + if( index ) *index = i; + found = TRUE; + break; + } + } + + return found; +} + +static tr_bool +findTrackerByURL( const tr_info * inf, + const char * url, + int * index ) +{ + int i; + tr_bool found = FALSE; + + for( i = 0; i < inf->trackerCount; ++i ) + { + const tr_tracker_info * t = &inf->trackers[i]; + if( !strcmp( t->announce, url ) ) + { + if( index ) *index = i; + found = TRUE; + break; + } + } + + return found; +} + +static const char* +addTracker( tr_torrent * tor, + tr_benc * tracker ) +{ + int i; + int64_t tmp; + tr_bool duplicate = FALSE; + const char * errmsg = NULL; + const char * announce; + const tr_info * inf = tr_torrentInfo( tor ); + + if( !tr_bencDictFindStr( tracker, "announce", &announce ) ) + return "no announce url supplied"; + + duplicate = findTrackerByURL( inf, announce, NULL ); + + if( !duplicate ) + { + int tier, trackerCount; + tr_tracker_info * trackers = tr_new0( tr_tracker_info, inf->trackerCount + 1 ); + + if( tr_bencDictFindInt( tracker, "tier", &tmp ) ) + tier = (int)tmp; + else + tier = -1; + + for( i = 0; i < inf->trackerCount; ++i ) + { + const tr_tracker_info * t = &inf->trackers[i]; + trackers[i].tier = t->tier; + trackers[i].announce = tr_strdup( t->announce ); + } + trackers[i].tier = tier < 0 ? trackers[i-1].tier + 1 : tier; + trackers[i].announce = tr_strdup( announce ); + trackerCount = inf->trackerCount + 1; + + if( !tr_torrentSetAnnounceList( tor, trackers, trackerCount ) ) + errmsg = "tracker URL was invalid"; + + for( i = 0; i < trackerCount; ++i ) + tr_free( trackers[i].announce ); + tr_free( trackers ); + } + else + errmsg = "tracker already exists"; + + return errmsg; +} + +static const char* +editTracker( tr_torrent * tor, + tr_benc * tracker ) +{ + int trackerIndex; + int64_t tmp; + tr_bool found = FALSE; + const char * errmsg = NULL; + const char * announce; + const tr_info * inf = tr_torrentInfo( tor ); + + if( tr_bencDictFindInt( tracker, "id", &tmp ) ) + found = findTrackerById( inf, (uint32_t)tmp, &trackerIndex ); + else if( tr_bencDictFindStr( tracker, "announce", &announce ) ) + found = findTrackerByURL( inf, announce, &trackerIndex ); + else + errmsg = "no tracker supplied"; + + if( found ) + { + int tier; + const char * new; + tr_bool rename = FALSE; + tr_bool move = FALSE; + + if( tr_bencDictFindStr( tracker, "announce-new", &new ) ) + { + rename = !findTrackerByURL( inf, new, NULL ); + if( !rename ) + errmsg = "tracker already exists"; + } + if( tr_bencDictFindInt( tracker, "tier", &tmp ) ) + { + tier = (int)tmp; + move = TRUE; + } + + if( ( rename || move ) && !errmsg ) + { + int i, trackerCount; + tr_tracker_info * trackers = tr_new0( tr_tracker_info, inf->trackerCount ); + + for( i = 0; i < inf->trackerCount; ++i ) + { + const tr_tracker_info * t = &inf->trackers[i]; + if( i != trackerIndex ) + { + trackers[i].tier = t->tier; + trackers[i].announce = tr_strdup( t->announce ); + } + else + { + trackers[i].tier = move ? tier : t->tier; + trackers[i].announce = tr_strdup( rename ? new : t->announce ); + } + } + trackerCount = i; + + if( !tr_torrentSetAnnounceList( tor, trackers, trackerCount ) ) + errmsg = "error setting announce list"; + + for( i = 0; i < trackerCount; ++i ) + tr_free( trackers[i].announce ); + tr_free( trackers ); + } + else if( !errmsg ) + errmsg = "no operation supplied"; + } + else + errmsg = "tracker doesn't exists"; + + return errmsg; +} + +static const char* +removeTracker( tr_torrent * tor, + tr_benc * tracker ) +{ + int trackerIndex; + int64_t tmp; + tr_bool found = FALSE; + const char * errmsg = NULL; + const char * announce; + const tr_info * inf = tr_torrentInfo( tor ); + + if( tr_bencDictFindInt( tracker, "id", &tmp ) ) + found = findTrackerById( inf, (uint32_t)tmp, &trackerIndex ); + else if( tr_bencDictFindStr( tracker, "announce", &announce ) ) + found = findTrackerByURL( inf, announce, &trackerIndex ); + else + errmsg = "no tracker supplied"; + + if( found ) + { + int i, j, trackerCount; + tr_tracker_info * trackers = tr_new0( tr_tracker_info, inf->trackerCount - 1 ); + + for( i = 0, j = 0; i < inf->trackerCount; ++i ) + { + if( i != trackerIndex ) + { + const tr_tracker_info * t = &inf->trackers[i]; + trackers[j].tier = t->tier; + trackers[j].announce = tr_strdup( t->announce ); + ++j; + } + } + trackerCount = j; + + if( !tr_torrentSetAnnounceList( tor, trackers, trackerCount ) ) + errmsg = "error setting announce list"; + + for( i = 0; i < trackerCount; ++i ) + tr_free( trackers[i].announce ); + tr_free( trackers ); + } + else + errmsg = "tracker doesn't exists"; + + return errmsg; +} + static const char* torrentSet( tr_session * session, tr_benc * args_in, @@ -769,6 +984,7 @@ torrentSet( tr_session * session, int64_t tmp; double d; tr_benc * files; + tr_benc * tracker; tr_bool boolVal; tr_torrent * tor = torrents[i]; @@ -801,6 +1017,12 @@ torrentSet( tr_session * session, tr_torrentSetRatioLimit( tor, d ); if( tr_bencDictFindInt( args_in, "seedRatioMode", &tmp ) ) tr_torrentSetRatioMode( tor, tmp ); + if( !errmsg && tr_bencDictFindDict( args_in, "trackerAdd", &tracker ) ) + errmsg = addTracker( tor, tracker ); + if( !errmsg && tr_bencDictFindDict( args_in, "trackerEdit", &tracker ) ) + errmsg = editTracker( tor, tracker ); + if( !errmsg && tr_bencDictFindDict( args_in, "trackerRemove", &tracker ) ) + errmsg = removeTracker( tor, tracker ); notify( session, TR_RPC_TORRENT_CHANGED, tor ); }