Ticket #2280: 0001-Manual-DHT-bootstrap.patch

File 0001-Manual-DHT-bootstrap.patch, 5.8 KB (added by jch, 11 years ago)
  • libtransmission/tr-dht.c

    From 232eb2a34b8fe9030368b65b9c62e0962f62ff8a Mon Sep 17 00:00:00 2001
    From: Juliusz Chroboczek <jch@pps.jussieu.fr>
    Date: Sat, 14 Nov 2009 04:11:07 +0100
    Subject: [PATCH] Manual DHT bootstrap.
    
    ---
     libtransmission/tr-dht.c |  114 ++++++++++++++++++++++++++++++++++++++-------
     1 files changed, 96 insertions(+), 18 deletions(-)
    
    diff --git a/libtransmission/tr-dht.c b/libtransmission/tr-dht.c
    index 46be697..a8a7c02 100644
    a b THE SOFTWARE. 
    3030#include <sys/time.h>
    3131#include <sys/types.h>
    3232#include <sys/socket.h> /* socket(), bind() */
     33#include <netdb.h>
    3334#include <unistd.h> /* close() */
    3435
    3536/* third party */
    struct bootstrap_closure { 
    9394    size_t len;
    9495};
    9596
     97static int
     98bootstrap_done( tr_session *session )
     99{
     100    int status = tr_dhtStatus(session, NULL);
     101    return status == TR_DHT_STOPPED || status >= TR_DHT_FIREWALLED;
     102}
     103
     104static void
     105sleep_a_bit( int roughly )
     106{
     107    struct timeval tv;
     108    tr_timevalSet( &tv, roughly / 2 + tr_cryptoWeakRandInt( roughly ),
     109                   tr_cryptoWeakRandInt( 1000000 ) );
     110    select( 0, NULL, NULL, NULL, &tv );
     111}
     112
    96113static void
    97114dht_bootstrap(void *closure)
    98115{
    dht_bootstrap(void *closure) 
    102119    if(session != cl->session)
    103120        return;
    104121
    105     for(i = 0; i < cl->len; i += 6)
    106     {
    107         struct timeval tv;
     122    if(cl->len > 0)
     123        tr_ninf( "DHT", "Bootstrapping from %d nodes", (int)(cl->len/6) );
     124
     125    for(i = 0; i < cl->len; i += 6) {
    108126        tr_port port;
    109127        struct tr_address addr;
    110         int status;
    111128
    112129        memset(&addr, 0, sizeof(addr));
    113130        addr.type = TR_AF_INET;
    dht_bootstrap(void *closure) 
    116133        port = ntohs(port);
    117134        /* There's no race here -- if we uninit between the test and the
    118135           AddNode, the AddNode will be ignored. */
    119         status = tr_dhtStatus(cl->session, NULL);
    120         if(status == TR_DHT_STOPPED || status >= TR_DHT_FIREWALLED)
     136        if( bootstrap_done(cl->session) )
    121137            break;
    122138        tr_dhtAddNode(cl->session, &addr, port, 1);
    123         tr_timevalSet( &tv, 2 + tr_cryptoWeakRandInt( 5 ), tr_cryptoWeakRandInt( 1000000 ) );
    124         select( 0, NULL, NULL, NULL, &tv );
     139        sleep_a_bit(4);
     140    }
     141
     142    if(!bootstrap_done(cl->session))
     143        sleep_a_bit(10);
     144
     145    if(!bootstrap_done(cl->session)) {
     146        char *bootstrap_file;
     147        FILE *f = NULL;
     148
     149        bootstrap_file =
     150            tr_buildPath(cl->session->configDir, "dht.bootstrap", NULL);
     151
     152        if(bootstrap_file)
     153            f = fopen(bootstrap_file, "r");
     154        if(f) {
     155            tr_ninf("DHT", "Attempting manual bootstrap");
     156            while(1) {
     157                struct addrinfo hints, *info, *infop;
     158                char buf[201], pp[10];
     159                char *p;
     160                int port = 0, rc;
     161
     162                p = fgets(buf, 200, f);
     163                if( p == NULL )
     164                    break;
     165
     166                p = memchr(buf, ' ', strlen(buf));
     167                if(p != NULL)
     168                    port = atoi(p + 1);
     169                if(p == NULL || port <= 0 || port >= 0x10000) {
     170                    tr_nerr("DHT", "Couldn't parse %s", buf);
     171                    continue;
     172                }
     173
     174                /* No, just passing p + 1 to gai won't work. */
     175                snprintf(pp, 10, "%d", port);
     176                *p = '\0';
     177
     178                memset(&hints, 0, sizeof(hints));
     179                hints.ai_socktype = SOCK_DGRAM;
     180                hints.ai_family = AF_INET;
     181                rc = getaddrinfo(buf, pp, &hints, &info);
     182                if(rc != 0) {
     183                    tr_nerr("DHT", "%s: %s", buf, gai_strerror(rc));
     184                    continue;
     185                }
     186
     187                infop = info;
     188
     189                while(infop) {
     190                    dht_ping_node(dht_socket,
     191                                  (struct sockaddr_in*)infop->ai_addr);
     192                    sleep_a_bit(4);
     193                    if(bootstrap_done(cl->session))
     194                        break;
     195                    infop = infop->ai_next;
     196                }
     197                freeaddrinfo(info);
     198                if(bootstrap_done(cl->session))
     199                    break;
     200            }
     201        }
    125202    }
     203
    126204    tr_free( cl->nodes );
    127205    tr_free( closure );
    128206    tr_ndbg( "DHT", "Finished bootstrapping" );
    tr_dhtInit(tr_session *ss, tr_address * tr_addr) 
    140218    const uint8_t * raw;
    141219    size_t len;
    142220    char v[5];
     221    struct bootstrap_closure * cl;
    143222
    144223    if( session ) /* already initialized */
    145224        return -1;
    tr_dhtInit(tr_session *ss, tr_address * tr_addr) 
    171250    if(rc == 0) {
    172251        if(( have_id = tr_bencDictFindRaw( &benc, "id", &raw, &len ) && len==20 ))
    173252            memcpy( myid, raw, len );
    174         if( tr_bencDictFindRaw( &benc, "nodes", &raw, &len ) && !(len%6) ) {
     253        if( tr_bencDictFindRaw( &benc, "nodes", &raw, &len ) && !(len%6) )
    175254            nodes = tr_memdup( raw, len );
    176             tr_ninf( "DHT", "Bootstrapping from %d old nodes", (int)(len/6) );
    177         }
    178255        tr_bencFree( &benc );
    179256    }
    180257
     258    if(nodes == NULL)
     259        len = 0;
     260
    181261    if( have_id )
    182262        tr_ninf( "DHT", "Reusing old id" );
    183263    else {
    tr_dhtInit(tr_session *ss, tr_address * tr_addr) 
    197277
    198278    session = ss;
    199279
    200     if(nodes) {
    201         struct bootstrap_closure * cl = tr_new( struct bootstrap_closure, 1 );
    202         cl->session = session;
    203         cl->nodes = nodes;
    204         cl->len = len;
    205         tr_threadNew( dht_bootstrap, cl );
    206     }
     280    cl = tr_new( struct bootstrap_closure, 1 );
     281    cl->session = session;
     282    cl->nodes = nodes;
     283    cl->len = len;
     284    tr_threadNew( dht_bootstrap, cl );
    207285
    208286    event_set( &dht_event, dht_socket, EV_READ, event_callback, NULL );
    209287    tr_timerAdd( &dht_event, 0, tr_cryptoWeakRandInt( 1000000 ) );