Changeset 12189


Ignore:
Timestamp:
Mar 20, 2011, 3:28:41 PM (11 years ago)
Author:
jordan
Message:

(trunk libT) #117 "UDP tracker protocol support" -- (1) fix connection attempt retries after a failed connection attempt. (2) extract method from tau_tracker_upkeep() for clarity: tau_tracker_send_reqs() and tau_tracker_timeout_reqs()
refactor the timeout/request code a bit.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/announcer-udp.c

    r12188 r12189  
    432432    time_t addr_expiration_time;
    433433
    434     tr_bool is_connecting;
     434    time_t connecting_at;
    435435    time_t connection_expiration_time;
    436436    tau_connection_t connection_id;
     
    525525}
    526526
     527static void
     528tau_tracker_send_reqs( struct tau_tracker * tracker )
     529{
     530    int i, n;
     531    tr_ptrArray * reqs;
     532    const time_t now = tr_time( );
     533
     534    assert( tracker->is_asking_dns == 0 );
     535    assert( tracker->connecting_at == 0 );
     536    assert( tracker->addr != NULL );
     537    assert( tracker->connection_expiration_time > now );
     538
     539    reqs = &tracker->announces;
     540    for( i=0, n=tr_ptrArraySize(reqs); i<n; ++i ) {
     541        struct tau_announce_request * req = tr_ptrArrayNth( reqs, i );
     542        if( !req->sent_at ) {
     543            dbgmsg( tracker->key, "sending announce req %p", req );
     544            req->sent_at = now;
     545            tau_tracker_send_request( tracker, req->payload, req->payload_len );
     546            if( req->callback == NULL ) {
     547                tau_announce_request_free( req );
     548                tr_ptrArrayRemove( reqs, i );
     549                --i;
     550                --n;
     551            }
     552        }
     553    }
     554
     555    reqs = &tracker->scrapes;
     556    for( i=0, n=tr_ptrArraySize(reqs); i<n; ++i ) {
     557        struct tau_scrape_request * req = tr_ptrArrayNth( reqs, i );
     558        if( !req->sent_at ) {
     559            dbgmsg( tracker->key, "sending scrape req %p", req );
     560            req->sent_at = now;
     561            tau_tracker_send_request( tracker, req->payload, req->payload_len );
     562            if( req->callback == NULL) {
     563                tau_scrape_request_free( req );
     564                tr_ptrArrayRemove( reqs, i );
     565                --i;
     566                --n;
     567            }
     568        }
     569    }
     570}
     571
     572static void
     573on_tracker_connection_response( struct tau_tracker  * tracker,
     574                                tau_action_t          action,
     575                                struct evbuffer     * buf )
     576{
     577    const time_t now = tr_time( );
     578
     579    tracker->connecting_at = 0;
     580    tracker->connection_transaction_id = 0;
     581
     582    if( action == TAU_ACTION_CONNECT )
     583    {
     584        tracker->connection_id = evbuffer_read_ntoh_64( buf );
     585        tracker->connection_expiration_time = now + TAU_CONNECTION_TTL_SECS;
     586        dbgmsg( tracker->key, "Got a new connection ID from tracker: %"PRIu64,
     587                tracker->connection_id );
     588    }
     589    else
     590    {
     591        char * errmsg;
     592        const size_t buflen = buf ? evbuffer_get_length( buf ) : 0;
     593
     594        if( ( action == TAU_ACTION_ERROR ) && ( buflen > 0 ) )
     595            errmsg = tr_strndup( evbuffer_pullup( buf, -1 ), buflen );
     596        else
     597            errmsg = tr_strdup( _( "Connection failed" ) );
     598
     599        dbgmsg( tracker->key, "%s", errmsg );
     600        tau_tracker_fail_all( tracker, TRUE, FALSE, errmsg );
     601        tr_free( errmsg );
     602    }
     603
     604    tau_tracker_upkeep( tracker );
     605}
     606
     607static void
     608tau_tracker_timeout_reqs( struct tau_tracker * tracker )
     609{
     610    int i, n;
     611    tr_ptrArray * reqs;
     612    const time_t now = time( NULL );
     613    const tr_bool cancel_all = tracker->close_at && ( tracker->close_at <= now );
     614
     615
     616    if( tracker->connecting_at && ( tracker->connecting_at + TAU_REQUEST_TTL < now ) ) {
     617        on_tracker_connection_response( tracker, TAU_ACTION_ERROR, NULL );
     618    }
     619
     620    reqs = &tracker->announces;
     621    for( i=0, n=tr_ptrArraySize(reqs); i<n; ++i ) {
     622        struct tau_announce_request * req = tr_ptrArrayNth( reqs, i );
     623        if( cancel_all || ( req->created_at + TAU_REQUEST_TTL < now ) ) {
     624            dbgmsg( tracker->key, "timeout announce req %p", req );
     625            tau_announce_request_fail( tracker->session, req, FALSE, TRUE, NULL );
     626            tau_announce_request_free( req );
     627            tr_ptrArrayRemove( reqs, i );
     628            --i;
     629            --n;
     630        }
     631    }
     632
     633    reqs = &tracker->scrapes;
     634    for( i=0, n=tr_ptrArraySize(reqs); i<n; ++i ) {
     635        struct tau_scrape_request * req = tr_ptrArrayNth( reqs, i );
     636        if( cancel_all || ( req->created_at + TAU_REQUEST_TTL < now ) ) {
     637            dbgmsg( tracker->key, "timeout scrape req %p", req );
     638            tau_scrape_request_fail( tracker->session, req, FALSE, TRUE, NULL );
     639            tau_scrape_request_free( req );
     640            tr_ptrArrayRemove( reqs, i );
     641            --i;
     642            --n;
     643        }
     644    }
     645}
     646
    527647static tr_bool
    528648tau_tracker_is_empty( const struct tau_tracker * tracker )
     
    535655tau_tracker_upkeep( struct tau_tracker * tracker )
    536656{
    537     int i;
    538     int n;
    539     tr_ptrArray * reqs;
    540657    const time_t now = tr_time( );
    541     const tr_bool is_connected = tracker->connection_expiration_time > now;
    542658
    543659    /* if the address info is too old, expire it */
     
    569685    }
    570686
     687    dbgmsg( tracker->key, "addr %p -- connected %d (%zu %zu) -- connecting_at %zu",
     688            tracker->addr,
     689            (int)(tracker->connection_expiration_time > now), (size_t)tracker->connection_expiration_time, (size_t)now,
     690            (size_t)tracker->connecting_at );
     691
    571692    /* also need a valid connection ID... */
    572     if( !is_connected && !tracker->is_connecting && tracker->addr )
     693    if( tracker->addr
     694        && ( tracker->connection_expiration_time <= now )
     695        && ( !tracker->connecting_at ) )
    573696    {
    574697        struct evbuffer * buf = evbuffer_new( );
    575         tracker->is_connecting = TRUE;
     698        tracker->connecting_at = now;
    576699        tracker->connection_transaction_id = tau_transaction_new( );
    577700        dbgmsg( tracker->key, "Trying to connect. Transaction ID is %u",
     
    587710    }
    588711
    589     /* send the announce requests */
    590     reqs = &tracker->announces;
    591     for( i=0, n=tr_ptrArraySize(reqs); i<n; ++i )
    592     {
    593         tr_bool remove_request = FALSE;
    594         struct tau_announce_request * req = tr_ptrArrayNth( reqs, i );
    595         if( is_connected && !req->sent_at && tracker->addr ) {
    596             dbgmsg( tracker->key, "Sending an announce request" );
    597             req->sent_at = now;
    598             tau_tracker_send_request( tracker, req->payload, req->payload_len );
    599             remove_request = req->callback == NULL;
    600         }
    601         else if( req->created_at + TAU_REQUEST_TTL < now ) {
    602             tau_announce_request_fail( tracker->session, req, FALSE, TRUE, NULL );
    603             remove_request = TRUE;
    604         }
    605         if( tracker->close_at && ( tracker->close_at <= time(NULL) ) )
    606             remove_request = TRUE;
    607         if( remove_request ) {
    608             tau_announce_request_free( req );
    609             tr_ptrArrayRemove( reqs, i );
    610             --i;
    611             --n;
    612         }
    613     }
    614 
    615     /* send the scrape requests */
    616     reqs = &tracker->scrapes;
    617     for( i=0, n=tr_ptrArraySize(reqs); i<n; ++i )
    618     {
    619         tr_bool remove_request = FALSE;
    620         struct tau_scrape_request * req = tr_ptrArrayNth( reqs, i );
    621         if( is_connected && !req->sent_at && tracker->addr ) {
    622             dbgmsg( tracker->key, "Sending a scrape request" );
    623             req->sent_at = now;
    624             tau_tracker_send_request( tracker, req->payload, req->payload_len );
    625             remove_request = req->callback == NULL;
    626         }
    627         else if( req->created_at + TAU_REQUEST_TTL < now ) {
    628             tau_scrape_request_fail( tracker->session, req, FALSE, TRUE, NULL );
    629             remove_request = TRUE;
    630         }
    631         if( tracker->close_at && ( tracker->close_at <= time(NULL) ) )
    632             remove_request = TRUE;
    633         if( remove_request ) {
    634             tau_scrape_request_free( req );
    635             tr_ptrArrayRemove( reqs, i );
    636             --i;
    637             --n;
    638         }
    639     }
    640 }
    641 
    642 static void
    643 on_tracker_connection_response( struct tau_tracker  * tracker,
    644                                 tau_action_t          action,
    645                                 struct evbuffer     * buf )
    646 {
    647     const time_t now = tr_time( );
    648 
    649     tracker->is_connecting = FALSE;
    650     tracker->connection_transaction_id = 0;
    651 
    652     if( action == TAU_ACTION_CONNECT )
    653     {
    654         tracker->connection_id = evbuffer_read_ntoh_64( buf );
    655         tracker->connection_expiration_time = now + TAU_CONNECTION_TTL_SECS;
    656         dbgmsg( tracker->key, "Got a new connection ID from tracker: %"PRIu64,
    657                 tracker->connection_id );
    658     }
    659     else
    660     {
    661         char * errmsg;
    662         const size_t buflen = evbuffer_get_length( buf );
    663 
    664         if( ( action == TAU_ACTION_ERROR ) && ( buflen > 0 ) )
    665             errmsg = tr_strndup( evbuffer_pullup( buf, -1 ), buflen );
    666         else
    667             errmsg = tr_strdup( _( "Connection refused" ) );
    668 
    669         dbgmsg( tracker->key, "%s", errmsg );
    670         tau_tracker_fail_all( tracker, TRUE, FALSE, errmsg );
    671         tr_free( errmsg );
    672     }
    673 
    674     tau_tracker_upkeep( tracker );
     712    tau_tracker_timeout_reqs( tracker );
     713
     714    if( ( tracker->addr != NULL ) && ( tracker->connection_expiration_time > now ) )
     715        tau_tracker_send_reqs( tracker );
    675716}
    676717
     
    853894
    854895        /* is it a connection response? */
    855         if( tracker->is_connecting
     896        if( tracker->connecting_at
    856897            && ( transaction_id == tracker->connection_transaction_id ) )
    857898        {
Note: See TracChangeset for help on using the changeset viewer.