mirror of
https://github.com/transmission/transmission
synced 2024-12-25 01:03:01 +00:00
(libT) #3291 "tr_torrent.infoDictOffset should be lazily evaluated"
This commit is contained in:
parent
59821c65c7
commit
13b073fcdc
6 changed files with 71 additions and 33 deletions
|
@ -402,7 +402,6 @@ static const char*
|
|||
tr_metainfoParseImpl( const tr_session * session,
|
||||
tr_info * inf,
|
||||
tr_bool * hasInfoDict,
|
||||
int * infoDictOffset,
|
||||
int * infoDictLength,
|
||||
const tr_benc * meta_in )
|
||||
{
|
||||
|
@ -461,18 +460,6 @@ tr_metainfoParseImpl( const tr_session * session,
|
|||
if( infoDictLength != NULL )
|
||||
*infoDictLength = len;
|
||||
|
||||
if( infoDictOffset != NULL )
|
||||
{
|
||||
int mlen = 0;
|
||||
char * mstr = tr_bencToStr( meta_in, TR_FMT_BENC, &mlen );
|
||||
const char * offset = tr_memmem( mstr, mlen, bstr, len );
|
||||
if( offset != NULL )
|
||||
*infoDictOffset = offset - mstr;
|
||||
tr_free( mstr );
|
||||
if( offset == NULL )
|
||||
return "info";
|
||||
}
|
||||
|
||||
tr_free( bstr );
|
||||
}
|
||||
|
||||
|
@ -563,13 +550,11 @@ tr_metainfoParse( const tr_session * session,
|
|||
const tr_benc * meta_in,
|
||||
tr_info * inf,
|
||||
tr_bool * hasInfoDict,
|
||||
int * infoDictOffset,
|
||||
int * infoDictLength )
|
||||
{
|
||||
const char * badTag = tr_metainfoParseImpl( session,
|
||||
inf,
|
||||
hasInfoDict,
|
||||
infoDictOffset,
|
||||
infoDictLength,
|
||||
meta_in );
|
||||
const tr_bool success = badTag == NULL;
|
||||
|
|
|
@ -25,7 +25,6 @@ tr_bool tr_metainfoParse( const tr_session * session,
|
|||
const struct tr_benc * benc,
|
||||
tr_info * setmeInfo,
|
||||
tr_bool * setmeHasInfoDict,
|
||||
int * setmeInfoDictOffset,
|
||||
int * setmeInfoDictLength );
|
||||
|
||||
void tr_metainfoRemoveSaved( const tr_session * session,
|
||||
|
|
|
@ -95,8 +95,54 @@ tr_torrentSetMetadataSizeHint( tr_torrent * tor, int size )
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
findInfoDictOffset( const tr_torrent * tor )
|
||||
{
|
||||
size_t fileLen;
|
||||
uint8_t * fileContents;
|
||||
int offset = 0;
|
||||
|
||||
/* load the file, and find the info dict's offset inside the file */
|
||||
if(( fileContents = tr_loadFile( tor->info.torrent, &fileLen )))
|
||||
{
|
||||
tr_benc top;
|
||||
|
||||
if( !tr_bencParse( fileContents, fileContents + fileLen, &top, NULL ) )
|
||||
{
|
||||
tr_benc * infoDict;
|
||||
|
||||
if( tr_bencDictFindDict( &top, "info", &infoDict ) )
|
||||
{
|
||||
int infoLen;
|
||||
char * infoContents = tr_bencToStr( infoDict, TR_FMT_BENC, &infoLen );
|
||||
const uint8_t * i = (const uint8_t*) tr_memmem( (char*)fileContents, fileLen, infoContents, infoLen );
|
||||
offset = i == NULL ? i - fileContents : 0;
|
||||
tr_free( infoContents );
|
||||
}
|
||||
|
||||
tr_bencFree( &top );
|
||||
}
|
||||
|
||||
tr_free( fileContents );
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static void
|
||||
ensureInfoDictOffsetIsCached( tr_torrent * tor )
|
||||
{
|
||||
assert( tr_torrentHasMetadata( tor ) );
|
||||
|
||||
if( !tor->infoDictOffsetIsCached )
|
||||
{
|
||||
tor->infoDictOffset = findInfoDictOffset( tor );
|
||||
tor->infoDictOffsetIsCached = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void*
|
||||
tr_torrentGetMetadataPiece( const tr_torrent * tor, int piece, int * len )
|
||||
tr_torrentGetMetadataPiece( tr_torrent * tor, int piece, int * len )
|
||||
{
|
||||
char * ret = NULL;
|
||||
|
||||
|
@ -104,9 +150,16 @@ tr_torrentGetMetadataPiece( const tr_torrent * tor, int piece, int * len )
|
|||
assert( piece >= 0 );
|
||||
assert( len != NULL );
|
||||
|
||||
if( tor->infoDictLength > 0 )
|
||||
if( tr_torrentHasMetadata( tor ) )
|
||||
{
|
||||
FILE * fp = fopen( tor->info.torrent, "rb" );
|
||||
FILE * fp;
|
||||
|
||||
ensureInfoDictOffsetIsCached( tor );
|
||||
|
||||
assert( tor->infoDictLength > 0 );
|
||||
assert( tor->infoDictOffset >= 0 );
|
||||
|
||||
fp = fopen( tor->info.torrent, "rb" );
|
||||
if( fp != NULL )
|
||||
{
|
||||
const int o = piece * METADATA_PIECE_SIZE;
|
||||
|
@ -208,8 +261,7 @@ tr_torrentSetMetadataPiece( tr_torrent * tor, int piece, const void * data, in
|
|||
dbgmsg( tor, "Saving completed metadata to \"%s\"", path );
|
||||
tr_bencMergeDicts( tr_bencDictAddDict( &newMetainfo, "info", 0 ), &infoDict );
|
||||
|
||||
success = tr_metainfoParse( tor->session, &newMetainfo, &tor->info,
|
||||
&hasInfo, &tor->infoDictOffset, &tor->infoDictLength );
|
||||
success = tr_metainfoParse( tor->session, &newMetainfo, &tor->info, &hasInfo, &tor->infoDictLength );
|
||||
|
||||
assert( hasInfo );
|
||||
assert( success );
|
||||
|
|
|
@ -25,7 +25,7 @@ enum
|
|||
METADATA_PIECE_SIZE = ( 1024 * 16 )
|
||||
};
|
||||
|
||||
void* tr_torrentGetMetadataPiece( const tr_torrent * tor, int piece, int * len );
|
||||
void* tr_torrentGetMetadataPiece( tr_torrent * tor, int piece, int * len );
|
||||
|
||||
void tr_torrentSetMetadataPiece( tr_torrent * tor, int piece, const void * data, int len );
|
||||
|
||||
|
|
|
@ -737,7 +737,7 @@ torrentInit( tr_torrent * tor, const tr_ctor * ctor )
|
|||
|
||||
static tr_parse_result
|
||||
torrentParseImpl( const tr_ctor * ctor, tr_info * setmeInfo,
|
||||
tr_bool * setmeHasInfo, int * dictOffset, int * dictLength )
|
||||
tr_bool * setmeHasInfo, int * dictLength )
|
||||
{
|
||||
int doFree;
|
||||
tr_bool didParse;
|
||||
|
@ -755,7 +755,7 @@ torrentParseImpl( const tr_ctor * ctor, tr_info * setmeInfo,
|
|||
return TR_PARSE_ERR;
|
||||
|
||||
didParse = tr_metainfoParse( session, metainfo, setmeInfo,
|
||||
&hasInfo, dictOffset, dictLength );
|
||||
&hasInfo, dictLength );
|
||||
doFree = didParse && ( setmeInfo == &tmp );
|
||||
|
||||
if( !didParse )
|
||||
|
@ -779,13 +779,13 @@ torrentParseImpl( const tr_ctor * ctor, tr_info * setmeInfo,
|
|||
tr_parse_result
|
||||
tr_torrentParse( const tr_ctor * ctor, tr_info * setmeInfo )
|
||||
{
|
||||
return torrentParseImpl( ctor, setmeInfo, NULL, NULL, NULL );
|
||||
return torrentParseImpl( ctor, setmeInfo, NULL, NULL );
|
||||
}
|
||||
|
||||
tr_torrent *
|
||||
tr_torrentNew( const tr_ctor * ctor, int * setmeError )
|
||||
{
|
||||
int off, len;
|
||||
int len;
|
||||
tr_bool hasInfo;
|
||||
tr_info tmpInfo;
|
||||
tr_parse_result r;
|
||||
|
@ -794,16 +794,13 @@ tr_torrentNew( const tr_ctor * ctor, int * setmeError )
|
|||
assert( ctor != NULL );
|
||||
assert( tr_isSession( tr_ctorGetSession( ctor ) ) );
|
||||
|
||||
r = torrentParseImpl( ctor, &tmpInfo, &hasInfo, &off, &len );
|
||||
r = torrentParseImpl( ctor, &tmpInfo, &hasInfo, &len );
|
||||
if( r == TR_PARSE_OK )
|
||||
{
|
||||
tor = tr_new0( tr_torrent, 1 );
|
||||
tor->info = tmpInfo;
|
||||
if( hasInfo )
|
||||
{
|
||||
tor->infoDictOffset = off;
|
||||
tor->infoDictLength = len;
|
||||
}
|
||||
torrentInit( tor, ctor );
|
||||
}
|
||||
else
|
||||
|
@ -2195,7 +2192,7 @@ tr_torrentSetAnnounceList( tr_torrent * tor,
|
|||
/* try to parse it back again, to make sure it's good */
|
||||
memset( &tmpInfo, 0, sizeof( tr_info ) );
|
||||
if( tr_metainfoParse( tor->session, &metainfo, &tmpInfo,
|
||||
&hasInfo, &tor->infoDictOffset, &tor->infoDictLength ) )
|
||||
&hasInfo, &tor->infoDictLength ) )
|
||||
{
|
||||
/* it's good, so keep these new trackers and free the old ones */
|
||||
|
||||
|
|
|
@ -165,10 +165,13 @@ struct tr_torrent
|
|||
/* Where the files are when the torrent is incomplete */
|
||||
char * incompleteDir;
|
||||
|
||||
/* Length, in bytes, of the "info" dict in the .torrent file */
|
||||
/* Length, in bytes, of the "info" dict in the .torrent file. */
|
||||
int infoDictLength;
|
||||
|
||||
/* Offset, in bytes, of the beginning of the "info" dict in the .torrent file */
|
||||
/* Offset, in bytes, of the beginning of the "info" dict in the .torrent file.
|
||||
*
|
||||
* Used by the torrent-magnet code for serving metainfo to peers.
|
||||
* This field is lazy-generated and might not be initialized yet. */
|
||||
int infoDictOffset;
|
||||
|
||||
/* Where the files are now.
|
||||
|
@ -232,6 +235,8 @@ struct tr_torrent
|
|||
tr_bool startAfterVerify;
|
||||
tr_bool isDirty;
|
||||
|
||||
tr_bool infoDictOffsetIsCached;
|
||||
|
||||
uint16_t maxConnectedPeers;
|
||||
|
||||
tr_verify_state verifyState;
|
||||
|
|
Loading…
Reference in a new issue