Changeset 12144


Ignore:
Timestamp:
Mar 13, 2011, 6:38:54 AM (11 years ago)
Author:
jordan
Message:

(trunk libT) #117 "UDP tracker support (BEP #15)" -- added request timeout

UDP announce and scrapes now have a 120 second TTL.

Location:
trunk/libtransmission
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/announcer-common.h

    r12141 r12144  
    239239                              void                       * user_data );
    240240
     241void tr_tracker_udp_upkeep( tr_session * session );
     242
    241243#endif /* _TR_ANNOUNCER_COMMON_H_ */
  • trunk/libtransmission/announcer-udp.c

    r12141 r12144  
    121121tau_action_t;
    122122
     123enum
     124{
     125    TAU_REQUEST_TTL = 120
     126};
     127
    123128/****
    124129*****
     
    158163                in->info_hash[i], SHA_DIGEST_LENGTH );
    159164
    160     /* build the scrape payload */
     165    /* build the payload */
    161166    buf = evbuffer_new( );
    162167    evbuffer_add_hton_32( buf, TAU_ACTION_SCRAPE );
     
    224229            row->downloads = evbuffer_read_ntoh_32( buf );
    225230            row->leechers  = evbuffer_read_ntoh_32( buf );
    226 
    227231        }
    228232
     
    260264{
    261265    /* used in the "event" field of an announce request */
    262     UDP_TRACKER_EVENT_NONE      = 0,
    263     UDP_TRACKER_EVENT_COMPLETED = 1,
    264     UDP_TRACKER_EVENT_STARTED   = 2,
    265     UDP_TRACKER_EVENT_STOPPED   = 3
     266    TAU_ANNOUNCE_EVENT_NONE      = 0,
     267    TAU_ANNOUNCE_EVENT_COMPLETED = 1,
     268    TAU_ANNOUNCE_EVENT_STARTED   = 2,
     269    TAU_ANNOUNCE_EVENT_STOPPED   = 3
    266270}
    267271tau_announce_event;
     
    272276    switch( e )
    273277    {
    274         case TR_ANNOUNCE_EVENT_COMPLETED:  return UDP_TRACKER_EVENT_COMPLETED;
    275         case TR_ANNOUNCE_EVENT_STARTED:    return UDP_TRACKER_EVENT_STARTED;
    276         case TR_ANNOUNCE_EVENT_STOPPED:    return UDP_TRACKER_EVENT_STOPPED;
    277         default:                           return UDP_TRACKER_EVENT_NONE;
     278        case TR_ANNOUNCE_EVENT_COMPLETED:  return TAU_ANNOUNCE_EVENT_COMPLETED;
     279        case TR_ANNOUNCE_EVENT_STARTED:    return TAU_ANNOUNCE_EVENT_STARTED;
     280        case TR_ANNOUNCE_EVENT_STOPPED:    return TAU_ANNOUNCE_EVENT_STOPPED;
     281        default:                           return TAU_ANNOUNCE_EVENT_NONE;
    278282    }
    279283}
     
    286290    struct evbuffer * buf;
    287291
    288     struct tau_announce_request * req = tr_new0( struct tau_announce_request, 1 );
    289     req->transaction_id = tau_transaction_new( );
    290     req->callback = callback;
    291     req->user_data = user_data;
    292     memcpy( req->response.info_hash, in->info_hash, SHA_DIGEST_LENGTH );
     292    struct tau_announce_request * r = tr_new0( struct tau_announce_request, 1 );
     293    r->transaction_id = tau_transaction_new( );
     294    r->callback = callback;
     295    r->user_data = user_data;
     296    memcpy( r->response.info_hash, in->info_hash, SHA_DIGEST_LENGTH );
    293297
    294298    /* build the announce payload */
    295299    buf = evbuffer_new( );
    296300    evbuffer_add_hton_32( buf, TAU_ACTION_ANNOUNCE );
    297     evbuffer_add_hton_32( buf, req->transaction_id );
     301    evbuffer_add_hton_32( buf, r->transaction_id );
    298302    evbuffer_add        ( buf, in->info_hash, SHA_DIGEST_LENGTH );
    299303    evbuffer_add        ( buf, in->peer_id, PEER_ID_LEN );
     
    306310    evbuffer_add_hton_32( buf, in->numwant );
    307311    evbuffer_add_hton_16( buf, in->port );
    308     req->payload_len = evbuffer_get_length( buf );
    309     req->payload = tr_memdup( evbuffer_pullup( buf, -1 ), req->payload_len );
     312    r->payload_len = evbuffer_get_length( buf );
     313    r->payload = tr_memdup( evbuffer_pullup( buf, -1 ), r->payload_len );
    310314    evbuffer_free( buf );
    311315
    312     return req;
     316    return r;
    313317}
    314318
     
    495499    tr_ptrArray * reqs;
    496500    const time_t now = tr_time( );
    497 
    498     /* FIXME: look for timed-out requests */
     501    const tr_bool is_connected = tracker->connection_expiration_time > now;
    499502
    500503    /* if the address info is too old, expire it */
     
    505508    }
    506509
    507     /* if no requests, there's nothing to do */
    508     if( tr_ptrArrayEmpty( &tracker->announces ) && tr_ptrArrayEmpty( &tracker->scrapes ) )
     510    /* are there any requests pending? */
     511    if( tr_ptrArrayEmpty( &tracker->announces ) &&
     512        tr_ptrArrayEmpty( &tracker->scrapes ) )
    509513        return;
    510514
    511     /* can't do anything without an address */
    512     if( !tracker->addr ) {
    513         if( !tracker->is_asking_dns ) {
    514             struct evutil_addrinfo hints;
    515             memset( &hints, 0, sizeof( hints ) );
    516             hints.ai_family = AF_UNSPEC;
    517             hints.ai_flags = EVUTIL_AI_CANONNAME;
    518             hints.ai_socktype = SOCK_DGRAM;
    519             hints.ai_protocol = IPPROTO_UDP;
    520             tracker->is_asking_dns = TRUE;
    521             dbgmsg( tracker->host, "Trying a new DNS lookup" );     
    522             evdns_getaddrinfo( tracker->session->evdns_base,
    523                                tracker->host, NULL, &hints, tau_tracker_on_dns, tracker );
    524         }
     515    /* if we don't have an address yet, try & get one now. */
     516    if( !tracker->addr && !tracker->is_asking_dns )
     517    {
     518        struct evutil_addrinfo hints;
     519        memset( &hints, 0, sizeof( hints ) );
     520        hints.ai_family = AF_UNSPEC;
     521        hints.ai_flags = EVUTIL_AI_CANONNAME;
     522        hints.ai_socktype = SOCK_DGRAM;
     523        hints.ai_protocol = IPPROTO_UDP;
     524        tracker->is_asking_dns = TRUE;
     525        dbgmsg( tracker->host, "Trying a new DNS lookup" );     
     526        evdns_getaddrinfo( tracker->session->evdns_base,
     527                           tracker->host, NULL, &hints,
     528                           tau_tracker_on_dns, tracker );
    525529        return;
    526530    }
    527531
    528532    /* also need a valid connection ID... */
    529     if( tracker->connection_expiration_time < now ) {
    530         if( !tracker->is_connecting ) {
    531             struct evbuffer * buf = evbuffer_new( );
    532             tracker->is_connecting = TRUE;
    533             tracker->connection_transaction_id = tau_transaction_new( );
    534             dbgmsg( tracker->key, "Trying to connect. Transaction ID is %u",
    535                     tracker->connection_transaction_id );
    536             evbuffer_add_hton_64( buf, 0x41727101980LL );
    537             evbuffer_add_hton_32( buf, TAU_ACTION_CONNECT );
    538             evbuffer_add_hton_32( buf, tracker->connection_transaction_id );
    539             tau_sendto( tracker->session, tracker->addr, tracker->port,
    540                         evbuffer_pullup( buf, -1 ),
    541                         evbuffer_get_length( buf ) );
    542             evbuffer_free( buf );
    543         }
     533    if( !is_connected && !tracker->is_connecting )
     534    {
     535        struct evbuffer * buf = evbuffer_new( );
     536        tracker->is_connecting = TRUE;
     537        tracker->connection_transaction_id = tau_transaction_new( );
     538        dbgmsg( tracker->key, "Trying to connect. Transaction ID is %u",
     539                tracker->connection_transaction_id );
     540        evbuffer_add_hton_64( buf, 0x41727101980LL );
     541        evbuffer_add_hton_32( buf, TAU_ACTION_CONNECT );
     542        evbuffer_add_hton_32( buf, tracker->connection_transaction_id );
     543        tau_sendto( tracker->session, tracker->addr, tracker->port,
     544                    evbuffer_pullup( buf, -1 ),
     545                    evbuffer_get_length( buf ) );
     546        evbuffer_free( buf );
    544547        return;
    545548    }
     
    547550    /* send the announce requests */
    548551    reqs = &tracker->announces;
    549     for( i=0, n=tr_ptrArraySize(reqs); i<n; ++i ) {
     552    for( i=0, n=tr_ptrArraySize(reqs); i<n; ++i )
     553    {
    550554        struct tau_announce_request * req = tr_ptrArrayNth( reqs, i );
    551         if( req->sent_at == 0 ) {
     555        if( is_connected && !req->sent_at ) {
    552556            dbgmsg( tracker->key, "Sending an announce request" );
    553557            req->sent_at = now;
    554558            tau_tracker_send_request( tracker, req->payload, req->payload_len );
    555559        }
     560        else if( req->sent_at && ( req->sent_at + TAU_REQUEST_TTL < now ) ) {
     561            tau_announce_request_fail( tracker->session, req, FALSE, TRUE, NULL );
     562            tau_announce_request_free( req );
     563            tr_ptrArrayRemove( reqs, i-- );
     564        }
    556565    }
    557566
    558567    /* send the scrape requests */
    559568    reqs = &tracker->scrapes;
    560     for( i=0, n=tr_ptrArraySize(reqs); i<n; ++i ) {
     569    for( i=0, n=tr_ptrArraySize(reqs); i<n; ++i )
     570    {
    561571        struct tau_scrape_request * req = tr_ptrArrayNth( reqs, i );
    562         if( req->sent_at == 0 ) {
     572        if( is_connected && !req->sent_at ) {
    563573            dbgmsg( tracker->key, "Sending a scrape request" );
    564574            req->sent_at = now;
    565575            tau_tracker_send_request( tracker, req->payload, req->payload_len );
     576        }
     577        else if( req->sent_at && ( req->sent_at + TAU_REQUEST_TTL < now ) ) {
     578            tau_scrape_request_fail( tracker->session, req, FALSE, TRUE, NULL );
     579            tau_scrape_request_free( req );
     580            tr_ptrArrayRemove( reqs, i-- );
    566581        }
    567582    }
     
    674689****/
    675690
     691void
     692tr_tracker_udp_upkeep( tr_session * session )
     693{
     694    struct tr_announcer_udp * tau = session->announcer_udp;
     695
     696    if( tau != NULL )
     697        tr_ptrArrayForeach( &tau->trackers,
     698                            (PtrArrayForeachFunc)tau_tracker_upkeep );
     699}
     700
    676701tr_bool
    677702tau_handle_message( tr_session     * session,
     
    712737
    713738        /* is it a connection response? */
    714         if( tracker->is_connecting && ( transaction_id == tracker->connection_transaction_id ) )
     739        if( tracker->is_connecting
     740            && ( transaction_id == tracker->connection_transaction_id ) )
    715741        {
    716742            dbgmsg( tracker->key, "%"PRIu32" matches my connection request!", transaction_id );
     
    762788    struct tr_announcer_udp * tau = announcer_udp_get( session );
    763789    struct tau_tracker * tracker = tau_session_get_tracker( tau, request->url );
    764     struct tau_announce_request * r = tau_announce_request_new( request, response_func, user_data );
     790    struct tau_announce_request * r = tau_announce_request_new( request,
     791                                                                response_func,
     792                                                                user_data );
    765793    tr_ptrArrayAppend( &tracker->announces, r );
    766794    tau_tracker_upkeep( tracker );
     
    775803    struct tr_announcer_udp * tau = announcer_udp_get( session );
    776804    struct tau_tracker * tracker = tau_session_get_tracker( tau, request->url );
    777     struct tau_scrape_request * r = tau_scrape_request_new( request, response_func, user_data );
     805    struct tau_scrape_request * r = tau_scrape_request_new( request,
     806                                                            response_func,
     807                                                            user_data );
    778808    tr_ptrArrayAppend( &tracker->scrapes, r );
    779809    tau_tracker_upkeep( tracker );
  • trunk/libtransmission/announcer.c

    r12141 r12144  
    6565
    6666    /* this is an upper limit for the frequency of LDS announces */
    67     LPD_HOUSEKEEPING_INTERVAL_SECS = 5
     67    LPD_HOUSEKEEPING_INTERVAL_SECS = 5,
     68
     69    /* this is how often to call the UDP tracker upkeep */
     70    TAU_UPKEEP_INTERVAL_SECS = 5
    6871};
    6972
     
    129132    int slotsAvailable;
    130133    int key;
    131     time_t lpdHouseKeepingAt;
     134    time_t lpdUpkeepAt;
     135    time_t tauUpkeepAt;
    132136}
    133137tr_announcer;
     
    140144
    141145static inline time_t
    142 calcRescheduleWithJitter( const int minPeriod )
     146valPlusJitter( const int minPeriod )
    143147{
    144148    const double jitter = 0.1;
     
    159163    tr_announcer * a;
    160164
    161     const time_t lpdAt =
    162         calcRescheduleWithJitter( LPD_HOUSEKEEPING_INTERVAL_SECS / 3 );
     165    const time_t lpdAt = valPlusJitter( LPD_HOUSEKEEPING_INTERVAL_SECS / 3 );
    163166
    164167    assert( tr_isSession( session ) );
     
    169172    a->session = session;
    170173    a->slotsAvailable = MAX_CONCURRENT_TASKS;
    171     a->lpdHouseKeepingAt = lpdAt;
     174    a->lpdUpkeepAt = lpdAt;
    172175    a->upkeepTimer = evtimer_new( session->event_base, onUpkeepTimer, a );
    173176    tr_timerAdd( a->upkeepTimer, UPKEEP_INTERVAL_SECS, 0 );
     
    14151418        }
    14161419    }
    1417 
    1418     /* Local Peer Discovery */
    1419     if( announcer->lpdHouseKeepingAt <= now )
    1420     {
    1421         tr_lpdAnnounceMore( now, LPD_HOUSEKEEPING_INTERVAL_SECS );
    1422 
    1423         /* reschedule more LDS announces for ( the future + jitter ) */
    1424         announcer->lpdHouseKeepingAt =
    1425             calcRescheduleWithJitter( LPD_HOUSEKEEPING_INTERVAL_SECS );
    1426     }
    14271420}
    14281421
     
    14301423onUpkeepTimer( int foo UNUSED, short bar UNUSED, void * vannouncer )
    14311424{
     1425    const time_t now = tr_time( );
    14321426    tr_announcer * announcer = vannouncer;
    14331427    tr_sessionLock( announcer->session );
     
    14381432    /* maybe send out some announcements to trackers */
    14391433    announceMore( announcer );
     1434
     1435    /* LPD upkeep */
     1436    if( announcer->lpdUpkeepAt <= now ) {
     1437        const int seconds = LPD_HOUSEKEEPING_INTERVAL_SECS;
     1438        announcer->lpdUpkeepAt = valPlusJitter( seconds );
     1439        tr_lpdAnnounceMore( now, seconds );
     1440    }
     1441
     1442    /* TAU upkeep */
     1443    if( announcer->tauUpkeepAt <= now ) {
     1444        announcer->tauUpkeepAt = now + TAU_UPKEEP_INTERVAL_SECS;
     1445        tr_tracker_udp_upkeep( announcer->session );
     1446    }
    14401447
    14411448    /* set up the next timer */
  • trunk/libtransmission/tr-udp.h

    r12141 r12144  
    3333void tr_udpSetSocketBuffers(tr_session *);
    3434
    35 tr_bool tau_handle_message( tr_session * session, const uint8_t  * msg, size_t msglen );
     35tr_bool tau_handle_message( tr_session * session,
     36                            const uint8_t  * msg, size_t msglen );
    3637
    3738#endif /* #ifndef TR_UDP_H */
Note: See TracChangeset for help on using the changeset viewer.