Changeset 10150


Ignore:
Timestamp:
Feb 10, 2010, 2:59:15 AM (12 years ago)
Author:
charles
Message:

(trunk libT) fix 1.82 memory corruption error reported by john doe

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/announcer.c

    r10149 r10150  
    352352    uint64_t byteCounts[3];
    353353
     354    tr_ptrArray announceEvents; /* const char* */
     355
    354356    tr_ptrArray trackers; /* tr_tracker_item */
    355357    tr_tracker_item * currentTracker;
     
    369371
    370372    time_t announceAt;
    371     const char * announceEvent;
     373    //const char * announceEvent;
    372374
    373375    /* unique lookup key */
     
    399401    t = tr_new0( tr_tier, 1 );
    400402    t->key = nextKey++;
     403    t->announceEvents = TR_PTR_ARRAY_INIT;
    401404    t->trackers = TR_PTR_ARRAY_INIT;
    402405    t->currentTracker = NULL;
     
    416419    tr_tier * tier = vtier;
    417420    tr_ptrArrayDestruct( &tier->trackers, trackerFree );
     421    tr_ptrArrayDestruct( &tier->announceEvents, NULL );
    418422    tr_free( tier );
    419423}
     
    862866
    863867static void
    864 tierClearNextAnnounce( tr_tier * tier )
    865 {
    866     tier->announceAt = 0;
    867     tier->announceEvent = NULL;
    868     dbgmsg( tier, "cleared out announceEvent -- no announces pending." );
    869 }
    870 
    871 static void
    872 tierSetNextAnnounce( tr_tier * tier, const char * announceEvent, time_t announceAt )
     868tierAddAnnounce( tr_tier * tier, const char * announceEvent, time_t announceAt )
    873869{
    874870    assert( tier != NULL );
    875     assert( announceEvent != NULL );
    876 
    877     if( !strcmp( announceEvent, "manual" ) && !tierCanManualAnnounce( tier ) )
    878         return;
    879 
     871    assert( event != NULL );
     872
     873    tr_ptrArrayAppend( &tier->announceEvents, (void*)announceEvent );
    880874    tier->announceAt = announceAt;
    881     tier->announceEvent = announceEvent;
    882     dbgmsg( tier, "next announce event is \"%s\" in %d seconds\n", announceEvent, (int)difftime(announceAt,time(NULL)) );
    883 }
    884 
    885 static void
    886 torrentSetNextAnnounce( tr_torrent * tor, const char * announceEvent, time_t announceAt )
     875
     876    dbgmsg( tier, "appended event \"%s\"; announcing in %d seconds\n", announceEvent, (int)difftime(announceAt,time(NULL)) );
     877}
     878
     879static void
     880torrentAddAnnounce( tr_torrent * tor, const char * announceEvent, time_t announceAt )
    887881{
    888882    int i;
     
    895889    n = tr_ptrArraySize( &tiers->tiers );
    896890    for( i=0; i<n; ++i )
    897         tierSetNextAnnounce( tr_ptrArrayNth( &tiers->tiers, i ), announceEvent, announceAt );
    898 }
    899 
     891        tierAddAnnounce( tr_ptrArrayNth( &tiers->tiers, i ), announceEvent, announceAt );
     892}
     893
     894void
     895tr_announcerTorrentStarted( tr_torrent * tor )
     896{
     897    torrentAddAnnounce( tor, "started", tr_time( ) );
     898}
    900899void
    901900tr_announcerManualAnnounce( tr_torrent * tor )
    902901{
    903     torrentSetNextAnnounce( tor, "manual", tr_time( ) );
    904 }
    905 void
    906 tr_announcerTorrentStarted( tr_torrent * tor )
    907 {
    908     torrentSetNextAnnounce( tor, "started", tr_time( ) );
     902    torrentAddAnnounce( tor, "", tr_time( ) );
    909903}
    910904void
    911905tr_announcerTorrentStopped( tr_torrent * tor )
    912906{
    913     torrentSetNextAnnounce( tor, "stopped", tr_time( ) );
     907    torrentAddAnnounce( tor, "stopped", tr_time( ) );
    914908}
    915909void
    916910tr_announcerTorrentCompleted( tr_torrent * tor )
    917911{
    918     torrentSetNextAnnounce( tor, "completed", tr_time( ) );
     912    torrentAddAnnounce( tor, "completed", tr_time( ) );
    919913}
    920914void
     
    12571251    tr_bool success = FALSE;
    12581252    const time_t now = time ( NULL );
    1259     const tr_bool isStopped = !strcmp( data->event, "stopped" );
     1253    const char * announceEvent = data->event;
     1254    const tr_bool isStopped = !strcmp( announceEvent, "stopped" );
    12601255
    12611256    if( announcer && tier )
     
    13251320            dbgmsg( tier, "No response from tracker... retrying in %d seconds.", interval );
    13261321            tier->manualAnnounceAllowedAt = ~(time_t)0;
    1327             tierSetNextAnnounce( tier, tier->announceEvent, now + interval );
     1322            tierAddAnnounce( tier, announceEvent, now + interval );
    13281323        }
    13291324        else if( 200 <= responseCode && responseCode <= 299 )
     
    13411336            tier->manualAnnounceAllowedAt = now + tier->announceMinIntervalSec;
    13421337
    1343             if( strcmp( tier->announceEvent, "stopped" ) == 0 )
    1344                 tierClearNextAnnounce( tier );
    1345             else
    1346                 tierSetNextAnnounce( tier, "", now + interval );
     1338            /* if we're running and the queue is empty, add the next update */
     1339            if( !isStopped && !tr_ptrArraySize( &tier->announceEvents ) )
     1340            {
     1341                tierAddAnnounce( tier, "", now + interval );
     1342            }
    13471343        }
    13481344        else if( 300 <= responseCode && responseCode <= 399 )
     
    13511347            const int interval = 5;
    13521348            dbgmsg( tier, "got a redirect. retrying in %d seconds", interval );
    1353             tierSetNextAnnounce( tier, tier->announceEvent, now + interval );
     1349            tierAddAnnounce( tier, announceEvent, now + interval );
    13541350            tier->manualAnnounceAllowedAt = now + tier->announceMinIntervalSec;
    13551351        }
     
    13621358                publishErrorMessageAndStop( tier, _( "Tracker returned a 4xx message" ) );
    13631359            tier->manualAnnounceAllowedAt = ~(time_t)0;
    1364             tierClearNextAnnounce( tier );
    13651360        }
    13661361        else if( 500 <= responseCode && responseCode <= 599 )
     
    13721367            const int interval = getRetryInterval( tier->currentTracker->host );
    13731368            tier->manualAnnounceAllowedAt = ~(time_t)0;
    1374             tierSetNextAnnounce( tier, tier->announceEvent, now + interval );
     1369            tierAddAnnounce( tier, announceEvent, now + interval );
    13751370        }
    13761371        else
     
    13801375            dbgmsg( tier, "Invalid response from tracker... retrying in two minutes." );
    13811376            tier->manualAnnounceAllowedAt = ~(time_t)0;
    1382             tierSetNextAnnounce( tier, tier->announceEvent, now + interval );
     1377            tierAddAnnounce( tier, announceEvent, now + interval );
    13831378        }
    13841379
     
    13931388                tier->currentTracker->host->lastSuccessfulRequest = now;
    13941389        }
    1395 
    1396         if( !success )
     1390        else if( responseCode != HTTP_OK )
     1391        {
    13971392            tierIncrementTracker( tier );
     1393
     1394            tr_ptrArrayInsert( &tier->announceEvents, (void*)announceEvent, 0 );
     1395        }
    13981396    }
    13991397
     
    14061404}
    14071405
    1408 static const char *
    1409 getAnnounceEvent( const tr_tier * tier )
    1410 {
    1411     const char * event;
     1406static const char*
     1407getNextAnnounceEvent( tr_tier * tier )
     1408{
     1409    int i, n;
     1410    int pos = -1;
     1411    tr_ptrArray tmp;
     1412    char ** events;
     1413    const char * str = NULL;
    14121414
    14131415    assert( tier != NULL );
     
    14151417    assert( tr_isTorrent( tier->tor ) );
    14161418
    1417     /* BEP 21: "In order to tell the tracker that a peer is a partial seed,
    1418      * it MUST send an event=paused parameter in every announce while
    1419      * it is a partial seed." */
     1419    /* rule #1: if there's a "stopped" in the queue, ignore everything before it */
     1420    events = (char**) tr_ptrArrayPeek( &tier->announceEvents, &n );
     1421    for( i=0; pos<0 && i<n; ++i )
     1422        if( !strcmp( events[i], "stopped" ) )
     1423            pos = i;
     1424
     1425fprintf( stderr, "in the queue: " );
     1426for( i=0; i<n; ++i ) fprintf( stderr, "(%d)%s, ", i, events[i] );
     1427fprintf( stderr, "\n" );
     1428
     1429    /* rule #2: if the next two events are the same, ignore the first one */
     1430    for( i=0; pos<0 && i<=n-2; ++i )
     1431        if( strcmp( events[i], events[i+1] ) )
     1432            pos = i;
     1433
     1434    /* otherwise use the next announce event in line */
     1435    if( ( pos < 0 ) && ( n > 0 ) )
     1436        pos = 0;
     1437
     1438    /* rule #3: BEP 21: "In order to tell the tracker that a peer is a
     1439     * partial seed, it MUST send an event=paused parameter in every
     1440     * announce while it is a partial seed." */
     1441    str = pos>=0 ? events[pos] : NULL;
    14201442    if( tr_cpGetStatus( &tier->tor->completion ) == TR_PARTIAL_SEED )
    1421         if( strcmp( tier->announceEvent, "stopped" ) )
    1422             return "paused";
    1423 
    1424     event = tier->announceEvent;
    1425 
    1426     if( !strcmp( event, "manual" ) )
    1427         return "started";
    1428 
    1429     return event;
     1443        if( !str || !strcmp( str, "stopped" ) )
     1444            str = "paused";
     1445
     1446    /* announceEvents array upkeep */
     1447fprintf( stderr, "what's left in the queue: " );
     1448    tmp = TR_PTR_ARRAY_INIT;
     1449    for( i=pos+1; i<n; ++i ) {
     1450        fprintf( stderr, "(%d)%s, ", i, events[i] );
     1451        tr_ptrArrayAppend( &tmp, events[i] );
     1452    }
     1453    tr_ptrArrayDestruct( &tier->announceEvents, NULL );
     1454    tier->announceEvents = tmp;
     1455fprintf( stderr, "\n" );
     1456
     1457fprintf( stderr, "returning [%s] (pos %d)\n", (str?str:"(null)"), pos );
     1458
     1459    return str;
    14301460}
    14311461
     
    14331463tierAnnounce( tr_announcer * announcer, tr_tier * tier )
    14341464{
    1435     char * url;
    1436     struct announce_data * data;
    1437     const tr_torrent * tor = tier->tor;
    1438     const time_t now = tr_time( );
     1465    const char * announceEvent = getNextAnnounceEvent( tier );
    14391466
    14401467    assert( !tier->isAnnouncing );
    14411468
    1442     data = tr_new0( struct announce_data, 1 );
    1443     data->torrentId = tr_torrentId( tor );
    1444     data->tierId = tier->key;
    1445     data->isRunningOnSuccess = tor->isRunning;
    1446     data->timeSent = now;
    1447     data->event = getAnnounceEvent( tier );
    1448     url = createAnnounceURL( announcer, tor, tier, data->event );
    1449 
    1450     tier->isAnnouncing = TRUE;
    1451     tier->lastAnnounceStartTime = now;
    1452     --announcer->slotsAvailable;
    1453     tr_webRun( announcer->session, url, NULL, onAnnounceDone, data );
    1454 
    1455     tr_free( url );
     1469    if( announceEvent != NULL )
     1470    {
     1471        char * url;
     1472        struct announce_data * data;
     1473        const tr_torrent * tor = tier->tor;
     1474        const time_t now = tr_time( );
     1475
     1476        data = tr_new0( struct announce_data, 1 );
     1477        data->torrentId = tr_torrentId( tor );
     1478        data->tierId = tier->key;
     1479        data->isRunningOnSuccess = tor->isRunning;
     1480        data->timeSent = now;
     1481        data->event = announceEvent;
     1482        url = createAnnounceURL( announcer, tor, tier, data->event );
     1483
     1484        tier->isAnnouncing = TRUE;
     1485        tier->lastAnnounceStartTime = now;
     1486        --announcer->slotsAvailable;
     1487        tr_webRun( announcer->session, url, NULL, onAnnounceDone, data );
     1488
     1489        tr_free( url );
     1490    }
    14561491}
    14571492
     
    16511686    return !tier->isAnnouncing
    16521687        && !tier->isScraping
    1653         && ( tier->announceEvent != NULL )
    1654         && ( tier->announceAt <= now );
     1688        && ( tier->announceAt <= now )
     1689        && ( tr_ptrArraySize( &tier->announceEvents ) != 0 );
    16551690}
    16561691
Note: See TracChangeset for help on using the changeset viewer.