/* * This file Copyright (C) 2008 Charles Kerr * * This file is licensed by the GPL version 2. Works owned by the * Transmission project are granted a special exemption to clause 2(b) * so that the bulk of its code can remain under the MIT license. * This exemption does not extend to derived works not owned by * the Transmission project. * * $Id:$ */ #include #include /* strcmp */ #include "transmission.h" #include "bencode.h" #include "ipc.h" #include "torrent.h" #include "utils.h" #define TR_N_ELEMENTS( ary ) ( sizeof( ary ) / sizeof( (ary)[0] ) ) /*** **** ***/ static tr_torrent ** getTorrents( tr_handle * handle, tr_benc * args, int * setmeCount ) { tr_torrent ** torrents = NULL; int torrentCount = 0; tr_benc * ids; if( tr_bencDictFindList( args, "ids", &ids ) ) { int i; const int n = tr_bencListSize( ids ); torrents = tr_new0( tr_torrent*, n ); for( i=0; ipeersFrom; const struct tr_tracker_stat * s = &st->tracker_stat; tr_bencDictAddInt( d, "id", tor->uniqueId ); tr_bencDictAddInt( d, "status", st->status ); tr_bencDictAddInt( d, "error", st->error ); tr_bencDictAddStr( d, "errorString", st->errorString ); tr_bencDictAddDouble( d, "recheckProgress", st->recheckProgress ); tr_bencDictAddDouble( d, "percentComplete", st->percentComplete ); tr_bencDictAddDouble( d, "percentDone", st->percentDone ); tr_bencDictAddDouble( d, "rateDownload", st->rateDownload ); tr_bencDictAddDouble( d, "rateUpload", st->rateUpload ); tr_bencDictAddDouble( d, "swarmspeed", st->swarmspeed ); tr_bencDictAddDouble( d, "ratio", st->ratio ); tr_bencDictAddInt( d, "eta", st->eta ); tr_bencDictAddInt( d, "peersKnown", st->peersKnown ); tr_bencDictAddInt( d, "peersConnected", st->peersConnected ); tr_bencDictAddInt( d, "peersSendingToUs", st->peersSendingToUs ); tr_bencDictAddInt( d, "peersGettingFromUs", st->peersGettingFromUs ); tr_bencDictAddInt( d, "seeders", st->seeders ); tr_bencDictAddInt( d, "leechers", st->leechers ); tr_bencDictAddInt( d, "completedFromTracker", st->completedFromTracker ); tr_bencDictAddInt( d, "manualAnnounceTime", st->manualAnnounceTime ); tr_bencDictAddInt( d, "sizeWhenDone", st->sizeWhenDone ); tr_bencDictAddInt( d, "leftUntilDone", st->leftUntilDone ); tr_bencDictAddInt( d, "desiredAvailable", st->desiredAvailable ); tr_bencDictAddInt( d, "corruptEver", st->corruptEver ); tr_bencDictAddInt( d, "uploadedEver", st->uploadedEver ); tr_bencDictAddInt( d, "downloadedEver", st->downloadedEver ); tr_bencDictAddInt( d, "haveValid", st->haveValid ); tr_bencDictAddInt( d, "haveUnchecked", st->haveUnchecked ); tr_bencDictAddInt( d, "startDate", st->startDate ); tr_bencDictAddInt( d, "activityDate", st->activityDate ); t = tr_bencDictAddDict( d, "peersFrom", 4 ); tr_bencDictAddInt( t, "cache", f[TR_PEER_FROM_CACHE] ); tr_bencDictAddInt( t, "incoming", f[TR_PEER_FROM_INCOMING] ); tr_bencDictAddInt( t, "pex", f[TR_PEER_FROM_PEX] ); tr_bencDictAddInt( t, "tracker", f[TR_PEER_FROM_TRACKER] ); t = tr_bencDictAddDict( d, "tracker_stat", 7 ); tr_bencDictAddStr( t, "scrapeResponse", s->scrapeResponse ); tr_bencDictAddStr( t, "announceResponse", s->announceResponse ); tr_bencDictAddInt( t, "lastScrapeTime", s->lastScrapeTime ); tr_bencDictAddInt( t, "nextScrapeTime", s->nextScrapeTime ); tr_bencDictAddInt( t, "lastAnnounceTime", s->lastAnnounceTime ); tr_bencDictAddInt( t, "nextAnnounceTime", s->nextAnnounceTime ); tr_bencDictAddInt( t, "nextManualAnnounceTime", s->nextManualAnnounceTime ); } /* cleanup */ tr_free( torrents ); return NULL; } static void addFiles( const tr_info * info, tr_benc * files ) { unsigned int i; for( i=0; ifileCount; ++i ) { const tr_file * file = &info->files[i]; tr_benc * d = tr_bencListAddDict( files, 4 ); tr_bencDictAddInt( d, "length", file->length ); tr_bencDictAddStr( d, "name", file->name ); tr_bencDictAddInt( d, "priority", file->priority ); tr_bencDictAddInt( d, "dnd", file->dnd ); } } static void addTrackers( const tr_info * info, tr_benc * trackers ) { int i; for( i=0; itrackerCount; ++i ) { const tr_tracker_info * t = &info->trackers[i]; tr_benc * d = tr_bencListAddDict( trackers, 3 ); tr_bencDictAddInt( d, "tier", t->tier ); tr_bencDictAddStr( d, "announce", t->announce ); tr_bencDictAddStr( d, "scrape", t->scrape ); } } static void serializeInfo( const tr_torrent * tor, tr_benc * d ) { const tr_info * inf = tr_torrentInfo( tor ); tr_bencInitDict( d, 14 ); tr_bencDictAddInt( d, "id", tor->uniqueId ); tr_bencDictAddStr( d, "torrent", inf->torrent ); tr_bencDictAddStr( d, "hashString", inf->hashString ); tr_bencDictAddStr( d, "name", inf->name ); tr_bencDictAddStr( d, "comment", inf->comment ? inf->comment : "" ); tr_bencDictAddStr( d, "creator", inf->creator ? inf->creator : "" ); tr_bencDictAddInt( d, "isPrivate", inf->isPrivate ); tr_bencDictAddInt( d, "isMultifile", inf->isMultifile ); tr_bencDictAddInt( d, "dateCreated", inf->dateCreated ); tr_bencDictAddInt( d, "pieceSize", inf->pieceSize ); tr_bencDictAddInt( d, "pieceCount", inf->pieceCount ); tr_bencDictAddInt( d, "totalSize", inf->totalSize ); addFiles ( inf, tr_bencDictAddList( d, "files", inf->fileCount ) ); addTrackers( inf, tr_bencDictAddList( d, "files", inf->trackerCount ) ); } static const char* torrentInfo( tr_handle * handle, tr_benc * args_in, tr_benc * args_out ) { int i, torrentCount; tr_torrent ** torrents = getTorrents( handle, args_in, &torrentCount ); tr_benc * list = tr_bencDictAddList( args_out, "status", torrentCount ); for( i=0; iuniqueId ); tr_bencDictAddInt( d, "peer-limit", tr_torrentGetPeerLimit( tor ) ); tr_bencDictAddInt( d, "speed-limit-down", tr_torrentGetSpeedLimit( tor, TR_DOWN ) ); tr_bencDictAddInt( d, "speed-limit-up", tr_torrentGetSpeedLimit( tor, TR_UP ) ); } tr_free( torrents ); return NULL; } static const char* torrentSet( tr_handle * handle, tr_benc * args_in, tr_benc * args_out UNUSED ) { int i, torrentCount; tr_torrent ** torrents = getTorrents( handle, args_in, &torrentCount ); for( i=0; iinfo.files[i].priority == TR_PRI_HIGH; } static int testFileLow( const tr_torrent * tor, int i ) { return tor->info.files[i].priority == TR_PRI_LOW; } static int testFileNormal( const tr_torrent * tor, int i ) { return tor->info.files[i].priority == TR_PRI_NORMAL; } static int testFileDND( const tr_torrent * tor, int i ) { return tor->info.files[i].dnd != 0; } static int testFileDownload( const tr_torrent * tor, int i ) { return tor->info.files[i].dnd == 0; } static void buildFileList( const tr_torrent * tor, tr_benc * dict, const char * key, fileTestFunc func ) { int i; const int n = tor->info.fileCount; tr_benc * list; int * files = tr_new0( int, n ); int fileCount = 0; for( i=0; iuniqueId ); buildFileList( tor, d, "priority-high", testFileHigh ); buildFileList( tor, d, "priority-low", testFileLow ); buildFileList( tor, d, "priority-normal", testFileNormal ); buildFileList( tor, d, "download", testFileDownload ); buildFileList( tor, d, "no-download", testFileDND ); } tr_free( torrents ); return NULL; } static void setFilePriorities( tr_torrent * tor, int priority, tr_benc * list ) { const int n = tr_bencListSize( list ); int i; int64_t tmp; int fileCount = 0; tr_file_index_t * files = tr_new0( tr_file_index_t, n ); for( i=0; i