예제 #1
0
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;
}
예제 #2
0
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 );
            }
        }
    }
}
예제 #3
0
int
tr_cryptoWeakRandInt( int upperBound )
{
    static tr_bool init = FALSE;

    assert( upperBound > 0 );

    if( !init )
    {
        srand( tr_time_msec( ) );
        init = TRUE;
    }

    return rand( ) % upperBound;
}
예제 #4
0
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);
        }
    }
예제 #5
0
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;
}
예제 #6
0
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);
}
예제 #7
0
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 );
}