1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-24 16:52:39 +00:00

Do bounds checking on bitfields.

This commit is contained in:
Josh Elsasser 2007-03-05 23:03:38 +00:00
parent 1713e5ff88
commit e9b4fd8aff
9 changed files with 145 additions and 106 deletions

View file

@ -30,9 +30,9 @@ tr_completion_t * tr_cpInit( tr_torrent_t * tor )
cp = malloc( sizeof( tr_completion_t ) );
cp->tor = tor;
cp->blockBitfield = malloc( ( tor->blockCount + 7 ) / 8 );
cp->blockBitfield = tr_bitfieldNew( tor->blockCount );
cp->blockDownloaders = malloc( tor->blockCount );
cp->pieceBitfield = malloc( ( tor->info.pieceCount + 7 ) / 8 );
cp->pieceBitfield = tr_bitfieldNew( tor->info.pieceCount );
cp->missingBlocks = malloc( tor->info.pieceCount * sizeof( int ) );
tr_cpReset( cp );
@ -42,11 +42,11 @@ tr_completion_t * tr_cpInit( tr_torrent_t * tor )
void tr_cpClose( tr_completion_t * cp )
{
free( cp->blockBitfield );
free( cp->blockDownloaders );
free( cp->pieceBitfield );
free( cp->missingBlocks );
free( cp );
tr_bitfieldFree( cp->blockBitfield );
free( cp->blockDownloaders );
tr_bitfieldFree( cp->pieceBitfield );
free( cp->missingBlocks );
free( cp );
}
void tr_cpReset( tr_completion_t * cp )
@ -55,9 +55,9 @@ void tr_cpReset( tr_completion_t * cp )
int i;
cp->blockCount = 0;
memset( cp->blockBitfield, 0, ( tor->blockCount + 7 ) / 8 );
tr_bitfieldClear( cp->blockBitfield );
memset( cp->blockDownloaders, 0, tor->blockCount );
memset( cp->pieceBitfield, 0, ( tor->info.pieceCount + 7 ) / 8 );
tr_bitfieldClear( cp->pieceBitfield );
for( i = 0; i < tor->info.pieceCount; i++ )
{
cp->missingBlocks[i] = tr_pieceCountBlocks( i );
@ -106,7 +106,7 @@ int tr_cpPieceIsComplete( tr_completion_t * cp, int piece )
return tr_bitfieldHas( cp->pieceBitfield, piece );
}
uint8_t * tr_cpPieceBitfield( tr_completion_t * cp )
tr_bitfield_t * tr_cpPieceBitfield( tr_completion_t * cp )
{
return cp->pieceBitfield;
}
@ -195,12 +195,12 @@ void tr_cpBlockRem( tr_completion_t * cp, int block )
tr_bitfieldRem( cp->blockBitfield, block );
}
uint8_t * tr_cpBlockBitfield( tr_completion_t * cp )
tr_bitfield_t * tr_cpBlockBitfield( tr_completion_t * cp )
{
return cp->blockBitfield;
}
void tr_cpBlockBitfieldSet( tr_completion_t * cp, uint8_t * bitfield )
void tr_cpBlockBitfieldSet( tr_completion_t * cp, tr_bitfield_t * bitfield )
{
tr_torrent_t * tor = cp->tor;
int i, j;
@ -237,7 +237,7 @@ float tr_cpPercentBlocksInPiece( tr_completion_t * cp, int piece )
int i;
int blockCount, startBlock, endBlock;
int complete;
uint8_t * bitfield;
tr_bitfield_t * bitfield;
blockCount = tr_pieceCountBlocks( piece );
startBlock = tr_pieceStartBlock( piece );

View file

@ -24,12 +24,12 @@
struct tr_completion_s
{
tr_torrent_t * tor;
uint8_t * blockBitfield;
uint8_t * blockDownloaders;
int blockCount;
uint8_t * pieceBitfield;
int * missingBlocks;
tr_torrent_t * tor;
tr_bitfield_t * blockBitfield;
uint8_t * blockDownloaders;
int blockCount;
tr_bitfield_t * pieceBitfield;
int * missingBlocks;
};
tr_completion_t * tr_cpInit( tr_torrent_t * );
@ -47,7 +47,7 @@ uint64_t tr_cpLeftBytes( tr_completion_t * );
/* Pieces */
int tr_cpPieceHasAllBlocks( tr_completion_t *, int piece );
int tr_cpPieceIsComplete( tr_completion_t *, int piece );
uint8_t * tr_cpPieceBitfield( tr_completion_t * );
tr_bitfield_t * tr_cpPieceBitfield( tr_completion_t * );
void tr_cpPieceAdd( tr_completion_t *, int piece );
void tr_cpPieceRem( tr_completion_t *, int piece );
@ -57,8 +57,8 @@ void tr_cpDownloaderRem( tr_completion_t *, int block );
int tr_cpBlockIsComplete( tr_completion_t *, int block );
void tr_cpBlockAdd( tr_completion_t *, int block );
void tr_cpBlockRem( tr_completion_t *, int block );
uint8_t * tr_cpBlockBitfield( tr_completion_t * );
void tr_cpBlockBitfieldSet( tr_completion_t *, uint8_t * );
tr_bitfield_t * tr_cpBlockBitfield( tr_completion_t * );
void tr_cpBlockBitfieldSet( tr_completion_t *, tr_bitfield_t * );
float tr_cpPercentBlocksInPiece( tr_completion_t * cp, int piece );
/* Missing = we don't have it and we are not getting it from any peer yet */
static inline int tr_cpMissingBlocksForPiece( tr_completion_t * cp, int piece )

View file

@ -191,6 +191,7 @@ static int fastResumeLoadProgress( tr_io_t * io, FILE * file )
int i, j;
uint8_t * buf;
size_t len;
tr_bitfield_t bitfield;
len = FR_PROGRESS_LEN( tor );
buf = calloc( len, 1 );
@ -219,7 +220,10 @@ static int fastResumeLoadProgress( tr_io_t * io, FILE * file )
free( fileMTimes );
/* Copy the bitfield for blocks and fill blockHave */
tr_cpBlockBitfieldSet( tor->completion, buf + FR_MTIME_LEN( tor ) );
memset( &bitfield, 0, sizeof bitfield );
bitfield.len = FR_BLOCK_BITFIELD_LEN( tor );
bitfield.bits = buf + FR_MTIME_LEN( tor );
tr_cpBlockBitfieldSet( tor->completion, &bitfield );
/* Copy the 'slotPiece' table */
memcpy( io->slotPiece, buf + FR_MTIME_LEN( tor ) +

View file

@ -124,6 +124,7 @@ static inline void tr_htonl( uint32_t a, uint8_t * p )
typedef struct tr_completion_s tr_completion_t;
typedef struct tr_shared_s tr_shared_t;
typedef struct tr_bitfield_s tr_bitfield_t;
typedef enum { TR_NET_OK, TR_NET_ERROR, TR_NET_WAIT } tr_tristate_t;

View file

@ -38,70 +38,70 @@ typedef struct tr_request_s
struct tr_peer_s
{
tr_torrent_t * tor;
tr_torrent_t * tor;
struct in_addr addr;
in_port_t port; /* peer's listening port, 0 if not known */
struct in_addr addr;
in_port_t port; /* peer's listening port, 0 if not known */
#define PEER_STATUS_IDLE 1 /* Need to connect */
#define PEER_STATUS_CONNECTING 2 /* Trying to send handshake */
#define PEER_STATUS_HANDSHAKE 4 /* Waiting for peer's handshake */
#define PEER_STATUS_CONNECTED 8 /* Got peer's handshake */
int status;
int socket;
char incoming;
uint64_t date;
uint64_t keepAlive;
#define PEER_STATUS_IDLE 1 /* Need to connect */
#define PEER_STATUS_CONNECTING 2 /* Trying to send handshake */
#define PEER_STATUS_HANDSHAKE 4 /* Waiting for peer's handshake */
#define PEER_STATUS_CONNECTED 8 /* Got peer's handshake */
int status;
int socket;
char incoming;
uint64_t date;
uint64_t keepAlive;
char amChoking;
char amInterested;
char peerChoking;
char peerInterested;
char amChoking;
char amInterested;
char peerChoking;
char peerInterested;
int optimistic;
uint64_t lastChoke;
int optimistic;
uint64_t lastChoke;
uint8_t id[20];
uint8_t id[20];
/* The pieces that the peer has */
uint8_t * bitfield;
int pieceCount;
float progress;
tr_bitfield_t * bitfield;
int pieceCount;
float progress;
int goodPcs;
int badPcs;
int banned;
int goodPcs;
int badPcs;
int banned;
/* The pieces that the peer is contributing to */
uint8_t * blamefield;
tr_bitfield_t * blamefield;
/* The bad pieces that the peer has contributed to */
uint8_t * banfield;
tr_bitfield_t * banfield;
uint8_t * buf;
int size;
int pos;
uint8_t * buf;
int size;
int pos;
uint8_t * outMessages;
int outMessagesSize;
int outMessagesPos;
uint8_t outBlock[13+16384];
int outBlockSize;
int outBlockLoaded;
int outBlockSending;
uint8_t * outMessages;
int outMessagesSize;
int outMessagesPos;
uint8_t outBlock[13+16384];
int outBlockSize;
int outBlockLoaded;
int outBlockSending;
int inRequestCount;
tr_request_t inRequests[OUR_REQUEST_COUNT];
int inIndex;
int inBegin;
int inLength;
uint64_t inTotal;
int inRequestCount;
tr_request_t inRequests[OUR_REQUEST_COUNT];
int inIndex;
int inBegin;
int inLength;
uint64_t inTotal;
int outRequestCount;
tr_request_t outRequests[MAX_REQUEST_COUNT];
uint64_t outTotal;
uint64_t outDate;
int outRequestCount;
tr_request_t outRequests[MAX_REQUEST_COUNT];
uint64_t outTotal;
uint64_t outDate;
tr_ratecontrol_t * download;
tr_ratecontrol_t * upload;
tr_ratecontrol_t * download;
tr_ratecontrol_t * upload;
};
#define peer_dbg( a... ) __peer_dbg( peer, ## a )
@ -162,18 +162,9 @@ void tr_peerDestroy( tr_peer_t * peer )
block = tr_block( r->index, r->begin );
tr_cpDownloaderRem( tor->completion, block );
}
if( peer->bitfield )
{
free( peer->bitfield );
}
if( peer->blamefield )
{
free( peer->blamefield );
}
if( peer->banfield )
{
free( peer->banfield );
}
tr_bitfieldFree( peer->bitfield );
tr_bitfieldFree( peer->blamefield );
tr_bitfieldFree( peer->banfield );
if( peer->buf )
{
free( peer->buf );
@ -532,7 +523,7 @@ int tr_peerPort( tr_peer_t * peer )
***********************************************************************
*
**********************************************************************/
uint8_t * tr_peerBitfield( tr_peer_t * peer )
tr_bitfield_t * tr_peerBitfield( tr_peer_t * peer )
{
return peer->bitfield;
}
@ -601,7 +592,7 @@ void tr_peerBlame( tr_peer_t * peer, int piece, int success )
{
/* Assume the peer wasn't responsible for the bad pieces
we was banned for */
memset( peer->banfield, 0x00, ( tor->info.pieceCount + 7 ) / 8 );
tr_bitfieldClear( peer->banfield );
}
}
else
@ -611,7 +602,7 @@ void tr_peerBlame( tr_peer_t * peer, int piece, int success )
/* Ban the peer for this piece */
if( !peer->banfield )
{
peer->banfield = calloc( ( tor->info.pieceCount + 7 ) / 8, 1 );
peer->banfield = tr_bitfieldNew( tor->info.pieceCount );
}
tr_bitfieldAdd( peer->banfield, piece );

View file

@ -45,7 +45,7 @@ int tr_peerIsChoking ( tr_peer_t * );
int tr_peerIsInterested ( tr_peer_t * );
float tr_peerProgress ( tr_peer_t * );
int tr_peerPort ( tr_peer_t * );
uint8_t * tr_peerBitfield ( tr_peer_t * );
tr_bitfield_t * tr_peerBitfield ( tr_peer_t * );
float tr_peerDownloadRate ( tr_peer_t * );
float tr_peerUploadRate ( tr_peer_t * );
void tr_peerChoke ( tr_peer_t * );

View file

@ -104,7 +104,7 @@ static inline int parseHave( tr_torrent_t * tor, tr_peer_t * peer,
if( !peer->bitfield )
{
peer->bitfield = calloc( ( tor->info.pieceCount + 7 ) / 8, 1 );
peer->bitfield = tr_bitfieldNew( tor->info.pieceCount );
}
if( !tr_bitfieldHas( peer->bitfield, piece ) )
{
@ -154,9 +154,10 @@ static inline int parseBitfield( tr_torrent_t * tor, tr_peer_t * peer,
if( !peer->bitfield )
{
peer->bitfield = malloc( bitfieldSize );
peer->bitfield = tr_bitfieldNew( inf->pieceCount );
}
memcpy( peer->bitfield, p, bitfieldSize );
assert( bitfieldSize == peer->bitfield->len );
memcpy( peer->bitfield->bits, p, bitfieldSize );
peer->pieceCount = 0;
for( i = 0; i < inf->pieceCount; i++ )
@ -294,7 +295,7 @@ static inline int parsePiece( tr_torrent_t * tor, tr_peer_t * peer,
/* Set blame/credit for this piece */
if( !peer->blamefield )
{
peer->blamefield = calloc( ( tor->info.pieceCount + 7 ) / 8, 1 );
peer->blamefield = tr_bitfieldNew( tor->info.pieceCount );
}
tr_bitfieldAdd( peer->blamefield, index );

View file

@ -104,11 +104,8 @@ static int checkPeer( tr_peer_t * peer )
**********************************************************************/
static int isInteresting( tr_torrent_t * tor, tr_peer_t * peer )
{
tr_info_t * inf = &tor->info;
int i;
int bitfieldSize = ( inf->pieceCount + 7 ) / 8;
uint8_t * bitfield = tr_cpPieceBitfield( tor->completion );
int ii;
tr_bitfield_t * bitfield = tr_cpPieceBitfield( tor->completion );
if( !peer->bitfield )
{
@ -116,9 +113,10 @@ static int isInteresting( tr_torrent_t * tor, tr_peer_t * peer )
return 0;
}
for( i = 0; i < bitfieldSize; i++ )
assert( bitfield->len == peer->bitfield->len );
for( ii = 0; ii < bitfield->len; ii++ )
{
if( ( peer->bitfield[i] & ~(bitfield[i]) ) & 0xFF )
if( ( peer->bitfield->bits[ii] & ~(bitfield->bits[ii]) ) & 0xFF )
{
return 1;
}
@ -197,7 +195,7 @@ static inline int chooseBlock( tr_torrent_t * tor, tr_peer_t * peer )
{
/* All pieces in 'pool' have 'minMissing' missing blocks. Find
the rarest ones. */
uint8_t * bitfield;
tr_bitfield_t * bitfield;
int piece;
int min, foo, j;
int * pool2;

View file

@ -101,25 +101,69 @@ static inline void tr_wait( uint64_t delay )
#endif
}
struct tr_bitfield_s
{
uint8_t * bits;
int len;
};
/* note that the argument is how many bits are needed, not bytes */
static inline tr_bitfield_t * tr_bitfieldNew( int bitcount )
{
tr_bitfield_t * ret;
ret = calloc( 1, sizeof *ret );
if( NULL == ret )
{
return NULL;
}
ret->len = ( bitcount + 7 ) / 8;
ret->bits = calloc( ret->len, 1 );
if( NULL == ret->bits )
{
free( ret );
return NULL;
}
return ret;
}
static inline void tr_bitfieldFree( tr_bitfield_t * bitfield )
{
if( bitfield )
{
free( bitfield->bits );
free( bitfield );
}
}
static inline void tr_bitfieldClear( tr_bitfield_t * bitfield )
{
memset( bitfield->bits, 0, bitfield->len );
}
/***********************************************************************
* tr_bitfieldHas
**********************************************************************/
static inline int tr_bitfieldHas( uint8_t * bitfield, int piece )
static inline int tr_bitfieldHas( tr_bitfield_t * bitfield, int piece )
{
return ( bitfield[ piece / 8 ] & ( 1 << ( 7 - ( piece % 8 ) ) ) );
assert( piece / 8 < bitfield->len );
return ( bitfield->bits[ piece / 8 ] & ( 1 << ( 7 - ( piece % 8 ) ) ) );
}
/***********************************************************************
* tr_bitfieldAdd
**********************************************************************/
static inline void tr_bitfieldAdd( uint8_t * bitfield, int piece )
static inline void tr_bitfieldAdd( tr_bitfield_t * bitfield, int piece )
{
bitfield[ piece / 8 ] |= ( 1 << ( 7 - ( piece % 8 ) ) );
assert( piece / 8 < bitfield->len );
bitfield->bits[ piece / 8 ] |= ( 1 << ( 7 - ( piece % 8 ) ) );
}
static inline void tr_bitfieldRem( uint8_t * bitfield, int piece )
static inline void tr_bitfieldRem( tr_bitfield_t * bitfield, int piece )
{
bitfield[ piece / 8 ] &= ~( 1 << ( 7 - ( piece % 8 ) ) );
assert( piece / 8 < bitfield->len );
bitfield->bits[ piece / 8 ] &= ~( 1 << ( 7 - ( piece % 8 ) ) );
}
#define tr_blockPiece(a) _tr_blockPiece(tor,a)