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;
|
return crypto->torrentHashIsSet ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tr_cryptoRandInt( int sup )
|
int
|
||||||
|
tr_cryptoRandInt( int sup )
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -277,6 +278,21 @@ int tr_cryptoRandInt( int sup )
|
||||||
return ((int) (sup * (abs(r) / (INT_MAX + 1.0))));
|
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 )
|
void tr_cryptoRandBuf ( unsigned char *buf, size_t len )
|
||||||
{
|
{
|
||||||
RAND_pseudo_bytes ( buf, 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) */
|
/** Returns a random number in the range of [0...n) */
|
||||||
int tr_cryptoRandInt ( int 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 */
|
/** Fills a buffer with random bytes */
|
||||||
void tr_cryptoRandBuf ( unsigned char *buf, size_t len );
|
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
|
static void
|
||||||
managerLock( const struct tr_peerMgr * manager )
|
managerLock( const struct tr_peerMgr * manager )
|
||||||
{
|
{
|
||||||
|
@ -626,7 +605,7 @@ getPreferredPieces( Torrent * t,
|
||||||
setme->piece = piece;
|
setme->piece = piece;
|
||||||
setme->priority = inf->pieces[piece].priority;
|
setme->priority = inf->pieces[piece].priority;
|
||||||
setme->peerCount = 0;
|
setme->peerCount = 0;
|
||||||
setme->random = tr_stupidRandInt( INT_MAX );
|
setme->random = tr_cryptoWeakRandInt( INT_MAX );
|
||||||
|
|
||||||
for( k=0; k<peerCount; ++k ) {
|
for( k=0; k<peerCount; ++k ) {
|
||||||
const tr_peer * peer = peers[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 */
|
* get a chance at the first blocks in the queue */
|
||||||
if( retCount ) {
|
if( retCount ) {
|
||||||
tr_peer ** tmp = tr_new( tr_peer*, 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( tmp, ret, sizeof(tr_peer*) * retCount );
|
||||||
memcpy( ret, tmp+i, sizeof(tr_peer*) * (retCount-i) );
|
memcpy( ret, tmp+i, sizeof(tr_peer*) * (retCount-i) );
|
||||||
memcpy( ret+(retCount-i), tmp, sizeof(tr_peer*) * i );
|
memcpy( ret+(retCount-i), tmp, sizeof(tr_peer*) * i );
|
||||||
|
@ -1663,7 +1642,7 @@ rechoke( Torrent * t )
|
||||||
|
|
||||||
if(( n = tr_ptrArraySize( randPool )))
|
if(( n = tr_ptrArraySize( randPool )))
|
||||||
{
|
{
|
||||||
c = tr_ptrArrayNth( randPool, tr_stupidRandInt( n ));
|
c = tr_ptrArrayNth( randPool, tr_cryptoWeakRandInt( n ));
|
||||||
c->doUnchoke = 1;
|
c->doUnchoke = 1;
|
||||||
t->optimistic = c->peer;
|
t->optimistic = c->peer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1766,28 +1766,38 @@ static void
|
||||||
sendBitfield( tr_peermsgs * msgs )
|
sendBitfield( tr_peermsgs * msgs )
|
||||||
{
|
{
|
||||||
struct evbuffer * out = msgs->outMessages;
|
struct evbuffer * out = msgs->outMessages;
|
||||||
const tr_piece_index_t pieceCount = msgs->torrent->info.pieceCount;
|
|
||||||
tr_bitfield * field;
|
tr_bitfield * field;
|
||||||
tr_piece_index_t lazyPieces[LAZY_PIECE_COUNT];
|
tr_piece_index_t lazyPieces[LAZY_PIECE_COUNT];
|
||||||
int i;
|
size_t i;
|
||||||
int lazyCount = 0;
|
size_t lazyCount = 0;
|
||||||
|
|
||||||
field = tr_bitfieldDup( tr_cpPieceBitfield( msgs->torrent->completion ) );
|
field = tr_bitfieldDup( tr_cpPieceBitfield( msgs->torrent->completion ) );
|
||||||
|
|
||||||
if( tr_sessionIsLazyBitfieldEnabled( msgs->session ) )
|
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 );
|
const int pos = tr_cryptoWeakRandInt( poolSize );
|
||||||
if( !tr_bitfieldHas( field, pos ) ) /* already removed it */
|
const tr_piece_index_t piece = pool[pos];
|
||||||
continue;
|
tr_bitfieldRem( field, piece );
|
||||||
dbgmsg( msgs, "lazy bitfield #%d: piece %d of %d",
|
lazyPieces[lazyCount++] = piece;
|
||||||
(int)(lazyCount+1), (int)pos, (int)pieceCount );
|
pool[pos] = pool[--poolSize];
|
||||||
tr_bitfieldRem( field, pos );
|
|
||||||
lazyPieces[lazyCount++] = pos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* cleanup */
|
||||||
|
tr_free( pool );
|
||||||
}
|
}
|
||||||
|
|
||||||
tr_peerIoWriteUint32( msgs->io, out, sizeof(uint8_t) + field->byteCount );
|
tr_peerIoWriteUint32( msgs->io, out, sizeof(uint8_t) + field->byteCount );
|
||||||
|
|
Loading…
Add table
Reference in a new issue