Changeset 4021


Ignore:
Timestamp:
Nov 30, 2007, 5:10:33 PM (14 years ago)
Author:
charles
Message:

be more forgiving of tracker failure

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/tracker.c

    r4008 r4021  
    3636{
    3737    /* seconds between tracker pulses */
    38     PULSE_INTERVAL_SEC = 1,
     38    PULSE_INTERVAL_MSEC = 750,
    3939
    4040    /* maximum number of concurrent tracker socket connections */
     
    6767***
    6868**/
    69 
    70 enum
    71 {
    72     TR_REQ_STARTED,
    73     TR_REQ_COMPLETED,
    74     TR_REQ_STOPPED,
    75     TR_REQ_REANNOUNCE,
    76     TR_REQ_COUNT
    77 };
    7869
    7970struct tr_tracker
     
    117108    char * trackerID;
    118109
    119     /* the last tracker request we sent. (started, stopped, etc.)
    120        automatic announces are an empty string;
    121        NULL means no message has ever been sent */
    122     char * lastRequest;
    123 
    124110    time_t manualAnnounceAllowedAt;
    125111    time_t reannounceAt;
    126112    time_t scrapeAt;
     113
     114    time_t resendRequestAt;
     115    int resendRequestType;
    127116
    128117    unsigned int isRunning     : 1;
     
    208197{
    209198    tr_torrent * torrent = tr_torrentFindFromHash( data->handle, data->hash );
     199    return torrent ? torrent->tracker : NULL;
     200}
     201
     202tr_tracker *
     203findTracker( tr_handle * handle, const uint8_t * hash )
     204{
     205    tr_torrent * torrent = tr_torrentFindFromHash( handle, hash );
    210206    return torrent ? torrent->tracker : NULL;
    211207}
     
    541537    const char * warning;
    542538    time_t nextScrapeSec = 60;
    543     tr_tracker * t;
    544 
    545     t = findTrackerFromHash( vhash );
     539    tr_tracker * t = findTrackerFromHash( vhash );
     540
     541    dbgmsg( t, "Got scrape response for '%s': %s", (t ? t->name : "(null)"), (req ? req->response_code_line : "(no line)") );
     542
    546543    tr_free( vhash );
    547544    if( t == NULL ) /* tracker's been closed... */
     
    611608***/
    612609
     610enum
     611{
     612    TR_REQ_STARTED,
     613    TR_REQ_COMPLETED,
     614    TR_REQ_STOPPED,
     615    TR_REQ_REANNOUNCE,
     616    TR_REQ_SCRAPE,
     617    TR_REQ_COUNT
     618};
     619
    613620struct tr_tracker_request
    614621{
    615622    int port;
    616623    int timeout;
     624    int reqtype; /* TR_REQ_* */
    617625    char * address;
    618626    char * uri;
    619627    struct evhttp_request * req;
     628    uint8_t torrent_hash[SHA_DIGEST_LENGTH];
    620629};
    621630
     
    694703createRequest( tr_handle * handle, const tr_tracker * tracker, int reqtype )
    695704{
    696     static const char* strings[TR_REQ_COUNT] = { "started", "completed", "stopped", "" };
     705    static const char* strings[TR_REQ_COUNT] = { "started", "completed", "stopped", "", "err" };
    697706    const tr_torrent * torrent = tr_torrentFindFromHash( handle, tracker->hash );
    698707    const tr_tracker_info * address = getCurrentAddress( tracker );
     
    706715    req->uri = buildTrackerRequestURI( tracker, torrent, eventName );
    707716    req->timeout = isStopping ? STOP_TIMEOUT_INTERVAL_SEC : TIMEOUT_INTERVAL_SEC;
     717    req->reqtype = reqtype;
    708718    req->req = isStopping
    709719        ? evhttp_request_new( onStoppedResponse, handle )
    710720        : evhttp_request_new( onTrackerResponse, torrentHashNew(handle, tracker) );
     721    memcpy( req->torrent_hash, tracker->hash, SHA_DIGEST_LENGTH );
    711722    addCommonHeaders( tracker, req->req );
    712723
     
    725736    req->timeout = TIMEOUT_INTERVAL_SEC;
    726737    req->req = evhttp_request_new( onScrapeResponse, torrentHashNew( handle, tracker ) );
     738    req->reqtype = TR_REQ_SCRAPE;
    727739    tr_asprintf( &req->uri, "%s%cinfo_hash=%s", a->scrape, strchr(a->scrape,'?')?'&':'?', tracker->escaped );
     740    memcpy( req->torrent_hash, tracker->hash, SHA_DIGEST_LENGTH );
    728741    addCommonHeaders( tracker, req->req );
    729742
     
    747760    {
    748761        handle->tracker = tr_new0( struct tr_tracker_handle, 1 );
    749         handle->tracker->pulseTimer = tr_timerNew( handle, pulse, handle, PULSE_INTERVAL_SEC*1000 );
     762        handle->tracker->pulseTimer = tr_timerNew( handle, pulse, handle, PULSE_INTERVAL_MSEC );
    750763        dbgmsg( NULL, "creating tracker timer" );
    751764    }
     
    822835}
    823836
    824 static void
     837static int
    825838invokeRequest( tr_handle * handle, const struct tr_tracker_request * req )
    826839{
     840    int err;
    827841    struct evhttp_connection * evcon = getConnection( handle, req->address, req->port );
    828     ++handle->tracker->socketCount;
    829     dbgmsg( NULL, "incrementing socket count to %d, sending '%s' to tracker %s:%d", handle->tracker->socketCount, req->uri, req->address, req->port );
     842    dbgmsg( NULL, "sending '%s' to tracker %s:%d, timeout is %d", req->uri, req->address, req->port, (int)req->timeout );
    830843    evhttp_connection_set_timeout( evcon, req->timeout );
    831     evhttp_make_request( evcon, req->req, EVHTTP_REQ_GET, req->uri );
     844    err = evhttp_make_request( evcon, req->req, EVHTTP_REQ_GET, req->uri );
     845    if( !err ) {
     846        ++handle->tracker->socketCount;
     847        dbgmsg( NULL, "incremented socket count to %d", handle->tracker->socketCount );
     848    }
     849    return err;
    832850}
    833851
     
    836854{
    837855    struct tr_tracker_request * req = tr_list_pop_front( list );
    838     invokeRequest( handle, req );
     856    const int err = invokeRequest( handle, req );
     857
     858    if( err )
     859    {
     860        tr_tracker * t = findTracker( handle, req->torrent_hash );
     861        if( t != NULL )
     862        {
     863            if( req->reqtype == TR_REQ_SCRAPE ) {
     864                t->scrapeAt = time(NULL) + 30;
     865                dbgmsg( t, "scrape failed... retrying in 30 seconds" );
     866            }
     867            else {
     868                dbgmsg( t, "request [%s] failed... retrying in 30 seconds", req->uri );
     869                t->resendRequestAt = time(NULL) + 30;
     870                t->resendRequestType = req->reqtype;
     871            }
     872        }
     873    }
     874
    839875    freeRequest( req );
    840876}
     
    847883
    848884static void ensureGlobalsExist( tr_handle * );
     885
     886static void
     887enqueueScrape( tr_handle * handle, const tr_tracker * tracker )
     888{
     889    struct tr_tracker_request * req;
     890    ensureGlobalsExist( handle );
     891    req = createScrape( handle, tracker );
     892    tr_list_append( &handle->tracker->scrapeQueue, req );
     893}
    849894
    850895static void
     
    857902}
    858903
    859 static void
    860 enqueueScrape( tr_handle * handle, const tr_tracker * tracker )
    861 {
    862     struct tr_tracker_request * req;
    863     ensureGlobalsExist( handle );
    864     req = createScrape( handle, tracker );
    865     tr_list_append( &handle->tracker->scrapeQueue, req );
     904/**
     905 * This function is called when there's been an error invoking a request,
     906 * or when the tracker has returned back a server error that might require
     907 * the request to be re-sent.
     908 */
     909static void
     910maybeRequeueRequest( tr_handle * handle, const tr_tracker * tracker, int reqtype )
     911{
     912    /* FIXME */
     913    enqueueRequest( handle, tracker, reqtype );
    866914}
    867915
     
    871919    tr_handle * handle = vhandle;
    872920    struct tr_tracker_handle * th = handle->tracker;
    873     tr_torrent * t;
     921    tr_torrent * tor;
    874922    const time_t now = time( NULL );
    875923
     
    878926
    879927    /* upkeep: queue periodic rescrape / reannounce */
    880     for( t=handle->torrentList; t; t=t->next ) {
    881         tr_tracker * tracker = t->tracker;
    882         if( tracker->scrapeAt && trackerSupportsScrape( tracker ) && ( now >= tracker->scrapeAt ) ) {
    883             tracker->scrapeAt = 0;
    884             enqueueScrape( handle, tracker );
     928    for( tor=handle->torrentList; tor; tor=tor->next )
     929    {
     930        tr_tracker * t = tor->tracker;
     931
     932        if( t->resendRequestAt && ( now >= t->resendRequestAt ) ) {
     933            t->resendRequestAt = 0;
     934            maybeRequeueRequest( handle, t, t->resendRequestType );
    885935        }
    886         if( tracker->reannounceAt && tracker->isRunning && ( now >= tracker->reannounceAt ) ) {
    887             tracker->reannounceAt = 0;
    888             enqueueRequest( handle, tracker, TR_REQ_REANNOUNCE );
     936
     937        if( t->scrapeAt && trackerSupportsScrape( t ) && ( now >= t->scrapeAt ) ) {
     938            t->scrapeAt = 0;
     939            enqueueScrape( handle, t );
     940        }
     941
     942        if( t->reannounceAt && t->isRunning && ( now >= t->reannounceAt ) ) {
     943            t->reannounceAt = 0;
     944            enqueueRequest( handle, t, TR_REQ_REANNOUNCE );
    889945        }
    890946    }
     
    10001056    tr_free( t->name );
    10011057    tr_free( t->trackerID );
    1002     tr_free( t->lastRequest );
    10031058
    10041059    /* addresses... */
Note: See TracChangeset for help on using the changeset viewer.