fix bug that caused very large torrents to crash Transmission

This commit is contained in:
Charles Kerr 2008-03-22 18:10:59 +00:00
parent 24fedbe044
commit c63b548195
17 changed files with 264 additions and 234 deletions

View File

@ -178,6 +178,8 @@ main( int argc, char ** argv )
if( !tr_torrentParse( h, ctor, &info ) )
{
tr_file_index_t ff;
printf( "hash:\t" );
for( i=0; i<SHA_DIGEST_LENGTH; ++i )
printf( "%02x", info.hash[i] );
@ -208,8 +210,8 @@ main( int argc, char ** argv )
printf( "private flag set\n" );
printf( "file(s):\n" );
for( i=0; i<info.fileCount; ++i )
printf( "\t%s (%"PRIu64")\n", info.files[i].name, info.files[i].length );
for( ff=0; ff<info.fileCount; ++ff )
printf( "\t%s (%"PRIu64")\n", info.files[ff].name, info.files[ff].length );
tr_metainfoFree( &info );
}

View File

@ -265,8 +265,10 @@ subtree_walk_dnd( GtkTreeStore * store,
/* update this node */
gtk_tree_model_get( GTK_TREE_MODEL(store), iter, FC_INDEX, &index, -1 );
if (index >= 0)
g_array_append_val( indices, index );
if (index >= 0) {
tr_file_index_t fi = index;
g_array_append_val( indices, fi );
}
gtk_tree_store_set( store, iter, FC_ENABLED, enabled, -1 );
/* visit the children */
@ -281,9 +283,9 @@ set_subtree_dnd( GtkTreeStore * store,
tr_torrent * tor,
gboolean enabled )
{
GArray * indices = g_array_new( FALSE, FALSE, sizeof(int) );
GArray * indices = g_array_new( FALSE, FALSE, sizeof(tr_file_index_t) );
subtree_walk_dnd( store, iter, tor, enabled, indices );
tr_torrentSetFileDLs( tor, (int*)indices->data, (int)indices->len, enabled );
tr_torrentSetFileDLs( tor, (tr_file_index_t*)indices->data, (tr_file_index_t)indices->len, enabled );
g_array_free( indices, TRUE );
}
@ -318,7 +320,7 @@ set_subtree_priority( GtkTreeStore * store,
{
GArray * indices = g_array_new( FALSE, FALSE, sizeof(int) );
subtree_walk_priority( store, iter, tor, priority, indices );
tr_torrentSetFilePriorities( tor, (int*)indices->data, (int)indices->len, priority );
tr_torrentSetFilePriorities( tor, (tr_file_index_t*)indices->data, (tr_file_index_t)indices->len, priority );
g_array_free( indices, TRUE );
}
@ -370,7 +372,7 @@ refreshModel( gpointer gdata )
if( data->gtor )
{
guint64 foo, bar;
int fileCount;
tr_file_index_t fileCount;
tr_torrent * tor;
tr_file_stat * fileStats;
@ -424,7 +426,7 @@ file_list_set_torrent( GtkWidget * w, TrTorrent * gtor )
/* populate the model */
if( gtor )
{
int i;
tr_file_index_t i;
const tr_info * inf = tr_torrent_info( gtor );
tr_torrent * tor = tr_torrent_handle( gtor );

View File

@ -332,7 +332,7 @@ tr_torrent_set_delete_flag( TrTorrent * gtor, gboolean do_delete )
void
tr_torrent_delete_files( TrTorrent * gtor )
{
int i;
tr_file_index_t i;
const tr_info * info = tr_torrent_info( gtor );
const char * stop = tr_torrentGetFolder( tr_torrent_handle( gtor ) );

View File

@ -269,7 +269,7 @@ checkFilterText( filter_text_mode_t filter_text_mode,
const tr_info * torInfo,
const char * text )
{
int i;
tr_file_index_t i;
int ret = 0;
char * pch;

View File

@ -97,7 +97,7 @@ tr_cpEnsureDoneValid( const tr_completion * ccp )
const tr_torrent * tor = ccp->tor;
const tr_info * info = &tor->info;
uint64_t have=0, total=0;
int i;
tr_piece_index_t i;
tr_completion * cp ;
if( !ccp->doneDirty )
@ -137,9 +137,9 @@ tr_cpInvalidateDND ( tr_completion * cp )
}
int
tr_cpPieceIsComplete( const tr_completion * cp, int piece )
tr_cpPieceIsComplete( const tr_completion * cp,
tr_piece_index_t piece )
{
assert( piece >= 0 );
assert( piece < cp->tor->info.pieceCount );
assert( cp->completeBlocks[piece] <= tr_torPieceCountBlocks(cp->tor,piece) );
@ -152,29 +152,27 @@ const tr_bitfield * tr_cpPieceBitfield( const tr_completion * cp )
}
void
tr_cpPieceAdd( tr_completion * cp, int piece )
tr_cpPieceAdd( tr_completion * cp, tr_piece_index_t piece )
{
const tr_torrent * tor = cp->tor;
const int start = tr_torPieceFirstBlock(tor,piece);
const int end = start + tr_torPieceCountBlocks(tor,piece);
int i;
const tr_block_index_t start = tr_torPieceFirstBlock(tor,piece);
const tr_block_index_t end = start + tr_torPieceCountBlocks(tor, piece);
tr_block_index_t i;
for( i=start; i<end; ++i )
tr_cpBlockAdd( cp, i );
}
void
tr_cpPieceRem( tr_completion * cp, int piece )
tr_cpPieceRem( tr_completion * cp, tr_piece_index_t piece )
{
const tr_torrent * tor = cp->tor;
const int start = tr_torPieceFirstBlock(tor,piece);
const int end = start + tr_torPieceCountBlocks(tor,piece);
int block;
const tr_block_index_t start = tr_torPieceFirstBlock(tor,piece);
const tr_block_index_t end = start + tr_torPieceCountBlocks(tor,piece);
tr_block_index_t block;
assert( cp != NULL );
assert( 0 <= piece );
assert( piece < tor->info.pieceCount );
assert( 0 <= start );
assert( start < tor->blockCount );
assert( start <= end );
assert( end <= tor->blockCount );
@ -197,19 +195,20 @@ tr_cpPieceRem( tr_completion * cp, int piece )
assert( cp->doneHave <= cp->completeHave );
}
int tr_cpBlockIsComplete( const tr_completion * cp, int block )
int
tr_cpBlockIsComplete( const tr_completion * cp, tr_block_index_t block )
{
return tr_bitfieldHas( cp->blockBitfield, block ) ? 1 : 0;
}
void
tr_cpBlockAdd( tr_completion * cp, int block )
tr_cpBlockAdd( tr_completion * cp, tr_block_index_t block )
{
const tr_torrent * tor = cp->tor;
if( !tr_cpBlockIsComplete( cp, block ) )
{
const int piece = tr_torBlockPiece( tor, block );
const tr_piece_index_t piece = tr_torBlockPiece( tor, block );
const int blockSize = tr_torBlockCountBytes( tor, block );
++cp->completeBlocks[piece];
@ -240,7 +239,7 @@ const tr_bitfield * tr_cpBlockBitfield( const tr_completion * cp )
void
tr_cpBlockBitfieldSet( tr_completion * cp, tr_bitfield * bitfield )
{
int i;
tr_block_index_t i;
assert( cp != NULL );
assert( bitfield != NULL );
@ -252,7 +251,8 @@ tr_cpBlockBitfieldSet( tr_completion * cp, tr_bitfield * bitfield )
tr_cpBlockAdd( cp, i );
}
float tr_cpPercentBlocksInPiece( const tr_completion * cp, int piece )
float
tr_cpPercentBlocksInPiece( const tr_completion * cp, tr_piece_index_t piece )
{
assert( cp != NULL );
@ -260,7 +260,7 @@ float tr_cpPercentBlocksInPiece( const tr_completion * cp, int piece )
}
int
tr_cpMissingBlocksInPiece( const tr_completion * cp, int piece )
tr_cpMissingBlocksInPiece( const tr_completion * cp, tr_piece_index_t piece )
{
assert( cp != NULL );
@ -323,7 +323,7 @@ tr_cpHaveValid( const tr_completion * cp )
uint64_t b = 0;
const tr_torrent * tor = cp->tor;
const tr_info * info = &tor->info;
int i;
tr_piece_index_t i;
for( i=0; i<info->pieceCount; ++i )
if( tr_cpPieceIsComplete( cp, i ) )

View File

@ -45,16 +45,16 @@ float tr_cpPercentDone( const tr_completion * );
void tr_cpInvalidateDND ( tr_completion * );
/* Pieces */
int tr_cpPieceIsComplete( const tr_completion *, int piece );
void tr_cpPieceAdd( tr_completion *, int piece );
void tr_cpPieceRem( tr_completion *, int piece );
int tr_cpPieceIsComplete( const tr_completion *, tr_piece_index_t piece );
void tr_cpPieceAdd( tr_completion *, tr_piece_index_t piece );
void tr_cpPieceRem( tr_completion *, tr_piece_index_t piece );
/* Blocks */
int tr_cpBlockIsComplete( const tr_completion *, int block );
void tr_cpBlockAdd( tr_completion *, int block );
int tr_cpBlockIsComplete( const tr_completion *, tr_block_index_t block );
void tr_cpBlockAdd( tr_completion *, tr_block_index_t block );
void tr_cpBlockBitfieldSet( tr_completion *, struct tr_bitfield * );
float tr_cpPercentBlocksInPiece( const tr_completion * cp, int piece );
int tr_cpMissingBlocksInPiece( const tr_completion * cp, int piece );
float tr_cpPercentBlocksInPiece( const tr_completion * cp, tr_piece_index_t piece );
int tr_cpMissingBlocksInPiece( const tr_completion * cp, tr_piece_index_t piece );
const struct tr_bitfield * tr_cpPieceBitfield( const tr_completion* );

View File

@ -399,11 +399,11 @@ parseProgress( tr_torrent * tor,
const uint8_t * buf,
uint32_t len )
{
int i;
uint64_t ret = 0;
if( len == FR_PROGRESS_LEN( tor ) )
{
int i;
int n;
tr_bitfield bitfield;
@ -433,9 +433,12 @@ parseProgress( tr_torrent * tor,
/* the files whose mtimes are wrong,
remove from completion pending a recheck... */
for( i=0; i<tor->info.pieceCount; ++i )
if( !tr_torrentIsPieceChecked( tor, i ) )
tr_cpPieceRem( tor->completion, i );
{
tr_piece_index_t i;
for( i=0; i<tor->info.pieceCount; ++i )
if( !tr_torrentIsPieceChecked( tor, i ) )
tr_cpPieceRem( tor->completion, i );
}
return ret;
}
@ -449,8 +452,8 @@ parsePriorities( tr_torrent * tor, const uint8_t * buf, uint32_t len )
{
const size_t n = tor->info.fileCount;
const size_t len = 2 * n;
int *dnd = NULL, dndCount = 0;
int *dl = NULL, dlCount = 0;
tr_file_index_t *dnd = NULL, dndCount = 0;
tr_file_index_t *dl = NULL, dlCount = 0;
size_t i;
const uint8_t * walk = buf;
@ -467,8 +470,8 @@ parsePriorities( tr_torrent * tor, const uint8_t * buf, uint32_t len )
}
/* set the dnd flags */
dl = tr_new( int, len );
dnd = tr_new( int, len );
dl = tr_new( tr_file_index_t, len );
dnd = tr_new( tr_file_index_t, len );
for( i=0; i<n; ++i )
if( *walk++ == 't' ) /* 't' means the DND flag is true */
dnd[dndCount++] = i;

View File

@ -41,7 +41,7 @@ enum { TR_IO_READ, TR_IO_WRITE };
static tr_errno
readOrWriteBytes( const tr_torrent * tor,
int ioMode,
int fileIndex,
tr_file_index_t fileIndex,
uint64_t fileOffset,
void * buf,
size_t buflen )
@ -56,7 +56,7 @@ readOrWriteBytes( const tr_torrent * tor,
int err;
int fileExists;
assert( 0<=fileIndex && fileIndex<info->fileCount );
assert( fileIndex < info->fileCount );
assert( !file->length || (fileOffset < file->length));
assert( fileOffset + buflen <= file->length );
@ -88,17 +88,17 @@ readOrWriteBytes( const tr_torrent * tor,
static tr_errno
findFileLocation( const tr_torrent * tor,
int pieceIndex,
int pieceOffset,
int * fileIndex,
tr_piece_index_t pieceIndex,
uint32_t pieceOffset,
tr_file_index_t * fileIndex,
uint64_t * fileOffset )
{
const tr_info * info = &tor->info;
int i;
tr_file_index_t i;
uint64_t piecePos = ((uint64_t)pieceIndex * info->pieceSize) + pieceOffset;
if( pieceIndex < 0 || pieceIndex >= info->pieceCount )
if( pieceIndex >= info->pieceCount )
return TR_ERROR_ASSERT;
if( pieceOffset >= tr_torPieceCountBytes( tor, pieceIndex ) )
return TR_ERROR_ASSERT;
@ -111,7 +111,7 @@ findFileLocation( const tr_torrent * tor,
*fileIndex = i;
*fileOffset = piecePos;
assert( 0<=*fileIndex && *fileIndex<info->fileCount );
assert( *fileIndex < info->fileCount );
assert( *fileOffset < info->files[i].length );
return 0;
}
@ -119,7 +119,7 @@ findFileLocation( const tr_torrent * tor,
#ifdef WIN32
static tr_errno
ensureMinimumFileSize( const tr_torrent * tor,
int fileIndex,
tr_file_index_t fileIndex,
uint64_t minBytes )
{
int fd;
@ -150,19 +150,19 @@ ensureMinimumFileSize( const tr_torrent * tor,
#endif
static tr_errno
readOrWritePiece( tr_torrent * tor,
int ioMode,
int pieceIndex,
int pieceOffset,
uint8_t * buf,
size_t buflen )
readOrWritePiece( tr_torrent * tor,
int ioMode,
tr_piece_index_t pieceIndex,
uint32_t pieceOffset,
uint8_t * buf,
size_t buflen )
{
tr_errno err = 0;
int fileIndex;
tr_file_index_t fileIndex;
uint64_t fileOffset;
const tr_info * info = &tor->info;
if( pieceIndex < 0 || pieceIndex >= tor->info.pieceCount )
if( pieceIndex >= tor->info.pieceCount )
err = TR_ERROR_ASSERT;
else if( buflen > ( size_t ) tr_torPieceCountBytes( tor, pieceIndex ) )
err = TR_ERROR_ASSERT;
@ -194,20 +194,20 @@ readOrWritePiece( tr_torrent * tor,
tr_errno
tr_ioRead( const tr_torrent * tor,
int pieceIndex,
int begin,
int len,
tr_piece_index_t pieceIndex,
uint32_t begin,
uint32_t len,
uint8_t * buf )
{
return readOrWritePiece( (tr_torrent*)tor, TR_IO_READ, pieceIndex, begin, buf, len );
}
tr_errno
tr_ioWrite( tr_torrent * tor,
int pieceIndex,
int begin,
int len,
const uint8_t * buf )
tr_ioWrite( tr_torrent * tor,
tr_piece_index_t pieceIndex,
uint32_t begin,
uint32_t len,
const uint8_t * buf )
{
return readOrWritePiece( tor, TR_IO_WRITE, pieceIndex, begin, (uint8_t*)buf, len );
}
@ -218,7 +218,7 @@ tr_ioWrite( tr_torrent * tor,
static tr_errno
tr_ioRecalculateHash( const tr_torrent * tor,
int pieceIndex,
tr_piece_index_t pieceIndex,
uint8_t * setme )
{
static uint8_t * buf = NULL;
@ -238,7 +238,7 @@ tr_ioRecalculateHash( const tr_torrent * tor,
assert( tor != NULL );
assert( setme != NULL );
assert( 0<=pieceIndex && pieceIndex<tor->info.pieceCount );
assert( pieceIndex < tor->info.pieceCount );
info = &tor->info;
n = tr_torPieceCountBytes( tor, pieceIndex );

View File

@ -33,9 +33,9 @@ struct tr_torrent;
* or TR_ERROR_IO_* otherwise.
*/
int tr_ioRead ( const struct tr_torrent * tor,
int pieceIndex,
int offset,
int len,
tr_piece_index_t pieceIndex,
uint32_t offset,
uint32_t len,
uint8_t * setme );
/**
@ -44,9 +44,9 @@ int tr_ioRead ( const struct tr_torrent * tor,
* or TR_ERROR_IO_* otherwise.
*/
tr_errno tr_ioWrite ( struct tr_torrent * tor,
int pieceIndex,
int offset,
int len,
tr_piece_index_t pieceIndex,
uint32_t offset,
uint32_t len,
const uint8_t * writeme );
/**

View File

@ -502,6 +502,7 @@ ipc_addinfo( tr_benc * list, int tor, const tr_info * inf, int types )
{
tr_benc * dict, * item, * file, * tier;
int ii, jj, kk;
tr_file_index_t ff;
/* always send torrent id */
types |= IPC_INF_ID;
@ -567,7 +568,7 @@ ipc_addinfo( tr_benc * list, int tor, const tr_info * inf, int types )
{
return -1;
}
for( jj = 0; inf->fileCount > jj; jj++ )
for( ff = 0; inf->fileCount > ff; ff++ )
{
file = tr_bencListAdd( item );
tr_bencInit( file, TYPE_DICT );
@ -576,9 +577,9 @@ ipc_addinfo( tr_benc * list, int tor, const tr_info * inf, int types )
return -1;
}
tr_bencInitStr( tr_bencDictAdd( file, "name" ),
inf->files[jj].name, -1, 1 );
inf->files[ff].name, -1, 1 );
tr_bencInitInt( tr_bencDictAdd( file, "size" ),
inf->files[jj].length );
inf->files[ff].length );
}
break;
case IPC_INF_HASH:

View File

@ -171,7 +171,7 @@ savedname( char * name, size_t len, const char * hash, const char * tag )
int
tr_metainfoParse( tr_info * inf, const tr_benc * meta_in, const char * tag )
{
int i;
tr_piece_index_t i;
tr_benc * beInfo, * val, * val2;
tr_benc * meta = (tr_benc *) meta_in;
char buf[4096];
@ -304,10 +304,11 @@ tr_metainfoParse( tr_info * inf, const tr_benc * meta_in, const char * tag )
void tr_metainfoFree( tr_info * inf )
{
tr_file_index_t ff;
int i, j;
for( i=0; i<inf->fileCount; ++i )
tr_free( inf->files[i].name );
for( ff=0; ff<inf->fileCount; ++ff )
tr_free( inf->files[ff].name );
tr_free( inf->pieces );
tr_free( inf->files );

View File

@ -594,7 +594,7 @@ compareRefillPiece (const void * aIn, const void * bIn)
static int
isPieceInteresting( const tr_torrent * tor,
int piece )
tr_piece_index_t piece )
{
if( tor->info.pieces[piece].dnd ) /* we don't want it */
return 0;
@ -611,7 +611,7 @@ getPreferredPieces( Torrent * t,
{
const tr_torrent * tor = t->tor;
const tr_info * inf = &tor->info;
int i;
tr_piece_index_t i;
uint32_t poolSize = 0;
uint32_t * pool = tr_new( uint32_t, inf->pieceCount );
int peerCount;
@ -665,7 +665,7 @@ getPreferredPieces( Torrent * t,
}
static uint64_t*
getPreferredBlocks( Torrent * t, uint64_t * setmeCount )
getPreferredBlocks( Torrent * t, tr_block_index_t * setmeCount )
{
int s;
uint32_t i;
@ -703,11 +703,11 @@ getPreferredBlocks( Torrent * t, uint64_t * setmeCount )
/* sort the blocks into our temp bins */
for( i=blockCount=0; i<pieceCount; ++i )
{
const uint32_t index = pieces[i];
const tr_piece_index_t index = pieces[i];
const int priorityIndex = tor->info.pieces[index].priority + 1;
const int begin = tr_torPieceFirstBlock( tor, index );
const int end = begin + tr_torPieceCountBlocks( tor, (int)index );
int block;
const tr_block_index_t begin = tr_torPieceFirstBlock( tor, index );
const tr_block_index_t end = begin + tr_torPieceCountBlocks( tor, index );
tr_block_index_t block;
for( block=begin; block<end; ++block )
{
@ -784,10 +784,10 @@ refillPulse( void * vtorrent )
{
Torrent * t = vtorrent;
tr_torrent * tor = t->tor;
uint32_t i;
tr_block_index_t i;
int peerCount;
tr_peer ** peers;
uint64_t blockCount;
tr_block_index_t blockCount;
uint64_t * blocks;
if( !t->isRunning )
@ -805,15 +805,15 @@ refillPulse( void * vtorrent )
{
int j;
const uint64_t block = blocks[i];
const uint32_t index = tr_torBlockPiece( tor, block );
const tr_block_index_t block = blocks[i];
const tr_piece_index_t index = tr_torBlockPiece( tor, block );
const uint32_t begin = (block * tor->blockSize) - (index * tor->info.pieceSize);
const uint32_t length = tr_torBlockCountBytes( tor, (int)block );
const uint32_t length = tr_torBlockCountBytes( tor, block );
assert( tr_torrentReqIsValid( tor, index, begin, length ) );
assert( _tr_block( tor, index, begin ) == (int)block );
assert( begin < (uint32_t)tr_torPieceCountBytes( tor, (int)index ) );
assert( (begin + length) <= (uint32_t)tr_torPieceCountBytes( tor, (int)index ) );
assert( _tr_block( tor, index, begin ) == block );
assert( begin < tr_torPieceCountBytes( tor, index ) );
assert( (begin + length) <= tr_torPieceCountBytes( tor, index ) );
/* find a peer who can ask for this block */
for( j=0; j<peerCount; )

View File

@ -461,7 +461,7 @@ isPieceInteresting( const tr_peermsgs * peer,
static int
isPeerInteresting( const tr_peermsgs * msgs )
{
int i;
tr_piece_index_t i;
const tr_torrent * torrent;
const tr_bitfield * bitfield;
const int clientIsSeed = tr_torrentIsSeed( msgs->torrent );
@ -630,7 +630,7 @@ sendFastAllowed( tr_peermsgs * msgs,
static void
sendFastAllowedSet( tr_peermsgs * msgs )
{
int i = 0;
tr_piece_index_t i = 0;
while (i <= msgs->torrent->info.pieceCount )
{
@ -1440,10 +1440,10 @@ reassignBytesToCorrupt( tr_peermsgs * msgs, uint32_t byteCount )
}
static void
gotBadPiece( tr_peermsgs * msgs, uint32_t pieceIndex )
gotBadPiece( tr_peermsgs * msgs, tr_piece_index_t pieceIndex )
{
const uint32_t byteCount =
tr_torPieceCountBytes( msgs->torrent, (int)pieceIndex );
tr_torPieceCountBytes( msgs->torrent, pieceIndex );
reassignBytesToCorrupt( msgs, byteCount );
}
@ -1468,12 +1468,12 @@ clientGotBlock( tr_peermsgs * msgs,
{
int err;
tr_torrent * tor = msgs->torrent;
const int block = _tr_block( tor, req->index, req->offset );
const tr_block_index_t block = _tr_block( tor, req->index, req->offset );
assert( msgs != NULL );
assert( req != NULL );
if( req->length != (uint32_t)tr_torBlockCountBytes( msgs->torrent, block ) )
if( req->length != tr_torBlockCountBytes( msgs->torrent, block ) )
{
dbgmsg( msgs, "wrong block size -- expected %u, got %d",
tr_torBlockCountBytes( msgs->torrent, block ), req->length );

View File

@ -191,13 +191,13 @@ getBytePiece( const tr_info * info, uint64_t byteOffset )
}
static void
initFilePieces ( tr_info * info, int fileIndex )
initFilePieces ( tr_info * info, tr_file_index_t fileIndex )
{
tr_file * file = &info->files[fileIndex];
uint64_t firstByte, lastByte;
assert( info != NULL );
assert( 0<=fileIndex && fileIndex<info->fileCount );
assert( fileIndex < info->fileCount );
file = &info->files[fileIndex];
firstByte = file->offset;
@ -207,17 +207,17 @@ initFilePieces ( tr_info * info, int fileIndex )
}
static int
pieceHasFile( int piece, const tr_file * file )
pieceHasFile( tr_piece_index_t piece, const tr_file * file )
{
return ( file->firstPiece <= piece ) && ( piece <= file->lastPiece );
}
static tr_priority_t
calculatePiecePriority ( const tr_torrent * tor,
int piece,
tr_piece_index_t piece,
int fileHint )
{
int i;
tr_file_index_t i;
int priority = TR_PRI_LOW;
/* find the first file that has data in this piece */
@ -256,19 +256,20 @@ calculatePiecePriority ( const tr_torrent * tor,
static void
tr_torrentInitFilePieces( tr_torrent * tor )
{
int i;
tr_file_index_t ff;
tr_piece_index_t pp;
uint64_t offset = 0;
assert( tor != NULL );
for( i=0; i<tor->info.fileCount; ++i ) {
tor->info.files[i].offset = offset;
offset += tor->info.files[i].length;
initFilePieces( &tor->info, i );
for( ff=0; ff<tor->info.fileCount; ++ff ) {
tor->info.files[ff].offset = offset;
offset += tor->info.files[ff].length;
initFilePieces( &tor->info, ff );
}
for( i=0; i<tor->info.pieceCount; ++i )
tor->info.pieces[i].priority = calculatePiecePriority( tor, i, -1 );
for( pp=0; pp<tor->info.pieceCount; ++pp )
tor->info.pieces[pp].priority = calculatePiecePriority( tor, pp, -1 );
}
static void
@ -636,7 +637,7 @@ tr_torrentStat( tr_torrent * tor )
{
int i;
tr_piece_index_t i;
tr_bitfield * availablePieces = tr_peerMgrGetAvailable( tor->handle->peerMgr,
tor->info.hash );
s->desiredSize = 0;
@ -671,24 +672,24 @@ tr_torrentStat( tr_torrent * tor )
***/
static uint64_t
fileBytesCompleted ( const tr_torrent * tor, int fileIndex )
fileBytesCompleted ( const tr_torrent * tor, tr_file_index_t fileIndex )
{
const tr_file * file = &tor->info.files[fileIndex];
const uint64_t firstBlock = file->offset / tor->blockSize;
const tr_block_index_t firstBlock = file->offset / tor->blockSize;
const uint64_t firstBlockOffset = file->offset % tor->blockSize;
const uint64_t lastOffset = file->length ? (file->length-1) : 0;
const uint64_t lastBlock = (file->offset + lastOffset) / tor->blockSize;
const tr_block_index_t lastBlock = (file->offset + lastOffset) / tor->blockSize;
const uint64_t lastBlockOffset = (file->offset + lastOffset) % tor->blockSize;
uint64_t haveBytes = 0;
assert( tor != NULL );
assert( 0<=fileIndex && fileIndex<tor->info.fileCount );
assert( fileIndex < tor->info.fileCount );
assert( file->offset + file->length <= tor->info.totalSize );
assert( ( (int)firstBlock < tor->blockCount ) || (!file->length && file->offset==tor->info.totalSize) );
assert( ( (int)lastBlock < tor->blockCount ) || (!file->length && file->offset==tor->info.totalSize) );
assert( ( firstBlock < tor->blockCount ) || (!file->length && file->offset==tor->info.totalSize) );
assert( ( lastBlock < tor->blockCount ) || (!file->length && file->offset==tor->info.totalSize) );
assert( firstBlock <= lastBlock );
assert( (int)tr_torBlockPiece( tor, firstBlock ) == file->firstPiece );
assert( (int)tr_torBlockPiece( tor, lastBlock ) == file->lastPiece );
assert( tr_torBlockPiece( tor, firstBlock ) == file->firstPiece );
assert( tr_torBlockPiece( tor, lastBlock ) == file->lastPiece );
if( firstBlock == lastBlock )
{
@ -697,7 +698,7 @@ fileBytesCompleted ( const tr_torrent * tor, int fileIndex )
}
else
{
uint64_t i;
tr_block_index_t i;
if( tr_cpBlockIsComplete( tor->completion, firstBlock ) )
haveBytes += tor->blockSize - firstBlockOffset;
@ -714,10 +715,10 @@ fileBytesCompleted ( const tr_torrent * tor, int fileIndex )
}
tr_file_stat *
tr_torrentFiles( const tr_torrent * tor, int * fileCount )
tr_torrentFiles( const tr_torrent * tor, tr_file_index_t * fileCount )
{
int i;
const int n = tor->info.fileCount;
tr_file_index_t i;
const tr_file_index_t n = tor->info.fileCount;
tr_file_stat * files = tr_new0( tr_file_stat, n );
tr_file_stat * walk = files;
@ -738,7 +739,7 @@ tr_torrentFiles( const tr_torrent * tor, int * fileCount )
}
void
tr_torrentFilesFree( tr_file_stat * files, int fileCount UNUSED )
tr_torrentFilesFree( tr_file_stat * files, tr_file_index_t fileCount UNUSED )
{
tr_free( files );
}
@ -805,12 +806,11 @@ tr_torrentResetTransferStats( tr_torrent * tor )
void
tr_torrentSetHasPiece( tr_torrent * tor, int pieceIndex, int has )
tr_torrentSetHasPiece( tr_torrent * tor, tr_piece_index_t pieceIndex, int has )
{
tr_torrentLock( tor );
assert( tor != NULL );
assert( pieceIndex >= 0 );
assert( pieceIndex < tor->info.pieceCount );
if( has )
@ -978,7 +978,7 @@ tr_torrentVerify( tr_torrent * tor )
static void
stopTorrent( void * vtor )
{
int i;
tr_file_index_t i;
tr_torrent * tor = vtor;
tr_verifyRemove( tor );
@ -1131,15 +1131,15 @@ tr_torrentIsSeed( const tr_torrent * tor )
**/
void
tr_torrentInitFilePriority( tr_torrent * tor,
int fileIndex,
tr_priority_t priority )
tr_torrentInitFilePriority( tr_torrent * tor,
tr_file_index_t fileIndex,
tr_priority_t priority )
{
int i;
tr_piece_index_t i;
tr_file * file;
assert( tor != NULL );
assert( 0<=fileIndex && fileIndex<tor->info.fileCount );
assert( fileIndex < tor->info.fileCount );
assert( priority==TR_PRI_LOW || priority==TR_PRI_NORMAL || priority==TR_PRI_HIGH );
file = &tor->info.files[fileIndex];
@ -1149,12 +1149,12 @@ tr_torrentInitFilePriority( tr_torrent * tor,
}
void
tr_torrentSetFilePriorities( tr_torrent * tor,
int * files,
int fileCount,
tr_priority_t priority )
tr_torrentSetFilePriorities( tr_torrent * tor,
tr_file_index_t * files,
tr_file_index_t fileCount,
tr_priority_t priority )
{
int i;
tr_file_index_t i;
tr_torrentLock( tor );
for( i=0; i<fileCount; ++i )
@ -1165,13 +1165,13 @@ tr_torrentSetFilePriorities( tr_torrent * tor,
}
tr_priority_t
tr_torrentGetFilePriority( const tr_torrent * tor, int file )
tr_torrentGetFilePriority( const tr_torrent * tor, tr_file_index_t file )
{
tr_priority_t ret;
tr_torrentLock( tor );
assert( tor != NULL );
assert( 0<=file && file<tor->info.fileCount );
assert( file < tor->info.fileCount );
ret = tor->info.files[file].priority;
tr_torrentUnlock( tor );
@ -1181,7 +1181,7 @@ tr_torrentGetFilePriority( const tr_torrent * tor, int file )
tr_priority_t*
tr_torrentGetFilePriorities( const tr_torrent * tor )
{
int i;
tr_file_index_t i;
tr_priority_t * p;
tr_torrentLock( tor );
@ -1199,12 +1199,12 @@ tr_torrentGetFilePriorities( const tr_torrent * tor )
int
tr_torrentGetFileDL( const tr_torrent * tor,
int file )
tr_file_index_t file )
{
int doDownload;
tr_torrentLock( tor );
assert( 0<=file && file<tor->info.fileCount );
assert( file < tor->info.fileCount );
doDownload = !tor->info.files[file].dnd;
tr_torrentUnlock( tor );
@ -1212,15 +1212,15 @@ tr_torrentGetFileDL( const tr_torrent * tor,
}
static void
setFileDND( tr_torrent * tor,
int fileIndex,
int doDownload )
setFileDND( tr_torrent * tor,
tr_file_index_t fileIndex,
int doDownload )
{
tr_file * file;
const int dnd = !doDownload;
int firstPiece, firstPieceDND;
int lastPiece, lastPieceDND;
int i;
tr_piece_index_t firstPiece, firstPieceDND;
tr_piece_index_t lastPiece, lastPieceDND;
tr_file_index_t i;
file = &tor->info.files[fileIndex];
file->dnd = dnd;
@ -1230,10 +1230,12 @@ setFileDND( tr_torrent * tor,
/* can't set the first piece to DND unless
every file using that piece is DND */
firstPieceDND = dnd;
for( i=fileIndex-1; firstPieceDND && i>=0; --i ) {
for( i=fileIndex-1; firstPieceDND; --i ) {
if( tor->info.files[i].lastPiece != firstPiece )
break;
firstPieceDND = tor->info.files[i].dnd;
if( !i )
break;
}
/* can't set the last piece to DND unless
@ -1251,20 +1253,21 @@ setFileDND( tr_torrent * tor,
}
else
{
tr_piece_index_t pp;
tor->info.pieces[firstPiece].dnd = firstPieceDND;
tor->info.pieces[lastPiece].dnd = lastPieceDND;
for( i=firstPiece+1; i<lastPiece; ++i )
tor->info.pieces[i].dnd = dnd;
for( pp=firstPiece+1; pp<lastPiece; ++pp )
tor->info.pieces[pp].dnd = dnd;
}
}
void
tr_torrentInitFileDLs ( tr_torrent * tor,
int * files,
int fileCount,
int doDownload )
tr_torrentInitFileDLs ( tr_torrent * tor,
tr_file_index_t * files,
tr_file_index_t fileCount,
int doDownload )
{
int i;
tr_file_index_t i;
tr_torrentLock( tor );
for( i=0; i<fileCount; ++i )
@ -1275,10 +1278,10 @@ tr_torrentInitFileDLs ( tr_torrent * tor,
}
void
tr_torrentSetFileDLs ( tr_torrent * tor,
int * files,
int fileCount,
int doDownload )
tr_torrentSetFileDLs ( tr_torrent * tor,
tr_file_index_t * files,
tr_file_index_t fileCount,
int doDownload )
{
tr_torrentLock( tor );
tr_torrentInitFileDLs( tor, files, fileCount, doDownload );
@ -1307,25 +1310,30 @@ tr_torrentGetMaxConnectedPeers( const tr_torrent * tor )
****
***/
int
_tr_block( const tr_torrent * tor, int index, int begin )
tr_block_index_t
_tr_block( const tr_torrent * tor,
tr_piece_index_t index,
uint32_t offset )
{
const tr_info * inf = &tor->info;
return index * ( inf->pieceSize / tor->blockSize ) +
begin / tor->blockSize;
tr_block_index_t ret;
ret = index;
ret *= ( inf->pieceSize / tor->blockSize );
ret += offset / tor->blockSize;
return ret;
}
int
tr_torrentReqIsValid( const tr_torrent * tor,
uint32_t index,
tr_piece_index_t index,
uint32_t offset,
uint32_t length )
{
int err = 0;
if( index >= (uint32_t) tor->info.pieceCount )
if( index >= tor->info.pieceCount )
err = 1;
else if ( (int)offset >= tr_torPieceCountBytes( tor, (int)index ) )
else if ( offset >= tr_torPieceCountBytes( tor, index ) )
err = 2;
else if( length > MAX_BLOCK_SIZE )
err = 3;
@ -1340,7 +1348,7 @@ tr_torrentReqIsValid( const tr_torrent * tor,
fprintf( stderr, "(ticket #751) req.length is %"PRIu32"\n", length );
fprintf( stderr, "(ticket #751) tor->info.totalSize is %"PRIu64"\n", tor->info.totalSize );
fprintf( stderr, "(ticket #751) tor->info.pieceCount is %d\n", tor->info.pieceCount );
fprintf( stderr, "(ticket #751) tr_torPieceCountBytes is %d\n", tr_torPieceCountBytes( tor, (int)index ) );
fprintf( stderr, "(ticket #751) tr_torPieceCountBytes is %d\n", tr_torPieceCountBytes( tor, index ) );
fprintf( stderr, "(ticket #751) tr_pieceOffset is %"PRIu64"\n", tr_pieceOffset( tor, index, offset, length ) );
}
@ -1349,12 +1357,15 @@ tr_torrentReqIsValid( const tr_torrent * tor,
uint64_t
tr_pieceOffset( const tr_torrent * tor, int index, int begin, int length )
tr_pieceOffset( const tr_torrent * tor,
tr_piece_index_t index,
uint32_t offset,
uint32_t length )
{
uint64_t ret;
ret = tor->info.pieceSize;
ret *= index;
ret += begin;
ret += offset;
ret += length;
return ret;
}
@ -1364,13 +1375,13 @@ tr_pieceOffset( const tr_torrent * tor, int index, int begin, int length )
***/
int
tr_torrentIsPieceChecked( const tr_torrent * tor, int piece )
tr_torrentIsPieceChecked( const tr_torrent * tor, tr_piece_index_t piece )
{
return tr_bitfieldHas( tor->checkedPieces, piece );
}
void
tr_torrentSetPieceChecked( tr_torrent * tor, int piece, int isChecked )
tr_torrentSetPieceChecked( tr_torrent * tor, tr_piece_index_t piece, int isChecked )
{
if( isChecked )
tr_bitfieldAdd( tor->checkedPieces, piece );
@ -1379,11 +1390,11 @@ tr_torrentSetPieceChecked( tr_torrent * tor, int piece, int isChecked )
}
void
tr_torrentSetFileChecked( tr_torrent * tor, int fileIndex, int isChecked )
tr_torrentSetFileChecked( tr_torrent * tor, tr_file_index_t fileIndex, int isChecked )
{
const tr_file * file = &tor->info.files[fileIndex];
const size_t begin = file->firstPiece;
const size_t end = file->lastPiece + 1;
const tr_piece_index_t begin = file->firstPiece;
const tr_piece_index_t end = file->lastPiece + 1;
if( isChecked )
tr_bitfieldAddRange ( tor->checkedPieces, begin, end );
@ -1392,12 +1403,12 @@ tr_torrentSetFileChecked( tr_torrent * tor, int fileIndex, int isChecked )
}
int
tr_torrentIsFileChecked( const tr_torrent * tor, int fileIndex )
tr_torrentIsFileChecked( const tr_torrent * tor, tr_file_index_t fileIndex )
{
const tr_file * file = &tor->info.files[fileIndex];
const size_t begin = file->firstPiece;
const size_t end = file->lastPiece + 1;
size_t i;
const tr_piece_index_t begin = file->firstPiece;
const tr_piece_index_t end = file->lastPiece + 1;
tr_piece_index_t i;
int isChecked = TRUE;
for( i=begin; isChecked && i<end; ++i )

View File

@ -26,10 +26,10 @@
#define TR_TORRENT_H 1
/* just like tr_torrentSetFileDLs but doesn't trigger a fastresume save */
void tr_torrentInitFileDLs( tr_torrent * tor,
int * files,
int fileCount,
int do_download );
void tr_torrentInitFileDLs( tr_torrent * tor,
tr_file_index_t * files,
tr_file_index_t fileCount,
int do_download );
int tr_torrentIsPrivate( const tr_torrent * );
@ -37,7 +37,9 @@ void tr_torrentRecheckCompleteness( tr_torrent * );
void tr_torrentResetTransferStats( tr_torrent * );
void tr_torrentSetHasPiece( tr_torrent * tor, int pieceIndex, int has );
void tr_torrentSetHasPiece( tr_torrent * tor,
tr_piece_index_t pieceIndex,
int has );
void tr_torrentLock ( const tr_torrent * );
void tr_torrentUnlock ( const tr_torrent * );
@ -73,25 +75,30 @@ int tr_torrentAllowsPex( const tr_torrent * );
( ((block)==((tor)->blockCount-1)) ? (tor)->lastBlockSize : (tor)->blockSize )
#define tr_block(a,b) _tr_block(tor,a,b)
int _tr_block( const tr_torrent * tor, int index, int begin );
tr_block_index_t _tr_block( const tr_torrent * tor,
tr_piece_index_t index,
uint32_t offset );
int tr_torrentReqIsValid( const tr_torrent * tor,
uint32_t index,
tr_piece_index_t index,
uint32_t offset,
uint32_t length );
uint64_t tr_pieceOffset( const tr_torrent * tor, int index, int begin, int length );
uint64_t tr_pieceOffset( const tr_torrent * tor,
tr_piece_index_t index,
uint32_t offset,
uint32_t length );
void tr_torrentInitFilePriority( tr_torrent * tor,
int fileIndex,
tr_priority_t priority );
void tr_torrentInitFilePriority( tr_torrent * tor,
tr_file_index_t fileIndex,
tr_priority_t priority );
int tr_torrentCountUncheckedPieces( const tr_torrent * );
int tr_torrentIsPieceChecked ( const tr_torrent *, int piece );
int tr_torrentIsFileChecked ( const tr_torrent *, int file );
void tr_torrentSetPieceChecked ( tr_torrent *, int piece, int isChecked );
void tr_torrentSetFileChecked ( tr_torrent *, int file, int isChecked );
int tr_torrentIsPieceChecked ( const tr_torrent *, tr_piece_index_t piece );
int tr_torrentIsFileChecked ( const tr_torrent *, tr_file_index_t file );
void tr_torrentSetPieceChecked ( tr_torrent *, tr_piece_index_t piece, int isChecked );
void tr_torrentSetFileChecked ( tr_torrent *, tr_file_index_t file, int isChecked );
void tr_torrentUncheck ( tr_torrent * );
typedef enum
@ -122,14 +129,14 @@ struct tr_torrent
char * destination;
/* How many bytes we ask for per request */
int blockSize;
int blockCount;
uint32_t blockSize;
tr_block_index_t blockCount;
int lastBlockSize;
int lastPieceSize;
uint32_t lastBlockSize;
uint32_t lastPieceSize;
int blockCountInPiece;
int blockCountInLastPiece;
uint32_t blockCountInPiece;
uint32_t blockCountInLastPiece;
struct tr_completion * completion;

View File

@ -50,6 +50,10 @@ extern "C" {
#define TR_DEFAULT_PORT 51413
typedef uint32_t tr_file_index_t;
typedef uint32_t tr_piece_index_t;
typedef uint64_t tr_block_index_t;
enum
{
TR_PEER_FROM_INCOMING = 0, /* connections made to the listening port */
@ -303,8 +307,8 @@ typedef int8_t tr_priority_t;
/* set a batch of files to a particular priority.
* priority must be one of TR_PRI_NORMAL, _HIGH, or _LOW */
void tr_torrentSetFilePriorities( tr_torrent * tor,
int * files,
int fileCount,
tr_file_index_t * files,
tr_file_index_t fileCount,
tr_priority_t priority );
/* returns a malloc()ed array of tor->info.fileCount items,
@ -314,16 +318,16 @@ tr_priority_t* tr_torrentGetFilePriorities( const tr_torrent * );
/* single-file form of tr_torrentGetFilePriorities.
* returns one of TR_PRI_NORMAL, _HIGH, or _LOW. */
tr_priority_t tr_torrentGetFilePriority( const tr_torrent *, int file );
tr_priority_t tr_torrentGetFilePriority( const tr_torrent *, tr_file_index_t file );
/* returns true if the file's `download' flag is set */
int tr_torrentGetFileDL( const tr_torrent *, int file );
int tr_torrentGetFileDL( const tr_torrent *, tr_file_index_t file );
/* set a batch of files to be downloaded or not. */
void tr_torrentSetFileDLs ( tr_torrent * tor,
int * files,
int fileCount,
int do_download );
void tr_torrentSetFileDLs ( tr_torrent * tor,
tr_file_index_t * files,
tr_file_index_t fileCount,
int do_download );
/***********************************************************************
* tr_torrentRates
@ -584,8 +588,8 @@ tr_peer_stat * tr_torrentPeers( const tr_torrent *, int * peerCount );
void tr_torrentPeersFree( tr_peer_stat *, int peerCount );
typedef struct tr_file_stat tr_file_stat;
tr_file_stat * tr_torrentFiles( const tr_torrent *, int * fileCount );
void tr_torrentFilesFree( tr_file_stat *, int fileCount );
tr_file_stat * tr_torrentFiles( const tr_torrent *, tr_file_index_t * fileCount );
void tr_torrentFilesFree( tr_file_stat *, tr_file_index_t fileCount );
/***********************************************************************
@ -629,13 +633,13 @@ void tr_torrentDelete( tr_torrent * );
typedef struct tr_file
{
uint64_t length; /* Length of the file, in bytes */
char * name; /* Path to the file */
int8_t priority; /* TR_PRI_HIGH, _NORMAL, or _LOW */
int8_t dnd; /* nonzero if the file shouldn't be downloaded */
int firstPiece; /* We need pieces [firstPiece... */
int lastPiece; /* ...lastPiece] to dl this file */
uint64_t offset; /* file begins at the torrent's nth byte */
uint64_t length; /* Length of the file, in bytes */
char * name; /* Path to the file */
int8_t priority; /* TR_PRI_HIGH, _NORMAL, or _LOW */
int8_t dnd; /* nonzero if the file shouldn't be downloaded */
tr_piece_index_t firstPiece; /* We need pieces [firstPiece... */
tr_piece_index_t lastPiece; /* ...lastPiece] to dl this file */
uint64_t offset; /* file begins at the torrent's nth byte */
}
tr_file;
@ -685,13 +689,13 @@ struct tr_info
int dateCreated;
/* Pieces info */
int pieceSize;
int pieceCount;
uint32_t pieceSize;
tr_piece_index_t pieceCount;
uint64_t totalSize;
tr_piece * pieces;
/* Files info */
int fileCount;
tr_file_index_t fileCount;
tr_file * files;
};
@ -792,7 +796,6 @@ struct tr_stat
tr_errno error;
char errorString[128];
float recheckProgress;
float percentComplete;
float percentDone;

View File

@ -57,11 +57,11 @@ static tr_lock* getVerifyLock( void )
}
static void
checkFile( tr_torrent * tor,
int fileIndex,
int * abortFlag )
checkFile( tr_torrent * tor,
tr_file_index_t fileIndex,
int * abortFlag )
{
int i;
tr_piece_index_t i;
int nofile;
struct stat sb;
char path[MAX_PATH_LENGTH];
@ -105,7 +105,7 @@ verifyThreadFunc( void * unused UNUSED )
{
for( ;; )
{
int i;
tr_file_index_t i;
tr_torrent * tor;
struct verify_node * node;