Changeset 11784


Ignore:
Timestamp:
Jan 29, 2011, 7:04:02 PM (11 years ago)
Author:
jordan
Message:

(trunk libT) "Announce is Queued" but torrent doesn't announce itself to trackers -- simplify http response code handling

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/announcer.c

    r11751 r11784  
    1313#include <assert.h>
    1414#include <limits.h>
     15#include <math.h> /* powl() */
    1516
    1617#include <event2/buffer.h>
     
    605606{
    606607    publishMessage( tier, NULL, TR_TRACKER_ERROR_CLEAR );
    607 }
    608 
    609 static void
    610 publishErrorMessageAndStop( tr_tier * tier, const char * msg )
    611 {
    612     tier->isRunning = FALSE;
    613 
    614     publishMessage( tier, msg, TR_TRACKER_ERROR );
    615608}
    616609
     
    10971090getRetryInterval( const tr_tracker_item * t )
    10981091{
    1099     int minutes;
    1100     const int jitter_seconds = tr_cryptoWeakRandInt( 120 );
    1101 
    1102     switch( t->consecutiveAnnounceFailures ) {
    1103         case 0:  minutes =  0; break;
    1104         case 1:  minutes =  1; break;
    1105         case 2:  minutes =  2; break;
    1106         case 3:  minutes =  4; break;
    1107         case 4:  minutes =  8; break;
    1108         case 5:  minutes = 16; break;
    1109         default: minutes = 32; break;
    1110     }
    1111 
    1112     return ( minutes * 60 ) + jitter_seconds;
     1092    const int jitter_seconds = tr_cryptoWeakRandInt( 60 );
     1093    const int minutes = powl( t->consecutiveAnnounceFailures, 2 );
     1094    return ( MIN( minutes, 128 ) * 60 ) + jitter_seconds;
    11131095}
    11141096
     
    13121294    struct announce_data * data = vdata;
    13131295    tr_tier * tier = getTier( announcer, data->torrentId, data->tierId );
    1314     tr_bool gotScrape = FALSE;
    1315     tr_bool success = FALSE;
    1316     const time_t now = time ( NULL );
     1296    const time_t now = tr_time( );
    13171297    const char * announceEvent = data->event;
    1318     const tr_bool isStopped = !strcmp( announceEvent, "stopped" );
    1319 
    1320     if( announcer && tier )
     1298
     1299    if( tier )
    13211300    {
    1322         if( tier->currentTracker->host )
    1323         {
    1324             tr_host * host = tier->currentTracker->host;
    1325             host->lastRequestTime = data->timeSent;
    1326             host->lastResponseInterval = now - data->timeSent;
    1327         }
     1301        tr_tracker_item * tracker;
    13281302
    13291303        tier->lastAnnounceTime = now;
     1304        tier->lastAnnounceTimedOut = responseCode == 0;
     1305        tier->lastAnnounceSucceeded = FALSE;
     1306        tier->isAnnouncing = FALSE;
     1307        tier->manualAnnounceAllowedAt = now + tier->announceMinIntervalSec;
     1308
     1309        if(( tracker = tier->currentTracker ))
     1310        {
     1311            ++tracker->consecutiveAnnounceFailures;
     1312
     1313            if( tracker->host )
     1314            {
     1315                tracker->host->lastRequestTime = data->timeSent;
     1316                tracker->host->lastResponseInterval = now - data->timeSent;
     1317            }
     1318        }
    13301319
    13311320        if( responseCode == HTTP_OK )
    13321321        {
    1333             tier->currentTracker->consecutiveAnnounceFailures = 0;
    1334             success = parseAnnounceResponse( tier, response, responseLen, &gotScrape );
    1335             dbgmsg( tier, "success is %d", success );
     1322            tr_bool gotScrape;
     1323            const tr_bool isStopped = !strcmp( announceEvent, "stopped" );
     1324
     1325            if( parseAnnounceResponse( tier, response, responseLen, &gotScrape ) )
     1326            {
     1327                tier->lastAnnounceSucceeded = TRUE;
     1328                tier->isRunning = data->isRunningOnSuccess;
     1329
     1330                if(( tracker = tier->currentTracker ))
     1331                {
     1332                    tracker->consecutiveAnnounceFailures = 0;
     1333   
     1334                    if( tracker->host )
     1335                        tracker->host->lastSuccessfulRequest = now;
     1336                }
     1337
     1338                if( gotScrape )
     1339                {
     1340                    tier->lastScrapeTime = now;
     1341                    tier->lastScrapeSucceeded = TRUE;
     1342                    tier->scrapeAt = now + tier->scrapeIntervalSec;
     1343                }
     1344            }
    13361345
    13371346            if( isStopped )
     
    13441353                tier->byteCounts[ TR_ANN_CORRUPT ] = 0;
    13451354            }
    1346         }
    1347         else if( responseCode )
    1348         {
    1349             /* %1$ld - http status code, such as 404
    1350              * %2$s - human-readable explanation of the http status code */
    1351             char * buf = tr_strdup_printf(
    1352                 _( "tracker gave HTTP Response Code %1$ld (%2$s)" ),
    1353                 responseCode,
    1354                 tr_webGetResponseStr( responseCode ) );
    1355 
    1356             tr_strlcpy( tier->lastAnnounceStr, buf,
    1357                         sizeof( tier->lastAnnounceStr ) );
    1358 
    1359             ++tier->currentTracker->consecutiveAnnounceFailures;
    1360 
    1361             /* if the response is serious, *and* if the response may require
    1362              * human intervention, then notify the user... otherwise just log it */
    1363             if( responseCode >= 400 )
    1364                 if( tr_torrentIsPrivate( tier->tor ) || ( tier->tor->info.trackerCount < 2 ) )
    1365                     publishWarning( tier, buf );
    1366             tr_torinf( tier->tor, "%s", buf );
    1367             dbgmsg( tier, "%s", buf );
    1368 
    1369             tr_free( buf );
    1370         }
    1371         else
    1372         {
    1373             tr_strlcpy( tier->lastAnnounceStr,
    1374                         _( "tracker did not respond" ),
    1375                         sizeof( tier->lastAnnounceStr ) );
    1376             dbgmsg( tier, "%s", tier->lastAnnounceStr );
    1377         }
    1378     }
    1379 
    1380     if( tier )
    1381     {
    1382         tier->isAnnouncing = FALSE;
    1383         tier->manualAnnounceAllowedAt = now + tier->announceMinIntervalSec;
    1384 
    1385         if( responseCode == 0 )
    1386         {
    1387             const int interval = getRetryInterval( tier->currentTracker );
    1388             dbgmsg( tier, "No response from tracker... retrying in %d seconds.", interval );
    1389             tierAddAnnounce( tier, announceEvent, now + interval );
    1390         }
    1391         else if( 200 <= responseCode && responseCode <= 299 )
    1392         {
    1393             const int interval = tier->announceIntervalSec;
    1394             dbgmsg( tier, "request succeeded. reannouncing in %d seconds", interval );
    1395 
    1396             if( gotScrape )
    1397             {
    1398                 tier->lastScrapeTime = now;
    1399                 tier->lastScrapeSucceeded = 1;
    1400                 tier->scrapeAt = now + tier->scrapeIntervalSec;
    1401             }
    1402 
    1403             /* if we're running and the queue is empty, add the next update */
     1355
    14041356            if( !isStopped && !tr_ptrArraySize( &tier->announceEvents ) )
    14051357            {
     1358                /* the queue is empty, so enqueue a perodic update */
     1359                const int interval = tier->announceIntervalSec;
     1360                dbgmsg( tier, "Sending periodic reannounce in %d seconds", interval );
    14061361                tierAddAnnounce( tier, "", now + interval );
    14071362            }
    14081363        }
    1409         else if( 300 <= responseCode && responseCode <= 399 )
    1410         {
    1411             /* how did this get here?  libcurl handles this */
    1412             const int interval = 5;
    1413             dbgmsg( tier, "got a redirect. retrying in %d seconds", interval );
     1364        else
     1365        {
     1366            int interval;
     1367
     1368            if( !responseCode )
     1369                tr_strlcpy( tier->lastAnnounceStr,
     1370                            _( "Tracker did not respond" ),
     1371                            sizeof( tier->lastAnnounceStr ) );
     1372            else {
     1373                /* %1$ld - http status code, such as 404
     1374                 * %2$s - human-readable explanation of the http status code */
     1375                tr_snprintf( tier->lastAnnounceStr, sizeof( tier->lastAnnounceStr ),
     1376                             _( "Tracker gave HTTP response code %1$ld (%2$s)" ),
     1377                             responseCode,
     1378                             tr_webGetResponseStr( responseCode ) );
     1379                if( responseCode >= 400 )
     1380                    if( tr_torrentIsPrivate( tier->tor ) || ( tier->tor->info.trackerCount == 1 ) )
     1381                        publishWarning( tier, tier->lastAnnounceStr );
     1382            }
     1383            dbgmsg( tier, "%s", tier->lastAnnounceStr );
     1384            tr_torinf( tier->tor, "%s", tier->lastAnnounceStr );
     1385
     1386            tierIncrementTracker( tier );
     1387
     1388            /* schedule the next announce */
     1389            interval = getRetryInterval( tier->currentTracker );
     1390            dbgmsg( tier, "Retrying announce in %d seconds.", interval );
    14141391            tierAddAnnounce( tier, announceEvent, now + interval );
    14151392        }
    1416         else if( ( responseCode == 404 ) || ( 500 <= responseCode && responseCode <= 599 ) )
    1417         {
    1418             /* 404: The requested resource could not be found but may be
    1419              * available again in the future. Subsequent requests by
    1420              * the client are permissible. */
    1421 
    1422             /* 5xx: indicate cases in which the server is aware that it
    1423              * has erred or is incapable of performing the request.
    1424              * So we pause a bit and try again. */
    1425 
    1426             tierAddAnnounce( tier, announceEvent, now + getRetryInterval( tier->currentTracker ) );
    1427         }
    1428         else if( 400 <= responseCode && responseCode <= 499 )
    1429         {
    1430             /* The request could not be understood by the server due to
    1431              * malformed syntax. The client SHOULD NOT repeat the
    1432              * request without modifications. */
    1433             if( tr_torrentIsPrivate( tier->tor ) || ( tier->tor->info.trackerCount < 2 ) )
    1434                 publishErrorMessageAndStop( tier, _( "Tracker returned a 4xx message" ) );
    1435             tier->announceAt = 0;
    1436             tier->manualAnnounceAllowedAt = ~(time_t)0;
    1437         }
    1438         else
    1439         {
    1440             /* WTF did we get?? */
    1441             const int interval = 120;
    1442             dbgmsg( tier, "Invalid response from tracker... retrying in two minutes." );
    1443             tierAddAnnounce( tier, announceEvent, now + interval );
    1444         }
    1445 
    1446         tier->lastAnnounceSucceeded = success;
    1447         tier->lastAnnounceTimedOut = responseCode == 0;
    1448 
    1449         if( success )
    1450         {
    1451             tier->isRunning = data->isRunningOnSuccess;
    1452 
    1453             if( tier->currentTracker->host )
    1454                 tier->currentTracker->host->lastSuccessfulRequest = now;
    1455         }
    1456         else if( responseCode != HTTP_OK )
    1457         {
    1458             tierIncrementTracker( tier );
    1459 
    1460             tr_ptrArrayInsert( &tier->announceEvents, (void*)announceEvent, 0 );
    1461         }
    1462     }
    1463 
    1464     if( announcer != NULL )
    1465     {
     1393    }
     1394
     1395    if( announcer )
    14661396        ++announcer->slotsAvailable;
    1467     }
    14681397
    14691398    tr_free( data );
Note: See TracChangeset for help on using the changeset viewer.