#412 - 0.90 "ignores" speed limits (deanr, berkut, SineOtter)
This commit is contained in:
parent
568bc5d4d5
commit
ab8ed6507d
|
@ -70,7 +70,7 @@ enum
|
||||||
|
|
||||||
KEEPALIVE_INTERVAL_SECS = 90, /* idle seconds before we send a keepalive */
|
KEEPALIVE_INTERVAL_SECS = 90, /* idle seconds before we send a keepalive */
|
||||||
PEX_INTERVAL = (60 * 1000), /* msec between calls to sendPex() */
|
PEX_INTERVAL = (60 * 1000), /* msec between calls to sendPex() */
|
||||||
PEER_PULSE_INTERVAL = (133), /* msec between calls to pulse() */
|
PEER_PULSE_INTERVAL = (100), /* msec between calls to pulse() */
|
||||||
RATE_PULSE_INTERVAL = (333), /* msec between calls to ratePulse() */
|
RATE_PULSE_INTERVAL = (333), /* msec between calls to ratePulse() */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -110,6 +110,7 @@ struct tr_peermsgs
|
||||||
|
|
||||||
tr_publisher_t * publisher;
|
tr_publisher_t * publisher;
|
||||||
|
|
||||||
|
struct evbuffer * outBlock; /* buffer of all the current piece message */
|
||||||
struct evbuffer * outMessages; /* buffer of all the non-piece messages */
|
struct evbuffer * outMessages; /* buffer of all the non-piece messages */
|
||||||
struct evbuffer * inBlock; /* the block we're currently receiving */
|
struct evbuffer * inBlock; /* the block we're currently receiving */
|
||||||
tr_list * peerAskedFor;
|
tr_list * peerAskedFor;
|
||||||
|
@ -234,25 +235,6 @@ protocolSendChoke( tr_peermsgs * msgs, int choke )
|
||||||
tr_peerIoWriteUint8 ( io, out, choke ? BT_CHOKE : BT_UNCHOKE );
|
tr_peerIoWriteUint8 ( io, out, choke ? BT_CHOKE : BT_UNCHOKE );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
protocolSendPiece( tr_peermsgs * msgs,
|
|
||||||
const struct peer_request * r,
|
|
||||||
const uint8_t * pieceData )
|
|
||||||
{
|
|
||||||
tr_peerIo * io = msgs->io;
|
|
||||||
struct evbuffer * out = evbuffer_new( );
|
|
||||||
|
|
||||||
dbgmsg( msgs, "sending block %u:%u->%u", r->index, r->offset, r->length );
|
|
||||||
tr_peerIoWriteUint32( io, out, sizeof(uint8_t) + 2*sizeof(uint32_t) + r->length );
|
|
||||||
tr_peerIoWriteUint8 ( io, out, BT_PIECE );
|
|
||||||
tr_peerIoWriteUint32( io, out, r->index );
|
|
||||||
tr_peerIoWriteUint32( io, out, r->offset );
|
|
||||||
tr_peerIoWriteBytes ( io, out, pieceData, r->length );
|
|
||||||
tr_peerIoWriteBuf ( io, out );
|
|
||||||
|
|
||||||
evbuffer_free( out );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*** EVENTS
|
*** EVENTS
|
||||||
**/
|
**/
|
||||||
|
@ -1363,27 +1345,28 @@ static int
|
||||||
canWrite( const tr_peermsgs * msgs )
|
canWrite( const tr_peermsgs * msgs )
|
||||||
{
|
{
|
||||||
/* don't let our outbuffer get too large */
|
/* don't let our outbuffer get too large */
|
||||||
if( tr_peerIoWriteBytesWaiting( msgs->io ) > 8192 )
|
if( tr_peerIoWriteBytesWaiting( msgs->io ) > 4096 )
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static size_t
|
||||||
canUpload( const tr_peermsgs * msgs )
|
getUploadMax( const tr_peermsgs * msgs )
|
||||||
{
|
{
|
||||||
|
static const size_t maxval = ~0;
|
||||||
const tr_torrent * tor = msgs->torrent;
|
const tr_torrent * tor = msgs->torrent;
|
||||||
|
|
||||||
if( !canWrite( msgs ) )
|
if( !canWrite( msgs ) )
|
||||||
return FALSE;
|
return 0;
|
||||||
|
|
||||||
if( tor->uploadLimitMode == TR_SPEEDLIMIT_GLOBAL )
|
if( tor->uploadLimitMode == TR_SPEEDLIMIT_GLOBAL )
|
||||||
return !tor->handle->useUploadLimit || tr_rcCanTransfer( tor->handle->upload );
|
return tor->handle->useUploadLimit ? tr_rcBytesLeft( tor->handle->upload ) : maxval;
|
||||||
|
|
||||||
if( tor->uploadLimitMode == TR_SPEEDLIMIT_SINGLE )
|
if( tor->uploadLimitMode == TR_SPEEDLIMIT_SINGLE )
|
||||||
return tr_rcCanTransfer( tor->upload );
|
return tr_rcBytesLeft( tor->upload );
|
||||||
|
|
||||||
return TRUE;
|
return maxval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1397,11 +1380,22 @@ ratePulse( void * vmsgs )
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct peer_request*
|
||||||
|
popNextRequest( tr_peermsgs * msgs )
|
||||||
|
{
|
||||||
|
struct peer_request * ret;
|
||||||
|
ret = tr_list_pop_front( &msgs->peerAskedForFast );
|
||||||
|
if( !ret )
|
||||||
|
ret = tr_list_pop_front( &msgs->peerAskedFor);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pulse( void * vmsgs )
|
pulse( void * vmsgs )
|
||||||
{
|
{
|
||||||
const time_t now = time( NULL );
|
const time_t now = time( NULL );
|
||||||
tr_peermsgs * msgs = (tr_peermsgs *) vmsgs;
|
tr_peermsgs * msgs = vmsgs;
|
||||||
|
struct peer_request * r;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
/* if we froze out a downloaded block because of speed limits,
|
/* if we froze out a downloaded block because of speed limits,
|
||||||
|
@ -1417,42 +1411,54 @@ pulse( void * vmsgs )
|
||||||
if( !canWrite( msgs ) )
|
if( !canWrite( msgs ) )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
else if(( len = EVBUFFER_LENGTH( msgs->outBlock ) ))
|
||||||
|
{
|
||||||
|
const size_t uploadMax = getUploadMax( msgs );
|
||||||
|
const size_t outlen = MIN( len, uploadMax );
|
||||||
|
tr_peerIoWrite( msgs->io, EVBUFFER_DATA( msgs->outBlock ), outlen );
|
||||||
|
evbuffer_drain( msgs->outBlock, outlen );
|
||||||
|
msgs->clientSentAnythingAt = now;
|
||||||
|
peerGotBytes( msgs, outlen );
|
||||||
|
len -= outlen;
|
||||||
|
dbgmsg( msgs, "wrote %d bytes; %d left in block", (int)outlen, (int)len );
|
||||||
|
fflush( stdout );
|
||||||
|
}
|
||||||
else if(( len = EVBUFFER_LENGTH( msgs->outMessages ) ))
|
else if(( len = EVBUFFER_LENGTH( msgs->outMessages ) ))
|
||||||
{
|
{
|
||||||
tr_peerIoWriteBuf( msgs->io, msgs->outMessages );
|
tr_peerIoWriteBuf( msgs->io, msgs->outMessages );
|
||||||
msgs->clientSentAnythingAt = now;
|
msgs->clientSentAnythingAt = now;
|
||||||
}
|
}
|
||||||
else if( msgs->peerAskedForFast || msgs->peerAskedFor )
|
|
||||||
{
|
|
||||||
if( canUpload( msgs ) )
|
|
||||||
{
|
|
||||||
struct peer_request * r;
|
|
||||||
uint8_t * buf;
|
|
||||||
|
|
||||||
r = tr_list_pop_front( &msgs->peerAskedForFast );
|
|
||||||
if( r == NULL )
|
|
||||||
r = tr_list_pop_front( &msgs->peerAskedFor);
|
|
||||||
|
|
||||||
buf = tr_new( uint8_t, r->length );
|
|
||||||
|
|
||||||
if( requestIsValid( msgs, r )
|
|
||||||
&& tr_cpPieceIsComplete( msgs->torrent->completion, r->index )
|
|
||||||
&& !tr_ioRead( msgs->torrent, r->index, r->offset, r->length, buf ) )
|
|
||||||
{
|
|
||||||
protocolSendPiece( msgs, r, buf );
|
|
||||||
peerGotBytes( msgs, r->length );
|
|
||||||
msgs->clientSentAnythingAt = now;
|
|
||||||
}
|
|
||||||
|
|
||||||
tr_free( buf );
|
|
||||||
tr_free( r );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( ( now - msgs->clientSentAnythingAt ) > KEEPALIVE_INTERVAL_SECS )
|
else if( ( now - msgs->clientSentAnythingAt ) > KEEPALIVE_INTERVAL_SECS )
|
||||||
{
|
{
|
||||||
sendKeepalive( msgs );
|
sendKeepalive( msgs );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( !EVBUFFER_LENGTH( msgs->outBlock )
|
||||||
|
&& (( r = popNextRequest( msgs )))
|
||||||
|
&& requestIsValid( msgs, r )
|
||||||
|
&& tr_cpPieceIsComplete( msgs->torrent->completion, r->index ) )
|
||||||
|
{
|
||||||
|
uint8_t * buf = tr_new( uint8_t, r->length );
|
||||||
|
|
||||||
|
if( !tr_ioRead( msgs->torrent, r->index, r->offset, r->length, buf ) )
|
||||||
|
{
|
||||||
|
tr_peerIo * io = msgs->io;
|
||||||
|
struct evbuffer * out = msgs->outBlock;
|
||||||
|
|
||||||
|
dbgmsg( msgs, "sending block %u:%u->%u", r->index, r->offset, r->length );
|
||||||
|
tr_peerIoWriteUint32( io, out, sizeof(uint8_t) + 2*sizeof(uint32_t) + r->length );
|
||||||
|
tr_peerIoWriteUint8 ( io, out, BT_PIECE );
|
||||||
|
tr_peerIoWriteUint32( io, out, r->index );
|
||||||
|
tr_peerIoWriteUint32( io, out, r->offset );
|
||||||
|
tr_peerIoWriteBytes ( io, out, buf, r->length );
|
||||||
|
}
|
||||||
|
|
||||||
|
tr_free( buf );
|
||||||
|
tr_free( r );
|
||||||
|
|
||||||
|
pulse( msgs ); /* start sending it right away */
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE; /* loop forever */
|
return TRUE; /* loop forever */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1660,6 +1666,7 @@ tr_peerMsgsNew( struct tr_torrent * torrent,
|
||||||
m->rateTimer = tr_timerNew( m->handle, ratePulse, m, RATE_PULSE_INTERVAL );
|
m->rateTimer = tr_timerNew( m->handle, ratePulse, m, RATE_PULSE_INTERVAL );
|
||||||
m->pexTimer = tr_timerNew( m->handle, pexPulse, m, PEX_INTERVAL );
|
m->pexTimer = tr_timerNew( m->handle, pexPulse, m, PEX_INTERVAL );
|
||||||
m->outMessages = evbuffer_new( );
|
m->outMessages = evbuffer_new( );
|
||||||
|
m->outBlock = evbuffer_new( );
|
||||||
m->inBlock = evbuffer_new( );
|
m->inBlock = evbuffer_new( );
|
||||||
m->peerAllowedPieces = NULL;
|
m->peerAllowedPieces = NULL;
|
||||||
m->clientAllowedPieces = NULL;
|
m->clientAllowedPieces = NULL;
|
||||||
|
@ -1724,6 +1731,7 @@ tr_peerMsgsFree( tr_peermsgs* msgs )
|
||||||
tr_list_free( &msgs->peerAskedForFast, tr_free );
|
tr_list_free( &msgs->peerAskedForFast, tr_free );
|
||||||
tr_list_free( &msgs->peerAskedFor, tr_free );
|
tr_list_free( &msgs->peerAskedFor, tr_free );
|
||||||
evbuffer_free( msgs->outMessages );
|
evbuffer_free( msgs->outMessages );
|
||||||
|
evbuffer_free( msgs->outBlock );
|
||||||
evbuffer_free( msgs->inBlock );
|
evbuffer_free( msgs->inBlock );
|
||||||
tr_free( msgs->pex );
|
tr_free( msgs->pex );
|
||||||
msgs->pexCount = 0;
|
msgs->pexCount = 0;
|
||||||
|
|
|
@ -112,6 +112,29 @@ tr_rcCanTransfer( const tr_ratecontrol * r )
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
tr_rcBytesLeft( const tr_ratecontrol * r )
|
||||||
|
{
|
||||||
|
size_t bytes = 0;
|
||||||
|
|
||||||
|
if( r != NULL )
|
||||||
|
{
|
||||||
|
float cur, max;
|
||||||
|
size_t kb;
|
||||||
|
|
||||||
|
tr_lockLock( (tr_lock*)r->lock );
|
||||||
|
|
||||||
|
cur = rateForInterval( r, SHORT_INTERVAL_MSEC );
|
||||||
|
max = r->limit;
|
||||||
|
kb = max>cur ? max-cur : 0;
|
||||||
|
bytes = kb * 1024u;
|
||||||
|
|
||||||
|
tr_lockUnlock( (tr_lock*)r->lock );
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
tr_rcRate( const tr_ratecontrol * r )
|
tr_rcRate( const tr_ratecontrol * r )
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,6 +31,7 @@ tr_ratecontrol * tr_rcInit( void );
|
||||||
void tr_rcSetLimit( tr_ratecontrol *, int );
|
void tr_rcSetLimit( tr_ratecontrol *, int );
|
||||||
int tr_rcGetLimit( const tr_ratecontrol * );
|
int tr_rcGetLimit( const tr_ratecontrol * );
|
||||||
int tr_rcCanTransfer( const tr_ratecontrol * );
|
int tr_rcCanTransfer( const tr_ratecontrol * );
|
||||||
|
size_t tr_rcBytesLeft( const tr_ratecontrol * );
|
||||||
void tr_rcTransferred( tr_ratecontrol *, size_t byteCount );
|
void tr_rcTransferred( tr_ratecontrol *, size_t byteCount );
|
||||||
float tr_rcRate( const tr_ratecontrol * );
|
float tr_rcRate( const tr_ratecontrol * );
|
||||||
void tr_rcReset( tr_ratecontrol * );
|
void tr_rcReset( tr_ratecontrol * );
|
||||||
|
|
Loading…
Reference in New Issue