Changeset 1685


Ignore:
Timestamp:
Apr 8, 2007, 5:41:44 AM (15 years ago)
Author:
joshe
Message:

Refactor multitracker code a bit.

Location:
trunk/libtransmission
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/internal.h

    r1650 r1685  
    132132typedef enum { TR_NET_OK, TR_NET_ERROR, TR_NET_WAIT } tr_tristate_t;
    133133
     134#include "bsdqueue.h"
     135#include "bsdtree.h"
    134136#include "platform.h"
    135137#include "bencode.h"
  • trunk/libtransmission/tracker.c

    r1612 r1685  
    2626#include "shared.h"
    2727
    28 typedef struct tr_announce_list_ptr_s tr_announce_list_ptr_t;
    29 struct tr_announce_list_ptr_s
    30 {
    31     tr_tracker_info_t * item;
    32     tr_announce_list_ptr_t * nextItem;
     28struct tclist
     29{
     30    tr_tracker_info_t   * tl_inf;
     31    int                   tl_badscrape;
     32    SLIST_ENTRY( tclist ) next;
    3333};
     34SLIST_HEAD( tchead, tclist );
    3435
    3536struct tr_tracker_s
     
    4041    char         * trackerid;
    4142
    42     tr_tracker_info_t * info;
    43    
    44     tr_announce_list_ptr_t ** trackerAnnounceListPtr;
     43    struct tchead * tiers;
     44    size_t          tierCount;
     45    size_t          tierIndex;
     46    struct tclist * tcCur;
    4547
    4648#define TC_CHANGE_NO        0
     
    4951#define TC_CHANGE_REDIRECT  4
    5052    int            shouldChangeAnnounce;
    51     int            announceTier;
    52     int            announceTierLast;
    5353   
    5454    char         * redirectAddress;
     
    8686};
    8787
    88 static void        setAnnounce      ( tr_tracker_t * tc, tr_announce_list_ptr_t * announceItem );
     88static void        setAnnounce      ( tr_tracker_t * tc, struct tclist * new );
    8989static void        failureAnnouncing( tr_tracker_t * tc );
    9090static tr_http_t * getQuery         ( tr_tracker_t * tc );
     
    102102
    103103    tr_tracker_t * tc;
    104     tr_announce_list_ptr_t * prev, * cur;
    105     int ii, jj;
    106 
    107     tc                 = calloc( 1, sizeof( tr_tracker_t ) );
     104    struct tclist * item;
     105    size_t ii, jj;
     106
     107    tc = calloc( 1, sizeof *tc );
     108    if( NULL == tc )
     109    {
     110        return NULL;
     111    }
     112
    108113    tc->tor            = tor;
    109114    tc->id             = tor->id;
     
    121126
    122127    tc->publicPort     = tor->publicPort;
    123    
    124     tc->trackerAnnounceListPtr = calloc( sizeof( int ), inf->trackerTiers );
    125     for( ii = 0; ii < inf->trackerTiers; ii++ )
    126     {
    127         prev = NULL;
    128         for( jj = 0; jj < inf->trackerList[ii].count; jj++ )
    129         {
    130             cur = calloc( sizeof( tr_announce_list_ptr_t ), 1 );
    131             cur->item = &inf->trackerList[ii].list[jj];
    132             if( NULL == prev )
     128
     129    assert( 0 <= inf->trackerTiers );
     130    assert( sizeof( struct tchead ) == sizeof *tc->tiers );
     131    tc->tiers          = calloc( inf->trackerTiers, sizeof *tc->tiers );
     132    tc->tierCount      = inf->trackerTiers;
     133    for( ii = 0; tc->tierCount > ii; ii++ )
     134    {
     135        assert( 0 <= inf->trackerList[ii].count );
     136        SLIST_INIT( &tc->tiers[ii] );
     137        for( jj = inf->trackerList[ii].count; 0 < jj; jj-- )
     138        {
     139            item = calloc( 1, sizeof *item );
     140            if( NULL == item )
    133141            {
    134                 tc->trackerAnnounceListPtr[ii] = cur;
     142                tr_trackerClose( tc );
     143                return NULL;
    135144            }
    136             else
    137             {
    138                 prev->nextItem = cur;
    139             }
    140             prev = cur;
    141         }
    142     }
    143    
    144     setAnnounce( tc, tc->trackerAnnounceListPtr[0] );
     145            item->tl_inf = &inf->trackerList[ii].list[jj-1];
     146            SLIST_INSERT_HEAD( &tc->tiers[ii], item, next );
     147        }
     148    }
     149
     150    setAnnounce( tc, SLIST_FIRST( &tc->tiers[0] ) );
    145151
    146152    return tc;
    147153}
    148154
    149 static void setAnnounce( tr_tracker_t * tc, tr_announce_list_ptr_t * announcePtr )
    150 {
    151     tc->info = announcePtr->item;
     155static void setAnnounce( tr_tracker_t * tc, struct tclist * new )
     156{
     157    tc->tcCur = new;
    152158
    153159    /* Needs a new scrape */
     
    160166static void failureAnnouncing( tr_tracker_t * tc )
    161167{
    162     tr_info_t * inf = &tc->tor->info;
    163    
    164     tc->shouldChangeAnnounce = tc->announceTier + 1 < inf->trackerTiers
    165                                 || tc->announceTierLast + 1 < inf->trackerList[tc->announceTier].count
    166                                 ? TC_CHANGE_NEXT : TC_CHANGE_NONEXT;
    167    
    168     if( tc->shouldChangeAnnounce == TC_CHANGE_NONEXT )
    169     {
     168    if( NULL != SLIST_NEXT( tc->tcCur, next ) ||
     169        tc->tierIndex + 1 < tc->tierCount )
     170    {
     171        tc->shouldChangeAnnounce = TC_CHANGE_NEXT;
     172    }
     173    else
     174    {
     175        tc->shouldChangeAnnounce = TC_CHANGE_NONEXT;
    170176        tc->completelyUnconnectable = 1;
    171177    }
     
    186192    now = tr_date();
    187193   
    188     /* If last attempt was an error and it did not change trackers, then all must have been errors */
     194    /* If last attempt was an error and it did not change trackers,
     195       then all must have been errors */
    189196    if( tc->lastError )
    190197    {
    191         /* Unreachable trackers, wait 10 seconds + random value before trying again */
     198        /* Unreachable trackers, wait 10 seconds + random value before
     199           trying again */
    192200        if( tc->allUnreachIfError )
    193201        {
     
    197205            }
    198206        }
    199         /* The tracker rejected us (like 4XX code, unauthorized IP...),
    200             don't hammer it - we'll probably get the same answer next time anyway */
     207        /* The tracker rejected us (like 4XX code, unauthorized
     208            IP...), don't hammer it - we'll probably get the same
     209            answer next time anyway */
    201210        else
    202211        {
     
    207216            else
    208217            {
    209                 tc->allUnreachIfError = 1; //since starting at the top of the list, reset if any were reached previously
     218                /* since starting at the top of the list, reset if any
     219                   were reached previously */
     220                tc->allUnreachIfError = 1;
    210221            }
    211222        }
     
    263274    /* in process of changing tracker or scrape not supported */
    264275    if( tc->shouldChangeAnnounce != TC_CHANGE_NO ||
    265         NULL == tc->info->scrape || tc->stopped )
     276        NULL == tc->tcCur->tl_inf->scrape || tc->tcCur->tl_badscrape ||
     277        tc->stopped )
    266278    {
    267279        return 0;
     
    283295                              uint8_t ** peerCompact, int manual )
    284296{
    285     tr_torrent_t * tor = tc->tor;
    286     tr_info_t    * inf = &tor->info;
    287297    const char   * data;
    288298    char         * address, * announce;
    289     int            len, i, port;
    290     tr_announce_list_ptr_t * announcePtr, * prevAnnouncePtr;
     299    int            len, port;
     300    struct tclist * next;
     301    struct tchead * tier;
    291302
    292303    *peerCount = 0;
     
    295306    if( ( NULL == tc->http ) && ( manual || shouldConnect( tc ) ) )
    296307    {
    297         //if announcing manually, don't consider not reaching a tracker an error
     308        /* if announcing manually, don't consider not reaching a
     309           tracker an error */
    298310        if( manual )
    299311        {
     
    313325            {
    314326                tr_err( "Tracker: redirected URL: %s:%d", address, port );
    315                 tc->http = tr_httpClient( TR_HTTP_GET, address, port, "%s", announce );
     327                tc->http = tr_httpClient( TR_HTTP_GET, address, port,
     328                                          "%s", announce );
    316329               
    317330                free( address );
     
    327340            if( tc->shouldChangeAnnounce == TC_CHANGE_NEXT )
    328341            {
    329                 tr_inf( "Tracker: failed to connect to %s, trying next",
    330                         tc->info->address );
    331                
    332                 if( tc->announceTierLast + 1 < inf->trackerList[tc->announceTier].count )
     342                tr_inf( "Tracker: failed to connect to %s:%i, trying next",
     343                        tc->tcCur->tl_inf->address, tc->tcCur->tl_inf->port );
     344                next = SLIST_NEXT( tc->tcCur, next );
     345                if( NULL == next )
    333346                {
    334                     tc->announceTierLast++;
    335                    
    336                     announcePtr = tc->trackerAnnounceListPtr[tc->announceTier];
    337                     for( i = 0; i < tc->announceTierLast; i++ )
    338                     {
    339                         announcePtr = announcePtr->nextItem;
    340                     }
    341                 }
    342                 else
    343                 {
    344                     tc->announceTierLast = 0;
    345                     tc->announceTier++;
    346                    
    347                     announcePtr = tc->trackerAnnounceListPtr[tc->announceTier];
     347                    assert( tc->tierCount > tc->tierIndex + 1 );
     348                    tc->tierIndex++;
     349                    next = SLIST_FIRST( &tc->tiers[tc->tierIndex] );
     350                    /* XXX will there always be at least one tracker
     351                       in a tier? */
    348352                }
    349353               
    350                 tr_inf( "Tracker: tracker address set to %s", tc->trackerAnnounceListPtr[tc->announceTier]->item->address );
    351                 setAnnounce( tc, announcePtr );
     354                tr_inf( "Tracker: switching to tracker http://%s:%i%s",
     355                        next->tl_inf->address, next->tl_inf->port,
     356                        next->tl_inf->announce );
     357                setAnnounce( tc, next );
    352358            }
    353359            /* Need to change to first in list */
    354             else if( tc->announceTier != 0 || tc->announceTierLast != 0 )
     360            else if( SLIST_FIRST( &tc->tiers[0] ) != tc->tcCur )
    355361            {
    356                 /* Check if the last announce was successful and wasn't the first in the sublist */
    357                 if( tc->shouldChangeAnnounce == TC_CHANGE_NO && tc->announceTierLast != 0 )
     362                tier = &tc->tiers[tc->tierIndex];
     363                /* Check if the last announce was successful and
     364                   wasn't the first in the sublist */
     365                if( tc->shouldChangeAnnounce == TC_CHANGE_NO &&
     366                    SLIST_FIRST( tier ) != tc->tcCur )
    358367                {
    359                     announcePtr = tc->trackerAnnounceListPtr[tc->announceTier];
    360                     prevAnnouncePtr = NULL;
    361                     for( i = 0; i < tc->announceTierLast; i++ )
    362                     {
    363                         prevAnnouncePtr = announcePtr;
    364                         announcePtr = announcePtr->nextItem;
    365                     }
    366                    
    367                     /* Move address to front of tier in announce list */
    368                     prevAnnouncePtr->nextItem = announcePtr->nextItem;
    369                     announcePtr->nextItem =  tc->trackerAnnounceListPtr[tc->announceTier];
    370                     tc->trackerAnnounceListPtr[tc->announceTier] = announcePtr;
     368                    SLIST_REMOVE( tier, tc->tcCur, tclist, next );
     369                    SLIST_INSERT_HEAD( tier, tc->tcCur, next );
    371370                }
    372371               
    373                 setAnnounce( tc, tc->trackerAnnounceListPtr[0] );
    374                 tc->announceTier = 0;
    375                 tc->announceTierLast = 0;
     372                setAnnounce( tc, SLIST_FIRST( tier ) );
    376373            }
    377            
     374
    378375            tc->http = getQuery( tc );
    379376
    380377            tr_inf( "Tracker: connecting to %s:%d (%s)",
    381                     tc->info->address, tc->info->port,
     378                    tc->tcCur->tl_inf->address, tc->tcCur->tl_inf->port,
    382379                    tc->started ? "sending 'started'" :
    383380                    ( tc->completed ? "sending 'completed'" :
    384381                      ( tc->stopped ? "sending 'stopped'" :
    385                         ( shouldChangePort( tc ) ? "sending 'stopped' to change port" :
     382                        ( shouldChangePort( tc ) ?
     383                          "sending 'stopped' to change port" :
    386384                          "getting peers" ) ) ) );
    387385        }
     
    420418        {
    421419            /* Use redirected address */
    422             if( !tr_httpParseUrl( tc->redirectScrapeAddress, tc->redirectScrapeAddressLen,
    423                                      &address, &port, &announce ) )
     420            if( !tr_httpParseUrl( tc->redirectScrapeAddress,
     421                                  tc->redirectScrapeAddressLen,
     422                                  &address, &port, &announce ) )
    424423            {
    425424                tr_err( "Scrape: redirected URL: %s:%d", address, port );
    426                 tc->httpScrape = tr_httpClient( TR_HTTP_GET, address, port, "%s", announce );
     425                tc->httpScrape = tr_httpClient( TR_HTTP_GET, address, port,
     426                                                "%s", announce );
    427427               
    428428                free( address );
     
    436436        {
    437437            tc->httpScrape = getScrapeQuery( tc );
    438             tr_inf( "Scrape: sent HTTP request to %s:%d%s",
    439                     tc->info->address, tc->info->port, tc->info->scrape );
     438            tr_inf( "Scrape: sent HTTP request for http://%s:%d%s",
     439                    tc->tcCur->tl_inf->address,
     440                    tc->tcCur->tl_inf->port,
     441                    tc->tcCur->tl_inf->scrape );
    440442        }
    441443    }
     
    486488void tr_trackerClose( tr_tracker_t * tc )
    487489{
    488     tr_torrent_t * tor = tc->tor;
    489     tr_info_t * inf = &tor->info;
    490     tr_announce_list_ptr_t * cur, * curFree;
    491     int ii;
     490    size_t          ii;
     491    struct tclist * dead;
    492492
    493493    killHttp( &tc->http );
    494494    killHttp( &tc->httpScrape );
    495495
    496     for( ii = 0; ii < inf->trackerTiers; ii++ )
    497     {
    498         for( cur = tc->trackerAnnounceListPtr[ii]; cur; )
    499         {
    500             curFree = cur;
    501             cur = cur->nextItem;
    502             free( curFree );
    503         }
    504     }
    505     free( tc->trackerAnnounceListPtr );
     496    for( ii = 0; tc->tierCount > ii; ii++ )
     497    {
     498        while( !SLIST_EMPTY( &tc->tiers[ii] ) )
     499        {
     500            dead = SLIST_FIRST( &tc->tiers[ii] );
     501            SLIST_REMOVE_HEAD( &tc->tiers[ii], next );
     502            free( dead );
     503        }
     504    }
     505    free( tc->tiers );
    506506
    507507    free( tc->trackerid );
     
    512512{
    513513    tr_torrent_t * tor = tc->tor;
     514    tr_tracker_info_t * tcInf = tc->tcCur->tl_inf;
    514515
    515516    char         * event, * trackerid, * idparam;
     
    558559    }
    559560
    560     start = ( strchr( tc->info->announce, '?' ) ? '&' : '?' );
     561    start = ( strchr( tcInf->announce, '?' ) ? '&' : '?' );
    561562    left  = tr_cpLeftBytes( tor->completion );
    562563
    563     return tr_httpClient( TR_HTTP_GET, tc->info->address, tc->info->port,
     564    return tr_httpClient( TR_HTTP_GET, tcInf->address, tcInf->port,
    564565                          "%s%c"
    565566                          "info_hash=%s&"
     
    574575                          "%s%s"
    575576                          "%s",
    576                           tc->info->announce, start, tor->escapedHashString,
     577                          tcInf->announce, start, tor->escapedHashString,
    577578                          tc->id, tc->publicPort, up, down, left, numwant,
    578579                          tor->key, idparam, trackerid, event );
     
    582583{
    583584    tr_torrent_t * tor = tc->tor;
     585    tr_tracker_info_t * tcInf = tc->tcCur->tl_inf;
    584586    char           start;
    585587
    586     start = ( strchr( tc->info->scrape, '?' ) ? '&' : '?' );
    587 
    588     return tr_httpClient( TR_HTTP_GET, tc->info->address, tc->info->port,
     588    start = ( strchr( tcInf->scrape, '?' ) ? '&' : '?' );
     589
     590    return tr_httpClient( TR_HTTP_GET, tcInf->address, tcInf->port,
    589591                          "%s%c"
    590592                          "info_hash=%s",
    591                           tc->info->scrape, start, tor->escapedHashString );
     593                          tcInf->scrape, start, tor->escapedHashString );
    592594}
    593595
     
    685687    }
    686688
    687     // tr_bencPrint( &beAll );
     689    /* tr_bencPrint( &beAll ); */
    688690
    689691    if( ( bePeers = tr_bencDictFind( &beAll, "failure reason" ) ) )
     
    891893        if( TR_HTTP_STATUS_FAIL_CLIENT( code ) )
    892894        {
    893             free( tc->info->scrape );
    894             tc->info->scrape = NULL;
     895            tc->tcCur->tl_badscrape = 1;
    895896        }
    896897        tc->lastScrapeFailed = 1;
     
    10031004        return NULL;
    10041005    }
    1005     return tc->info;
     1006    return tc->tcCur->tl_inf;
    10061007}
    10071008
     
    10261027    tc = tr_trackerInit( tor );
    10271028
    1028     if( NULL == tc->info->scrape )
     1029    if( NULL == tc->tcCur->tl_inf->scrape || tc->tcCur->tl_badscrape )
    10291030    {
    10301031        return 1;
Note: See TracChangeset for help on using the changeset viewer.