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:
parent
1713e5ff88
commit
e9b4fd8aff
9 changed files with 145 additions and 106 deletions
|
@ -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 );
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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 ) +
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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 * );
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue