diff --git a/libtransmission/completion.c b/libtransmission/completion.c index 8512a2ced..af3317871 100644 --- a/libtransmission/completion.c +++ b/libtransmission/completion.c @@ -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 ); diff --git a/libtransmission/completion.h b/libtransmission/completion.h index e3167de98..44dca6a7d 100644 --- a/libtransmission/completion.h +++ b/libtransmission/completion.h @@ -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 ) diff --git a/libtransmission/fastresume.h b/libtransmission/fastresume.h index 851d69639..20a7e6fe8 100644 --- a/libtransmission/fastresume.h +++ b/libtransmission/fastresume.h @@ -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 ) + diff --git a/libtransmission/internal.h b/libtransmission/internal.h index 000cefdf6..c17627727 100644 --- a/libtransmission/internal.h +++ b/libtransmission/internal.h @@ -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; diff --git a/libtransmission/peer.c b/libtransmission/peer.c index 14e936325..0ecf1a796 100644 --- a/libtransmission/peer.c +++ b/libtransmission/peer.c @@ -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 ); diff --git a/libtransmission/peer.h b/libtransmission/peer.h index ee8ea60dc..d73d53285 100644 --- a/libtransmission/peer.h +++ b/libtransmission/peer.h @@ -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 * ); diff --git a/libtransmission/peerparse.h b/libtransmission/peerparse.h index b3f0b2310..1268cf0ef 100644 --- a/libtransmission/peerparse.h +++ b/libtransmission/peerparse.h @@ -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 ); diff --git a/libtransmission/peerutils.h b/libtransmission/peerutils.h index 5ca5a86d7..272f32d83 100644 --- a/libtransmission/peerutils.h +++ b/libtransmission/peerutils.h @@ -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; diff --git a/libtransmission/utils.h b/libtransmission/utils.h index 2d778e246..0af6e586f 100644 --- a/libtransmission/utils.h +++ b/libtransmission/utils.h @@ -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)