Guest

jhujhiti

By: a guest on Sep 28th, 2009  |  syntax: Objective C  |  size: 34.75 KB  |  hits: 64  |  expires: Never
download  |  raw  |  embed  |  report abuse
Copied
  1. Index: libtransmission/announcer.c
  2. ===================================================================
  3. --- libtransmission/announcer.c (revision 9219)
  4. +++ libtransmission/announcer.c (working copy)
  5.  -30,8 +30,7 @@
  6.  #define dbgmsg( tier, ... ) \
  7.  if( tr_deepLoggingIsActive( ) ) do { \
  8.    char name[128]; \
  9. -  tr_snprintf( name, sizeof( name ), "[%s--%s]", tr_torrentName( tier->tor ), \
  10. -      ( tier->currentTracker ? tier->currentTracker->host->name : "" ) ); \
  11. +  tr_snprintf( name, sizeof( name ), "[%s]", tr_torrentName( tier->tor ) ); \
  12.    tr_deepLog( __FILE__, __LINE__, name, __VA_ARGS__ ); \
  13.  } while( 0 )
  14.  
  15.  -200,7 +199,7 @@
  16.  typedef struct tr_announcer
  17.  {
  18.      tr_ptrArray hosts; /* tr_host */
  19. -    tr_ptrArray stops; /* struct stop_message */
  20. +    tr_ptrArray stopsArray[NUM_TR_AF_INET_TYPES]; /* struct stop_message */
  21.      tr_session * session;
  22.      struct event * upkeepTimer;
  23.      int announceSlotsAvailable;
  24.  -232,12 +231,14 @@
  25.  tr_announcerInit( tr_session * session )
  26.  {
  27.      tr_announcer * a;
  28. +   int i;
  29.  
  30.      assert( tr_isSession( session ) );
  31.  
  32.      a = tr_new0( tr_announcer, 1 );
  33.      a->hosts = TR_PTR_ARRAY_INIT;
  34. -    a->stops = TR_PTR_ARRAY_INIT;
  35. +   for( i = 0 ; i < NUM_TR_AF_INET_TYPES ; i++ )
  36. +       a->stopsArray[i] = TR_PTR_ARRAY_INIT;
  37.      a->session = session;
  38.      a->announceSlotsAvailable = MAX_CONCURRENT_ANNOUNCES;
  39.      a->scrapeSlotsAvailable = MAX_CONCURRENT_SCRAPES;
  40.  -254,6 +255,7 @@
  41.  tr_announcerClose( tr_session * session )
  42.  {
  43.      tr_announcer * announcer = session->announcer;
  44. +   int i;
  45.  
  46.      flushCloseMessages( announcer );
  47.  
  48.  -261,7 +263,8 @@
  49.      tr_free( announcer->upkeepTimer );
  50.      announcer->upkeepTimer = NULL;
  51.  
  52. -    tr_ptrArrayDestruct( &announcer->stops, NULL );
  53. +   for( i = 0 ; i < NUM_TR_AF_INET_TYPES ; i++ )
  54. +       tr_ptrArrayDestruct( &announcer->stopsArray[i], NULL );
  55.      tr_ptrArrayDestruct( &announcer->hosts, hostFree );
  56.  
  57.      session->announcer = NULL;
  58.  -291,6 +294,9 @@
  59.       * to verify us if our IP address changes.
  60.       * This is immutable for the life of the tracker object. */
  61.      char key_param[KEYLEN + 1];
  62. +  
  63. +   /* this tracker's address family */
  64. +   tr_address_type af;
  65.  }
  66.  tr_tracker_item;
  67.  
  68.  -307,9 +313,10 @@
  69.  }
  70.  
  71.  static tr_tracker_item*
  72. -trackerNew( tr_announcer  * announcer,
  73. -            const char    * announce,
  74. -            const char    * scrape )
  75. +trackerNew( tr_announcer    * announcer,
  76. +            const char      * announce,
  77. +            const char      * scrape,
  78. +            tr_address_type   af)
  79.  {
  80.      tr_tracker_item * tracker = tr_new0( tr_tracker_item, 1  );
  81.      tracker->host = getHost( announcer, announce );
  82.  -319,6 +326,7 @@
  83.      tracker->seederCount = -1;
  84.      tracker->leecherCount = -1;
  85.      tracker->downloadCount = -1;
  86. +    tracker->af = af;
  87.      return tracker;
  88.  }
  89.  
  90.  -345,8 +353,8 @@
  91.   */
  92.  typedef struct
  93.  {
  94. -    tr_ptrArray trackers; /* tr_tracker_item */
  95. -    tr_tracker_item * currentTracker;
  96. +    tr_ptrArray trackersArray[NUM_TR_AF_INET_TYPES]; /* tr_tracker_item */
  97. +    tr_tracker_item * currentTrackers[NUM_TR_AF_INET_TYPES];
  98.  
  99.      tr_torrent * tor;
  100.  
  101.  -366,7 +374,7 @@
  102.      /* unique lookup key */
  103.      int key;
  104.  
  105. -    int currentTrackerIndex;
  106. +    int currentTrackerIndexes[NUM_TR_AF_INET_TYPES];
  107.      int scrapeIntervalSec;
  108.      int announceIntervalSec;
  109.      int announceMinIntervalSec;
  110.  -376,9 +384,9 @@
  111.      int randOffset;
  112.      int lastAnnouncePeerCount;
  113.  
  114. -    tr_bool isRunning;
  115. -    tr_bool isAnnouncing;
  116. -    tr_bool isScraping;
  117. +    tr_bool isRunningArray[NUM_TR_AF_INET_TYPES];
  118. +    tr_bool isAnnouncingArray[NUM_TR_AF_INET_TYPES];
  119. +    tr_bool isScrapingArray[NUM_TR_AF_INET_TYPES];
  120.  
  121.      char lastAnnounceStr[128];
  122.      char lastScrapeStr[128];
  123.  -389,15 +397,18 @@
  124.  tierNew( tr_torrent * tor )
  125.  {
  126.      tr_tier * t;
  127. +   int i;
  128.      static int nextKey = 1;
  129.      const time_t now = time( NULL );
  130.  
  131.      t = tr_new0( tr_tier, 1 );
  132.      t->randOffset = tr_cryptoRandInt( 60 );
  133.      t->key = nextKey++;
  134. -    t->trackers = TR_PTR_ARRAY_INIT;
  135. -    t->currentTracker = NULL;
  136. -    t->currentTrackerIndex = -1;
  137. +   for( i = 0 ; i < NUM_TR_AF_INET_TYPES ; i++ ) {
  138. +       t->trackersArray[i] = TR_PTR_ARRAY_INIT;
  139. +       t->currentTrackers[i] = NULL;
  140. +       t->currentTrackerIndexes[i] = -1;
  141. +   }
  142.      t->scrapeIntervalSec = DEFAULT_SCRAPE_INTERVAL_SEC;
  143.      t->announceIntervalSec = DEFAULT_ANNOUNCE_INTERVAL_SEC;
  144.      t->announceMinIntervalSec = DEFAULT_ANNOUNCE_MIN_INTERVAL_SEC;
  145.  -411,17 +422,19 @@
  146.  tierFree( void * vtier )
  147.  {
  148.      tr_tier * tier = vtier;
  149. -    tr_ptrArrayDestruct( &tier->trackers, trackerFree );
  150. +   int i;
  151. +   for( i = 0 ; i < NUM_TR_AF_INET_TYPES ; i++ )
  152. +       tr_ptrArrayDestruct( &tier->trackersArray[i], trackerFree );
  153.      tr_free( tier );
  154.  }
  155.  
  156.  static void
  157. -tierIncrementTracker( tr_tier * tier )
  158. +tierIncrementTracker( tr_tier * tier, tr_address_type af )
  159.  {
  160. -    const int i = ( tier->currentTrackerIndex + 1 )
  161. -                        % tr_ptrArraySize( &tier->trackers );
  162. -    tier->currentTracker = tr_ptrArrayNth( &tier->trackers, i );
  163. -    tier->currentTrackerIndex = i;
  164. +    const int i = ( tier->currentTrackerIndexes[af] + 1 )
  165. +                   % tr_ptrArraySize( &tier->trackersArray[af] );
  166. +   tier->currentTrackers[af] = tr_ptrArrayNth( &tier->trackersArray[af], i );
  167. +   tier->currentTrackerIndexes[af] = i;
  168.  
  169.      /* reset some of the tier's fields */
  170.      tier->scrapeIntervalSec = DEFAULT_SCRAPE_INTERVAL_SEC;
  171.  -429,25 +442,26 @@
  172.      tier->announceMinIntervalSec = DEFAULT_ANNOUNCE_MIN_INTERVAL_SEC;
  173.      tier->retryAnnounceIntervalSec = FIRST_ANNOUNCE_RETRY_INTERVAL_SEC;
  174.      tier->retryScrapeIntervalSec = FIRST_SCRAPE_RETRY_INTERVAL_SEC;
  175. -    tier->isAnnouncing = FALSE;
  176. -    tier->isScraping = FALSE;
  177. +    tier->isAnnouncingArray[af] = FALSE;
  178. +    tier->isScrapingArray[af] = FALSE;
  179.      tier->lastAnnounceStartTime = 0;
  180.      tier->lastScrapeStartTime = 0;
  181.  }
  182.  
  183.  static void
  184. -tierAddTracker( tr_announcer * announcer,
  185. -                tr_tier      * tier,
  186. -                const char   * announce,
  187. -                const char   * scrape )
  188. +tierAddTracker( tr_announcer  * announcer,
  189. +                tr_tier       * tier,
  190. +                const char    * announce,
  191. +                const char    * scrape,
  192. +                tr_address_type af)
  193.  {
  194. -    tr_tracker_item * tracker = trackerNew( announcer, announce, scrape );
  195. +    tr_tracker_item * tracker = trackerNew( announcer, announce, scrape, af );
  196.  
  197. -    tr_ptrArrayAppend( &tier->trackers, tracker );
  198. -    dbgmsg( tier, "adding tracker %s", announce );
  199. +   tr_ptrArrayAppend( &tier->trackersArray[af], tracker );
  200.  
  201. -    if( !tier->currentTracker )
  202. -        tierIncrementTracker( tier );
  203. +   dbgmsg( tier, "adding tracker %s address family %d", announce, af );    
  204. +   if( !tier->currentTrackers[af] )
  205. +       tierIncrementTracker( tier, af );
  206.  }
  207.  
  208.  
  209.  -535,9 +549,9 @@
  210.  }
  211.  
  212.  static void
  213. -publishErrorMessageAndStop( tr_tier * tier, const char * msg )
  214. +publishErrorMessageAndStop( tr_tier * tier, tr_address_type af, const char * msg )
  215.  {
  216. -    tier->isRunning = FALSE;
  217. +    tier->isRunningArray[af] = FALSE;
  218.  
  219.      publishMessage( tier, msg, TR_TRACKER_ERROR );
  220.  }
  221.  -590,6 +604,8 @@
  222.  
  223.          walk += sizeof( tr_address ) + 2;
  224.          compactWalk += 6;
  225. +        
  226. +        tr_dbg("new v4 peer %s", tr_ntop_non_ts(&addr));
  227.      }
  228.  
  229.      publishNewPeers( tier, allAreSeeds, array, arrayLen );
  230.  -623,6 +639,8 @@
  231.          memcpy( walk, &addr, sizeof( addr ) );
  232.          memcpy( walk + sizeof( addr ), &port, 2 );
  233.          walk += sizeof( tr_address ) + 2;
  234. +        
  235. +        tr_dbg("new v6 peer %s", tr_ntop_non_ts(&addr));
  236.      }
  237.      publishNewPeers( tier, allAreSeeds, array, arrayLen );
  238.      tr_free( array );
  239.  -634,11 +652,12 @@
  240.  createAnnounceURL( const tr_announcer     * announcer,
  241.                     const tr_torrent       * torrent,
  242.                     const tr_tier          * tier,
  243. +                  tr_address_type          af,
  244.                     const char             * eventName )
  245.  {
  246.      const int isStopping = !strcmp( eventName, "stopped" );
  247.      const int numwant = isStopping ? 0 : NUMWANT;
  248. -    const tr_tracker_item  * tracker = tier->currentTracker;
  249. +    const tr_tracker_item  * tracker = tier->currentTrackers[af];
  250.      const char * ann = tracker->announce;
  251.      struct evbuffer * buf = evbuffer_new( );
  252.      char * ret;
  253.  -724,7 +743,11 @@
  254.              }
  255.  
  256.              tierAddTracker( announcer, tier, tor->info.trackers[i].announce,
  257. -                                             tor->info.trackers[i].scrape );
  258. +                                             tor->info.trackers[i].scrape,
  259. +                                            TR_AF_INET );
  260. +           tierAddTracker( announcer, tier, tor->info.trackers[i].announce,
  261. +                                            tor->info.trackers[i].scrape,
  262. +                                            TR_AF_INET6 );
  263.          }
  264.      }
  265.  
  266.  -750,7 +773,7 @@
  267.  static tr_bool
  268.  tierCanManualAnnounce( const tr_tier * tier )
  269.  {
  270. -    return tier->isRunning
  271. +    return ( tier->isRunningArray[TR_AF_INET] || tier->isRunningArray[TR_AF_INET6] )
  272.          && tier->manualAnnounceAllowedAt <= time( NULL );
  273.  }
  274.  
  275.  -787,7 +810,7 @@
  276.      n = tr_ptrArraySize( &tiers->tiers );
  277.      for( i=0; i<n; ++i ) {
  278.          tr_tier * tier = tr_ptrArrayNth( (tr_ptrArray*)&tiers->tiers, i );
  279. -        if( tier->isRunning )
  280. +        if( tier->isRunningArray[TR_AF_INET] || tier->isRunningArray[TR_AF_INET6] )
  281.              ret = MIN( ret, tier->manualAnnounceAllowedAt );
  282.      }
  283.  
  284.  -865,20 +888,22 @@
  285.  
  286.      if( tor->tiers )
  287.      {
  288. -        int i;
  289. +        int i, j;
  290.          const int n = tr_ptrArraySize( &tor->tiers->tiers );
  291.          for( i=0; i<n; ++i )
  292.          {
  293.              tr_tier * tier = tr_ptrArrayNth( &tor->tiers->tiers, i );
  294. -
  295. -            if( tier->isRunning )
  296. -            {
  297. -                struct stop_message * s = tr_new0( struct stop_message, 1 );
  298. -                s->up = tor->uploadedCur;
  299. -                s->down = tor->downloadedCur;
  300. -                s->url = createAnnounceURL( announcer, tor, tier, "stopped" );
  301. -                s->host = tier->currentTracker->host;
  302. -                tr_ptrArrayInsertSorted( &announcer->stops, s, compareStops );
  303. +          
  304. +           for( j = 0 ; j < NUM_TR_AF_INET_TYPES ; j++ ) {
  305. +               if( tier->isRunningArray[j] )
  306. +               {
  307. +                   struct stop_message * s = tr_new0( struct stop_message, 1 );
  308. +                   s->up = tor->uploadedCur;
  309. +                   s->down = tor->downloadedCur;
  310. +                   s->url = createAnnounceURL( announcer, tor, tier, j, "stopped" );
  311. +                   s->host = tier->currentTrackers[j]->host;
  312. +                   tr_ptrArrayInsertSorted( &announcer->stopsArray[j], s, compareStops );
  313. +               }
  314.              }
  315.          }
  316.  
  317.  -900,8 +925,10 @@
  318.  static tr_bool
  319.  tierIsNotResponding( const tr_tier * tier, const time_t now )
  320.  {
  321. -    return !tier->currentTracker
  322. -        || hostIsNotResponding( tier->currentTracker->host, now );
  323. +    return !tier->currentTrackers[TR_AF_INET]
  324. +        || hostIsNotResponding( tier->currentTrackers[TR_AF_INET]->host, now )
  325. +        || !tier->currentTrackers[TR_AF_INET6]
  326. +       || hostIsNotResponding( tier->currentTrackers[TR_AF_INET6]->host, now );
  327.  }
  328.  
  329.  static int
  330.  -992,10 +1019,11 @@
  331.  }
  332.  
  333.  static tr_bool
  334. -parseAnnounceResponse( tr_tier     * tier,
  335. -                       const char  * response,
  336. -                       size_t        responseLen,
  337. -                       tr_bool     * gotScrape )
  338. +parseAnnounceResponse( tr_tier         * tier,
  339. +                      tr_address_type   af,
  340. +                       const char      * response,
  341. +                       size_t            responseLen,
  342. +                       tr_bool         * gotScrape )
  343.  {
  344.      tr_benc benc;
  345.      tr_bool success = FALSE;
  346.  -1048,25 +1076,25 @@
  347.  
  348.          if( tr_bencDictFindStr( &benc, "tracker id", &str ) )
  349.          {
  350. -            tier->currentTracker->tracker_id = tr_strdup( str );
  351. +            tier->currentTrackers[af]->tracker_id = tr_strdup( str );
  352.          }
  353.  
  354.          if( tr_bencDictFindInt( &benc, "complete", &i ) )
  355.          {
  356.              ++scrapeFields;
  357. -            tier->currentTracker->seederCount = i;
  358. +            tier->currentTrackers[af]->seederCount = i;
  359.          }
  360.  
  361.          if( tr_bencDictFindInt( &benc, "incomplete", &i ) )
  362.          {
  363.              ++scrapeFields;
  364. -            tier->currentTracker->leecherCount = incomplete = i;
  365. +            tier->currentTrackers[af]->leecherCount = incomplete = i;
  366.          }
  367.  
  368.          if( tr_bencDictFindInt( &benc, "downloaded", &i ) )
  369.          {
  370.              ++scrapeFields;
  371. -            tier->currentTracker->downloadCount = i;
  372. +            tier->currentTrackers[af]->downloadCount = i;
  373.          }
  374.  
  375.          if( tr_bencDictFindRaw( &benc, "peers", &raw, &rawlen ) )
  376.  -1113,6 +1141,8 @@
  377.  
  378.      /** If the request succeeds, the value for tier's "isRunning" flag */
  379.      tr_bool isRunningOnSuccess;
  380. +  
  381. +   tr_address_type af;
  382.  };
  383.  
  384.  static void
  385.  -1128,14 +1158,15 @@
  386.      tr_bool gotScrape = FALSE;
  387.      tr_bool success = FALSE;
  388.      const time_t now = time ( NULL );
  389. +   tr_address_type af = data->af;
  390.  
  391.      if( announcer && tier )
  392.      {
  393.          tier->lastAnnouncePeerCount = 0;
  394.  
  395. -        if( tier->currentTracker->host )
  396. +        if( tier->currentTrackers[af]->host )
  397.          {
  398. -            tr_host * host = tier->currentTracker->host;
  399. +            tr_host * host = tier->currentTrackers[af]->host;
  400.              host->lastRequestTime = data->timeSent;
  401.              host->lastResponseInterval = now - data->timeSent;
  402.          }
  403.  -1143,7 +1174,7 @@
  404.          if( responseCode == HTTP_OK )
  405.          {
  406.              tier->lastAnnounceTime = now;
  407. -            success = parseAnnounceResponse( tier, response, responseLen, &gotScrape );
  408. +            success = parseAnnounceResponse( tier, af, response, responseLen, &gotScrape );
  409.              dbgmsg( tier, "success is %d", success );
  410.          }
  411.          else if( responseCode )
  412.  -1178,7 +1209,7 @@
  413.  
  414.      if( tier )
  415.      {
  416. -        tier->isAnnouncing = FALSE;
  417. +        tier->isAnnouncingArray[af] = FALSE;
  418.  
  419.          if( responseCode == 0 )
  420.          {
  421.  -1217,7 +1248,7 @@
  422.              /* The request could not be understood by the server due to
  423.               * malformed syntax. The client SHOULD NOT repeat the
  424.               * request without modifications. */
  425. -            publishErrorMessageAndStop( tier, _( "Tracker returned a 4xx message" ) );
  426. +            publishErrorMessageAndStop( tier, af, _( "Tracker returned a 4xx message" ) );
  427.              tier->manualAnnounceAllowedAt = ~(time_t)0;
  428.          }
  429.          else if( 500 <= responseCode && responseCode <= 599 )
  430.  -1242,10 +1273,10 @@
  431.          tier->lastAnnounceSucceeded = success;
  432.  
  433.          if( success )
  434. -            tier->isRunning = data->isRunningOnSuccess;
  435. +            tier->isRunningArray[af] = data->isRunningOnSuccess;
  436.  
  437.          if( !success )
  438. -            tierIncrementTracker( tier );
  439. +            tierIncrementTracker( tier, af );
  440.      }
  441.  
  442.      if( announcer != NULL )
  443.  -1286,29 +1317,33 @@
  444.      struct announce_data * data;
  445.      const tr_torrent * tor = tier->tor;
  446.      const time_t now = time( NULL );
  447. +   int i;
  448.  
  449. -    assert( !tier->isAnnouncing );
  450. +    assert( !tier->isAnnouncingArray[TR_AF_INET] || !tier->isAnnouncingArray[TR_AF_INET6] );
  451.  
  452. -    data = tr_new0( struct announce_data, 1 );
  453. -    data->torrentId = tr_torrentId( tor );
  454. -    data->tierId = tier->key;
  455. -    data->isRunningOnSuccess = tor->isRunning;
  456. -    data->timeSent = now;
  457. +   for( i = 0 ; i < NUM_TR_AF_INET_TYPES ; i++ ) {
  458. +       tier->isAnnouncingArray[i] = TRUE;
  459. +       tier->lastAnnounceStartTime = now;
  460. +       --announcer->announceSlotsAvailable;
  461.  
  462. -    url = createAnnounceURL( announcer, tor, tier, getAnnounceEvent( tier ) );
  463. +       data = tr_new0( struct announce_data, 1 );
  464. +       data->torrentId = tr_torrentId( tor );
  465. +       data->tierId = tier->key;
  466. +       data->isRunningOnSuccess = tor->isRunning;
  467. +       data->timeSent = now;
  468. +       data->af = i;
  469. +       url = createAnnounceURL( announcer, tor, tier, i, getAnnounceEvent( tier ) );
  470. +       tr_webRun( announcer->session, url, i, NULL, onAnnounceDone, data );
  471. +   }
  472.  
  473. -    tier->isAnnouncing = TRUE;
  474. -    tier->lastAnnounceStartTime = now;
  475. -    --announcer->announceSlotsAvailable;
  476. -    tr_webRun( announcer->session, url, NULL, onAnnounceDone, data );
  477. -
  478.      tr_free( url );
  479.  }
  480.  
  481.  static tr_bool
  482. -parseScrapeResponse( tr_tier     * tier,
  483. -                     const char  * response,
  484. -                     size_t        responseLen )
  485. +parseScrapeResponse( tr_tier         * tier,
  486. +                    tr_address_type   af,
  487. +                     const char      * response,
  488. +                     size_t            responseLen )
  489.  {
  490.      tr_bool success = FALSE;
  491.      tr_benc benc, *files;
  492.  -1330,16 +1365,16 @@
  493.              publishErrorClear( tier );
  494.  
  495.              if( ( tr_bencDictFindInt( val, "complete", &intVal ) ) )
  496. -                tier->currentTracker->seederCount = intVal;
  497. +                tier->currentTrackers[af]->seederCount = intVal;
  498.  
  499.              if( ( tr_bencDictFindInt( val, "incomplete", &intVal ) ) )
  500. -                tier->currentTracker->leecherCount = intVal;
  501. +                tier->currentTrackers[af]->leecherCount = intVal;
  502.  
  503.              if( ( tr_bencDictFindInt( val, "downloaded", &intVal ) ) )
  504. -                tier->currentTracker->downloadCount = intVal;
  505. +                tier->currentTrackers[af]->downloadCount = intVal;
  506.  
  507.              if( ( tr_bencDictFindInt( val, "downloaders", &intVal ) ) )
  508. -                tier->currentTracker->downloaderCount = intVal;
  509. +                tier->currentTrackers[af]->downloaderCount = intVal;
  510.  
  511.              if( tr_bencDictFindDict( val, "flags", &flags ) )
  512.                  if( ( tr_bencDictFindInt( flags, "min_request_interval", &intVal ) ) )
  513.  -1376,25 +1411,26 @@
  514.      tr_tier * tier = getTier( announcer, data->torrentId, data->tierId );
  515.      const time_t now = time( NULL );
  516.      tr_bool success = FALSE;
  517. -
  518. +   tr_address_type af = data->af;
  519. +  
  520.      if( announcer )
  521.          ++announcer->scrapeSlotsAvailable;
  522.  
  523.      if( announcer && tier )
  524.      {
  525. -        tier->isScraping = FALSE;
  526. +        tier->isScrapingArray[af] = FALSE;
  527.          tier->lastScrapeTime = now;
  528.      
  529. -        if( tier->currentTracker->host )
  530. +        if( tier->currentTrackers[af]->host )
  531.          {
  532. -            tr_host * host = tier->currentTracker->host;
  533. +            tr_host * host = tier->currentTrackers[af]->host;
  534.              host->lastRequestTime = data->timeSent;
  535.              host->lastResponseInterval = now - data->timeSent;
  536.          }
  537.  
  538.          if( responseCode == HTTP_OK )
  539.          {
  540. -            success = parseScrapeResponse( tier, response, responseLen );
  541. +            success = parseScrapeResponse( tier, af, response, responseLen );
  542.          }
  543.  
  544.          if( 200 <= responseCode && responseCode <= 299 )
  545.  -1444,54 +1480,64 @@
  546.      struct evbuffer * buf;
  547.      struct announce_data * data;
  548.      const time_t now = time( NULL );
  549. +   int i;
  550.  
  551.      assert( tier );
  552. -    assert( !tier->isScraping );
  553. -    assert( tier->currentTracker != NULL );
  554. +    assert( !tier->isScrapingArray[TR_AF_INET] || !tier->isScrapingArray[TR_AF_INET6] );
  555. +    assert( tier->currentTrackers[TR_AF_INET] != NULL );
  556. +   assert( tier->currentTrackers[TR_AF_INET6] != NULL );
  557.      assert( tr_isTorrent( tier->tor ) );
  558. +  
  559. +   for( i = 0 ; i < NUM_TR_AF_INET_TYPES ; i++ ) {
  560. +       tier->isScrapingArray[i] = TRUE;
  561. +       tier->lastScrapeStartTime = now;
  562. +       --announcer->scrapeSlotsAvailable;
  563. +  
  564. +       data = tr_new0( struct announce_data, 1 );
  565. +       data->torrentId = tr_torrentId( tier->tor );
  566. +       data->tierId = tier->key;
  567.  
  568. -    data = tr_new0( struct announce_data, 1 );
  569. -    data->torrentId = tr_torrentId( tier->tor );
  570. -    data->tierId = tier->key;
  571. +       scrape = tier->currentTrackers[i]->scrape;
  572.  
  573. -    scrape = tier->currentTracker->scrape;
  574. +       buf = evbuffer_new( );
  575. +       evbuffer_add_printf( buf, "%s%cinfo_hash=%s",
  576. +                            scrape,
  577. +                            strchr( scrape, '?' ) ? '&' : '?',
  578. +                            tier->tor->info.hashEscaped );
  579.  
  580. -    buf = evbuffer_new( );
  581. -    evbuffer_add_printf( buf, "%s%cinfo_hash=%s",
  582. -                         scrape,
  583. -                         strchr( scrape, '?' ) ? '&' : '?',
  584. -                         tier->tor->info.hashEscaped );
  585. +       dbgmsg( tier, "scraping \"%s\"", (const char*)EVBUFFER_DATA(buf) );
  586. +       tr_webRun( announcer->session, (const char*)EVBUFFER_DATA(buf), i, NULL, onScrapeDone, data );
  587.  
  588. -    tier->isScraping = TRUE;
  589. -    tier->lastScrapeStartTime = now;
  590. -    --announcer->scrapeSlotsAvailable;
  591. -    dbgmsg( tier, "scraping \"%s\"", (const char*)EVBUFFER_DATA(buf) );
  592. -    tr_webRun( announcer->session, (const char*)EVBUFFER_DATA(buf), NULL, onScrapeDone, data );
  593. -
  594. -    evbuffer_free( buf );
  595. +       evbuffer_free( buf );
  596. +   }
  597.  }
  598.  
  599.  static void
  600.  flushCloseMessages( tr_announcer * announcer )
  601.  {
  602. -    int i;
  603. -    const int n = tr_ptrArraySize( &announcer->stops );
  604. +    int i, j;
  605. +  
  606. +   for( j = 0 ; j < NUM_TR_AF_INET_TYPES ; j++ ) {
  607. +       const int n = tr_ptrArraySize( &announcer->stopsArray[j] );
  608.  
  609. -    for( i=0; i<n; ++i )
  610. -    {
  611. -        struct stop_message * stop = tr_ptrArrayNth( &announcer->stops, i );
  612. -        tr_webRun( announcer->session, stop->url, NULL, NULL, NULL );
  613. -        stopFree( stop );
  614. -    }
  615. +       for( i=0; i<n; ++i )
  616. +       {
  617. +           struct stop_message * stop = tr_ptrArrayNth( &announcer->stopsArray[j], i );
  618. +           tr_webRun( announcer->session, stop->url, j, NULL, NULL, NULL );
  619. +           stopFree( stop );
  620. +       }
  621.  
  622. -    tr_ptrArrayClear( &announcer->stops );
  623. +       tr_ptrArrayClear( &announcer->stopsArray[j] );
  624. +   }
  625.  }
  626.  
  627.  static tr_bool
  628.  tierNeedsToAnnounce( const tr_tier * tier, const time_t now )
  629.  {
  630. -    return !tier->isAnnouncing
  631. -        && !tier->isScraping
  632. +    return !tier->isAnnouncingArray[TR_AF_INET]
  633. +       && !tier->isAnnouncingArray[TR_AF_INET6]
  634. +        && !tier->isScrapingArray[TR_AF_INET]
  635. +       && !tier->isScrapingArray[TR_AF_INET6]
  636.          && ( tier->announceEvent != NULL )
  637.          && ( tier->announceAt <= now );
  638.  }
  639.  -1499,10 +1545,13 @@
  640.  static tr_bool
  641.  tierNeedsToScrape( const tr_tier * tier, const time_t now )
  642.  {
  643. -    return !tier->isScraping
  644. +    return !tier->isScrapingArray[TR_AF_INET]
  645. +       && !tier->isScrapingArray[TR_AF_INET6]
  646.          && ( tier->scrapeAt <= now )
  647. -        && ( tier->currentTracker != NULL )
  648. -        && ( tier->currentTracker->scrape != NULL );
  649. +        && ( ( ( tier->currentTrackers[TR_AF_INET] != NULL )
  650. +              && ( tier->currentTrackers[TR_AF_INET]->scrape != NULL ) )
  651. +            || ( ( tier->currentTrackers[TR_AF_INET6] != NULL )
  652. +                 && ( tier->currentTrackers[TR_AF_INET6]->scrape != NULL ) ) );
  653.  }
  654.  
  655.  static void
  656.  -1585,7 +1634,7 @@
  657.  tr_announcerStats( const tr_torrent * torrent,
  658.                     int              * setmeTrackerCount )
  659.  {
  660. -    int i;
  661. +    int i, k;
  662.      int n;
  663.      int out = 0;
  664.      int tierCount;
  665.  -1596,7 +1645,8 @@
  666.      /* count the trackers... */
  667.      for( i=n=0, tierCount=tr_ptrArraySize( &torrent->tiers->tiers ); i<tierCount; ++i ) {
  668.          const tr_tier * tier = tr_ptrArrayNth( &torrent->tiers->tiers, i );
  669. -        n += tr_ptrArraySize( &tier->trackers );
  670. +       for( k = 0 ; k < NUM_TR_AF_INET_TYPES ; k++ )
  671. +           n += tr_ptrArraySize( &tier->trackersArray[k] );
  672.      }
  673.  
  674.      /* alloc the stats */
  675.  -1608,42 +1658,46 @@
  676.      {
  677.          int j;
  678.          const tr_tier * tier = tr_ptrArrayNth( &torrent->tiers->tiers, i );
  679. -        n = tr_ptrArraySize( &tier->trackers );
  680. -        for( j=0; j<n; ++j )
  681. -        {
  682. -            const tr_tracker_item * tracker = tr_ptrArrayNth( (tr_ptrArray*)&tier->trackers, j );
  683. -            tr_tracker_stat * st = ret + out++;
  684. +       for( k = 0 ; k < NUM_TR_AF_INET_TYPES ; k++ ) {
  685. +           n = tr_ptrArraySize( &tier->trackersArray[k] );
  686. +           for( j=0; j<n; ++j )
  687. +           {
  688. +               const tr_tracker_item * tracker = tr_ptrArrayNth( (tr_ptrArray*)&tier->trackersArray[k], j );
  689. +               tr_tracker_stat * st = ret + out++;
  690.  
  691. -            tr_strlcpy( st->host, tracker->host->name, sizeof( st->host ) );
  692. -            tr_strlcpy( st->announce, tracker->announce, sizeof( st->announce ) );
  693. -            st->tier = i + 1;
  694. -            st->isActive = tracker == tier->currentTracker;
  695. -            st->lastScrapeStartTime = tier->lastScrapeStartTime;
  696. -            if(( st->hasScraped = tier->lastScrapeTime != 0 )) {
  697. -                st->lastScrapeTime = tier->lastScrapeTime;
  698. -                st->lastScrapeSucceeded = tier->lastScrapeSucceeded;
  699. -                tr_strlcpy( st->lastScrapeResult, tier->lastScrapeStr, sizeof( st->lastScrapeResult ) );
  700. -            }
  701. -            st->isScraping = tier->isScraping;
  702. -            if(( st->willScrape = st->isActive && !tier->isScraping )) {
  703. -                st->nextScrapeTime = tier->scrapeAt;
  704. -            }
  705. -            st->lastAnnounceStartTime = tier->lastAnnounceStartTime;
  706. -            if(( st->hasAnnounced = tier->lastAnnounceTime != 0 )) {
  707. -                st->lastAnnounceTime = tier->lastAnnounceTime;
  708. -                tr_strlcpy( st->lastAnnounceResult, tier->lastAnnounceStr, sizeof( st->lastAnnounceResult ) );
  709. -                if(( st->lastAnnounceSucceeded = tier->lastAnnounceSucceeded )) {
  710. -                    st->lastAnnouncePeerCount = tier->lastAnnouncePeerCount;
  711. -                }
  712. -            }
  713. -            st->isAnnouncing = tier->isAnnouncing;
  714. -            if(( st->willAnnounce = torrent->isRunning && !tier->isAnnouncing )) {
  715. -                st->nextAnnounceTime = tier->announceAt;
  716. -            }
  717. -            st->seederCount = tracker->seederCount;
  718. -            st->leecherCount = tracker->leecherCount;
  719. -            st->downloadCount = tracker->downloadCount;
  720. -        }
  721. +               tr_strlcpy( st->host, tracker->host->name, sizeof( st->host ) );
  722. +               tr_strlcpy( st->announce, tracker->announce, sizeof( st->announce ) );
  723. +               st->tier = i + 1;
  724. +               st->isActive = tracker == tier->currentTrackers[k];
  725. +               st->lastScrapeStartTime = tier->lastScrapeStartTime;
  726. +               if(( st->hasScraped = tier->lastScrapeTime != 0 )) {
  727. +                   st->lastScrapeTime = tier->lastScrapeTime;
  728. +                   st->lastScrapeSucceeded = tier->lastScrapeSucceeded;
  729. +                   tr_strlcpy( st->lastScrapeResult, tier->lastScrapeStr, sizeof( st->lastScrapeResult ) );
  730. +               }
  731. +               st->isScraping = tier->isScrapingArray[k];
  732. +               if(( st->willScrape = st->isActive && !tier->isScrapingArray[k] )) {
  733. +                   st->nextScrapeTime = tier->scrapeAt;
  734. +               }
  735. +               st->lastAnnounceStartTime = tier->lastAnnounceStartTime;
  736. +               if(( st->hasAnnounced = tier->lastAnnounceTime != 0 )) {
  737. +                   st->lastAnnounceTime = tier->lastAnnounceTime;
  738. +                   tr_strlcpy( st->lastAnnounceResult, tier->lastAnnounceStr, sizeof( st->lastAnnounceResult ) );
  739. +                   if(( st->lastAnnounceSucceeded = tier->lastAnnounceSucceeded )) {
  740. +                       st->lastAnnouncePeerCount = tier->lastAnnouncePeerCount;
  741. +                   }
  742. +               }
  743. +               st->isAnnouncing = tier->isAnnouncingArray[k];
  744. +               if(( st->willAnnounce = torrent->isRunning && !tier->isAnnouncingArray[k] )) {
  745. +                   st->nextAnnounceTime = tier->announceAt;
  746. +               }
  747. +               st->seederCount = tracker->seederCount;
  748. +               st->leecherCount = tracker->leecherCount;
  749. +               st->downloadCount = tracker->downloadCount;
  750. +              
  751. +               st->af = tracker->af;
  752. +           }
  753. +       }
  754.      }
  755.  
  756.      return ret;
  757. Index: libtransmission/rpcimpl.c
  758. ===================================================================
  759. --- libtransmission/rpcimpl.c   (revision 9219)
  760. +++ libtransmission/rpcimpl.c   (working copy)
  761.  -859,7 +859,7 @@
  762.  {
  763.      const int port = tr_sessionGetPeerPort( session );
  764.      char * url = tr_strdup_printf( "http://portcheck.transmissionbt.com/%d", port );
  765. -    tr_webRun( session, url, NULL, portTested, idle_data );
  766. +    tr_webRun( session, url, TR_AF_UNSPEC, NULL, portTested, idle_data );
  767.      tr_free( url );
  768.      return NULL;
  769.  }
  770.  -916,7 +916,7 @@
  771.                   struct tr_rpc_idle_data  * idle_data )
  772.  {
  773.      const char * url = "http://update.transmissionbt.com/level1";
  774. -    tr_webRun( session, url, NULL, gotNewBlocklist, idle_data );
  775. +    tr_webRun( session, url, TR_AF_UNSPEC, NULL, gotNewBlocklist, idle_data );
  776.      return NULL;
  777.  }
  778.  
  779.  -1093,7 +1093,7 @@
  780.              struct add_torrent_idle_data * d = tr_new0( struct add_torrent_idle_data, 1 );
  781.              d->data = idle_data;
  782.              d->ctor = ctor;
  783. -            tr_webRun( session, filename, NULL, gotMetadataFromURL, d );
  784. +            tr_webRun( session, filename, TR_AF_UNSPEC, NULL, gotMetadataFromURL, d );
  785.          }
  786.          else
  787.          {
  788. Index: libtransmission/webseed.c
  789. ===================================================================
  790. --- libtransmission/webseed.c   (revision 9219)
  791. +++ libtransmission/webseed.c   (working copy)
  792.  -213,7 +213,7 @@
  793.  /*fprintf( stderr, "url is [%s]\n", url );*/
  794.          range = tr_strdup_printf( "%"PRIu64"-%"PRIu64, fileOffset, fileOffset + thisPass - 1 );
  795.  /*fprintf( stderr, "range is [%s] ... we want %lu total, we have %lu, so %lu are left, and we're asking for %lu this time\n", range, (unsigned long)w->byteCount, (unsigned long)have, (unsigned long)left, (unsigned long)thisPass );*/
  796. -        tr_webRun( w->session, url, range, webResponseFunc, w );
  797. +        tr_webRun( w->session, url, TR_AF_UNSPEC, range, webResponseFunc, w );
  798.          tr_free( range );
  799.          tr_free( url );
  800.      }
  801. Index: libtransmission/transmission.h
  802. ===================================================================
  803. --- libtransmission/transmission.h      (revision 9219)
  804. +++ libtransmission/transmission.h      (working copy)
  805.  -103,6 +103,15 @@
  806.      TR_ENCRYPTION_REQUIRED
  807.  }
  808.  tr_encryption_mode;
  809. +    
  810. +typedef enum tr_address_type
  811. +{
  812. +    TR_AF_INET,
  813. +    TR_AF_INET6,
  814. +    NUM_TR_AF_INET_TYPES,
  815. +    TR_AF_UNSPEC /* keep this after the NUM_ entry since it's not really an AF */
  816. +}
  817. +tr_address_type;
  818.  
  819.  
  820.  /***
  821.  -1315,6 +1324,9 @@
  822.  
  823.      /* true if we're not scraping now but will at nextScrapeTime */
  824.      tr_bool willScrape;
  825. +    
  826. +    /* address family (ipv4/ipv6) of this tracker */
  827. +    tr_address_type af;
  828.  }
  829.  tr_tracker_stat;
  830.  
  831. Index: libtransmission/web.c
  832. ===================================================================
  833. --- libtransmission/web.c       (revision 9219)
  834. +++ libtransmission/web.c       (working copy)
  835.  -156,6 +156,7 @@
  836.      tr_session * session;
  837.      tr_web_done_func * done_func;
  838.      void * done_func_user_data;
  839. +   tr_address_type af; /* address family */
  840.  };
  841.  
  842.  static size_t
  843.  -209,7 +210,12 @@
  844.              tr_free( str );
  845.          }
  846.  
  847. -        curl_easy_setopt( easy, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );
  848. +       if( task->af == TR_AF_INET )
  849. +           curl_easy_setopt( easy, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );
  850. +       else if( task->af == TR_AF_INET6 )
  851. +           curl_easy_setopt( easy, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6 );
  852. +       else /* TR_AF_UNSPEC */
  853. +           curl_easy_setopt( easy, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER );
  854.  
  855.          /* set a time limit for announces & scrapes */
  856.          if( strstr( task->url, "scrape" ) != NULL )
  857.  -499,6 +505,7 @@
  858.  void
  859.  tr_webRun( tr_session         * session,
  860.             const char         * url,
  861. +          tr_address_type      af,
  862.             const char         * range,
  863.             tr_web_done_func     done_func,
  864.             void               * done_func_user_data )
  865.  -516,6 +523,7 @@
  866.          task->done_func_user_data = done_func_user_data;
  867.          task->tag = ++tag;
  868.          task->response = evbuffer_new( );
  869. +       task->af = af;
  870.  
  871.          tr_runInEventThread( session, addTask, task );
  872.      }
  873. Index: libtransmission/web.h
  874. ===================================================================
  875. --- libtransmission/web.h       (revision 9219)
  876. +++ libtransmission/web.h       (working copy)
  877.  -29,6 +29,7 @@
  878.  
  879.  void         tr_webRun( tr_session        * session,
  880.                          const char        * url,
  881. +                       tr_address_type     af,
  882.                          const char        * range,
  883.                          tr_web_done_func    done_func,
  884.                          void              * done_func_user_data );
  885. Index: libtransmission/net.h
  886. ===================================================================
  887. --- libtransmission/net.h       (revision 9219)
  888. +++ libtransmission/net.h       (working copy)
  889.  -58,14 +58,6 @@
  890.  
  891.  struct tr_session;
  892.  
  893. -typedef enum tr_address_type
  894. -{
  895. -    TR_AF_INET,
  896. -    TR_AF_INET6,
  897. -    NUM_TR_AF_INET_TYPES
  898. -}
  899. -tr_address_type;
  900. -
  901.  typedef struct tr_address
  902.  {
  903.      tr_address_type type;
  904. Index: macosx/TrackerCell.m
  905. ===================================================================
  906. --- macosx/TrackerCell.m        (revision 9219)
  907. +++ macosx/TrackerCell.m        (working copy)
  908.  -295,7 +295,8 @@
  909.  
  910.  - (NSAttributedString *) attributedName
  911.  {
  912. -    NSString * name = [(TrackerNode *)[self objectValue] host];
  913. +    TrackerNode * node = [self objectValue];
  914. +    NSString * name = [NSString stringWithFormat:@"%@ (%@)", [node host], [node addressFamily]];
  915.      return [[[NSAttributedString alloc] initWithString: name attributes: fNameAttributes] autorelease];
  916.  }
  917.  
  918. Index: macosx/TrackerNode.h
  919. ===================================================================
  920. --- macosx/TrackerNode.h        (revision 9219)
  921. +++ macosx/TrackerNode.h        (working copy)
  922.  -33,6 +33,7 @@
  923.  - (id) initWithTrackerStat: (tr_tracker_stat *) stat;
  924.  
  925.  - (NSString *) host;
  926. +- (NSString *) addressFamily;
  927.  - (NSString *) fullAnnounceAddress;
  928.  
  929.  - (NSInteger) totalSeeders;
  930. Index: macosx/TrackerNode.m
  931. ===================================================================
  932. --- macosx/TrackerNode.m        (revision 9219)
  933. +++ macosx/TrackerNode.m        (working copy)
  934.  -49,6 +49,15 @@
  935.      return [NSString stringWithUTF8String: fStat.host];
  936.  }
  937.  
  938. +- (NSString *) addressFamily
  939. +{
  940. +    if( fStat.af == TR_AF_INET )
  941. +        return @"IPv4";
  942. +    if( fStat.af == TR_AF_INET6 )
  943. +        return @"IPv6";
  944. +    return @"?";
  945. +}
  946. +
  947.  - (NSString *) fullAnnounceAddress
  948.  {
  949.      return [NSString stringWithUTF8String: fStat.announce];