the torrent ctor is here.
This commit is contained in:
parent
7a5369023e
commit
287975caf5
|
@ -254,7 +254,7 @@ torrent_cell_renderer_get_size( GtkCellRenderer * cell,
|
|||
const tr_torrent * tor = self->priv->tor;
|
||||
const tr_info * info = tr_torrentInfo( tor );
|
||||
const char * name = info->name;
|
||||
const tr_stat * torStat = tr_torrentStat( (tr_torrent*)tor );
|
||||
const tr_stat * torStat = tr_torrentStatCached( (tr_torrent*)tor );
|
||||
char * str;
|
||||
int w=0, h=0;
|
||||
struct TorrentCellRendererPrivate * p = self->priv;
|
||||
|
@ -490,7 +490,7 @@ torrent_cell_renderer_render( GtkCellRenderer * cell,
|
|||
const tr_torrent * tor = self->priv->tor;
|
||||
const tr_info * info = tr_torrentInfo( tor );
|
||||
const char * name = info->name;
|
||||
const tr_stat * torStat = tr_torrentStat( (tr_torrent*)tor );
|
||||
const tr_stat * torStat = tr_torrentStatCached( (tr_torrent*)tor );
|
||||
GdkRectangle my_bg;
|
||||
GdkRectangle my_cell;
|
||||
GdkRectangle my_expose;
|
||||
|
|
|
@ -191,8 +191,8 @@ compareByActivity( GtkTreeModel * model,
|
|||
gtk_tree_model_get( model, a, MC_TORRENT_RAW, &ta, -1 );
|
||||
gtk_tree_model_get( model, b, MC_TORRENT_RAW, &tb, -1 );
|
||||
|
||||
sa = tr_torrentStat( ta );
|
||||
sb = tr_torrentStat( tb );
|
||||
sa = tr_torrentStatCached( ta );
|
||||
sb = tr_torrentStatCached( tb );
|
||||
|
||||
if(( i = compareDouble( sa->rateUpload + sa->rateDownload,
|
||||
sb->rateUpload + sb->rateDownload ) ))
|
||||
|
@ -240,8 +240,8 @@ compareByProgress( GtkTreeModel * model,
|
|||
const tr_stat *sa, *sb;
|
||||
gtk_tree_model_get( model, a, MC_TORRENT_RAW, &ta, -1 );
|
||||
gtk_tree_model_get( model, b, MC_TORRENT_RAW, &tb, -1 );
|
||||
sa = tr_torrentStat( ta );
|
||||
sb = tr_torrentStat( tb );
|
||||
sa = tr_torrentStatCached( ta );
|
||||
sb = tr_torrentStatCached( tb );
|
||||
ret = compareDouble( sa->percentDone, sb->percentDone );
|
||||
if( !ret )
|
||||
ret = compareDouble( sa->ratio, sa->ratio );
|
||||
|
@ -257,7 +257,7 @@ compareByState( GtkTreeModel * model,
|
|||
tr_torrent *ta, *tb;
|
||||
gtk_tree_model_get( model, a, MC_TORRENT_RAW, &ta, -1 );
|
||||
gtk_tree_model_get( model, b, MC_TORRENT_RAW, &tb, -1 );
|
||||
return tr_torrentStat(ta)->status - tr_torrentStat(tb)->status;
|
||||
return tr_torrentStatCached(ta)->status - tr_torrentStatCached(tb)->status;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -453,17 +453,24 @@ tr_core_load( TrCore * self, gboolean paused )
|
|||
int count = 0;
|
||||
tr_torrent ** torrents;
|
||||
char * path;
|
||||
tr_ctor * ctor;
|
||||
|
||||
TR_IS_CORE( self );
|
||||
|
||||
path = getdownloaddir( );
|
||||
|
||||
torrents = tr_loadTorrents ( self->handle, path, paused, &count );
|
||||
ctor = tr_ctorNew( self->handle );
|
||||
tr_ctorSetPaused( ctor, TR_FORCE, paused );
|
||||
tr_ctorSetDestination( ctor, TR_FALLBACK, path );
|
||||
|
||||
torrents = tr_loadTorrents ( self->handle, ctor, &count );
|
||||
for( i=0; i<count; ++i )
|
||||
tr_core_insert( self, tr_torrent_new_preexisting( torrents[i] ) );
|
||||
tr_free( torrents );
|
||||
|
||||
tr_free( torrents );
|
||||
tr_ctorFree( ctor );
|
||||
g_free( path );
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ tr_torrent_handle(TrTorrent *tor)
|
|||
const tr_stat *
|
||||
tr_torrent_stat(TrTorrent *tor)
|
||||
{
|
||||
return tor && !tor->severed ? tr_torrentStat( tor->handle ) : NULL;
|
||||
return tor && !tor->severed ? tr_torrentStatCached( tor->handle ) : NULL;
|
||||
}
|
||||
|
||||
const tr_info *
|
||||
|
|
|
@ -199,9 +199,6 @@ int _tr_bencLoad( char * buf, int len, benc_val_t * val, char ** end )
|
|||
}
|
||||
}
|
||||
|
||||
val->begin = buf;
|
||||
val->end = *end;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,8 +30,6 @@
|
|||
|
||||
typedef struct benc_val_s
|
||||
{
|
||||
char * begin;
|
||||
char * end;
|
||||
#define TYPE_INT 1
|
||||
#define TYPE_STR 2
|
||||
#define TYPE_LIST 4
|
||||
|
|
|
@ -545,22 +545,23 @@ parsePeers( tr_torrent * tor, const uint8_t * buf, uint32_t len )
|
|||
}
|
||||
|
||||
static uint64_t
|
||||
parseDestination( tr_torrent * tor, const uint8_t * buf, uint32_t len,
|
||||
const char * destination, int argIsFallback )
|
||||
parseDestination( tr_torrent * tor, const uint8_t * buf, uint32_t len )
|
||||
{
|
||||
if( argIsFallback )
|
||||
tor->destination = tr_strdup( len ? (const char*)buf : destination );
|
||||
else
|
||||
tor->destination = tr_strdup( len ? destination : (const char*)buf );
|
||||
uint64_t ret = 0;
|
||||
|
||||
return TR_FR_DESTINATION;
|
||||
if( buf && *buf && len ) {
|
||||
tr_free( tor->destination );
|
||||
tor->destination = tr_strndup( (char*)buf, len );
|
||||
ret = TR_FR_DESTINATION;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
parseVersion1( tr_torrent * tor, const uint8_t * buf, const uint8_t * end,
|
||||
uint64_t fieldsToLoad,
|
||||
tr_bitfield * uncheckedPieces,
|
||||
const char * destination, int argIsFallback )
|
||||
tr_bitfield * uncheckedPieces )
|
||||
{
|
||||
uint64_t ret = 0;
|
||||
|
||||
|
@ -582,7 +583,7 @@ parseVersion1( tr_torrent * tor, const uint8_t * buf, const uint8_t * end,
|
|||
case FR_ID_CORRUPT: ret |= parseCorrupt( tor, buf, len ); break;
|
||||
case FR_ID_PEERS: ret |= parsePeers( tor, buf, len ); break;
|
||||
case FR_ID_PEX: ret |= parsePex( tor, buf, len ); break;
|
||||
case FR_ID_DESTINATION: ret |= parseDestination( tor, buf, len, destination, argIsFallback ); break;
|
||||
case FR_ID_DESTINATION: ret |= parseDestination( tor, buf, len ); break;
|
||||
default: tr_dbg( "Skipping unknown resume code %d", (int)id ); break;
|
||||
}
|
||||
|
||||
|
@ -620,9 +621,7 @@ loadResumeFile( const tr_torrent * tor, size_t * len )
|
|||
static uint64_t
|
||||
fastResumeLoadImpl ( tr_torrent * tor,
|
||||
uint64_t fieldsToLoad,
|
||||
tr_bitfield * uncheckedPieces,
|
||||
const char * destination,
|
||||
int argIsFallback )
|
||||
tr_bitfield * uncheckedPieces )
|
||||
{
|
||||
uint64_t ret = 0;
|
||||
size_t size = 0;
|
||||
|
@ -637,7 +636,7 @@ fastResumeLoadImpl ( tr_torrent * tor,
|
|||
uint32_t version;
|
||||
readBytes( &version, &walk, sizeof(version) );
|
||||
if( version == 1 )
|
||||
ret |= parseVersion1 ( tor, walk, end, fieldsToLoad, uncheckedPieces, destination, argIsFallback );
|
||||
ret |= parseVersion1 ( tor, walk, end, fieldsToLoad, uncheckedPieces );
|
||||
else
|
||||
tr_inf( "Unsupported resume file %d for '%s'", version, tor->info.name );
|
||||
}
|
||||
|
@ -648,20 +647,56 @@ fastResumeLoadImpl ( tr_torrent * tor,
|
|||
return ret;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
tr_fastResumeLoad( tr_torrent * tor,
|
||||
uint64_t fieldsToLoad,
|
||||
tr_bitfield * uncheckedPieces,
|
||||
const char * destination,
|
||||
int argIsFallback )
|
||||
static uint64_t
|
||||
setFromCtor( tr_torrent * tor, uint64_t fields, const tr_ctor * ctor, int mode )
|
||||
{
|
||||
const uint64_t ret = fastResumeLoadImpl( tor, fieldsToLoad, uncheckedPieces, destination, argIsFallback );
|
||||
uint64_t ret = 0;
|
||||
|
||||
if( ! ( ret & TR_FR_PROGRESS ) )
|
||||
tr_bitfieldAddRange( uncheckedPieces, 0, tor->info.pieceCount );
|
||||
if( fields & TR_FR_MAX_UNCHOKED )
|
||||
if( !tr_ctorGetMaxUnchokedPeers( ctor, mode, &tor->maxUnchokedPeers ) )
|
||||
ret |= TR_FR_MAX_UNCHOKED;
|
||||
|
||||
if( !tor->destination )
|
||||
tor->destination = tr_strdup( destination );
|
||||
if( fields & TR_FR_MAX_PEERS )
|
||||
if( !tr_ctorGetMaxConnectedPeers( ctor, mode, &tor->maxConnectedPeers ) )
|
||||
ret |= TR_FR_MAX_PEERS;
|
||||
|
||||
if( fields & TR_FR_DESTINATION ) {
|
||||
const char * destination;
|
||||
if( !tr_ctorGetDestination( ctor, mode, &destination ) ) {
|
||||
ret |= TR_FR_DESTINATION;
|
||||
tr_free( tor->destination );
|
||||
tor->destination = tr_strdup( destination );
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
useManditoryFields( tr_torrent * tor, uint64_t fields, const tr_ctor * ctor )
|
||||
{
|
||||
return setFromCtor( tor, fields, ctor, TR_FORCE );
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
useFallbackFields( tr_torrent * tor, uint64_t fields, const tr_ctor * ctor )
|
||||
{
|
||||
return setFromCtor( tor, fields, ctor, TR_FALLBACK );
|
||||
}
|
||||
|
||||
uint64_t
|
||||
tr_fastResumeLoad( tr_torrent * tor,
|
||||
uint64_t fieldsToLoad,
|
||||
tr_bitfield * uncheckedPieces,
|
||||
const tr_ctor * ctor )
|
||||
{
|
||||
uint64_t ret = 0;
|
||||
|
||||
ret |= useManditoryFields( tor, fieldsToLoad, ctor );
|
||||
fieldsToLoad &= ~ret;
|
||||
ret |= fastResumeLoadImpl( tor, fieldsToLoad, uncheckedPieces );
|
||||
fieldsToLoad &= ~ret;
|
||||
ret |= useFallbackFields( tor, fieldsToLoad, ctor );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,9 @@ enum
|
|||
TR_FR_SPEEDLIMIT = (1<<6),
|
||||
TR_FR_RUN = (1<<7),
|
||||
TR_FR_DESTINATION = (1<<8),
|
||||
TR_FR_PEX = (1<<9)
|
||||
TR_FR_PEX = (1<<9),
|
||||
TR_FR_MAX_PEERS = (1<<10),
|
||||
TR_FR_MAX_UNCHOKED = (1<<11),
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -47,7 +49,6 @@ enum
|
|||
uint64_t tr_fastResumeLoad( tr_torrent * tor,
|
||||
uint64_t fieldsToLoad,
|
||||
struct tr_bitfield * uncheckedPieces,
|
||||
const char * destination,
|
||||
int destinationIsFallback );
|
||||
const tr_ctor * ctor );
|
||||
|
||||
#endif
|
||||
|
|
|
@ -160,8 +160,8 @@ struct tr_torrent
|
|||
unsigned int statCur : 1;
|
||||
unsigned int isRunning : 1;
|
||||
|
||||
uint8_t maxUnchokedPeers;
|
||||
uint16_t maxConnectedPeers;
|
||||
uint16_t maxUnchokedPeers;
|
||||
|
||||
tr_recheck_state recheckState;
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ tr_httpParseUrl( const char * url_in, int len,
|
|||
* Local prototypes
|
||||
**********************************************************************/
|
||||
static int realparse( tr_info * inf, const uint8_t * buf, size_t len );
|
||||
static int realparse2( tr_info * inf, const benc_val_t * meta );
|
||||
static void savedname( char * name, size_t len, const char * hash,
|
||||
const char * tag );
|
||||
static uint8_t * readtorrent( const char * path, size_t * len );
|
||||
|
@ -221,6 +222,26 @@ tr_metainfoParseData( tr_info * inf, const char * tag,
|
|||
return TR_OK;
|
||||
}
|
||||
|
||||
int
|
||||
tr_metainfoParseBenc( tr_info * inf, const char * tag, const benc_val_t * val, int save )
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if( !err && realparse2( inf, val ) )
|
||||
err = TR_EINVALID;
|
||||
|
||||
if( !err && save ) {
|
||||
int len;
|
||||
uint8_t * text = (uint8_t *) tr_bencSave( val, &len );
|
||||
err = savetorrent( inf->hashString, tag, text, len );
|
||||
tr_free( text );
|
||||
if( !err )
|
||||
savedname( inf->torrent, sizeof( inf->torrent ), inf->hashString, tag );
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
tr_metainfoParseHash( tr_info * inf, const char * tag, const char * hash )
|
||||
{
|
||||
|
@ -273,26 +294,44 @@ tr_metainfoParseHash( tr_info * inf, const char * tag, const char * hash )
|
|||
static int
|
||||
realparse( tr_info * inf, const uint8_t * buf, size_t size )
|
||||
{
|
||||
benc_val_t meta, * beInfo, * val, * val2;
|
||||
int i;
|
||||
int err = 0;
|
||||
benc_val_t meta;
|
||||
|
||||
/* Parse bencoded infos */
|
||||
if( tr_bencLoad( buf, size, &meta, NULL ) )
|
||||
{
|
||||
if( !err && tr_bencLoad( buf, size, &meta, NULL ) ) {
|
||||
err = TR_EINVALID;
|
||||
tr_err( "Error while parsing bencoded data [%*.*s]", (int)size, (int)size, (char*)buf );
|
||||
return TR_EINVALID;
|
||||
}
|
||||
|
||||
/* Get info hash */
|
||||
beInfo = tr_bencDictFind( &meta, "info" );
|
||||
if( NULL == beInfo || TYPE_DICT != beInfo->type )
|
||||
{
|
||||
tr_err( "%s \"info\" dictionary", ( beInfo ? "Invalid" : "Missing" ) );
|
||||
if( !err ) {
|
||||
err = realparse2( inf, &meta );
|
||||
tr_bencFree( &meta );
|
||||
return TR_EINVALID;
|
||||
}
|
||||
|
||||
tr_sha1( inf->hash, beInfo->begin, beInfo->end - beInfo->begin, NULL );
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
realparse2( tr_info * inf, const benc_val_t * meta_in )
|
||||
{
|
||||
int i;
|
||||
benc_val_t * beInfo, * val, * val2;
|
||||
benc_val_t * meta = (benc_val_t *) meta_in;
|
||||
|
||||
/* info_hash: urlencoded 20-byte SHA1 hash of the value of the info key
|
||||
* from the Metainfo file. Note that the value will be a bencoded
|
||||
* dictionary, given the definition of the info key above. */
|
||||
if(( beInfo = tr_bencDictFindType( meta, "info", TYPE_DICT )))
|
||||
{
|
||||
int len;
|
||||
char * str = tr_bencSave( beInfo, &len );
|
||||
tr_sha1( inf->hash, str, len, NULL );
|
||||
tr_free( str );
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_err( "info dictionary not found!" );
|
||||
return TR_EINVALID;
|
||||
}
|
||||
|
||||
for( i = 0; i < SHA_DIGEST_LENGTH; i++ )
|
||||
{
|
||||
|
@ -301,14 +340,14 @@ realparse( tr_info * inf, const uint8_t * buf, size_t size )
|
|||
}
|
||||
|
||||
/* Comment info */
|
||||
val = tr_bencDictFindFirst( &meta, "comment.utf-8", "comment", NULL );
|
||||
val = tr_bencDictFindFirst( meta, "comment.utf-8", "comment", NULL );
|
||||
if( NULL != val && TYPE_STR == val->type )
|
||||
{
|
||||
strlcat_utf8( inf->comment, val->val.s.s, sizeof( inf->comment ), 0 );
|
||||
}
|
||||
|
||||
/* Creator info */
|
||||
val = tr_bencDictFindFirst( &meta, "created by.utf-8", "created by", NULL );
|
||||
val = tr_bencDictFindFirst( meta, "created by.utf-8", "created by", NULL );
|
||||
if( NULL != val && TYPE_STR == val->type )
|
||||
{
|
||||
strlcat_utf8( inf->creator, val->val.s.s, sizeof( inf->creator ), 0 );
|
||||
|
@ -316,7 +355,7 @@ realparse( tr_info * inf, const uint8_t * buf, size_t size )
|
|||
|
||||
/* Date created */
|
||||
inf->dateCreated = 0;
|
||||
val = tr_bencDictFind( &meta, "creation date" );
|
||||
val = tr_bencDictFind( meta, "creation date" );
|
||||
if( NULL != val && TYPE_INT == val->type )
|
||||
{
|
||||
inf->dateCreated = val->val.i;
|
||||
|
@ -324,7 +363,7 @@ realparse( tr_info * inf, const uint8_t * buf, size_t size )
|
|||
|
||||
/* Private torrent */
|
||||
val = tr_bencDictFind( beInfo, "private" );
|
||||
val2 = tr_bencDictFind( &meta, "private" );
|
||||
val2 = tr_bencDictFind( meta, "private" );
|
||||
if( ( NULL != val && ( TYPE_INT != val->type || 0 != val->val.i ) ) ||
|
||||
( NULL != val2 && ( TYPE_INT != val2->type || 0 != val2->val.i ) ) )
|
||||
{
|
||||
|
@ -393,17 +432,15 @@ realparse( tr_info * inf, const uint8_t * buf, size_t size )
|
|||
}
|
||||
|
||||
/* get announce or announce-list */
|
||||
if( getannounce( inf, &meta ) )
|
||||
if( getannounce( inf, meta ) )
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
tr_bencFree( &meta );
|
||||
return TR_OK;
|
||||
|
||||
fail:
|
||||
tr_metainfoFree( inf );
|
||||
tr_bencFree( &meta );
|
||||
return TR_EINVALID;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,11 +27,14 @@
|
|||
|
||||
#include "transmission.h"
|
||||
|
||||
struct benc_val_t;
|
||||
|
||||
int tr_metainfoParseFile( tr_info *, const char * tag,
|
||||
const char * path, int save );
|
||||
int tr_metainfoParseData( tr_info *, const char * tag,
|
||||
const uint8_t * data, size_t size, int save );
|
||||
int tr_metainfoParseHash( tr_info *, const char * tag, const char * hash );
|
||||
int tr_metainfoParseBenc( tr_info *, const char * tag, const struct benc_val_s *, int save );
|
||||
void tr_metainfoFree( tr_info * inf );
|
||||
void tr_metainfoRemoveSaved( const char * hashString, const char * tag );
|
||||
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
#include "trcompat.h" /* strlcpy */
|
||||
#include "utils.h"
|
||||
|
||||
#define DEFAULT_MAX_UNCHOKED_PEERS 16
|
||||
#define DEFAULT_MAX_CONNECTED_PEERS 50
|
||||
|
||||
struct optional_args
|
||||
{
|
||||
unsigned int isSet_paused : 1;
|
||||
|
@ -31,74 +34,61 @@ struct optional_args
|
|||
|
||||
struct tr_ctor
|
||||
{
|
||||
tr_handle * handle;
|
||||
const tr_handle * handle;
|
||||
|
||||
unsigned int isSet_metadata : 1;
|
||||
benc_val_t metadata;
|
||||
unsigned int isSet_metainfo : 1;
|
||||
benc_val_t metainfo;
|
||||
|
||||
struct optional_args optionalArgs[2];
|
||||
};
|
||||
|
||||
tr_ctor*
|
||||
tr_ctorNew( tr_handle * handle )
|
||||
{
|
||||
tr_ctor * ctor = tr_new0( struct tr_ctor, 1 );
|
||||
ctor->handle = handle;
|
||||
tr_ctorSetMaxConnectedPeers( ctor, TR_FALLBACK, 50 );
|
||||
tr_ctorSetMaxUnchokedPeers( ctor, TR_FALLBACK, 16 );
|
||||
tr_ctorSetPaused( ctor, TR_FALLBACK, FALSE );
|
||||
return ctor;
|
||||
}
|
||||
|
||||
void
|
||||
tr_ctorFree( tr_ctor * ctor )
|
||||
{
|
||||
tr_free( ctor );
|
||||
}
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
static void
|
||||
clearMetadata( tr_ctor * ctor )
|
||||
clearMetainfo( tr_ctor * ctor )
|
||||
{
|
||||
if( ctor->isSet_metadata ) {
|
||||
ctor->isSet_metadata = 0;
|
||||
tr_bencFree( &ctor->metadata );
|
||||
if( ctor->isSet_metainfo ) {
|
||||
ctor->isSet_metainfo = 0;
|
||||
tr_bencFree( &ctor->metainfo );
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
tr_ctorSetMetadata( tr_ctor * ctor,
|
||||
const uint8_t * metadata,
|
||||
tr_ctorSetMetainfo( tr_ctor * ctor,
|
||||
const uint8_t * metainfo,
|
||||
size_t len )
|
||||
{
|
||||
int err;
|
||||
clearMetadata( ctor );
|
||||
err = tr_bencLoad( metadata, len, &ctor->metadata, NULL );
|
||||
ctor->isSet_metadata = !err;
|
||||
clearMetainfo( ctor );
|
||||
err = tr_bencLoad( metainfo, len, &ctor->metainfo, NULL );
|
||||
ctor->isSet_metainfo = !err;
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
tr_ctorSetMetadataFromFile( tr_ctor * ctor,
|
||||
tr_ctorSetMetainfoFromFile( tr_ctor * ctor,
|
||||
const char * filename )
|
||||
{
|
||||
uint8_t * metadata;
|
||||
uint8_t * metainfo;
|
||||
size_t len;
|
||||
int err;
|
||||
|
||||
metadata = tr_loadFile( filename, &len );
|
||||
if( metadata && len )
|
||||
err = tr_ctorSetMetadata( ctor, metadata, len );
|
||||
metainfo = tr_loadFile( filename, &len );
|
||||
if( metainfo && len )
|
||||
err = tr_ctorSetMetainfo( ctor, metainfo, len );
|
||||
else {
|
||||
clearMetadata( ctor );
|
||||
clearMetainfo( ctor );
|
||||
err = 1;
|
||||
}
|
||||
|
||||
tr_free( metadata );
|
||||
tr_free( metainfo );
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
tr_ctorSetMetadataFromHash( tr_ctor * ctor,
|
||||
tr_ctorSetMetainfoFromHash( tr_ctor * ctor,
|
||||
const char * hashString )
|
||||
{
|
||||
int err = -1;
|
||||
|
@ -108,12 +98,14 @@ tr_ctorSetMetadataFromHash( tr_ctor * ctor,
|
|||
if( err && ( ctor->handle->tag != NULL ) ) {
|
||||
snprintf( basename, sizeof(basename), "%s-%s", hashString, ctor->handle->tag );
|
||||
tr_buildPath( filename, sizeof(filename), tr_getTorrentsDirectory(), basename );
|
||||
err = tr_ctorSetMetadataFromFile( ctor, filename );
|
||||
err = tr_ctorSetMetainfoFromFile( ctor, filename );
|
||||
fprintf( stderr, "trying [%s] returned %d\n", filename, err );
|
||||
}
|
||||
|
||||
if( err ) {
|
||||
tr_buildPath( filename, sizeof(filename), tr_getTorrentsDirectory(), hashString );
|
||||
err = tr_ctorSetMetadataFromFile( ctor, filename );
|
||||
err = tr_ctorSetMetainfoFromFile( ctor, filename );
|
||||
fprintf( stderr, "trying [%s] returned %d\n", filename, err );
|
||||
}
|
||||
|
||||
return err;
|
||||
|
@ -126,11 +118,11 @@ tr_ctorSetMetadataFromHash( tr_ctor * ctor,
|
|||
void
|
||||
tr_ctorSetPaused( tr_ctor * ctor,
|
||||
tr_ctorMode mode,
|
||||
int isPaused )
|
||||
uint8_t isPaused )
|
||||
{
|
||||
struct optional_args * args = &ctor->optionalArgs[mode];
|
||||
args->isSet_paused = 1;
|
||||
args->isPaused = isPaused;
|
||||
args->isPaused = isPaused ? 1 : 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -168,11 +160,15 @@ tr_ctorGetMaxConnectedPeers( const tr_ctor * ctor,
|
|||
tr_ctorMode mode,
|
||||
uint16_t * setmeCount )
|
||||
{
|
||||
int err = 0;
|
||||
const struct optional_args * args = &ctor->optionalArgs[mode];
|
||||
const int isSet = args->isSet_connected;
|
||||
if( isSet )
|
||||
|
||||
if( args->isSet_connected )
|
||||
*setmeCount = args->maxConnectedPeers;
|
||||
return isSet;
|
||||
else
|
||||
err = 1;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -180,23 +176,31 @@ tr_ctorGetMaxUnchokedPeers( const tr_ctor * ctor,
|
|||
tr_ctorMode mode,
|
||||
uint8_t * setmeCount )
|
||||
{
|
||||
int err = 0;
|
||||
const struct optional_args * args = &ctor->optionalArgs[mode];
|
||||
const int isSet = args->isSet_unchoked;
|
||||
if( isSet )
|
||||
|
||||
if( args->isSet_unchoked )
|
||||
*setmeCount = args->maxUnchokedPeers;
|
||||
return isSet;
|
||||
else
|
||||
err = 1;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
tr_ctorGetIsPaused( const tr_ctor * ctor,
|
||||
tr_ctorMode mode,
|
||||
int * setmeIsPaused )
|
||||
uint8_t * setmeIsPaused )
|
||||
{
|
||||
int err = 0;
|
||||
const struct optional_args * args = &ctor->optionalArgs[mode];
|
||||
const int isSet = args->isSet_paused;
|
||||
if( isSet )
|
||||
*setmeIsPaused = args->isPaused;
|
||||
return isSet;
|
||||
|
||||
if( args->isSet_paused )
|
||||
*setmeIsPaused = args->isPaused ? 1 : 0;
|
||||
else
|
||||
err = 1;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -204,19 +208,49 @@ tr_ctorGetDestination( const tr_ctor * ctor,
|
|||
tr_ctorMode mode,
|
||||
const char ** setmeDestination )
|
||||
{
|
||||
int err = 0;
|
||||
const struct optional_args * args = &ctor->optionalArgs[mode];
|
||||
const int isSet = args->isSet_destination;
|
||||
if( isSet )
|
||||
|
||||
if( args->isSet_destination )
|
||||
*setmeDestination = args->destination;
|
||||
return isSet;
|
||||
else
|
||||
err = 1;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
tr_ctorGetMetadata( const tr_ctor * ctor,
|
||||
tr_ctorGetMetainfo( const tr_ctor * ctor,
|
||||
const struct benc_val_s ** setme )
|
||||
{
|
||||
const int isSet = ctor->isSet_metadata;
|
||||
if( isSet )
|
||||
*setme = &ctor->metadata;
|
||||
return isSet;
|
||||
int err = 0;
|
||||
|
||||
if( ctor->isSet_metainfo )
|
||||
*setme = &ctor->metainfo;
|
||||
else
|
||||
err = 1;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
tr_ctor*
|
||||
tr_ctorNew( const tr_handle * handle )
|
||||
{
|
||||
tr_ctor * ctor = tr_new0( struct tr_ctor, 1 );
|
||||
ctor->handle = handle;
|
||||
tr_ctorSetMaxConnectedPeers( ctor, TR_FALLBACK, DEFAULT_MAX_CONNECTED_PEERS );
|
||||
tr_ctorSetMaxUnchokedPeers( ctor, TR_FALLBACK, DEFAULT_MAX_UNCHOKED_PEERS );
|
||||
tr_ctorSetPaused( ctor, TR_FALLBACK, FALSE );
|
||||
return ctor;
|
||||
}
|
||||
|
||||
void
|
||||
tr_ctorFree( tr_ctor * ctor )
|
||||
{
|
||||
clearMetainfo( ctor );
|
||||
tr_free( ctor );
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <sys/types.h>
|
||||
|
||||
#include "transmission.h"
|
||||
#include "bencode.h"
|
||||
#include "completion.h"
|
||||
#include "crypto.h" /* for tr_sha1 */
|
||||
#include "fastresume.h"
|
||||
|
@ -47,9 +48,6 @@
|
|||
#include "trevent.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define DEFAULT_MAX_CONNECTED_PEERS 50
|
||||
#define DEFAULT_MAX_UNCHOKED_PEERS 16
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
@ -259,11 +257,12 @@ tr_torrentInitFilePieces( tr_torrent * tor )
|
|||
}
|
||||
|
||||
static void
|
||||
torrentRealInit( tr_handle * h,
|
||||
tr_torrent * tor,
|
||||
const char * destination,
|
||||
int destinationIsFallback,
|
||||
int isPaused )
|
||||
torrentRealInit( tr_handle * h,
|
||||
tr_torrent * tor,
|
||||
const tr_ctor * ctor )
|
||||
//const char * destination,
|
||||
//int destinationIsFallback,
|
||||
//int isPaused )
|
||||
{
|
||||
int doStart;
|
||||
uint64_t loaded;
|
||||
|
@ -275,8 +274,6 @@ torrentRealInit( tr_handle * h,
|
|||
|
||||
tor->handle = h;
|
||||
tor->pexDisabled = 0;
|
||||
tor->maxConnectedPeers = DEFAULT_MAX_CONNECTED_PEERS;
|
||||
tor->maxUnchokedPeers = DEFAULT_MAX_UNCHOKED_PEERS;
|
||||
|
||||
/**
|
||||
* Decide on a block size. constraints:
|
||||
|
@ -345,18 +342,11 @@ torrentRealInit( tr_handle * h,
|
|||
|
||||
uncheckedPieces = tr_bitfieldNew( tor->info.pieceCount );
|
||||
|
||||
loaded = tr_fastResumeLoad( tor, ~0, uncheckedPieces, destination, destinationIsFallback );
|
||||
loaded = tr_fastResumeLoad( tor, ~0, uncheckedPieces, ctor );
|
||||
|
||||
assert( tor->destination != NULL );
|
||||
|
||||
/* the `paused' flag has highest precedence...
|
||||
after that, the fastresume setting is used...
|
||||
if that's not found, default to RUNNING */
|
||||
if( isPaused )
|
||||
doStart = 0;
|
||||
else if( loaded & TR_FR_RUN )
|
||||
doStart = tor->isRunning;
|
||||
else
|
||||
doStart = 1;
|
||||
doStart = tor->isRunning;
|
||||
tor->isRunning = 0;
|
||||
|
||||
if( tr_bitfieldIsEmpty( uncheckedPieces ) )
|
||||
|
@ -364,7 +354,6 @@ torrentRealInit( tr_handle * h,
|
|||
else
|
||||
tor->uncheckedPieces = uncheckedPieces;
|
||||
|
||||
|
||||
if( !(loaded & TR_FR_SPEEDLIMIT ) ) {
|
||||
int limit, enabled;
|
||||
tr_getGlobalSpeedLimit( tor->handle, TR_UP, &enabled, &limit );
|
||||
|
@ -388,21 +377,6 @@ torrentRealInit( tr_handle * h,
|
|||
tr_torrentStart( tor );
|
||||
}
|
||||
|
||||
static int
|
||||
pathIsInUse ( const tr_handle * h,
|
||||
const char * destination,
|
||||
const char * name )
|
||||
{
|
||||
const tr_torrent * tor;
|
||||
|
||||
for( tor=h->torrentList; tor; tor=tor->next )
|
||||
if( !strcmp( destination, tor->destination )
|
||||
&& !strcmp( name, tor->info.name ) )
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
hashExists( const tr_handle * h,
|
||||
const uint8_t * hash )
|
||||
|
@ -416,202 +390,147 @@ hashExists( const tr_handle * h,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
infoCanAdd( const tr_handle * h,
|
||||
const char * destination,
|
||||
const tr_info * info )
|
||||
{
|
||||
if( hashExists( h, info->hash ) )
|
||||
return TR_EDUPLICATE;
|
||||
|
||||
if( destination && pathIsInUse( h, destination, info->name ) )
|
||||
return TR_EDUPLICATE;
|
||||
|
||||
return TR_OK;
|
||||
}
|
||||
|
||||
int
|
||||
tr_torrentParse( const tr_handle * h,
|
||||
const char * path,
|
||||
const char * destination,
|
||||
tr_info * setme_info )
|
||||
tr_torrentParseFromCtor( const tr_handle * handle,
|
||||
const tr_ctor * ctor,
|
||||
tr_info * setmeInfo )
|
||||
{
|
||||
int ret, doFree;
|
||||
int err = 0;
|
||||
int doFree;
|
||||
tr_info tmp;
|
||||
const benc_val_t * metainfo;
|
||||
|
||||
if( setme_info == NULL )
|
||||
setme_info = &tmp;
|
||||
if( setmeInfo == NULL )
|
||||
setmeInfo = &tmp;
|
||||
memset( setmeInfo, 0, sizeof( tr_info ) );
|
||||
|
||||
memset( setme_info, 0, sizeof( tr_info ) );
|
||||
ret = tr_metainfoParseFile( setme_info, h->tag, path, FALSE );
|
||||
doFree = !ret && (setme_info == &tmp);
|
||||
if( !err && tr_ctorGetMetainfo( ctor, &metainfo ) )
|
||||
return TR_EINVALID;
|
||||
|
||||
if( ret == TR_OK )
|
||||
ret = infoCanAdd( h, destination, setme_info );
|
||||
err = tr_metainfoParseBenc( setmeInfo, handle->tag, metainfo, FALSE );
|
||||
doFree = !err && ( setmeInfo == &tmp );
|
||||
|
||||
if( !err && hashExists( handle, setmeInfo->hash ) )
|
||||
err = TR_EDUPLICATE;
|
||||
|
||||
if( doFree )
|
||||
tr_metainfoFree( &tmp );
|
||||
tr_metainfoFree( setmeInfo );
|
||||
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
static tr_torrent *
|
||||
tr_torrentInitImpl( tr_handle * h,
|
||||
const char * path,
|
||||
const char * destination,
|
||||
int destinationIsFallback,
|
||||
int isPaused,
|
||||
int * error )
|
||||
|
||||
tr_torrent *
|
||||
tr_torrentNew( tr_handle * handle,
|
||||
const tr_ctor * ctor,
|
||||
int * setmeError )
|
||||
{
|
||||
int val;
|
||||
int tmpError;
|
||||
int err;
|
||||
tr_info tmpInfo;
|
||||
tr_torrent * tor = NULL;
|
||||
|
||||
if( !error )
|
||||
error = &tmpError;
|
||||
|
||||
if(( val = tr_torrentParse( h, path, destination, NULL )))
|
||||
*error = val;
|
||||
else if(!(( tor = tr_new0( tr_torrent, 1 ))))
|
||||
*error = TR_EOTHER;
|
||||
else {
|
||||
tr_metainfoParseFile( &tor->info, h->tag, path, TRUE );
|
||||
torrentRealInit( h, tor, destination, destinationIsFallback, isPaused );
|
||||
err = tr_torrentParseFromCtor( handle, ctor, &tmpInfo );
|
||||
if( !err ) {
|
||||
tor = tr_new0( tr_torrent, 1 );
|
||||
tor->info = tmpInfo;
|
||||
torrentRealInit( handle, tor, ctor );
|
||||
} else if( setmeError ) {
|
||||
*setmeError = err;
|
||||
}
|
||||
|
||||
return tor;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
/** @deprecated */
|
||||
int
|
||||
tr_torrentParse( const tr_handle * h,
|
||||
const char * path,
|
||||
const char * destination,
|
||||
tr_info * setmeInfo )
|
||||
{
|
||||
int err;
|
||||
tr_ctor * ctor = tr_ctorNew( h );
|
||||
tr_ctorSetMetainfoFromFile( ctor, path );
|
||||
tr_ctorSetDestination( ctor, TR_FORCE, destination );
|
||||
err = tr_torrentParseFromCtor( h, ctor, setmeInfo );
|
||||
tr_ctorFree( ctor );
|
||||
return err;
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
tr_torrent *
|
||||
tr_torrentInit( tr_handle * h,
|
||||
const char * path,
|
||||
const char * destination,
|
||||
int isPaused,
|
||||
int * error )
|
||||
int * setmeError )
|
||||
{
|
||||
return tr_torrentInitImpl( h, path, destination, FALSE, isPaused, error );
|
||||
}
|
||||
|
||||
tr_torrent *
|
||||
tr_torrentLoad( tr_handle * h,
|
||||
const char * metainfoFilename,
|
||||
const char * destination,
|
||||
int isPaused,
|
||||
int * error )
|
||||
{
|
||||
return tr_torrentInitImpl( h, metainfoFilename, destination, TRUE, isPaused, error );
|
||||
tr_torrent * tor;
|
||||
tr_ctor * ctor = tr_ctorNew( h );
|
||||
tr_ctorSetMetainfoFromFile( ctor, path );
|
||||
tr_ctorSetDestination( ctor, TR_FORCE, destination );
|
||||
tr_ctorSetPaused( ctor, TR_FORCE, isPaused );
|
||||
tor = tr_torrentNew( h, ctor, setmeError );
|
||||
tr_ctorFree( ctor );
|
||||
return tor;
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
int
|
||||
tr_torrentParseHash( const tr_handle * h,
|
||||
const char * hashStr,
|
||||
const char * destination,
|
||||
tr_info * setme_info )
|
||||
tr_info * setmeInfo )
|
||||
{
|
||||
int ret, doFree;
|
||||
tr_info tmp;
|
||||
|
||||
if( setme_info == NULL )
|
||||
setme_info = &tmp;
|
||||
|
||||
memset( setme_info, 0, sizeof( tr_info ) );
|
||||
ret = tr_metainfoParseHash( setme_info, h->tag, hashStr );
|
||||
doFree = !ret && (setme_info == &tmp);
|
||||
|
||||
if( ret == TR_OK )
|
||||
ret = infoCanAdd( h, destination, setme_info );
|
||||
|
||||
if( doFree )
|
||||
tr_metainfoFree( &tmp );
|
||||
|
||||
return ret;
|
||||
int err;
|
||||
tr_ctor * ctor = tr_ctorNew( h );
|
||||
tr_ctorSetMetainfoFromHash( ctor, hashStr );
|
||||
tr_ctorSetDestination( ctor, TR_FORCE, destination );
|
||||
err = tr_torrentParseFromCtor( h, ctor, setmeInfo );
|
||||
tr_ctorFree( ctor );
|
||||
return err;
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
tr_torrent *
|
||||
tr_torrentInitSaved( tr_handle * h,
|
||||
const char * hashStr,
|
||||
const char * destination,
|
||||
int isPaused,
|
||||
int * error )
|
||||
int * setmeError )
|
||||
{
|
||||
int val;
|
||||
int tmpError;
|
||||
tr_torrent * tor = NULL;
|
||||
|
||||
if( !error )
|
||||
error = &tmpError;
|
||||
|
||||
if(( val = tr_torrentParseHash( h, hashStr, destination, NULL )))
|
||||
*error = val;
|
||||
else if(!(( tor = tr_new0( tr_torrent, 1 ))))
|
||||
*error = TR_EOTHER;
|
||||
else {
|
||||
tr_metainfoParseHash( &tor->info, h->tag, hashStr );
|
||||
torrentRealInit( h, tor, destination, FALSE, isPaused );
|
||||
}
|
||||
|
||||
tr_torrent * tor;
|
||||
tr_ctor * ctor = tr_ctorNew( h );
|
||||
tr_ctorSetMetainfoFromHash( ctor, hashStr );
|
||||
tr_ctorSetDestination( ctor, TR_FORCE, destination );
|
||||
tr_ctorSetPaused( ctor, TR_FORCE, isPaused );
|
||||
tor = tr_torrentNew( h, ctor, setmeError );
|
||||
tr_ctorFree( ctor );
|
||||
return tor;
|
||||
}
|
||||
|
||||
static int
|
||||
tr_torrentParseData( const tr_handle * h,
|
||||
const uint8_t * data,
|
||||
size_t size,
|
||||
const char * destination,
|
||||
tr_info * setme_info )
|
||||
{
|
||||
int ret, doFree;
|
||||
tr_info tmp;
|
||||
|
||||
if( setme_info == NULL )
|
||||
setme_info = &tmp;
|
||||
|
||||
memset( setme_info, 0, sizeof( tr_info ) );
|
||||
ret = tr_metainfoParseData( setme_info, h->tag, data, size, FALSE );
|
||||
doFree = !ret && (setme_info == &tmp);
|
||||
|
||||
if( ret == TR_OK )
|
||||
ret = infoCanAdd( h, destination, setme_info );
|
||||
|
||||
if( doFree )
|
||||
tr_metainfoFree( &tmp );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
tr_torrent *
|
||||
tr_torrentInitData( tr_handle * h,
|
||||
const uint8_t * data,
|
||||
size_t size,
|
||||
const uint8_t * metainfo,
|
||||
size_t len,
|
||||
const char * destination,
|
||||
int isPaused,
|
||||
int * error )
|
||||
int * setmeError )
|
||||
{
|
||||
int val;
|
||||
int tmpError;
|
||||
tr_torrent * tor = NULL;
|
||||
|
||||
if( !error )
|
||||
error = &tmpError;
|
||||
|
||||
if(( val = tr_torrentParseData( h, data, size, destination, NULL )))
|
||||
*error = val;
|
||||
else if(!(( tor = tr_new0( tr_torrent, 1 ))))
|
||||
*error = TR_EOTHER;
|
||||
else {
|
||||
tr_metainfoParseData( &tor->info, h->tag, data, size, TRUE );
|
||||
torrentRealInit( h, tor, destination, FALSE, isPaused );
|
||||
}
|
||||
|
||||
tr_torrent * tor;
|
||||
tr_ctor * ctor = tr_ctorNew( h );
|
||||
tr_ctorSetMetainfo( ctor, metainfo, len );
|
||||
tr_ctorSetDestination( ctor, TR_FORCE, destination );
|
||||
tr_ctorSetPaused( ctor, TR_FORCE, isPaused );
|
||||
tor = tr_torrentNew( h, ctor, setmeError );
|
||||
tr_ctorFree( ctor );
|
||||
return tor;
|
||||
}
|
||||
|
||||
const tr_info *
|
||||
tr_torrentInfo( const tr_torrent * tor )
|
||||
{
|
||||
return &tor->info;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
@ -711,23 +630,31 @@ tr_torrentGetRates( const tr_torrent * tor,
|
|||
if( toPeer )
|
||||
*toPeer = showSpeed ? tr_rcRate( tor->upload ) : 0.0;
|
||||
}
|
||||
const tr_info *
|
||||
tr_torrentInfo( const tr_torrent * tor )
|
||||
{
|
||||
return &tor->info;
|
||||
}
|
||||
|
||||
const tr_stat *
|
||||
tr_torrentStatCached( tr_torrent * tor )
|
||||
{
|
||||
const time_t now = time( NULL );
|
||||
|
||||
return now == tor->lastStatTime
|
||||
? &tor->stats[tor->statCur]
|
||||
: tr_torrentStat( tor );
|
||||
}
|
||||
|
||||
const tr_stat *
|
||||
tr_torrentStat( tr_torrent * tor )
|
||||
{
|
||||
tr_stat * s;
|
||||
struct tr_tracker * tc;
|
||||
const time_t now = time( NULL );
|
||||
|
||||
/* generating these stats is expensive --
|
||||
* update a maximum of once per second */
|
||||
if( tor->lastStatTime == now )
|
||||
return &tor->stats[tor->statCur];
|
||||
tor->lastStatTime = now;
|
||||
|
||||
tr_torrentLock( tor );
|
||||
|
||||
tor->lastStatTime = time( NULL );
|
||||
tr_torrentRecheckCompleteness( tor );
|
||||
|
||||
tor->statCur = !tor->statCur;
|
||||
|
@ -1074,7 +1001,7 @@ tr_torrentStart( tr_torrent * tor )
|
|||
{
|
||||
if( !tor->uncheckedPieces )
|
||||
tor->uncheckedPieces = tr_bitfieldNew( tor->info.pieceCount );
|
||||
tr_fastResumeLoad( tor, TR_FR_PROGRESS, tor->uncheckedPieces, tor->destination, FALSE );
|
||||
tr_fastResumeLoad( tor, TR_FR_PROGRESS, tor->uncheckedPieces, NULL );
|
||||
tor->isRunning = 1;
|
||||
tr_ioRecheckAdd( tor, checkAndStartCB );
|
||||
}
|
||||
|
|
|
@ -383,20 +383,19 @@ tr_close( tr_handle * h )
|
|||
|
||||
tr_torrent **
|
||||
tr_loadTorrents ( tr_handle * h,
|
||||
const char * fallbackDestination,
|
||||
int isPaused,
|
||||
tr_ctor * ctor,
|
||||
int * setmeCount )
|
||||
{
|
||||
int i, n = 0;
|
||||
struct stat sb;
|
||||
DIR * odir = NULL;
|
||||
const char * torrentDir = tr_getTorrentsDirectory( );
|
||||
const char * dirname = tr_getTorrentsDirectory( );
|
||||
tr_torrent ** torrents;
|
||||
tr_list *l=NULL, *list=NULL;
|
||||
|
||||
if( !stat( torrentDir, &sb )
|
||||
if( !stat( dirname, &sb )
|
||||
&& S_ISDIR( sb.st_mode )
|
||||
&& (( odir = opendir ( torrentDir ) )) )
|
||||
&& (( odir = opendir ( dirname ) )) )
|
||||
{
|
||||
struct dirent *d;
|
||||
for (d = readdir( odir ); d!=NULL; d=readdir( odir ) )
|
||||
|
@ -404,9 +403,10 @@ tr_loadTorrents ( tr_handle * h,
|
|||
if( d->d_name && d->d_name[0]!='.' ) /* skip dotfiles, ., and .. */
|
||||
{
|
||||
tr_torrent * tor;
|
||||
char path[MAX_PATH_LENGTH];
|
||||
tr_buildPath( path, sizeof(path), torrentDir, d->d_name, NULL );
|
||||
tor = tr_torrentLoad( h, path, fallbackDestination, isPaused, NULL );
|
||||
char filename[MAX_PATH_LENGTH];
|
||||
tr_buildPath( filename, sizeof(filename), dirname, d->d_name, NULL );
|
||||
tr_ctorSetMetainfoFromFile( ctor, filename );
|
||||
tor = tr_torrentNew( h, ctor, NULL );
|
||||
if( tor != NULL ) {
|
||||
tr_list_append( &list, tor );
|
||||
n++;
|
||||
|
|
|
@ -341,41 +341,31 @@ void tr_torrentRates( tr_handle *, float *, float * );
|
|||
|
||||
|
||||
|
||||
/**
|
||||
* Load all the torrents in tr_getTorrentsDirectory().
|
||||
* This can be used at startup to kickstart all the torrents
|
||||
* from the previous session.
|
||||
*/
|
||||
tr_torrent ** tr_loadTorrents ( tr_handle * h,
|
||||
const char * fallback_destination,
|
||||
int isPaused,
|
||||
int * setmeCount );
|
||||
|
||||
|
||||
/**
|
||||
* Torrent Instantiation
|
||||
*
|
||||
* Creating torrents has gotten more complicated as we've added options,
|
||||
* and there are now a lot of functions for creating torrents, all slightly
|
||||
* different. To remedy this, a Torrent Constructor (struct tr_ctor) has
|
||||
* been introduced. You can fill in the settings you want, and leave the
|
||||
* rest to the system defaults. It also gives us a backwards-compatable
|
||||
* way of adding features in the future -- we can add new tr_ctor() functions
|
||||
* and leave tr_torrentInit()'s signature alone.
|
||||
* Instantiating a tr_torrent has gotten a lot more complaticated as we
|
||||
* add more options to them. At the worst point there were four functions
|
||||
* to check metainfo, and four (or five) functions to create tr_torrents.
|
||||
* They all did mostly the same thing, but each was just *slightly* different.
|
||||
*
|
||||
* You _must_ call one of the SetMetadata() functions before creating
|
||||
* To remedy this, a Torrent Constructor (struct tr_ctor) has been introduced:
|
||||
* + Simplifies the API down to two (non-deprecated) functions.
|
||||
* + You can set the fields you want; the system sets defaults for the rest.
|
||||
* + You can specify whether or not your fields should supercede fastresume's.
|
||||
* + We can add new features to tr_ctor without breaking tr_torrentNew()'s API.
|
||||
*
|
||||
* All the tr_ctor{Get,Set}*() functions with a return value return
|
||||
* an error number, or zero if no error occurred.
|
||||
*
|
||||
* You must call one of the SetMetainfo() functions before creating
|
||||
* a torrent with a tr_ctor. The other functions are optional.
|
||||
*
|
||||
* You can reuse a tr_ctor when creating a batch of torrents.
|
||||
* Just call one of the SetMetadata() functions between each
|
||||
* tr_torrentInit() call.
|
||||
* You can reuse a single tr_ctor to create a batch of torrents --
|
||||
* just call one of the SetMetainfo() functions between each
|
||||
* tr_torrentNew() call.
|
||||
*
|
||||
* The tr_ctorGet*() functions will return nonzero if that field
|
||||
* has been set via one of the tr_ctorSet*() functions.
|
||||
*
|
||||
* Every call to tr_ctorSetMetadata*() will free the previous metadata.
|
||||
* The tr_ctorSetMetadata*() functions return an error number, or zero
|
||||
* if no error occurred.
|
||||
* Every call to tr_ctorSetMetainfo*() frees the previous metainfo.
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
|
@ -383,25 +373,26 @@ typedef enum
|
|||
TR_FALLBACK, /* indicates the ctor value should be used only
|
||||
in case of missing fastresume settings */
|
||||
|
||||
TR_FORCE, /* manditory use -- overrides the fastresume settings */
|
||||
TR_FORCE, /* indicates the ctor value should be used
|
||||
regardless of what's in the fastresume settings */
|
||||
}
|
||||
tr_ctorMode;
|
||||
|
||||
typedef struct tr_ctor tr_ctor;
|
||||
struct benc_val_s;
|
||||
|
||||
tr_ctor* tr_ctorNew ( tr_handle * handle);
|
||||
tr_ctor* tr_ctorNew ( const tr_handle * handle);
|
||||
|
||||
void tr_ctorFree ( tr_ctor * ctor );
|
||||
|
||||
int tr_ctorSetMetadata ( tr_ctor * ctor,
|
||||
const uint8_t * metadata,
|
||||
int tr_ctorSetMetainfo ( tr_ctor * ctor,
|
||||
const uint8_t * metainfo,
|
||||
size_t len );
|
||||
|
||||
int tr_ctorSetMetadataFromFile ( tr_ctor * ctor,
|
||||
int tr_ctorSetMetainfoFromFile ( tr_ctor * ctor,
|
||||
const char * filename );
|
||||
|
||||
int tr_ctorSetMetadataFromHash ( tr_ctor * ctor,
|
||||
int tr_ctorSetMetainfoFromHash ( tr_ctor * ctor,
|
||||
const char * hashString );
|
||||
|
||||
void tr_ctorSetMaxConnectedPeers ( tr_ctor * ctor,
|
||||
|
@ -418,7 +409,7 @@ void tr_ctorSetDestination ( tr_ctor * ctor,
|
|||
|
||||
void tr_ctorSetPaused ( tr_ctor * ctor,
|
||||
tr_ctorMode mode,
|
||||
int isPaused );
|
||||
uint8_t isPaused );
|
||||
|
||||
int tr_ctorGetMaxConnectedPeers ( const tr_ctor * ctor,
|
||||
tr_ctorMode mode,
|
||||
|
@ -430,15 +421,17 @@ int tr_ctorGetMaxUnchokedPeers ( const tr_ctor * ctor,
|
|||
|
||||
int tr_ctorGetIsPaused ( const tr_ctor * ctor,
|
||||
tr_ctorMode mode,
|
||||
int * setmeIsPaused );
|
||||
uint8_t * setmeIsPaused );
|
||||
|
||||
int tr_ctorGetDestination ( const tr_ctor * ctor,
|
||||
tr_ctorMode mode,
|
||||
const char ** setmeDestination );
|
||||
|
||||
int tr_ctorGetMetadata ( const tr_ctor * ctor,
|
||||
int tr_ctorGetMetainfo ( const tr_ctor * ctor,
|
||||
const struct benc_val_s ** setme );
|
||||
|
||||
typedef struct tr_info tr_info;
|
||||
|
||||
/**
|
||||
* Parses the specified metainfo.
|
||||
* Returns TR_OK if it parsed and can be added to Transmission.
|
||||
|
@ -448,14 +441,15 @@ int tr_ctorGetMetadata ( const tr_ctor * ctor,
|
|||
*
|
||||
* "setme_info" can be NULL if you don't need the information.
|
||||
* If the metainfo can be parsed and setme_info is non-NULL,
|
||||
* it will be filled with the metadata's info. You'll need to
|
||||
* it will be filled with the metainfo's info. You'll need to
|
||||
* call tr_metainfoFree( setme_info ) when done with it.
|
||||
*/
|
||||
int tr_torrentParseFromCtor( tr_handle * handle,
|
||||
const tr_ctor * ctor );
|
||||
int tr_torrentParseFromCtor( const tr_handle * handle,
|
||||
const tr_ctor * ctor,
|
||||
tr_info * setme_info );
|
||||
|
||||
/**
|
||||
* Instantiate the torrent from the given tr_ctor.
|
||||
* Instantiate a single torrent.
|
||||
*/
|
||||
#define TR_EINVALID 1
|
||||
#define TR_EUNSUPPORTED 2
|
||||
|
@ -466,37 +460,36 @@ tr_torrent * tr_torrentNew( tr_handle * handle,
|
|||
int * setmeError );
|
||||
|
||||
|
||||
/**
|
||||
* Load all the torrents in tr_getTorrentsDirectory().
|
||||
* This can be used at startup to kickstart all the torrents
|
||||
* from the previous session.
|
||||
*/
|
||||
tr_torrent ** tr_loadTorrents ( tr_handle * h,
|
||||
tr_ctor * ctor,
|
||||
int * setmeCount );
|
||||
|
||||
|
||||
/**
|
||||
***
|
||||
**/
|
||||
|
||||
/***********************************************************************
|
||||
* tr_torrentInit
|
||||
***********************************************************************
|
||||
* Opens and parses torrent file at 'path'. If the file exists and is
|
||||
* a valid torrent file, returns an handle and adds it to the list of
|
||||
* torrents (but doesn't start it). Returns NULL and sets *error
|
||||
* otherwise. If hash is not NULL and the torrent is already loaded
|
||||
* then it's 20-byte hash will be copied in. If the TR_FLAG_SAVE flag
|
||||
* is passed then a copy of the torrent file will be saved.
|
||||
**********************************************************************/
|
||||
*
|
||||
* !! DO NOT USE THIS FUNCTION IN NEW CODE !!
|
||||
*/
|
||||
tr_torrent * tr_torrentInit( tr_handle * handle,
|
||||
const char * metainfo_filename,
|
||||
const char * destination,
|
||||
int isPaused,
|
||||
int * setme_error );
|
||||
|
||||
/* This is a stupid hack to fix #415. Probably I should fold all
|
||||
* these torrent constructors into a single function that takes
|
||||
* a function object to hold all these esoteric arguments. */
|
||||
tr_torrent * tr_torrentLoad( tr_handle * handle,
|
||||
const char * metainfo_filename,
|
||||
const char * fallback_destination,
|
||||
int isPaused,
|
||||
int * setme_error );
|
||||
|
||||
typedef struct tr_info tr_info;
|
||||
|
||||
/**
|
||||
* Parses the specified metainfo file.
|
||||
*
|
||||
|
@ -509,8 +502,10 @@ typedef struct tr_info tr_info;
|
|||
*
|
||||
" "setme_info" can be NULL if you don't need the information.
|
||||
* If the metainfo can be parsed and setme_info is non-NULL,
|
||||
* it will be filled with the metadata's info. You'll need to
|
||||
* it will be filled with the metainfo's info. You'll need to
|
||||
* call tr_metainfoFree( setme_info ) when done with it.
|
||||
*
|
||||
* !! DO NOT USE THIS FUNCTION IN NEW CODE !!
|
||||
*/
|
||||
int tr_torrentParse( const tr_handle * handle,
|
||||
const char * metainfo_filename,
|
||||
|
@ -520,6 +515,8 @@ int tr_torrentParse( const tr_handle * handle,
|
|||
/**
|
||||
* Parses the cached metainfo file that matches the given hash string.
|
||||
* See tr_torrentParse() for a description of the arguments
|
||||
*
|
||||
* !! DO NOT USE THIS FUNCTION IN NEW CODE !!
|
||||
*/
|
||||
int
|
||||
tr_torrentParseHash( const tr_handle * h,
|
||||
|
@ -529,11 +526,11 @@ tr_torrentParseHash( const tr_handle * h,
|
|||
|
||||
|
||||
/***********************************************************************
|
||||
* tr_torrentInitData
|
||||
***********************************************************************
|
||||
* Like tr_torrentInit, except the actual torrent data is passed in
|
||||
* instead of the filename.
|
||||
**********************************************************************/
|
||||
*
|
||||
* !! DO NOT USE THIS FUNCTION IN NEW CODE !!
|
||||
*/
|
||||
tr_torrent * tr_torrentInitData( tr_handle *,
|
||||
const uint8_t * data, size_t size,
|
||||
const char * destination,
|
||||
|
@ -541,12 +538,12 @@ tr_torrent * tr_torrentInitData( tr_handle *,
|
|||
int * error );
|
||||
|
||||
/***********************************************************************
|
||||
* tr_torrentInitSaved
|
||||
***********************************************************************
|
||||
* Opens and parses a torrent file as with tr_torrentInit, only taking
|
||||
* the hash string of a saved torrent file instead of a filename. There
|
||||
* are currently no valid flags for this function.
|
||||
**********************************************************************/
|
||||
*
|
||||
* !! DO NOT USE THIS FUNCTION IN NEW CODE !!
|
||||
*/
|
||||
tr_torrent * tr_torrentInitSaved( tr_handle *,
|
||||
const char * hashStr,
|
||||
const char * destination,
|
||||
|
@ -641,6 +638,7 @@ int tr_torrentCanManualUpdate( const tr_torrent * );
|
|||
**********************************************************************/
|
||||
typedef struct tr_stat tr_stat;
|
||||
const tr_stat * tr_torrentStat( tr_torrent * );
|
||||
const tr_stat * tr_torrentStatCached( tr_torrent * );
|
||||
|
||||
/***********************************************************************
|
||||
* tr_torrentPeers
|
||||
|
@ -676,12 +674,10 @@ void tr_torrentRemoveSaved( tr_torrent * );
|
|||
|
||||
void tr_torrentRecheck( tr_torrent * );
|
||||
|
||||
/***********************************************************************
|
||||
* tr_torrentClose
|
||||
***********************************************************************
|
||||
* Frees memory allocated by tr_torrentInit. If the torrent was running,
|
||||
* it is stopped first.
|
||||
**********************************************************************/
|
||||
/**
|
||||
* Frees memory allocated by tr_torrentNew().
|
||||
* Running torrents are stopped first.
|
||||
*/
|
||||
void tr_torrentClose( tr_torrent * );
|
||||
|
||||
/***********************************************************************
|
||||
|
|
Loading…
Reference in New Issue