Changeset 1154


Ignore:
Timestamp:
Dec 5, 2006, 12:14:52 AM (15 years ago)
Author:
livings124
Message:

initial support for announce-list (currently crashes when a tracker fails)

Location:
branches/multitracker
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • branches/multitracker/libtransmission/internal.h

    r1149 r1154  
    161161    char              escapedHashString[3*SHA_DIGEST_LENGTH+1];
    162162
    163     char              scrape[MAX_PATH_LENGTH];
    164 
    165163    /* Where to download */
    166164    char            * destination;
  • branches/multitracker/libtransmission/metainfo.c

    r1124 r1154  
    3131 **********************************************************************/
    3232#define strcatUTF8( dst, src) _strcatUTF8( (dst), sizeof( dst ) - 1, (src) )
     33
    3334static void _strcatUTF8( char *, int, char * );
     35static int parseAnnounce( char * original, char * address, int * port, char * announce );
     36
     37static int parseAnnounce( char * original, char * address, int * port, char * announce )
     38{
     39    char * colon, * slash;
     40   
     41    /* Skip spaces */
     42    while( *original && *original == ' ' )
     43    {
     44        original++;
     45    }
     46
     47    /* Parse announce URL */
     48    if( strncmp( original, "http://", 7 ) )
     49    {
     50        return 0;
     51    }
     52   
     53    colon = strchr( original + 7, ':' );
     54    slash = strchr( original + 7, '/' );
     55    if( colon && colon < slash )
     56    {
     57        memcpy( address, original + 7, (long) colon - (long) original - 7 );
     58        *port = atoi( colon + 1 );
     59        snprintf( announce, MAX_PATH_LENGTH, "%s", slash );
     60       
     61        return 1;
     62    }
     63    else if( slash )
     64    {
     65        memcpy( address, original + 7, (long) slash - (long) original - 7 );
     66        *port = 80;
     67        snprintf( announce, MAX_PATH_LENGTH, "%s", slash );   
     68       
     69        return 1;
     70    }
     71    else
     72    {
     73        return 0;
     74    }
     75}
    3476
    3577/***********************************************************************
     
    4385    FILE       * file;
    4486    char       * buf;
    45     benc_val_t   meta, * beInfo, * list, * val;
    46     char * s, * s2, * s3;
    47     int          i;
     87    benc_val_t   meta, * beInfo, * list, * val, * sublist;
     88    char       * address, * announce;
     89    int          i, j, k, tiers, inTier, port, random;
    4890    struct stat sb;
     91    tr_announce_list_item_t * announceItem, * lastAnnounceItem;
    4992
    5093    assert( NULL == path || NULL == savedHash );
     
    148191    /* We won't need this anymore */
    149192    free( buf );
    150 
    151     if( !( val = tr_bencDictFind( &meta, "announce" ) ) )
    152     {
    153         tr_err( "No \"announce\" entry" );
    154         tr_bencFree( &meta );
    155         return 1;
    156     }
    157    
    158     /* Skip spaces */
    159     s3 = val->val.s.s;
    160     while( *s3 && *s3 == ' ' )
    161     {
    162         s3++;
    163     }
    164 
    165     /* Parse announce URL */
    166     if( strncmp( s3, "http://", 7 ) )
    167     {
    168         tr_err( "Invalid announce URL (%s)", inf->trackerAddress );
    169         tr_bencFree( &meta );
    170         return 1;
    171     }
    172     s  = strchr( s3 + 7, ':' );
    173     s2 = strchr( s3 + 7, '/' );
    174     if( s && s < s2 )
    175     {
    176         memcpy( inf->trackerAddress, s3 + 7,
    177                 (long) s - (long) s3 - 7 );
    178         inf->trackerPort = atoi( s + 1 );
    179     }
    180     else if( s2 )
    181     {
    182         memcpy( inf->trackerAddress, s3 + 7,
    183                 (long) s2 - (long) s3 - 7 );
    184         inf->trackerPort = 80;
    185     }
    186     else
    187     {
    188         tr_err( "Invalid announce URL (%s)", inf->trackerAddress );
    189         tr_bencFree( &meta );
    190         return 1;
    191     }
    192     snprintf( inf->trackerAnnounce, MAX_PATH_LENGTH, "%s", s2 );
    193    
     193   
     194    address = calloc( sizeof( char ), 256 );
     195    announce = calloc( sizeof( char ), MAX_PATH_LENGTH );
     196   
     197    if( ( val = tr_bencDictFind( &meta, "announce-list" ) ) )
     198    {
     199        list = val->val.l.vals;
     200       
     201        inf->trackerAnnounceList = calloc( sizeof( tr_announce_list_item_t ), val->val.l.count );
     202       
     203        tiers = 0;
     204        for( i = 0; i < val->val.l.count; i++ )
     205        {
     206            sublist = list[i].val.l.vals;
     207           
     208            inTier = 0;
     209            for( j = 0; j < list[i].val.l.count; j++ )
     210            {
     211                if( !parseAnnounce( sublist[j].val.s.s, address, &port, announce ) )
     212                {
     213                    continue;
     214                }
     215               
     216                if( inTier == 0 )
     217                {
     218                    announceItem = & inf->trackerAnnounceList[tiers];
     219                }
     220                else
     221                {
     222                    announceItem = calloc( sizeof( tr_announce_list_item_t ), 1 );
     223                   
     224                    /* Shuffle order of tier addresses */
     225                    random = tr_rand( inTier + 1 );
     226                    if( random == 0 )
     227                    {
     228                        *announceItem = inf->trackerAnnounceList[tiers];
     229                        inf->trackerAnnounceList[tiers].nextItem = announceItem;
     230                        announceItem = & inf->trackerAnnounceList[tiers];
     231                    }
     232                    else
     233                    {
     234                        lastAnnounceItem = & inf->trackerAnnounceList[tiers];
     235                        for( k = 0; k < random - 1; k++ )
     236                        {
     237                            lastAnnounceItem = lastAnnounceItem->nextItem;
     238                        }
     239                       
     240                        announceItem->nextItem = lastAnnounceItem->nextItem;
     241                        lastAnnounceItem->nextItem = announceItem;
     242                    }
     243                }
     244               
     245                snprintf( announceItem->address, 256, "%s", address );
     246                announceItem->port = port;
     247                snprintf( announceItem->announce, MAX_PATH_LENGTH, "%s", announce );
     248               
     249                inTier++;
     250            }
     251           
     252            /* Only use tier if there are useable addresses */
     253            if (inTier)
     254            {
     255                tiers++;
     256            }
     257        }
     258       
     259        inf->trackerAnnounceTiers = tiers;
     260    }
     261
     262    tr_err( "announce-list:" );
     263    for( i = 0; i < inf->trackerAnnounceTiers; i++ )
     264    {
     265        tr_err( "list %d:", i );
     266        for (announceItem = & inf->trackerAnnounceList[i]; announceItem != NULL; announceItem = announceItem->nextItem)
     267        {
     268            tr_err( "%s:%d%s", announceItem->address, announceItem->port, announceItem->announce );
     269        }
     270    }
     271   
     272    /* Regular announce value */
     273    if ( !inf->trackerAnnounceTiers )
     274    {
     275        if( !( val = tr_bencDictFind( &meta, "announce" ) ) )
     276        {
     277            tr_err( "No \"announce\" entry" );
     278            tr_bencFree( &meta );
     279            return 1;
     280        }
     281       
     282        if ( !parseAnnounce( val->val.s.s, address, &port, announce ) )
     283        {
     284            tr_err( "Invalid announce URL (%s)", val->val.s.s );
     285            tr_bencFree( &meta );
     286            return 1;
     287        }
     288       
     289        if ( !inf->trackerAnnounceList )
     290            inf->trackerAnnounceList = calloc( sizeof( tr_announce_list_item_t ), 1 );
     291       
     292        inf->trackerAnnounceTiers = 1;
     293        snprintf( inf->trackerAnnounceList[0].address, 256, "%s", address );
     294        inf->trackerAnnounceList[0].port = port;
     295        snprintf( inf->trackerAnnounceList[0].announce, MAX_PATH_LENGTH, "%s", announce );
     296    }
     297   
     298    free( address );
     299    free( announce );
     300       
    194301    /* Comment info */
    195302    if( ( val = tr_bencDictFind( &meta, "comment.utf-8" ) ) || ( val = tr_bencDictFind( &meta, "comment" ) ) )
  • branches/multitracker/libtransmission/tracker.c

    r1149 r1154  
    4848    uint64_t       dateScrape;
    4949    int            lastScrapeFailed;
     50   
     51    int            shouldsetAnnounce;
     52    int            announceTier;
     53    int            announceTierLast;
    5054
    5155#define TC_ATTEMPT_NOREACH 1
     
    6266};
    6367
     68static void        setAnnounce( tr_tracker_t * tc, tr_announce_list_item_t * announceItem );
     69static int         announceToScrape( char * announce, char * scrape );
     70static void        failureAnnouncing( tr_tracker_t * tc );
    6471static tr_http_t * getQuery         ( tr_tracker_t * tc );
    6572static tr_http_t * getScrapeQuery   ( tr_tracker_t * tc );
     
    7582    tc->tor            = tor;
    7683    tc->id             = tor->id;
     84   
     85    setAnnounce( tc, &tor->info.trackerAnnounceList[0] );
    7786
    7887    tc->started        = 1;
     
    92101}
    93102
     103static void setAnnounce( tr_tracker_t * tc, tr_announce_list_item_t * announceItem )
     104{
     105    tr_torrent_t * tor = tc->tor;
     106    tr_info_t    * inf = &tor->info;
     107   
     108    tr_lockLock( &tor->lock );
     109   
     110    snprintf( inf->trackerAddress, 256, "%s", announceItem->address );
     111    inf->trackerPort = announceItem->port;
     112    snprintf( inf->trackerAnnounce, MAX_PATH_LENGTH, "%s", announceItem->announce );
     113   
     114    inf->trackerCanScrape = announceToScrape( announceItem->announce, inf->trackerScrape );
     115    tc->dateScrape = 0;
     116   
     117    tr_lockUnlock( &tor->lock );
     118}
     119
     120static int announceToScrape( char * announce, char * scrape )
     121{   
     122    char * slash, * nextSlash;
     123    int pre, post;
     124   
     125    slash = strchr( announce, '/' );
     126    while( ( nextSlash = strchr( slash + 1, '/' ) ) )
     127    {
     128        slash = nextSlash;
     129    }
     130    slash++;
     131   
     132    if( !strncmp( slash, "announce", 8 ) )
     133    {
     134        pre  = (long) slash - (long) announce;
     135        post = strlen( announce ) - pre - 8;
     136        memcpy( scrape, announce, pre );
     137        sprintf( &scrape[pre], "scrape" );
     138        memcpy( &scrape[pre+6], &announce[pre+8], post );
     139        scrape[pre+6+post] = 0;
     140       
     141        return 1;
     142    }
     143    else
     144    {
     145        return 0;
     146    }
     147}
     148
     149static void failureAnnouncing( tr_tracker_t * tc )
     150{
     151    tr_torrent_t * tor = tc->tor;
     152    tr_info_t    * inf = &tor->info;
     153   
     154    int i;
     155    tr_announce_list_item_t * announceItem;
     156   
     157    tc->announceTierLast++;
     158    tc->shouldsetAnnounce = 1;
     159   
     160    /* If there are no more trackers don't try to change the announce */
     161    if( tc->announceTier <= inf->trackerAnnounceTiers)
     162        return;
     163   
     164    announceItem = &inf->trackerAnnounceList[tc->announceTier];
     165    for( i = 0; i <= tc->announceTierLast; i++ )
     166    {
     167        announceItem = announceItem->nextItem;
     168    }
     169   
     170    if( announceItem == NULL )
     171    {
     172        tc->shouldsetAnnounce = 0;
     173    }
     174}
     175
    94176static int shouldConnect( tr_tracker_t * tc )
    95177{
    96178    tr_torrent_t * tor = tc->tor;
    97179    uint64_t       now;
    98 
     180   
     181    /* Last tracker failed, try next */
     182    if( tc->shouldsetAnnounce )
     183    {
     184        return 1;
     185    }
     186   
    99187    now = tr_date();
    100188
     
    162250static int shouldScrape( tr_tracker_t * tc )
    163251{
     252    tr_torrent_t * tor = tc->tor;
     253    tr_info_t    * inf = &tor->info;
    164254    uint64_t now, interval;
    165255
    166     /* scrape not supported */
    167     if( !tc->tor->scrape[0] )
     256    /* in process of changing tracker or scrape not supported */
     257    if( tc->shouldsetAnnounce || !inf->trackerCanScrape )
    168258    {
    169259        return 0;
     
    192282    tr_info_t    * inf = &tor->info;
    193283    const char   * data;
    194     int            len;
     284    int            len, i;
     285    tr_announce_list_item_t * announceItem;
    195286
    196287    if( ( NULL == tc->http ) && shouldConnect( tc ) )
    197288    {
     289        if( tc->shouldsetAnnounce )
     290        {
     291            tr_err( "Tracker: %s failed to connect, trying next", inf->trackerAddress );
     292           
     293            announceItem = &inf->trackerAnnounceList[tc->announceTier];
     294            for( i = 0; i <= tc->announceTierLast; i++ )
     295            {
     296                announceItem = announceItem->nextItem;
     297            }
     298           
     299            if( announceItem != NULL )
     300            {
     301                tc->announceTierLast++;
     302               
     303                /* Move address to front of tier in announce list */
     304            }
     305            else
     306            {
     307                tc->announceTierLast = 0;
     308                tc->announceTier++;
     309               
     310                announceItem = &inf->trackerAnnounceList[tc->announceTier];
     311            }
     312           
     313            setAnnounce( tc, announceItem );
     314           
     315            tc->shouldsetAnnounce = 0;
     316        }
     317        else
     318        {
     319            if( tc->announceTier != 0 )
     320            {
     321                setAnnounce( tc, inf->trackerAnnounceList );
     322                tc->announceTier = 0;
     323            }
     324            tc->announceTierLast = 0;
     325        }
     326       
    198327        if( tr_fdSocketWillCreate( tor->fdlimit, 1 ) )
    199328        {
     
    222351                killHttp( &tc->http, tor->fdlimit );
    223352                tc->dateTry = tr_date();
    224                 break;
     353               
     354                failureAnnouncing( tc );
     355                if ( tc->shouldsetAnnounce )
     356                {
     357                    tr_trackerPulse( tc );
     358                }
     359               
     360                return;
    225361
    226362            case TR_OK:
    227363                readAnswer( tc, data, len );
    228364                killHttp( &tc->http, tor->fdlimit );
     365               
     366                /* Something happened to need to try next address */
     367                if ( tc->shouldsetAnnounce )
     368                {
     369                    tr_trackerPulse( tc );
     370                    return;
     371                }
     372               
    229373                break;
    230374        }
     
    258402                readScrapeAnswer( tc, data, len );
    259403                killHttp( &tc->httpScrape, tor->fdlimit );
     404               
    260405                break;
    261406        }
     
    377522    char           start;
    378523
    379     start = ( strchr( tor->scrape, '?' ) ? '&' : '?' );
     524    start = ( strchr( inf->trackerScrape, '?' ) ? '&' : '?' );
    380525
    381526    return tr_httpClient( TR_HTTP_GET, inf->trackerAddress, inf->trackerPort,
    382527                          "%s%c"
    383528                          "info_hash=%s",
    384                           tor->scrape, start, tor->escapedHashString );
     529                          inf->trackerScrape, start, tor->escapedHashString );
    385530}
    386531
     
    397542    tc->dateTry = tr_date();
    398543    code = tr_httpResponseCode( data, len );
     544   
    399545    if( 0 > code )
    400546    {
     
    402548        tr_inf( "Tracker: invalid HTTP status line" );
    403549        tc->lastAttempt = TC_ATTEMPT_NOREACH;
     550        failureAnnouncing( tc );
    404551        return;
    405552    }
     
    410557        tr_err( "Tracker: invalid HTTP status code: %i", code );
    411558        tc->lastAttempt = TC_ATTEMPT_ERROR;
     559        failureAnnouncing( tc );
    412560        return;
    413561    }
     
    419567        tr_err( "Tracker: could not find end of HTTP headers" );
    420568        tc->lastAttempt = TC_ATTEMPT_NOREACH;
     569        failureAnnouncing( tc );
    421570        return;
    422571    }
     
    443592        tr_err( "Tracker: no valid dictionary found in answer" );
    444593        tc->lastAttempt = TC_ATTEMPT_ERROR;
     594        failureAnnouncing( tc );
    445595        return;
    446596    }
     
    455605                  "%s", bePeers->val.s.s );
    456606        tc->lastAttempt = TC_ATTEMPT_ERROR;
     607        failureAnnouncing( tc );
    457608        goto cleanup;
    458609    }
     
    543694        }
    544695        tr_err( "Tracker: no \"peers\" field" );
     696        failureAnnouncing( tc );
    545697        goto cleanup;
    546698    }
     
    755907int tr_trackerScrape( tr_torrent_t * tor, int * s, int * l, int * d )
    756908{
     909    tr_info_t    * inf = &tor->info;
     910   
    757911    tr_tracker_t * tc;
    758912    tr_http_t    * http;
     
    761915    int            ret;
    762916
    763     if( !tor->scrape[0] )
     917    if( !inf->trackerCanScrape )
    764918    {
    765919        return 1;
  • branches/multitracker/libtransmission/transmission.c

    r1149 r1154  
    302302    tor->bindPort = &h->bindPort;
    303303        tor->finished = 0;
    304 
    305 
    306     /* Guess scrape URL */
    307     s1 = strchr( inf->trackerAnnounce, '/' );
    308     while( ( s2 = strchr( s1 + 1, '/' ) ) )
    309     {
    310         s1 = s2;
    311     }
    312     s1++;
    313     if( !strncmp( s1, "announce", 8 ) )
    314     {
    315         int pre  = (long) s1 - (long) inf->trackerAnnounce;
    316         int post = strlen( inf->trackerAnnounce ) - pre - 8;
    317         memcpy( tor->scrape, inf->trackerAnnounce, pre );
    318         sprintf( &tor->scrape[pre], "scrape" );
    319         memcpy( &tor->scrape[pre+6], &inf->trackerAnnounce[pre+8], post );
    320     }
    321304
    322305    /* Escaped info hash for HTTP queries */
  • branches/multitracker/libtransmission/transmission.h

    r1149 r1154  
    6262tr_handle_t * tr_init();
    6363
     64typedef struct tr_announce_list_item_s tr_announce_list_item_t;
     65
    6466/***********************************************************************
    6567 * tr_setMessageLevel
     
    316318
    317319    /* Tracker info */
    318     char        trackerAddress[256];
    319     int         trackerPort;
    320     char        trackerAnnounce[MAX_PATH_LENGTH];
     320    char                trackerAddress[256];
     321    int                 trackerPort;
     322    char                trackerAnnounce[MAX_PATH_LENGTH];
     323    char                trackerScrape[MAX_PATH_LENGTH];
     324    int                 trackerCanScrape;
     325   
     326    tr_announce_list_item_t  * trackerAnnounceList;
     327    int                 trackerAnnounceTiers;
    321328   
    322329    /* Torrent info */
     
    396403};
    397404
     405struct tr_announce_list_item_s
     406{
     407    char address[256];
     408    int port;
     409    char announce[MAX_PATH_LENGTH];
     410   
     411    tr_announce_list_item_t * nextItem;
     412};
     413
    398414#ifdef __TRANSMISSION__
    399415#  include "internal.h"
  • branches/multitracker/macosx/InfoWindowController.m

    r1149 r1154  
    5050@interface InfoWindowController (Private)
    5151
     52- (void) updateInfoGeneral;
    5253- (void) updateInfoActivity;
    5354- (void) updateInfoPeers;
     
    204205        [fSizeField setStringValue: [NSString stringForFileSize: [torrent size]]];
    205206       
    206         NSString * tracker = [[torrent tracker] stringByAppendingString: [torrent announce]],
    207                 * hashString = [torrent hashString],
     207        NSString * hashString = [torrent hashString],
    208208                * commentString = [torrent comment];
    209         [fTrackerField setStringValue: tracker];
    210         [fTrackerField setToolTip: tracker];
    211209        [fPiecesField setStringValue: [NSString stringWithFormat: @"%d, %@", [torrent pieceCount],
    212210                                        [NSString stringForFileSize: [torrent pieceSize]]]];
     
    280278    else if ([[[fTabView selectedTabViewItem] identifier] isEqualToString: TAB_PEERS_IDENT])
    281279        [self updateInfoPeers];
     280    else if ([[[fTabView selectedTabViewItem] identifier] isEqualToString: TAB_INFO_IDENT])
     281        [self updateInfoGeneral];
    282282    else;
     283}
     284
     285- (void) updateInfoGeneral
     286{   
     287    int numberSelected = [fTorrents count];
     288    if (numberSelected != 1)
     289        return;
     290   
     291    Torrent * torrent = [fTorrents objectAtIndex: 0];
     292    NSString * tracker = [[torrent tracker] stringByAppendingString: [torrent announce]];
     293    [fTrackerField setStringValue: tracker];
     294    [fTrackerField setToolTip: tracker];
    283295}
    284296
Note: See TracChangeset for help on using the changeset viewer.