Changeset 12167


Ignore:
Timestamp:
Mar 15, 2011, 3:21:25 AM (11 years ago)
Author:
jordan
Message:

(trunk libT) annnouncer.c: as discussed with Waldorf, massage the tracker lists a bit:

  1. remove duplicate URLs caused by implicit vs. explicit port numbers
  2. if two announce URLs are duplicates /except/ for their scheme, put them in the same tier.
  3. try announce URLs with a "udp" scheme before trying ones with an "http" scheme.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/announcer.c

    r12164 r12167  
    226226trackerNew( const char * announce, const char * scrape, uint32_t id )
    227227{
    228     tr_tracker * tracker = tr_new0( tr_tracker, 1  );
     228    tr_tracker * tracker = tr_new0( tr_tracker, 1 );
    229229    tracker->key = getKey( announce );
    230230    tracker->announce = tr_strdup( announce );
     
    349349{
    350350    /* move our index to the next tracker in the tier */
    351     const int i = ( tier->currentTrackerIndex + 1 )
    352                         % tr_ptrArraySize( &tier->trackers );
     351    const int i = ( tier->currentTracker == NULL )
     352                ? 0
     353                : ( tier->currentTrackerIndex + 1 ) % tr_ptrArraySize( &tier->trackers );
    353354    tier->currentTracker = tr_ptrArrayNth( &tier->trackers, i );
    354355    tier->currentTrackerIndex = i;
     
    520521***/
    521522
     523struct ann_tracker_info
     524{
     525    tr_tracker_info info;
     526
     527    char * scheme;
     528    char * host;
     529    char * path;
     530    int port;
     531};
     532
     533
     534/* primary key: tier
     535 * secondary key: udp comes before http */
     536static int
     537filter_trackers_compare_func( const void * va, const void * vb )
     538{
     539    const struct ann_tracker_info * a = va;
     540    const struct ann_tracker_info * b = vb;
     541    if( a->info.tier != b->info.tier )
     542        return a->info.tier - b->info.tier;
     543    return -strcmp( a->scheme, b->scheme );
     544}
     545
     546/**
     547 * Massages the incoming list of trackers into something we can use.
     548 */
     549static tr_tracker_info *
     550filter_trackers( tr_tracker_info * input, int input_count, int * setme_count )
     551{
     552    int i, in;
     553    int j, jn;
     554    int n = 0;
     555    struct tr_tracker_info * ret;
     556    struct ann_tracker_info * tmp = tr_new0( struct ann_tracker_info, input_count );
     557
     558    /*for( i=0, in=input_count; i<in; ++i ) fprintf( stderr, "IN: [%d][%s]\n", input[i].tier, input[i].announce );*/
     559
     560    /* build a list of valid trackers */
     561    for( i=0, in=input_count; i<in; ++i ) {
     562        if( tr_urlIsValidTracker( input[i].announce ) ) {
     563            int port;
     564            char * scheme;
     565            char * host;
     566            char * path;
     567            tr_bool is_duplicate = FALSE;
     568            tr_urlParse( input[i].announce, -1, &scheme, &host, &port, &path );
     569
     570            /* weed out one common source of duplicates:
     571             * "http://tracker/announce" +
     572             * "http://tracker:80/announce"
     573             */
     574            for( j=0, jn=n; !is_duplicate && j<jn; ++j )
     575                is_duplicate = (tmp[j].port==port)
     576                            && !strcmp(tmp[j].scheme,scheme)
     577                            && !strcmp(tmp[j].host,host)
     578                            && !strcmp(tmp[j].path,path);
     579
     580            if( is_duplicate ) {
     581                tr_free( path );
     582                tr_free( host );
     583                tr_free( scheme );
     584                continue;
     585            }
     586            tmp[n].info = input[i];
     587            tmp[n].scheme = scheme;
     588            tmp[n].host = host;
     589            tmp[n].port = port;
     590            tmp[n].path = path;
     591            n++;
     592        }
     593    }
     594
     595    /* if two announce URLs differ only by scheme, put them in the same tier.
     596     * (note: this can leave gaps in the `tier' values, but since the calling
     597     * function doesn't care, there's no point in removing the gaps...) */
     598    for( i=0, in=n; i<n; ++i )
     599        for( j=0, jn=n; j<n; ++j )
     600            if( (i!=j) && (tmp[i].port==tmp[j].port)
     601                       && !tr_strcmp0(tmp[i].host,tmp[j].host)
     602                       && !tr_strcmp0(tmp[i].path,tmp[j].path) )
     603                tmp[j].info.tier = tmp[i].info.tier;
     604
     605    /* sort them, for two reasons:
     606     * (1) unjumble the tiers from the previous step
     607     * (2) move the UDP trackers to the front of each tier */
     608    qsort( tmp, n, sizeof(struct ann_tracker_info), filter_trackers_compare_func );
     609
     610    /* build the output */
     611    *setme_count = n;
     612    ret = tr_new0( tr_tracker_info, n );
     613    for( i=0, in=n; i<in; ++i )
     614        ret[i] = tmp[i].info;
     615
     616    /* cleanup */
     617    for( i=0, in=n; i<n; ++i ) {
     618        tr_free( tmp[i].path );
     619        tr_free( tmp[i].host );
     620        tr_free( tmp[i].scheme );
     621    }
     622    tr_free( tmp );
     623
     624    /*for( i=0, in=n; i<in; ++i ) fprintf( stderr, "OUT: [%d][%s]\n", ret[i].tier, ret[i].announce );*/
     625    return ret;
     626}
     627
     628
    522629static void
    523630addTorrentToTier( tr_torrent_tiers * tiers, tr_torrent * tor )
    524631{
    525632    int i, n;
    526     const tr_tracker_info ** infos;
    527     const int trackerCount = tor->info.trackerCount;
    528     const tr_tracker_info  * trackers = tor->info.trackers;
    529 
    530     /* get the trackers that we support... */
    531     infos = tr_new0( const tr_tracker_info*, trackerCount );
    532     for( i=n=0; i<trackerCount; ++i )
    533         if( tr_urlIsValidTracker( trackers[i].announce ) )
    534             infos[n++] = &trackers[i];
    535 
    536     /* build our private table of tiers... */
     633    tr_tracker_info * infos = filter_trackers( tor->info.trackers,
     634                                               tor->info.trackerCount, &n );
     635
     636    /* build our internal table of tiers... */
    537637    if( n > 0 )
    538638    {
     
    542642        for( i=0; i<n; ++i )
    543643        {
    544             const tr_tracker_info * info = infos[i];
     644            const tr_tracker_info * info = &infos[i];
    545645
    546646            if( info->tier != tierIndex )
     
    621721    time_t ret = ~(time_t)0;
    622722
    623     assert( tr_isTorrent( tor  ) );
     723    assert( tr_isTorrent( tor ) );
    624724
    625725    /* find the earliest manual announce time from all peers */
Note: See TracChangeset for help on using the changeset viewer.