mirror of
https://github.com/transmission/transmission
synced 2025-03-04 02:28:03 +00:00
(libT) maybe fix the hangs reported by users in the recent nightlies.
This commit is contained in:
parent
9d35118808
commit
64e08510f0
4 changed files with 48 additions and 37 deletions
|
@ -268,7 +268,8 @@ tr_cryptoHasTorrentHash( const tr_crypto * crypto )
|
|||
return crypto->torrentHashIsSet ? 1 : 0;
|
||||
}
|
||||
|
||||
int tr_cryptoRandInt( int sup )
|
||||
int
|
||||
tr_cryptoRandInt( int sup )
|
||||
{
|
||||
int r;
|
||||
|
||||
|
@ -277,6 +278,21 @@ int tr_cryptoRandInt( int sup )
|
|||
return ((int) (sup * (abs(r) / (INT_MAX + 1.0))));
|
||||
}
|
||||
|
||||
int
|
||||
tr_cryptoWeakRandInt( int sup )
|
||||
{
|
||||
static int init = 0;
|
||||
assert( sup > 0 );
|
||||
|
||||
if( !init )
|
||||
{
|
||||
srand( tr_date( ) );
|
||||
init = 1;
|
||||
}
|
||||
|
||||
return rand() % sup;
|
||||
}
|
||||
|
||||
void tr_cryptoRandBuf ( unsigned char *buf, size_t len )
|
||||
{
|
||||
RAND_pseudo_bytes ( buf, len );
|
||||
|
|
|
@ -79,6 +79,12 @@ void tr_sha1 ( uint8_t * setme,
|
|||
/** Returns a random number in the range of [0...n) */
|
||||
int tr_cryptoRandInt ( int n );
|
||||
|
||||
/** Returns a vaguely random number in the range of [0...n).
|
||||
This is faster -- BUT WEAKER -- than tr_cryptoRandInt()
|
||||
and should only be used when tr_cryptoRandInt() is too
|
||||
slow, and NEVER in sensitive cases */
|
||||
int tr_cryptoWeakRandInt( int n );
|
||||
|
||||
/** Fills a buffer with random bytes */
|
||||
void tr_cryptoRandBuf ( unsigned char *buf, size_t len );
|
||||
|
||||
|
|
|
@ -130,27 +130,6 @@ struct tr_peerMgr
|
|||
***
|
||||
**/
|
||||
|
||||
/* The following is not a very high quality random number generator. It
|
||||
* is mainly used as a simple stupid random number generator inside some
|
||||
* functions below. Please don't use it for anything else unless you
|
||||
* know what you're doing. Use tr_cryptoRandInt() instead.
|
||||
*/
|
||||
|
||||
static int
|
||||
tr_stupidRandInt( int sup )
|
||||
{
|
||||
static int init = 0;
|
||||
assert( sup > 0 );
|
||||
|
||||
if( !init )
|
||||
{
|
||||
srand( tr_date() );
|
||||
init = 1;
|
||||
}
|
||||
|
||||
return rand() % sup;
|
||||
}
|
||||
|
||||
static void
|
||||
managerLock( const struct tr_peerMgr * manager )
|
||||
{
|
||||
|
@ -626,7 +605,7 @@ getPreferredPieces( Torrent * t,
|
|||
setme->piece = piece;
|
||||
setme->priority = inf->pieces[piece].priority;
|
||||
setme->peerCount = 0;
|
||||
setme->random = tr_stupidRandInt( INT_MAX );
|
||||
setme->random = tr_cryptoWeakRandInt( INT_MAX );
|
||||
|
||||
for( k=0; k<peerCount; ++k ) {
|
||||
const tr_peer * peer = peers[k];
|
||||
|
@ -667,7 +646,7 @@ getPeersUploadingToClient( Torrent * t, int * setmeCount )
|
|||
* get a chance at the first blocks in the queue */
|
||||
if( retCount ) {
|
||||
tr_peer ** tmp = tr_new( tr_peer*, retCount );
|
||||
i = tr_stupidRandInt( retCount );
|
||||
i = tr_cryptoWeakRandInt( retCount );
|
||||
memcpy( tmp, ret, sizeof(tr_peer*) * retCount );
|
||||
memcpy( ret, tmp+i, sizeof(tr_peer*) * (retCount-i) );
|
||||
memcpy( ret+(retCount-i), tmp, sizeof(tr_peer*) * i );
|
||||
|
@ -1663,7 +1642,7 @@ rechoke( Torrent * t )
|
|||
|
||||
if(( n = tr_ptrArraySize( randPool )))
|
||||
{
|
||||
c = tr_ptrArrayNth( randPool, tr_stupidRandInt( n ));
|
||||
c = tr_ptrArrayNth( randPool, tr_cryptoWeakRandInt( n ));
|
||||
c->doUnchoke = 1;
|
||||
t->optimistic = c->peer;
|
||||
}
|
||||
|
|
|
@ -1766,28 +1766,38 @@ static void
|
|||
sendBitfield( tr_peermsgs * msgs )
|
||||
{
|
||||
struct evbuffer * out = msgs->outMessages;
|
||||
const tr_piece_index_t pieceCount = msgs->torrent->info.pieceCount;
|
||||
tr_bitfield * field;
|
||||
tr_piece_index_t lazyPieces[LAZY_PIECE_COUNT];
|
||||
int i;
|
||||
int lazyCount = 0;
|
||||
size_t i;
|
||||
size_t lazyCount = 0;
|
||||
|
||||
field = tr_bitfieldDup( tr_cpPieceBitfield( msgs->torrent->completion ) );
|
||||
|
||||
if( tr_sessionIsLazyBitfieldEnabled( msgs->session ) )
|
||||
{
|
||||
const int maxLazyCount = MIN( LAZY_PIECE_COUNT, pieceCount );
|
||||
/** Lazy bitfields aren't a high priority or secure, so I'm opting for
|
||||
speed over a truly random sample -- let's limit the pool size to
|
||||
the first 1000 pieces so large torrents don't bog things down */
|
||||
size_t poolSize = MIN( msgs->torrent->info.pieceCount, 1000 );
|
||||
tr_piece_index_t * pool = tr_new( tr_piece_index_t, poolSize );
|
||||
|
||||
while( lazyCount < maxLazyCount )
|
||||
/* build the pool */
|
||||
for( i=0; i<poolSize; ++i )
|
||||
pool[i] = i;
|
||||
poolSize = i;
|
||||
|
||||
/* pull random piece indices from the pool */
|
||||
while( ( poolSize > 0 ) && ( lazyCount < LAZY_PIECE_COUNT ) )
|
||||
{
|
||||
const size_t pos = tr_cryptoRandInt ( pieceCount );
|
||||
if( !tr_bitfieldHas( field, pos ) ) /* already removed it */
|
||||
continue;
|
||||
dbgmsg( msgs, "lazy bitfield #%d: piece %d of %d",
|
||||
(int)(lazyCount+1), (int)pos, (int)pieceCount );
|
||||
tr_bitfieldRem( field, pos );
|
||||
lazyPieces[lazyCount++] = pos;
|
||||
const int pos = tr_cryptoWeakRandInt( poolSize );
|
||||
const tr_piece_index_t piece = pool[pos];
|
||||
tr_bitfieldRem( field, piece );
|
||||
lazyPieces[lazyCount++] = piece;
|
||||
pool[pos] = pool[--poolSize];
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
tr_free( pool );
|
||||
}
|
||||
|
||||
tr_peerIoWriteUint32( msgs->io, out, sizeof(uint8_t) + field->byteCount );
|
||||
|
|
Loading…
Add table
Reference in a new issue