1
0
Fork 0
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:
Charles Kerr 2010-06-16 03:05:23 +00:00
parent 59821c65c7
commit 13b073fcdc
6 changed files with 71 additions and 33 deletions

View file

@ -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;

View file

@ -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,

View file

@ -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 );

View file

@ -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 );

View file

@ -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 */

View file

@ -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;