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 ); } } } }
void tr_bandwidthUsed( tr_bandwidth * b, tr_direction dir, size_t byteCount, tr_bool isPieceData, uint64_t now ) { struct tr_band * band; assert( tr_isBandwidth( b ) ); assert( tr_isDirection( dir ) ); band = &b->band[dir]; if( band->isLimited && isPieceData ) band->bytesLeft -= MIN( band->bytesLeft, byteCount ); #ifdef DEBUG_DIRECTION if( ( dir == DEBUG_DIRECTION ) && ( band->isLimited ) ) fprintf( stderr, "%p consumed %5zu bytes of %5s data... was %6zu, now %6zu left\n", b, byteCount, (isPieceData?"piece":"raw"), oldBytesLeft, band->bytesLeft ); #endif bytesUsed( now, &band->raw, byteCount ); if( isPieceData ) bytesUsed( now, &band->piece, byteCount ); if( b->parent != NULL ) tr_bandwidthUsed( b->parent, dir, byteCount, isPieceData, now ); }
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 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 ); }