Beispiel #1
0
static uint64_t
loadSpeedLimits( tr_benc * dict, tr_torrent * tor )
{
    tr_benc * d;
    uint64_t ret = 0;


    if( tr_bencDictFindDict( dict, KEY_SPEEDLIMIT_UP, &d ) )
    {
        loadSingleSpeedLimit( d, TR_UP, tor );
        ret = TR_FR_SPEEDLIMIT;
    }
    if( tr_bencDictFindDict( dict, KEY_SPEEDLIMIT_DOWN, &d ) )
    {
        loadSingleSpeedLimit( d, TR_DOWN, tor );
        ret = TR_FR_SPEEDLIMIT;
    }

    /* older speedlimit structure */
    if( !ret && tr_bencDictFindDict( dict, KEY_SPEEDLIMIT_OLD, &d ) )
    {

        int64_t i;
        if( tr_bencDictFindInt( d, KEY_SPEEDLIMIT_DOWN_SPEED, &i ) )
            tr_torrentSetSpeedLimit_Bps( tor, TR_DOWN, i*1024 );
        if( tr_bencDictFindInt( d, KEY_SPEEDLIMIT_DOWN_MODE, &i ) ) {
            tr_torrentUseSpeedLimit( tor, TR_DOWN, i==TR_SPEEDLIMIT_SINGLE );
            tr_torrentUseSessionLimits( tor, i==TR_SPEEDLIMIT_GLOBAL );
         }
        if( tr_bencDictFindInt( d, KEY_SPEEDLIMIT_UP_SPEED, &i ) )
            tr_torrentSetSpeedLimit_Bps( tor, TR_UP, i*1024 );
        if( tr_bencDictFindInt( d, KEY_SPEEDLIMIT_UP_MODE, &i ) ) {
            tr_torrentUseSpeedLimit( tor, TR_UP, i==TR_SPEEDLIMIT_SINGLE );
            tr_torrentUseSessionLimits( tor, i==TR_SPEEDLIMIT_GLOBAL );
        }
        ret = TR_FR_SPEEDLIMIT;
    }

    return ret;
}
Beispiel #2
0
static uint64_t
loadIdleLimits( tr_benc * dict, tr_torrent * tor )
{
    tr_benc * d;
    uint64_t ret = 0;

    if( tr_bencDictFindDict( dict, KEY_IDLELIMIT, &d ) )
    {
        int64_t i;
        int64_t imin;
        if( tr_bencDictFindInt( d, KEY_IDLELIMIT_MINS, &imin ) )
            tr_torrentSetIdleLimit( tor, imin );
        if( tr_bencDictFindInt( d, KEY_IDLELIMIT_MODE, &i ) )
            tr_torrentSetIdleMode( tor, i );
      ret = TR_FR_IDLELIMIT;
    }

    return ret;
}
Beispiel #3
0
static uint64_t
loadRatioLimits( tr_benc * dict, tr_torrent * tor )
{
    tr_benc * d;
    uint64_t ret = 0;

    if( tr_bencDictFindDict( dict, KEY_RATIOLIMIT, &d ) )
    {
        int64_t i;
        double dratio;
        if( tr_bencDictFindReal( d, KEY_RATIOLIMIT_RATIO, &dratio ) )
            tr_torrentSetRatioLimit( tor, dratio );
        if( tr_bencDictFindInt( d, KEY_RATIOLIMIT_MODE, &i ) )
            tr_torrentSetRatioMode( tor, i );
      ret = TR_FR_RATIOLIMIT;
    }

    return ret;
}
Beispiel #4
0
int
tr_ctorSetMetainfoFromFile( tr_ctor *    ctor,
                            const char * filename )
{
    uint8_t * metainfo;
    size_t    len;
    int       err;

    metainfo = tr_loadFile( filename, &len );
    if( metainfo && len )
        err = tr_ctorSetMetainfo( ctor, metainfo, len );
    else
    {
        clearMetainfo( ctor );
        err = 1;
    }

    setSourceFile( ctor, filename );

    /* if no `name' field was set, then set it from the filename */
    if( ctor->isSet_metainfo )
    {
        tr_benc * info;
        if( tr_bencDictFindDict( &ctor->metainfo, "info", &info ) )
        {
            const char * name;
            if( !tr_bencDictFindStr( info, "name.utf-8", &name ) )
                if( !tr_bencDictFindStr( info, "name", &name ) )
                    name = NULL;
            if( !name || !*name )
            {
                char * base = tr_basename( filename );
                tr_bencDictAddStr( info, "name", base );
                tr_free( base );
            }
        }
    }

    tr_free( metainfo );
    return err;
}
Beispiel #5
0
static uint64_t
loadSpeedLimits( tr_benc *    dict,
                 tr_torrent * tor )
{
    uint64_t  ret = 0;
    tr_benc * d;

    if( tr_bencDictFindDict( dict, KEY_SPEEDLIMIT, &d ) )
    {
        int64_t i;
        if( tr_bencDictFindInt( d, KEY_SPEEDLIMIT_DOWN_SPEED, &i ) )
            tr_torrentSetSpeedLimit( tor, TR_DOWN, i );
        if( tr_bencDictFindInt( d, KEY_SPEEDLIMIT_DOWN_MODE, &i ) )
            tr_torrentSetSpeedMode( tor, TR_DOWN, i );
        if( tr_bencDictFindInt( d, KEY_SPEEDLIMIT_UP_SPEED, &i ) )
            tr_torrentSetSpeedLimit( tor, TR_UP, i );
        if( tr_bencDictFindInt( d, KEY_SPEEDLIMIT_UP_MODE, &i ) )
            tr_torrentSetSpeedMode( tor, TR_UP, i );
        ret = TR_FR_SPEEDLIMIT;
    }

    return ret;
}
Beispiel #6
0
static uint64_t
loadProgress( tr_benc * dict, tr_torrent * tor )
{
    size_t i, n;
    uint64_t ret = 0;
    tr_benc * prog;
    const tr_info * inf = tr_torrentInfo( tor );

    for( i=0, n=inf->pieceCount; i<n; ++i )
        inf->pieces[i].timeChecked = 0;

    if( tr_bencDictFindDict( dict, KEY_PROGRESS, &prog ) )
    {
        const char * err;
        const char * str;
        const uint8_t * raw;
        size_t rawlen;
        tr_benc * l;
        tr_benc * b;
        struct tr_bitset bitset = TR_BITSET_INIT;

        if( tr_bencDictFindList( prog, KEY_PROGRESS_CHECKTIME, &l ) )
        {
            /* per-piece timestamps were added in 2.20.
              
               If some of a file's pieces have been checked more recently than
               the file's mtime, and some lest recently, then that file will
               have a list containing timestamps for each piece.
              
               However, the most common use case is that the file doesn't change
               after it's downloaded. To reduce overhead in the .resume file,
               only a single timestamp is saved for the file if *all* or *none*
               of the pieces were tested more recently than the file's mtime. */

            tr_file_index_t fi;

            for( fi=0; fi<inf->fileCount; ++fi )
            {
                tr_benc * b = tr_bencListChild( l, fi );
                const tr_file * f = &inf->files[fi];
                tr_piece * p = &inf->pieces[f->firstPiece];
                const tr_piece * pend = &inf->pieces[f->lastPiece]+1;

                if( tr_bencIsInt( b ) )
                {
                    int64_t t;
                    tr_bencGetInt( b, &t );
                    for( ; p!=pend; ++p )
                        p->timeChecked = (time_t)t;
                }
                else if( tr_bencIsList( b ) )
                {
                    int i = 0;
                    int64_t offset = 0;
                    const int pieces = f->lastPiece + 1 - f->firstPiece;

                    tr_bencGetInt( tr_bencListChild( b, 0 ), &offset );

                    for( i=0; i<pieces; ++i )
                    {
                        int64_t t = 0;
                        tr_bencGetInt( tr_bencListChild( b, i+1 ), &t );
                        inf->pieces[f->firstPiece+i].timeChecked = (time_t)(t ? t + offset : 0);
                    }
                }
            }
        }
        else if( tr_bencDictFindList( prog, KEY_PROGRESS_MTIMES, &l ) )
        {
            tr_file_index_t fi;

            /* Before 2.20, we stored the files' mtimes in the .resume file.
               When loading the .resume file, a torrent's file would be flagged
               as untested if its stored mtime didn't match its real mtime. */

            for( fi=0; fi<inf->fileCount; ++fi )
            {
                int64_t t;

                if( tr_bencGetInt( tr_bencListChild( l, fi ), &t ) )
                {
                    const tr_file * f = &inf->files[fi];
                    tr_piece * p = &inf->pieces[f->firstPiece];
                    const tr_piece * pend = &inf->pieces[f->lastPiece];
                    const time_t mtime = tr_torrentGetFileMTime( tor, fi );
                    const time_t timeChecked = mtime==t ? mtime : 0;

                    for( ; p!=pend; ++p )
                        p->timeChecked = timeChecked;
                }
            }
        }

        err = NULL;

        if(( b = tr_bencDictFind( prog, KEY_PROGRESS_BLOCKS )))
        {
            if( !tr_bitsetFromBenc( &bitset, b ) )
                err = "Invalid value for PIECES";
        }
        else if( tr_bencDictFindStr( prog, KEY_PROGRESS_HAVE, &str ) )
        {
            if( !strcmp( str, "all" ) )
                tr_bitsetSetHaveAll( &bitset );
            else
                err = "Invalid value for HAVE";
        }
        else if( tr_bencDictFindRaw( prog, KEY_PROGRESS_BITFIELD, &raw, &rawlen ) )
        {
            bitset.bitfield.bits = (void*) raw;
            bitset.bitfield.byteCount = rawlen;
            bitset.bitfield.bitCount = rawlen * 8;
        }
        else err = "Couldn't find 'pieces' or 'have' or 'bitfield'";

        if( !err && !tr_cpBlockBitsetInit( &tor->completion, &bitset ) )
            err = "Error loading bitfield";
        if( err != NULL )
            tr_tordbg( tor, "Torrent needs to be verified - %s", err );

        ret = TR_FR_PROGRESS;
    }

    return ret;
}
Beispiel #7
0
static void
on_scrape_done( tr_session   * session,
                bool           did_connect,
                bool           did_timeout,
                long           response_code,
                const void   * msg,
                size_t         msglen,
                void         * vdata )
{
    tr_scrape_response * response;
    struct scrape_data * data = vdata;

    response = &data->response;
    response->did_connect = did_connect;
    response->did_timeout = did_timeout;
    dbgmsg( data->log_name, "Got scrape response for \"%s\"", response->url );

    if( response_code != HTTP_OK )
    {
        const char * fmt = _( "Tracker gave HTTP response code %1$ld (%2$s)" );
        const char * response_str = tr_webGetResponseStr( response_code );
        response->errmsg = tr_strdup_printf( fmt, response_code, response_str );
    }
    else
    {
        tr_benc top;
        int64_t intVal;
        tr_benc * files;
        const char * str;
        const int benc_loaded = !tr_bencLoad( msg, msglen, &top, NULL );
        if( benc_loaded )
        {
            if( tr_bencDictFindStr( &top, "failure reason", &str ) )
                response->errmsg = tr_strdup( str );

            if( tr_bencDictFindInt( &top, "min_request_interval", &intVal ) )
                response->min_request_interval = intVal;

            if( tr_bencDictFindDict( &top, "files", &files ) )
            {
                int i = 0;

                for( ;; )
                {
                    int j;
                    tr_benc * val;
                    const char * key;

                    /* get the next "file" */
                    if( !tr_bencDictChild( files, i++, &key, &val ) )
                        break;

                    /* populate the corresponding row in our response array */
                    for( j=0; j<response->row_count; ++j )
                    {
                        struct tr_scrape_response_row * row = &response->rows[j];
                        if( !memcmp( key, row->info_hash, SHA_DIGEST_LENGTH ) )
                        {
                            if( tr_bencDictFindInt( val, "complete", &intVal ) )
                                row->seeders = intVal;
                            if( tr_bencDictFindInt( val, "incomplete", &intVal ) )
                                row->leechers = intVal;
                            if( tr_bencDictFindInt( val, "downloaded", &intVal ) )
                                row->downloads = intVal;
                            if( tr_bencDictFindInt( val, "downloaders", &intVal ) )
                                row->downloaders = intVal;
                            break;
                        }
                    }
                }
            }

            tr_bencFree( &top );
        }
    }

    tr_runInEventThread( session, on_scrape_done_eventthread, data );
}
Beispiel #8
0
static uint64_t
loadProgress( tr_benc *    dict,
              tr_torrent * tor )
{
    uint64_t  ret = 0;
    tr_benc * p;

    if( tr_bencDictFindDict( dict, KEY_PROGRESS, &p ) )
    {
        const uint8_t * raw;
        size_t          rawlen;
        tr_benc *       m;
        size_t          n;
        time_t *        curMTimes = tr_torrentGetMTimes( tor, &n );

        if( tr_bencDictFindList( p, KEY_PROGRESS_MTIMES, &m )
          && ( n == tor->info.fileCount )
          && ( n == tr_bencListSize( m ) ) )
        {
            size_t i;
            for( i = 0; i < n; ++i )
            {
                int64_t tmp;
                if( !tr_bencGetInt( tr_bencListChild( m, i ), &tmp ) )
                {
                    tr_tordbg(
                        tor,
                        "File #%zu needs to be verified - couldn't find benc entry",
                        i );
                    tr_torrentSetFileChecked( tor, i, FALSE );
                }
                else
                {
                    const time_t t = (time_t) tmp;
                    if( t == curMTimes[i] )
                        tr_torrentSetFileChecked( tor, i, TRUE );
                    else
                    {
                        tr_tordbg(
                            tor,
                            "File #%zu needs to be verified - times %lu and %lu don't match",
                            i, t, curMTimes[i] );
                        tr_torrentSetFileChecked( tor, i, FALSE );
                    }
                }
            }
        }
        else
        {
            tr_torrentUncheck( tor );
            tr_tordbg(
                tor, "Torrent needs to be verified - unable to find mtimes" );
        }

        if( tr_bencDictFindRaw( p, KEY_PROGRESS_BITFIELD, &raw, &rawlen ) )
        {
            tr_bitfield tmp;
            tmp.byteCount = rawlen;
            tmp.bitCount = tmp.byteCount * 8;
            tmp.bits = (uint8_t*) raw;
            if( !tr_cpBlockBitfieldSet( tor->completion, &tmp ) )
            {
                tr_torrentUncheck( tor );
                tr_tordbg(
                    tor,
                    "Torrent needs to be verified - error loading bitfield" );
            }
        }
        else
        {
            tr_torrentUncheck( tor );
            tr_tordbg(
                tor,
                "Torrent needs to be verified - unable to find bitfield" );
        }

        tr_free( curMTimes );
        ret = TR_FR_PROGRESS;
    }

    return ret;
}