static unsigned int getSpeed_Bps (const struct bratecontrol * r, unsigned int interval_msec, uint64_t now) { if (!now) now = tr_time_msec (); if (now != r->cache_time) { int i = r->newest; uint64_t bytes = 0; const uint64_t cutoff = now - interval_msec; struct bratecontrol * rvolatile = (struct bratecontrol*) r; for (;;) { if (r->transfers[i].date <= cutoff) break; bytes += r->transfers[i].size; if (--i == -1) i = HISTORY_SIZE - 1; /* circular history */ if (i == r->newest) break; /* we've come all the way around */ } rvolatile->cache_val = (unsigned int)((bytes * 1000u) / interval_msec); rvolatile->cache_time = now; } return r->cache_val; }
static void didWriteWrapper( tr_peerIo * io, unsigned int bytes_transferred ) { while( bytes_transferred && tr_isPeerIo( io ) ) { struct tr_datatype * next = io->outbuf_datatypes->data; const unsigned int payload = MIN( next->length, bytes_transferred ); const unsigned int overhead = guessPacketOverhead( payload ); const uint64_t now = tr_time_msec( ); tr_bandwidthUsed( &io->bandwidth, TR_UP, payload, next->isPieceData, now ); if( overhead > 0 ) tr_bandwidthUsed( &io->bandwidth, TR_UP, overhead, FALSE, now ); if( io->didWrite ) io->didWrite( io, payload, next->isPieceData, io->userData ); if( tr_isPeerIo( io ) ) { bytes_transferred -= payload; next->length -= payload; if( !next->length ) { tr_list_pop_front( &io->outbuf_datatypes ); tr_free( next ); } } } }
int tr_cryptoWeakRandInt( int upperBound ) { static tr_bool init = FALSE; assert( upperBound > 0 ); if( !init ) { srand( tr_time_msec( ) ); init = TRUE; } return rand( ) % upperBound; }
static void on_content_changed (struct evbuffer * buf, const struct evbuffer_cb_info * info, void * vtask) { uint32_t len; const size_t n_added = info->n_added; struct tr_webseed_task * task = vtask; struct tr_webseed * w = task->webseed; if (n_added <= 0) return; if (!w->is_stopping) { tr_bandwidthUsed (&w->bandwidth, TR_DOWN, n_added, true, tr_time_msec ()); fire_client_got_data (w, n_added); } len = evbuffer_get_length (buf); if (!task->response_code) { tr_webGetTaskInfo (task->web_task, TR_WEB_GET_CODE, &task->response_code); if (task->response_code == 206) { const char * url; struct connection_succeeded_data * data; url = NULL; tr_webGetTaskInfo (task->web_task, TR_WEB_GET_REAL_URL, &url); data = tr_new (struct connection_succeeded_data, 1); data->webseed = w; data->real_url = tr_strdup (url); data->piece_index = task->piece_index; data->piece_offset = task->piece_offset + (task->blocks_done * task->block_size) + (len - 1); /* processing this uses a tr_torrent pointer, so push the work to the libevent thread... */ tr_runInEventThread (w->session, connection_succeeded, data); } }
static unsigned int bandwidthClamp (const tr_bandwidth * b, uint64_t now, tr_direction dir, unsigned int byteCount) { assert (tr_isBandwidth (b)); assert (tr_isDirection (dir)); if (b) { if (b->band[dir].isLimited) { byteCount = MIN (byteCount, b->band[dir].bytesLeft); /* if we're getting close to exceeding the speed limit, * clamp down harder on the bytes available */ if (byteCount > 0) { double current; double desired; double r; if (now == 0) now = tr_time_msec (); current = tr_bandwidthGetRawSpeed_Bps (b, now, TR_DOWN); desired = tr_bandwidthGetDesiredSpeed_Bps (b, TR_DOWN); r = desired >= 1 ? current / desired : 0; if (r > 1.0) byteCount = 0; else if (r > 0.9) byteCount *= 0.8; else if (r > 0.8) byteCount *= 0.9; } } if (b->parent && b->band[dir].honorParentLimits && (byteCount > 0)) byteCount = bandwidthClamp (b->parent, now, dir, byteCount); } return byteCount; }
static unsigned int getSpeed_Bps( const struct bratecontrol * r, unsigned int interval_msec, uint64_t now ) { uint64_t bytes = 0; const uint64_t cutoff = (now?now:tr_time_msec()) - interval_msec; int i = r->newest; for( ;; ) { if( r->transfers[i].date <= cutoff ) break; bytes += r->transfers[i].size; if( --i == -1 ) i = HISTORY_SIZE - 1; /* circular history */ if( i == r->newest ) break; /* we've come all the way around */ } return (unsigned int)(( bytes * 1000u ) / interval_msec); }
static void canReadWrapper( tr_peerIo * io ) { tr_bool err = 0; tr_bool done = 0; tr_session * session; dbgmsg( io, "canRead" ); assert( tr_isPeerIo( io ) ); assert( tr_isSession( io->session ) ); tr_peerIoRef( io ); session = io->session; /* try to consume the input buffer */ if( io->canRead ) { tr_sessionLock( session ); while( !done && !err ) { size_t piece = 0; const size_t oldLen = EVBUFFER_LENGTH( io->inbuf ); const int ret = io->canRead( io, io->userData, &piece ); const size_t used = oldLen - EVBUFFER_LENGTH( io->inbuf ); assert( tr_isPeerIo( io ) ); if( piece || (piece!=used) ) { const uint64_t now = tr_time_msec( ); if( piece ) tr_bandwidthUsed( &io->bandwidth, TR_DOWN, piece, TRUE, now ); if( used != piece ) tr_bandwidthUsed( &io->bandwidth, TR_DOWN, used - piece, FALSE, now ); } switch( ret ) { case READ_NOW: if( EVBUFFER_LENGTH( io->inbuf ) ) continue; done = 1; break; case READ_LATER: done = 1; break; case READ_ERR: err = 1; break; } assert( tr_isPeerIo( io ) ); } tr_sessionUnlock( session ); } /* keep the iobuf's excess capacity from growing too large */ if( EVBUFFER_LENGTH( io->inbuf ) == 0 ) { evbuffer_free( io->inbuf ); io->inbuf = evbuffer_new( ); } assert( tr_isPeerIo( io ) ); tr_peerIoUnref( io ); }