Changeset 9549


Ignore:
Timestamp:
11/24/09 01:59:51 (7 years ago)
Author:
charles
Message:

(trunk libT) jch's patches 0001 through 0004 for ticket #2576, IPv6 support for DHT (BEP #32)

Location:
trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/announcer.c

    r9533 r9549  
    16511651    while(( tor = tr_torrentNext( announcer->session, tor ))) {
    16521652        if( tor->dhtAnnounceAt <= now ) {
    1653             int rc = 1;
    1654             if( tor->isRunning && tr_torrentAllowsDHT(tor) )
    1655                 rc = tr_dhtAnnounce(tor, 1);
    1656             if(rc == 0)
    1657                 /* The DHT is not ready yet.  Try again soon. */
    1658                 tor->dhtAnnounceAt = now + 5 + tr_cryptoWeakRandInt( 5 );
    1659             else
    1660                 /* We should announce at least once every 30 minutes. */
    1661                 tor->dhtAnnounceAt = now + 25 * 60 + tr_cryptoWeakRandInt( 3 * 60 );
     1653            if( tor->isRunning && tr_torrentAllowsDHT(tor) ) {
     1654                int rc;
     1655                rc = tr_dhtAnnounce(tor, AF_INET, 1);
     1656                if(rc == 0)
     1657                    /* The DHT is not ready yet.  Try again soon. */
     1658                    tor->dhtAnnounceAt = now + 5 + tr_cryptoWeakRandInt( 5 );
     1659                else
     1660                    /* We should announce at least once every 30 minutes. */
     1661                    tor->dhtAnnounceAt =
     1662                        now + 25 * 60 + tr_cryptoWeakRandInt( 3 * 60 );
     1663            }
     1664        }
     1665
     1666        if( tor->dhtAnnounce6At <= now ) {
     1667            if( tor->isRunning && tr_torrentAllowsDHT(tor) ) {
     1668                int rc;
     1669                rc = tr_dhtAnnounce(tor, AF_INET6, 1);
     1670                if(rc == 0)
     1671                    tor->dhtAnnounce6At = now + 5 + tr_cryptoWeakRandInt( 5 );
     1672                else
     1673                    tor->dhtAnnounce6At =
     1674                        now + 25 * 60 + tr_cryptoWeakRandInt( 3 * 60 );
     1675            }
    16621676        }
    16631677    }
  • trunk/libtransmission/peer-msgs.c

    r9540 r9549  
    21292129
    21302130    if(tr_peerIoSupportsDHT(peer->io)) {
    2131         /* We don't have an IPv6 DHT yet.
    2132          * According to BEP-32, we can't send PORT over IPv6. */
     2131        /* Only send PORT over IPv6 when the IPv6 DHT is running (BEP-32). */
    21332132        const struct tr_address *addr = tr_peerIoGetAddress( peer->io, NULL );
    2134         if( addr->type == TR_AF_INET ) {
     2133        if( addr->type == TR_AF_INET || tr_globalIPv6() ) {
    21352134            protocolSendPort( m, tr_dhtPort( torrent->session ) );
    21362135        }
  • trunk/libtransmission/torrent.c

    r9540 r9549  
    13201320        tr_announcerTorrentStarted( tor );
    13211321        tor->dhtAnnounceAt = now + tr_cryptoWeakRandInt( 20 );
     1322        tor->dhtAnnounce6At = now + tr_cryptoWeakRandInt( 20 );
    13221323        tr_peerMgrStartTorrent( tor );
    13231324    }
  • trunk/libtransmission/torrent.h

    r9540 r9549  
    182182
    183183    time_t                     dhtAnnounceAt;
     184    time_t                     dhtAnnounce6At;
    184185    tr_bool                    dhtAnnounceInProgress;
     186    tr_bool                    dhtAnnounce6InProgress;
    185187
    186188    uint64_t                   downloadedCur;
  • trunk/libtransmission/tr-dht.c

    r9522 r9549  
    3131#include <sys/types.h>
    3232#include <sys/socket.h> /* socket(), bind() */
     33#include <netdb.h>
    3334#include <unistd.h> /* close() */
    3435
     
    5152#include "version.h"
    5253
    53 static int dht_socket;
    54 static struct event dht_event;
     54static int dht_socket = -1, dht6_socket = -1;
     55static struct event dht_event, dht6_event;
    5556static tr_port dht_port;
    5657static unsigned char myid[20];
     
    6263    tr_session *session;
    6364    uint8_t *nodes;
    64     size_t len;
     65    uint8_t *nodes6;
     66    size_t len, len6;
    6567};
     68
     69static int
     70bootstrap_done( tr_session *session, int af )
     71{
     72    int status;
     73
     74    if(af == 0)
     75        return
     76            bootstrap_done(session, AF_INET) &&
     77            bootstrap_done(session, AF_INET6);
     78
     79    status = tr_dhtStatus(session, af, NULL);
     80    return status == TR_DHT_STOPPED || status >= TR_DHT_FIREWALLED;
     81}
     82
     83static void
     84nap( int roughly )
     85{
     86    struct timeval tv;
     87    tr_timevalSet( &tv, roughly / 2 + tr_cryptoWeakRandInt( roughly ),
     88                   tr_cryptoWeakRandInt( 1000000 ) );
     89    select( 0, NULL, NULL, NULL, &tv );
     90}
     91
     92static int
     93bootstrap_af(tr_session *session)
     94{
     95    if( bootstrap_done(session, AF_INET6) )
     96        return AF_INET;
     97    else if ( bootstrap_done(session, AF_INET) )
     98        return AF_INET6;
     99    else
     100        return 0;
     101}
     102
     103static void
     104bootstrap_from_name( const char *name, short int port, int af )
     105{
     106    struct addrinfo hints, *info, *infop;
     107    char pp[10];
     108    int rc;
     109
     110    memset(&hints, 0, sizeof(hints));
     111    hints.ai_socktype = SOCK_DGRAM;
     112    hints.ai_family = af;
     113    /* No, just passing p + 1 to gai won't work. */
     114    snprintf(pp, 10, "%d", port);
     115
     116    rc = getaddrinfo(name, pp, &hints, &info);
     117    if(rc != 0) {
     118        tr_nerr("DHT", "%s:%s: %s", name, pp, gai_strerror(rc));
     119        return;
     120    }
     121
     122    infop = info;
     123    while(infop) {
     124        dht_ping_node(infop->ai_addr, infop->ai_addrlen);
     125
     126        nap(15);
     127
     128        if(bootstrap_done(session, af))
     129            break;
     130        infop = infop->ai_next;
     131    }
     132    freeaddrinfo(info);
     133}
    66134
    67135static void
     
    69137{
    70138    struct bootstrap_closure *cl = closure;
    71     size_t i;
     139    int i;
     140    int num = cl->len / 6, num6 = cl->len6 / 18;
    72141
    73142    if(session != cl->session)
    74143        return;
    75144
    76     for(i = 0; i < cl->len; i += 6)
    77     {
    78         struct timeval tv;
    79         tr_port port;
    80         struct tr_address addr;
    81         int status;
    82 
    83         memset(&addr, 0, sizeof(addr));
    84         addr.type = TR_AF_INET;
    85         memcpy(&addr.addr.addr4, &cl->nodes[i], 4);
    86         memcpy(&port, &cl->nodes[i + 4], 2);
    87         port = ntohs(port);
    88         /* There's no race here -- if we uninit between the test and the
    89            AddNode, the AddNode will be ignored. */
    90         status = tr_dhtStatus(cl->session, NULL);
    91         if(status == TR_DHT_STOPPED || status >= TR_DHT_FIREWALLED)
     145    if(cl->len > 0)
     146        tr_ninf( "DHT", "Bootstrapping from %d nodes", num );
     147
     148    if(cl->len6 > 0)
     149        tr_ninf( "DHT", "Bootstrapping from %d IPv6 nodes", num6 );
     150
     151
     152    for(i = 0; i < MAX(num, num6); i++) {
     153        if( i < num && !bootstrap_done(cl->session, AF_INET) ) {
     154            tr_port port;
     155            struct tr_address addr;
     156
     157            memset(&addr, 0, sizeof(addr));
     158            addr.type = TR_AF_INET;
     159            memcpy(&addr.addr.addr4, &cl->nodes[i * 6], 4);
     160            memcpy(&port, &cl->nodes[i * 6 + 4], 2);
     161            port = ntohs(port);
     162            tr_dhtAddNode(cl->session, &addr, port, 1);
     163        }
     164        if( i < num6 && !bootstrap_done(cl->session, AF_INET6) ) {
     165            tr_port port;
     166            struct tr_address addr;
     167
     168            memset(&addr, 0, sizeof(addr));
     169            addr.type = TR_AF_INET6;
     170            memcpy(&addr.addr.addr6, &cl->nodes6[i * 18], 16);
     171            memcpy(&port, &cl->nodes6[i * 18 + 16], 2);
     172            port = ntohs(port);
     173            tr_dhtAddNode(cl->session, &addr, port, 1);
     174        }
     175
     176        /* Our DHT code is able to take up to 9 nodes in a row without
     177           dropping any.  After that, it takes some time to split buckets.
     178           So ping the first 8 nodes quickly, then slow down. */
     179        if(i < 8)
     180            nap(2);
     181        else
     182            nap(15);
     183
     184        if(bootstrap_done( session, 0 ))
    92185            break;
    93         tr_dhtAddNode(cl->session, &addr, port, 1);
    94         tr_timevalSet( &tv, 2 + tr_cryptoWeakRandInt( 5 ), tr_cryptoWeakRandInt( 1000000 ) );
    95         select( 0, NULL, NULL, NULL, &tv );
    96     }
    97     tr_free( cl->nodes );
     186    }
     187
     188    if(!bootstrap_done(cl->session, 0)) {
     189        char *bootstrap_file;
     190        FILE *f = NULL;
     191
     192        bootstrap_file =
     193            tr_buildPath(cl->session->configDir, "dht.bootstrap", NULL);
     194
     195        if(bootstrap_file)
     196            f = fopen(bootstrap_file, "r");
     197        if(f) {
     198            tr_ninf("DHT", "Attempting manual bootstrap");
     199            while(1) {
     200                char buf[201];
     201                char *p;
     202                int port = 0;
     203
     204                p = fgets(buf, 200, f);
     205                if( p == NULL )
     206                    break;
     207
     208                p = memchr(buf, ' ', strlen(buf));
     209                if(p != NULL)
     210                    port = atoi(p + 1);
     211                if(p == NULL || port <= 0 || port >= 0x10000) {
     212                    tr_nerr("DHT", "Couldn't parse %s", buf);
     213                    continue;
     214                }
     215
     216                *p = '\0';
     217
     218                bootstrap_from_name( buf, port, bootstrap_af(session) );
     219
     220                if(bootstrap_done(cl->session, 0))
     221                    break;
     222            }
     223        }
     224    }
     225
     226    /* We really don't want to abuse our bootstrap nodes.
     227       Be glacially slow. */
     228    if(!bootstrap_done(cl->session, 0))
     229        nap(30);
     230
     231    if(!bootstrap_done(cl->session, 0)) {
     232        tr_ninf("DHT", "Attempting bootstrap from dht.transmissionbt.com");
     233        bootstrap_from_name( "dht.transmissionbt.com", 6881,
     234                             bootstrap_af(session) );
     235    }
     236
     237    if( cl->nodes )
     238        tr_free( cl->nodes );
     239    if( cl->nodes6 )
     240        tr_free( cl->nodes6 );
    98241    tr_free( closure );
    99242    tr_ndbg( "DHT", "Finished bootstrapping" );
    100243}
    101244
     245/* BEP-32 has a rather nice explanation of why we need to bind to one
     246   IPv6 address, if I may say so myself. */
     247
     248static int
     249rebind_ipv6(int force)
     250{
     251    struct sockaddr_in6 sin6;
     252    const unsigned char *ipv6 = tr_globalIPv6();
     253    static unsigned char *last_bound = NULL;
     254    int rc;
     255
     256    if(dht6_socket < 0)
     257        return 0;
     258
     259    if(!force &&
     260       ((ipv6 == NULL && last_bound == NULL) ||
     261        (ipv6 != NULL && last_bound != NULL &&
     262         memcmp(ipv6, last_bound, 16) == 0)))
     263        return 0;
     264
     265    memset(&sin6, 0, sizeof(sin6));
     266    sin6.sin6_family = AF_INET6;
     267    if(ipv6)
     268        memcpy(&sin6.sin6_addr, ipv6, 16);
     269    sin6.sin6_port = htons(dht_port);
     270    rc = bind(dht6_socket, (struct sockaddr*)&sin6, sizeof(sin6));
     271
     272    if(last_bound)
     273        free(last_bound);
     274    last_bound = NULL;
     275
     276    if(rc >= 0 && ipv6) {
     277        last_bound = malloc(16);
     278        if(last_bound)
     279            memcpy(last_bound, ipv6, 16);
     280    }
     281    return rc;
     282}
     283
    102284int
    103 tr_dhtInit(tr_session *ss, tr_address * tr_addr)
     285tr_dhtInit(tr_session *ss, const tr_address * tr_addr)
    104286{
    105287    struct sockaddr_in sin;
     
    108290    tr_bool have_id = FALSE;
    109291    char * dat_file;
    110     uint8_t * nodes = NULL;
     292    uint8_t * nodes = NULL, * nodes6 = NULL;
    111293    const uint8_t * raw;
    112     size_t len;
     294    size_t len, len6;
    113295    char v[5];
     296    struct bootstrap_closure * cl;
    114297
    115298    if( session ) /* already initialized */
     
    128311    memset(&sin, 0, sizeof(sin));
    129312    sin.sin_family = AF_INET;
    130     memcpy(&(sin.sin_addr), &(tr_addr->addr.addr4), sizeof (struct in_addr));
     313    memcpy(&sin.sin_addr, &tr_addr->addr.addr4, sizeof (struct in_addr));
    131314    sin.sin_port = htons(dht_port);
    132315    rc = bind(dht_socket, (struct sockaddr*)&sin, sizeof(sin));
     
    134317        goto fail;
    135318
     319    if(tr_globalIPv6()) {
     320        dht6_socket = socket(PF_INET6, SOCK_DGRAM, 0);
     321        if(dht6_socket < 0)
     322            goto fail;
     323
     324        rebind_ipv6(1);
     325
     326    }
     327
    136328    if( getenv( "TR_DHT_VERBOSE" ) != NULL )
    137329        dht_debug = stderr;
     
    141333    tr_free( dat_file );
    142334    if(rc == 0) {
    143         if(( have_id = tr_bencDictFindRaw( &benc, "id", &raw, &len ) && len==20 ))
     335        have_id = tr_bencDictFindRaw(&benc, "id", &raw, &len);
     336        if( have_id && len==20 )
    144337            memcpy( myid, raw, len );
    145         if( tr_bencDictFindRaw( &benc, "nodes", &raw, &len ) && !(len%6) ) {
    146             nodes = tr_memdup( raw, len );
    147             tr_ninf( "DHT", "Bootstrapping from %d old nodes", (int)(len/6) );
     338        if( dht_socket >= 0 &&
     339            tr_bencDictFindRaw( &benc, "nodes", &raw, &len ) && !(len%6) ) {
     340                nodes = tr_memdup( raw, len );
     341        }
     342        if( dht6_socket > 0 &&
     343            tr_bencDictFindRaw( &benc, "nodes6", &raw, &len6 ) && !(len6%18) ) {
     344            nodes6 = tr_memdup( raw, len6 );
    148345        }
    149346        tr_bencFree( &benc );
    150347    }
     348
     349    if(nodes == NULL)
     350        len = 0;
     351    if(nodes6 == NULL)
     352        len6 = 0;
    151353
    152354    if( have_id )
     
    163365    v[2] = (SVN_REVISION_NUM >> 8) & 0xFF;
    164366    v[3] = SVN_REVISION_NUM & 0xFF;
    165     rc = dht_init( dht_socket, myid, (const unsigned char*)v );
     367    rc = dht_init( dht_socket, dht6_socket, myid, (const unsigned char*)v );
    166368    if(rc < 0)
    167369        goto fail;
     
    169371    session = ss;
    170372
    171     if(nodes) {
    172         struct bootstrap_closure * cl = tr_new( struct bootstrap_closure, 1 );
    173         cl->session = session;
    174         cl->nodes = nodes;
    175         cl->len = len;
    176         tr_threadNew( dht_bootstrap, cl );
    177     }
     373    cl = tr_new( struct bootstrap_closure, 1 );
     374    cl->session = session;
     375    cl->nodes = nodes;
     376    cl->nodes6 = nodes6;
     377    cl->len = len;
     378    cl->len6 = len6;
     379    tr_threadNew( dht_bootstrap, cl );
    178380
    179381    event_set( &dht_event, dht_socket, EV_READ, event_callback, NULL );
     382    event_set( &dht6_event, dht6_socket, EV_READ, event_callback, NULL );
    180383    tr_timerAdd( &dht_event, 0, tr_cryptoWeakRandInt( 1000000 ) );
     384    tr_timerAdd( &dht6_event, 0, tr_cryptoWeakRandInt( 1000000 ) );
    181385
    182386    tr_ndbg( "DHT", "DHT initialized" );
     
    188392        const int save = errno;
    189393        close(dht_socket);
    190         dht_socket = -1;
     394        if( dht6_socket >= 0 )
     395            close(dht6_socket);
     396        dht_socket = dht6_socket = -1;
    191397        session = NULL;
    192398        tr_ndbg( "DHT", "DHT initialization failed (errno = %d)", save );
     
    206412
    207413    event_del(&dht_event);
     414    event_del(&dht6_event);
    208415
    209416    /* Since we only save known good nodes, avoid erasing older data if we
    210417       don't know enough nodes. */
    211     if(tr_dhtStatus(ss, NULL) < TR_DHT_FIREWALLED)
     418    if(tr_dhtStatus(ss, AF_INET, NULL) < TR_DHT_FIREWALLED)
    212419        tr_ninf( "DHT", "Not saving nodes, DHT not ready" );
    213420    else {
    214421        tr_benc benc;
    215422        struct sockaddr_in sins[300];
    216         char compact[300 * 6];
     423        struct sockaddr_in6 sins6[300];
     424        char compact[300 * 6], compact6[300 * 18];
    217425        char *dat_file;
    218         int i;
    219         int n = dht_get_nodes(sins, 300);
    220         int j = 0;
    221 
    222         tr_ninf( "DHT", "Saving %d nodes", n );
    223         for( i=0; i<n; ++i ) {
     426        int i, j, num = 300, num6 = 300;
     427        int n = dht_get_nodes(sins, &num, sins6, &num6);
     428
     429        tr_ninf( "DHT", "Saving %d (%d + %d) nodes", n, num, num6 );
     430
     431        j = 0;
     432        for( i=0; i<num; ++i ) {
    224433            memcpy( compact + j, &sins[i].sin_addr, 4 );
    225434            memcpy( compact + j + 4, &sins[i].sin_port, 2 );
    226435            j += 6;
    227436        }
    228         tr_bencInitDict( &benc, 2 );
     437        j = 0;
     438        for( i=0; i<num6; ++i ) {
     439            memcpy( compact6 + j, &sins6[i].sin6_addr, 16 );
     440            memcpy( compact6 + j + 16, &sins6[i].sin6_port, 2 );
     441            j += 18;
     442        }
     443        tr_bencInitDict( &benc, 3 );
    229444        tr_bencDictAddRaw( &benc, "id", myid, 20 );
    230         tr_bencDictAddRaw( &benc, "nodes", compact, j );
     445        if(num > 0)
     446            tr_bencDictAddRaw( &benc, "nodes", compact, num * 6 );
     447        if(num6 > 0)
     448            tr_bencDictAddRaw( &benc, "nodes6", compact6, num6 * 18 );
    231449        dat_file = tr_buildPath( ss->configDir, "dht.dat", NULL );
    232450        tr_bencToFile( &benc, TR_FMT_BENC, dat_file );
     
    235453    }
    236454
    237     dht_uninit( dht_socket, 0 );
     455    dht_uninit( 1 );
    238456    tr_netCloseSocket( dht_socket );
     457    if(dht6_socket > 0)
     458        tr_netCloseSocket( dht6_socket );
    239459
    240460    tr_ndbg("DHT", "Done uninitializing DHT");
     
    244464
    245465tr_bool
    246 tr_dhtEnabled( const tr_session * ss )
     466tr_dhtEnabled( tr_session * ss )
    247467{
    248468    return ss && ( ss == session );
     
    251471struct getstatus_closure
    252472{
     473    int af;
    253474    sig_atomic_t status;
    254475    sig_atomic_t count;
     
    256477
    257478static void
    258 getstatus( void * closure )
    259 {
    260     struct getstatus_closure * ret = closure;
     479getstatus( void * cl )
     480{
     481    struct getstatus_closure * closure = cl;
    261482    int good, dubious, incoming;
    262483
    263     dht_nodes( &good, &dubious, NULL, &incoming );
    264 
    265     ret->count = good + dubious;
     484    dht_nodes( closure->af, &good, &dubious, NULL, &incoming );
     485
     486    closure->count = good + dubious;
    266487
    267488    if( good < 4 || good + dubious <= 8 )
    268         ret->status = TR_DHT_BROKEN;
     489        closure->status = TR_DHT_BROKEN;
    269490    else if( good < 40 )
    270         ret->status = TR_DHT_POOR;
     491        closure->status = TR_DHT_POOR;
    271492    else if( incoming < 8 )
    272         ret->status = TR_DHT_FIREWALLED;
     493        closure->status = TR_DHT_FIREWALLED;
    273494    else
    274         ret->status = TR_DHT_GOOD;
     495        closure->status = TR_DHT_GOOD;
    275496}
    276497
    277498int
    278 tr_dhtStatus( tr_session * ss, int * nodes_return )
    279 {
    280     struct getstatus_closure ret = { -1, - 1 };
     499tr_dhtStatus( tr_session * ss, int af, int * nodes_return )
     500{
     501    struct getstatus_closure closure = { af, -1, -1 };
    281502
    282503    if( !tr_dhtEnabled( ss ) )
    283504        return TR_DHT_STOPPED;
    284505
    285     tr_runInEventThread( ss, getstatus, &ret );
    286     while( ret.status < 0 )
     506    if(dht_socket < 0 && dht6_socket < 0)
     507        return TR_DHT_STOPPED;
     508
     509    if(af == AF_INET && dht_socket < 0)
     510        return TR_DHT_STOPPED;
     511
     512    if(af == AF_INET6 && dht6_socket < 0)
     513        return TR_DHT_STOPPED;
     514
     515    tr_runInEventThread( ss, getstatus, &closure );
     516    while( closure.status < 0 )
    287517        tr_wait( 10 /*msec*/ );
    288518
    289519    if( nodes_return )
    290         *nodes_return = ret.count;
    291 
    292     return ret.status;
     520        *nodes_return = closure.count;
     521
     522    return closure.status;
    293523}
    294524
    295525tr_port
    296 tr_dhtPort( const tr_session *ss )
     526tr_dhtPort( tr_session *ss )
    297527{
    298528    return tr_dhtEnabled( ss ) ? dht_port : 0;
     
    305535               tr_bool            bootstrap )
    306536{
    307     struct sockaddr_in sin;
     537    int af = address->type == TR_AF_INET ? AF_INET : AF_INET6;
    308538
    309539    if( !tr_dhtEnabled( ss ) )
    310540        return 0;
    311541
    312     if( address->type != TR_AF_INET )
    313         return 0;
    314 
    315542    /* Since we don't want to abuse our bootstrap nodes,
    316543     * we don't ping them if the DHT is in a good state. */
     544
    317545    if(bootstrap) {
    318         if(tr_dhtStatus(ss, NULL) >= TR_DHT_FIREWALLED)
     546        if(tr_dhtStatus(ss, af, NULL) >= TR_DHT_FIREWALLED)
    319547            return 0;
    320548    }
    321549
    322     memset(&sin, 0, sizeof(sin));
    323     sin.sin_family = AF_INET;
    324     memcpy(&sin.sin_addr, &address->addr.addr4, 4);
    325     sin.sin_port = htons(port);
    326     dht_ping_node(dht_socket, &sin);
    327 
    328     return 1;
     550    if( address->type == TR_AF_INET ) {
     551        struct sockaddr_in sin;
     552        memset(&sin, 0, sizeof(sin));
     553        sin.sin_family = AF_INET;
     554        memcpy(&sin.sin_addr, &address->addr.addr4, 4);
     555        sin.sin_port = htons(port);
     556        dht_ping_node((struct sockaddr*)&sin, sizeof(sin));
     557        return 1;
     558    } else if( address->type == TR_AF_INET6 ) {
     559        struct sockaddr_in6 sin6;
     560        memset(&sin6, 0, sizeof(sin6));
     561        sin6.sin6_family = AF_INET6;
     562        memcpy(&sin6.sin6_addr, &address->addr.addr6, 16);
     563        sin6.sin6_port = htons(port);
     564        dht_ping_node((struct sockaddr*)&sin6, sizeof(sin6));
     565        return 1;
     566    }
     567
     568    return 0;
    329569}
    330570
     
    346586          unsigned char *info_hash, void *data, size_t data_len )
    347587{
    348     if( event == DHT_EVENT_VALUES )
    349     {
     588    if( event == DHT_EVENT_VALUES || event == DHT_EVENT_VALUES6 ) {
    350589        tr_torrent *tor;
    351590        tr_globalLock( session );
     
    354593        {
    355594            size_t i, n;
    356             tr_pex * pex = tr_peerMgrCompactToPex(data, data_len, NULL, 0, &n);
     595            tr_pex * pex;
     596            if( event == DHT_EVENT_VALUES )
     597                pex = tr_peerMgrCompactToPex(data, data_len, NULL, 0, &n);
     598            else
     599                pex = tr_peerMgrCompact6ToPex(data, data_len, NULL, 0, &n);
    357600            for( i=0; i<n; ++i )
    358601                tr_peerMgrAddPex( tor, TR_PEER_FROM_DHT, pex+i );
    359602            tr_free(pex);
    360             tr_torinf(tor, "Learned %d peers from DHT", (int)n);
     603            tr_torinf(tor, "Learned %d%s peers from DHT",
     604                      (int)n,
     605                      event == DHT_EVENT_VALUES6 ? " IPv6" : "");
    361606        }
    362607        tr_globalUnlock( session );
    363     }
    364     else if( event == DHT_EVENT_SEARCH_DONE )
    365     {
     608    } else if( event == DHT_EVENT_SEARCH_DONE ||
     609               event == DHT_EVENT_SEARCH_DONE6) {
    366610        tr_torrent * tor = tr_torrentFindFromHash( session, info_hash );
    367611        if( tor ) {
    368             tr_torinf(tor, "DHT announce done");
    369             tor->dhtAnnounceInProgress = 0;
     612            if( event == DHT_EVENT_SEARCH_DONE ) {
     613                tr_torinf(tor, "DHT announce done");
     614                tor->dhtAnnounceInProgress = 0;
     615            } else {
     616                tr_torinf(tor, "IPv6 DHT announce done");
     617                tor->dhtAnnounce6InProgress = 0;
     618            }
    370619        }
    371620    }
     
    373622
    374623int
    375 tr_dhtAnnounce(tr_torrent *tor, tr_bool announce)
    376 {
    377     int rc, status, numnodes;
     624tr_dhtAnnounce(tr_torrent *tor, int af, tr_bool announce)
     625{
     626    int rc, status, numnodes, ret = 0;
    378627
    379628    if( !tr_torrentAllowsDHT( tor ) )
    380629        return -1;
    381630
    382     status = tr_dhtStatus( tor->session, &numnodes );
    383     if(status < TR_DHT_POOR ) {
    384         tr_tordbg(tor, "DHT not ready (%s, %d nodes)",
     631    status = tr_dhtStatus( tor->session, af, &numnodes );
     632    if(status >= TR_DHT_POOR ) {
     633        rc = dht_search( tor->info.hash,
     634                         announce ? tr_sessionGetPeerPort(session) : 0,
     635                         af, callback, NULL);
     636        if( rc >= 1 ) {
     637            tr_torinf(tor, "Starting%s DHT announce (%s, %d nodes)",
     638                      af == AF_INET6 ? " IPv6" : "",
     639                      tr_dhtPrintableStatus(status), numnodes);
     640            if(af == AF_INET)
     641                tor->dhtAnnounceInProgress = TRUE;
     642            else
     643                tor->dhtAnnounce6InProgress = TRUE;
     644            ret = 1;
     645        } else {
     646            tr_torerr(tor, "%sDHT announce failed, errno = %d (%s, %d nodes)",
     647                      af == AF_INET6 ? "IPv6 " : "",
     648                      errno, tr_dhtPrintableStatus(status), numnodes);
     649        }
     650    } else {
     651        tr_tordbg(tor, "%sDHT not ready (%s, %d nodes)",
     652                  af == AF_INET6 ? "IPv6 " : "",
    385653                  tr_dhtPrintableStatus(status), numnodes);
    386         return 0;
    387     }
    388 
    389     rc = dht_search( dht_socket, tor->info.hash,
    390                      announce ? tr_sessionGetPeerPort(session) : 0,
    391                      callback, NULL);
    392 
    393     if( rc >= 1 ) {
    394         tr_torinf(tor, "Starting DHT announce (%s, %d nodes)",
    395                   tr_dhtPrintableStatus(status), numnodes);
    396         tor->dhtAnnounceInProgress = TRUE;
    397     } else {
    398         tr_torerr(tor, "DHT announce failed, errno = %d (%s, %d nodes)",
    399                   errno, tr_dhtPrintableStatus(status), numnodes);
    400     }
    401 
    402     return 1;
     654    }
     655
     656    return ret;
    403657}
    404658
     
    406660event_callback(int s, short type, void *ignore UNUSED )
    407661{
     662    struct event *event = (s == dht_socket) ? &dht_event : &dht6_event;
    408663    time_t tosleep;
    409 
    410     if( dht_periodic(s, type == EV_READ, &tosleep, callback, NULL) < 0 ) {
     664    static int count = 0;
     665
     666    if( dht_periodic( type == EV_READ, &tosleep, callback, NULL) < 0 ) {
    411667        if(errno == EINTR) {
    412668            tosleep = 0;
     
    419675    }
    420676
     677    /* Only do this once in a while.  Counting rather than measuring time
     678       avoids a system call. */
     679    count++;
     680    if(count >= 128) {
     681        rebind_ipv6(0);
     682        count = 0;
     683    }
     684
    421685    /* Being slightly late is fine,
    422686       and has the added benefit of adding some jitter. */
    423     tr_timerAdd( &dht_event, tosleep, tr_cryptoWeakRandInt( 1000000 ) );
     687    tr_timerAdd( event, tosleep, tr_cryptoWeakRandInt( 1000000 ) );
    424688}
    425689
  • trunk/libtransmission/tr-dht.h

    r9434 r9549  
    2727#define TR_DHT_GOOD 4
    2828
    29 int  tr_dhtInit( tr_session *, tr_address * );
     29int  tr_dhtInit( tr_session *, const tr_address * );
    3030void tr_dhtUninit( tr_session * );
    31 tr_bool tr_dhtEnabled( const tr_session * );
    32 tr_port tr_dhtPort ( const tr_session * );
    33 int tr_dhtStatus( tr_session *, int * setme_nodeCount );
     31tr_bool tr_dhtEnabled( tr_session * );
     32tr_port tr_dhtPort ( tr_session * );
     33int tr_dhtStatus( tr_session *, int af, int * setme_nodeCount );
    3434const char *tr_dhtPrintableStatus(int status);
    3535int tr_dhtAddNode( tr_session *, const tr_address *, tr_port, tr_bool bootstrap );
    36 int tr_dhtAnnounce( tr_torrent *, tr_bool announce );
     36int tr_dhtAnnounce( tr_torrent *, int af, tr_bool announce );
  • trunk/third-party/dht/CHANGES

    r9323 r9549  
     122 November 2009: dht-0.11
     2
     3  * Implemented IPv6 support (BEP-32).
     4  * Fixed a bug which could cause us to never mark a search as finished.
     5  * Fixed a bug that could cause us to send incomplete lists in response to
     6    find_nodes.
     7  * Limit the number of hashes that we're willing to track.
     8  * Made bucket maintenance slightly more aggressive.
     9  * Produce on-the-wire error messages to give a hint to the other side.
     10  * Added a bunch of options to dht-example to make it useful as
     11    a bootstrap node.
     12  * Send version "JC\0\0" when using dht-example.
     13
    11418 October 2009: dht-0.10
    215
  • trunk/third-party/dht/README

    r9145 r9549  
    2020
    2121This must be called before using the library.  You pass it a bound IPv4
    22 datagram socket, and your node id, a 20-octet array that should be globally
    23 unique.
     22datagram socket, a bound IPv6 datagram socket, and your node id, a 20-octet
     23array that should be globally unique.
     24
     25If you're on a multi-homed host, you should bind the sockets to one of your
     26addresses.
    2427
    2528Node ids must be well distributed, so you cannot just use your Bittorrent
     
    2831idea to keep the id stable, so you may want to store it in stable storage
    2932at client shutdown.
     33
    3034 
    3135* dht_uninit
     
    148152
    149153The callback function is called with 5 arguments.  Closure is simply the
    150 value that you passed to dht_periodic.  Event is one of DHT_EVENT_VALUES,
    151 which indicates that we have new values, or DHT_EVENT_SEARCH_DONE, which
    152 indicates that a search has completed.  In either case, info_hash is set to
    153 the info-hash of the search.
     154value that you passed to dht_periodic.  Event is one of DHT_EVENT_VALUES or
     155DHT_EVENT_VALUES6, which indicates that we have new values, or
     156DHT_EVENT_SEARCH_DONE or DHT_EVENT_SEARCH_DONE6, which indicates that
     157a search has completed.  In either case, info_hash is set to the info-hash
     158of the search.
    154159
    155160In the case of DHT_EVENT_VALUES, data is a list of nodes in ``compact''
    156 format -- 6 bytes per node, 4 for the IP address and 2 for the port.  It's
    157 length in bytes is in data_len.
     161format -- 6 or 18 bytes per node.  Its length in bytes is in data_len.
    158162
    159163* dht_hash
     
    187191keep both pieces.
    188192
    189 IPv6 support is deliberately not included: designing a double-stack
    190 distributed hash table raises some tricky issues, and doing it naively may
    191 break connectivity for everyone.
    192193
    193194                                        Juliusz Chroboczek
  • trunk/third-party/dht/dht-example.c

    r9323 r9549  
    2121
    2222#define MAX_BOOTSTRAP_NODES 20
    23 static struct sockaddr_in bootstrap_nodes[MAX_BOOTSTRAP_NODES];
     23static struct sockaddr_storage bootstrap_nodes[MAX_BOOTSTRAP_NODES];
    2424static int num_bootstrap_nodes = 0;
    2525
     
    9393{
    9494    int i, rc, fd;
    95     int s, port;
     95    int s = -1, s6 = -1, port;
    9696    int have_id = 0;
    9797    unsigned char myid[20];
    9898    time_t tosleep = 0;
     99    char *id_file = "dht-example.id";
     100    int opt;
     101    int quiet = 0, ipv4 = 1, ipv6 = 1;
     102    struct sockaddr_in sin;
     103    struct sockaddr_in6 sin6;
     104
     105    memset(&sin, 0, sizeof(sin));
     106    sin.sin_family = AF_INET;
     107
     108    memset(&sin6, 0, sizeof(sin6));
     109    sin6.sin6_family = AF_INET6;
     110
     111
     112
     113    while(1) {
     114        opt = getopt(argc, argv, "q46b:i:");
     115        if(opt < 0)
     116            break;
     117
     118        switch(opt) {
     119        case 'q': quiet = 1; break;
     120        case '4': ipv6 = 0; break;
     121        case '6': ipv4 = 0; break;
     122        case 'b': {
     123            char buf[16];
     124            int rc;
     125            rc = inet_pton(AF_INET, optarg, buf);
     126            if(rc == 1) {
     127                memcpy(&sin.sin_addr, buf, 4);
     128                break;
     129            }
     130            rc = inet_pton(AF_INET6, optarg, buf);
     131            if(rc == 1) {
     132                memcpy(&sin6.sin6_addr, buf, 16);
     133                break;
     134            }
     135            goto usage;
     136        }
     137            break;
     138        case 'i':
     139            id_file = optarg;
     140            break;
     141        default:
     142            goto usage;
     143        }
     144    }
    99145
    100146    /* Ids need to be distributed evenly, so you cannot just use your
    101147       bittorrent id.  Either generate it randomly, or take the SHA-1 of
    102148       something. */
    103     fd = open("dht-example.id", O_RDONLY);
     149    fd = open(id_file, O_RDONLY);
    104150    if(fd >= 0) {
    105151        rc = read(fd, myid, 20);
     
    109155    }
    110156   
     157    fd = open("/dev/urandom", O_RDONLY);
     158    if(fd < 0) {
     159        perror("open(random)");
     160        exit(1);
     161    }
     162
    111163    if(!have_id) {
    112         fd = open("/dev/urandom", O_RDONLY);
    113         if(fd < 0) {
    114             perror("open(random)");
    115             exit(1);
    116         }
     164        int ofd;
     165
    117166        rc = read(fd, myid, 20);
    118167        if(rc < 0) {
     
    123172        close(fd);
    124173
    125         fd = open("dht-example.id", O_WRONLY | O_CREAT | O_TRUNC, 0666);
    126         if(fd >= 0) {
    127             rc = write(fd, myid, 20);
     174        ofd = open(id_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
     175        if(ofd >= 0) {
     176            rc = write(ofd, myid, 20);
    128177            if(rc < 20)
    129                 unlink("dht-example.id");
    130             close(fd);
    131         }
    132     }
     178                unlink(id_file);
     179            close(ofd);
     180        }
     181    }
     182
     183    {
     184        unsigned seed;
     185        read(fd, &seed, sizeof(seed));
     186        srandom(seed);
     187    }
     188
     189    close(fd);
    133190
    134191    if(argc < 2)
    135192        goto usage;
    136193
    137     i = 1;
     194    i = optind;
    138195
    139196    if(argc < i + 1)
     
    147204        struct addrinfo hints, *info, *infop;
    148205        memset(&hints, 0, sizeof(hints));
    149         hints.ai_family = AF_INET;
    150206        hints.ai_socktype = SOCK_DGRAM;
    151         rc = getaddrinfo(argv[i], NULL, &hints, &info);
     207        if(!ipv6)
     208            hints.ai_family = AF_INET;
     209        else if(!ipv4)
     210            hints.ai_family = AF_INET6;
     211        else
     212            hints.ai_family = 0;
     213        rc = getaddrinfo(argv[i], argv[i + 1], &hints, &info);
    152214        if(rc != 0) {
    153215            fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rc));
     
    161223        infop = info;
    162224        while(infop) {
    163             if(infop->ai_addr->sa_family == AF_INET) {
    164                 struct sockaddr_in sin;
    165                 memcpy(&sin, infop->ai_addr, infop->ai_addrlen);
    166                 sin.sin_port = htons(atoi(argv[i]));
    167                 bootstrap_nodes[num_bootstrap_nodes] = sin;
    168                 num_bootstrap_nodes++;
    169             }
     225            memcpy(&bootstrap_nodes[num_bootstrap_nodes],
     226                   infop->ai_addr, infop->ai_addrlen);
    170227            infop = infop->ai_next;
     228            num_bootstrap_nodes++;
    171229        }
    172230        freeaddrinfo(info);
     
    177235    /* If you set dht_debug to a stream, every action taken by the DHT will
    178236       be logged. */
    179     dht_debug = stdout;
    180 
    181     /* We need an IPv4 socket, bound to a stable port.  Rumour has it that
    182        uTorrent works better when it is the same as your Bittorrent port. */
    183     s = socket(PF_INET, SOCK_DGRAM, 0);
    184     if(s < 0) {
    185         perror("socket");
     237    if(!quiet)
     238        dht_debug = stdout;
     239
     240    /* We need an IPv4 and an IPv6 socket, bound to a stable port.  Rumour
     241       has it that uTorrent works better when it is the same as your
     242       Bittorrent port. */
     243    if(ipv4) {
     244        s = socket(PF_INET, SOCK_DGRAM, 0);
     245        if(s < 0) {
     246            perror("socket(IPv4)");
     247        }
     248    }
     249
     250    if(ipv6) {
     251        s6 = socket(PF_INET6, SOCK_DGRAM, 0);
     252        if(s6 < 0) {
     253            perror("socket(IPv6)");
     254        }
     255    }
     256
     257    if(s < 0 && s6 < 0) {
     258        fprintf(stderr, "Eek!");
    186259        exit(1);
    187260    }
    188261
    189     {
    190         struct sockaddr_in sin;
    191         memset(&sin, 0, sizeof(sin));
    192         sin.sin_family = AF_INET;
     262
     263    if(s >= 0) {
    193264        sin.sin_port = htons(port);
    194265        rc = bind(s, (struct sockaddr*)&sin, sizeof(sin));
    195266        if(rc < 0) {
    196             perror("bind");
     267            perror("bind(IPv4)");
    197268            exit(1);
    198269        }
    199270    }
    200271
     272    if(s6 >= 0) {
     273        int rc;
     274        int val = 1;
     275
     276        rc = setsockopt(s6, IPPROTO_IPV6, IPV6_V6ONLY,
     277                        (char *)&val, sizeof(val));
     278        if(rc < 0) {
     279            perror("setsockopt(IPV6_V6ONLY)");
     280            exit(1);
     281        }
     282
     283        /* BEP-32 mandates that we should bind this socket to one of our
     284           global IPv6 addresses.  In this simple example, this only
     285           happens if the user used the -b flag. */
     286
     287        sin6.sin6_port = htons(port);
     288        rc = bind(s6, (struct sockaddr*)&sin6, sizeof(sin6));
     289        if(rc < 0) {
     290            perror("bind(IPv6)");
     291            exit(1);
     292        }
     293    }
     294
    201295    /* Init the dht.  This sets the socket into non-blocking mode. */
    202     rc = dht_init(s, myid, NULL);
     296    rc = dht_init(s, s6, myid, (unsigned char*)"JC\0\0");
    203297    if(rc < 0) {
    204298        perror("dht_init");
     
    218312       dht_insert_node.  If the ids are incorrect, the DHT will recover. */
    219313    for(i = 0; i < num_bootstrap_nodes; i++) {
    220         dht_ping_node(s, &bootstrap_nodes[i]);
     314        dht_ping_node((struct sockaddr*)&bootstrap_nodes[i],
     315                      sizeof(bootstrap_nodes[i]));
    221316        usleep(random() % 100000);
    222317    }
     
    229324
    230325        FD_ZERO(&readfds);
    231         FD_SET(s, &readfds);
    232         rc = select(s + 1, &readfds, NULL, NULL, &tv);
     326        if(s >= 0)
     327            FD_SET(s, &readfds);
     328        if(s6 >= 0)
     329            FD_SET(s6, &readfds);
     330        rc = select(s > s6 ? s + 1 : s6 + 1, &readfds, NULL, NULL, &tv);
    233331        if(rc < 0) {
    234332            if(errno != EINTR) {
     
    241339            break;
    242340
    243         rc = dht_periodic(s, rc > 0, &tosleep, callback, NULL);
     341        rc = dht_periodic(rc > 0, &tosleep, callback, NULL);
    244342        if(rc < 0) {
    245343            if(errno == EINTR) {
     
    254352
    255353        /* This is how you trigger a search for a torrent hash.  If port
    256            (the third argument) is non-zero, it also performs an announce.
     354           (the second argument) is non-zero, it also performs an announce.
    257355           Since peers expire announced data after 30 minutes, it's a good
    258356           idea to reannounce every 28 minutes or so. */
    259357        if(searching) {
    260             dht_search(s, hash, 0, callback, NULL);
     358            if(s >= 0)
     359                dht_search(hash, 0, AF_INET, callback, NULL);
     360            if(s6 >= 0)
     361                dht_search(hash, 0, AF_INET6, callback, NULL);
    261362            searching = 0;
    262363        }
     
    270371
    271372    {
    272         struct sockaddr_in sins[500];
     373        struct sockaddr_in sin[500];
     374        struct sockaddr_in6 sin6[500];
     375        int num = 500, num6 = 500;
    273376        int i;
    274         i = dht_get_nodes(sins, 500);
    275         printf("Found %d good nodes.\n", i);
    276     }
    277 
    278     dht_uninit(s, 1);
     377        i = dht_get_nodes(sin, &num, sin6, &num6);
     378        printf("Found %d (%d + %d) good nodes.\n", i, num, num6);
     379    }
     380
     381    dht_uninit(1);
    279382    return 0;
    280383   
    281384 usage:
    282     fprintf(stderr, "Foo!\n");
     385    printf("Usage: dht-example [-q] [-4] [-6] [-i filename] [-b address]...\n"
     386           "                   port [address port]...\n");
    283387    exit(1);
    284388}
  • trunk/third-party/dht/dht.c

    r9524 r9549  
    5858
    5959/* We set sin_family to 0 to mark unused slots. */
    60 #if AF_INET == 0
     60#if AF_INET == 0 || AF_INET6 == 0
    6161#error You lose
    6262#endif
     
    8181struct node {
    8282    unsigned char id[20];
    83     struct sockaddr_in sin;
     83    struct sockaddr_storage ss;
     84    int sslen;
    8485    time_t time;                /* time of last message received */
    8586    time_t reply_time;          /* time of last correct reply received */
     
    9091
    9192struct bucket {
     93    int af;
    9294    unsigned char first[20];
    9395    int count;                  /* number of nodes */
    9496    int time;                   /* time of last reply in this bucket */
    9597    struct node *nodes;
    96     struct sockaddr_in cached;  /* the address of a likely candidate */
     98    struct sockaddr_storage cached;  /* the address of a likely candidate */
     99    int cachedlen;
    97100    struct bucket *next;
    98101};
     
    100103struct search_node {
    101104    unsigned char id[20];
    102     struct sockaddr_in sin;
     105    struct sockaddr_storage ss;
     106    int sslen;
    103107    time_t request_time;        /* the time of the last unanswered request */
    104108    time_t reply_time;          /* the time of the last reply */
     
    117121struct search {
    118122    unsigned short tid;
     123    int af;
    119124    time_t step_time;           /* the time of the last search_step */
    120125    unsigned char id[20];
     
    128133struct peer {
    129134    time_t time;
    130     unsigned char ip[4];
     135    unsigned char ip[16];
     136    unsigned short len;
    131137    unsigned short port;
    132138};
     
    137143#endif
    138144
     145/* The maximum number of hashes we're willing to track. */
     146#ifndef DHT_MAX_HASHES
     147#define DHT_MAX_HASHES 16384
     148#endif
     149
    139150/* The maximum number of searches we keep data about. */
    140151#ifndef DHT_MAX_SEARCHES
     
    149160struct storage {
    150161    unsigned char id[20];
    151     int numpeers;
    152     int maxpeers;
     162    int numpeers, maxpeers;
    153163    struct peer *peers;
    154164    struct storage *next;
    155165};
    156166
    157 static int send_ping(int s, struct sockaddr *sa, int salen,
     167static int send_ping(struct sockaddr *sa, int salen,
    158168                     const unsigned char *tid, int tid_len);
    159 static int send_pong(int s, struct sockaddr *sa, int salen,
     169static int send_pong(struct sockaddr *sa, int salen,
    160170                     const unsigned char *tid, int tid_len);
    161 static int send_find_node(int s, struct sockaddr *sa, int salen,
     171static int send_find_node(struct sockaddr *sa, int salen,
    162172                          const unsigned char *tid, int tid_len,
    163                           const unsigned char *target, int confirm);
    164 static int send_nodes_peers(int s, struct sockaddr *sa, int salen,
     173                          const unsigned char *target, int want, int confirm);
     174static int send_nodes_peers(struct sockaddr *sa, int salen,
    165175                            const unsigned char *tid, int tid_len,
    166176                            const unsigned char *nodes, int nodes_len,
    167                             struct peer *peers1, int numpeers1,
    168                             struct peer *peers2, int numpeers2,
     177                            const unsigned char *nodes6, int nodes6_len,
     178                            int af, struct storage *st,
    169179                            const unsigned char *token, int token_len);
    170 static int send_closest_nodes(int s, struct sockaddr *sa, int salen,
     180static int send_closest_nodes(struct sockaddr *sa, int salen,
    171181                              const unsigned char *tid, int tid_len,
    172                               const unsigned char *id,
    173                               struct peer *peers1, int numpeers1,
    174                               struct peer *peers2, int numpeers2,
     182                              const unsigned char *id, int want,
     183                              int af, struct storage *st,
    175184                              const unsigned char *token, int token_len);
    176 static int send_get_peers(int s, struct sockaddr *sa, int salen,
     185static int send_get_peers(struct sockaddr *sa, int salen,
    177186                          unsigned char *tid, int tid_len,
    178                           unsigned char *infohash, int confirm);
    179 static int send_announce_peer(int s, struct sockaddr *sa, int salen,
     187                          unsigned char *infohash, int want, int confirm);
     188static int send_announce_peer(struct sockaddr *sa, int salen,
    180189                              unsigned char *tid, int tid_len,
    181190                              unsigned char *infohas, unsigned short port,
    182191                              unsigned char *token, int token_len, int confirm);
    183 int send_peer_announced(int s, struct sockaddr *sa, int salen,
    184                         unsigned char *tid, int tid_len);
    185 
    186 #define REPLY 0
    187 #define PING 1
    188 #define FIND_NODE 2
    189 #define GET_PEERS 3
    190 #define ANNOUNCE_PEER 4
     192static int send_peer_announced(struct sockaddr *sa, int salen,
     193                               unsigned char *tid, int tid_len);
     194static int send_error(struct sockaddr *sa, int salen,
     195                      unsigned char *tid, int tid_len,
     196                      int code, const char *message);
     197
     198#define ERROR 0
     199#define REPLY 1
     200#define PING 2
     201#define FIND_NODE 3
     202#define GET_PEERS 4
     203#define ANNOUNCE_PEER 5
     204
     205#define WANT4 1
     206#define WANT6 2
     207
    191208static int parse_message(const unsigned char *buf, int buflen,
    192209                         unsigned char *tid_return, int *tid_len,
     
    197214                         unsigned char *token_return, int *token_len,
    198215                         unsigned char *nodes_return, int *nodes_len,
    199                          const unsigned char *values_return, int *values_len);
     216                         unsigned char *nodes6_return, int *nodes6_len,
     217                         unsigned char *values_return, int *values_len,
     218                         unsigned char *values6_return, int *values6_len,
     219                         int *want_return);
    200220
    201221static const unsigned char zeroes[20] = {0};
     
    205225    0xFF, 0xFF, 0xFF, 0xFF
    206226};
     227
     228static int dht_socket = -1;
     229static int dht_socket6 = -1;
     230
    207231static time_t search_time;
    208232static time_t confirm_nodes_time;
     
    216240
    217241static struct bucket *buckets = NULL;
     242static struct bucket *buckets6 = NULL;
    218243static struct storage *storage;
     244static int numstorage;
    219245
    220246static struct search *searches = NULL;
     
    227253#define DHT_MAX_BLACKLISTED 10
    228254#endif
    229 static struct sockaddr_in blacklist[DHT_MAX_BLACKLISTED];
     255static struct sockaddr_storage blacklist[DHT_MAX_BLACKLISTED];
    230256int next_blacklisted;
    231257
    232258static struct timeval now;
    233 static time_t mybucket_grow_time;
     259static time_t mybucket_grow_time, mybucket6_grow_time;
    234260static time_t expire_stuff_time;
    235261
     
    356382
    357383static struct bucket *
    358 find_bucket(unsigned const char *id)
    359 {
    360     struct bucket *b = buckets;
     384find_bucket(unsigned const char *id, int af)
     385{
     386    struct bucket *b = af == AF_INET ? buckets : buckets6;
     387
     388    if(b == NULL)
     389        return NULL;
    361390
    362391    while(1) {
     
    372401previous_bucket(struct bucket *b)
    373402{
    374     struct bucket *p = buckets;
     403    struct bucket *p = b->af == AF_INET ? buckets : buckets6;
    375404
    376405    if(b == p)
     
    388417/* Every bucket contains an unordered list of nodes. */
    389418static struct node *
    390 find_node(const unsigned char *id)
    391 {
    392     struct bucket *b = find_bucket(id);
     419find_node(const unsigned char *id, int af)
     420{
     421    struct bucket *b = find_bucket(id, af);
    393422    struct node *n;
    394423
    395424    if(b == NULL)
    396425        return NULL;
     426
    397427    n = b->nodes;
    398428    while(n) {
     
    459489        id_return[i] = random() & 0xFF;
    460490    return 1;
    461 }   
     491}
    462492
    463493/* Insert a new node into a bucket. */
     
    465495insert_node(struct node *node)
    466496{
    467     struct bucket *b = find_bucket(node->id);
     497    struct bucket *b = find_bucket(node->id, node->ss.ss_family);
     498
     499    if(b == NULL)
     500        return NULL;
    468501
    469502    node->next = b->nodes;
     
    509542/* Every bucket caches the address of a likely node.  Ping it. */
    510543static int
    511 send_cached_ping(int s, struct bucket *b)
    512 {
     544send_cached_ping(struct bucket *b)
     545{
     546    unsigned char tid[4];
    513547    int rc;
    514548    /* We set family to 0 when there's no cached node. */
    515     if(b->cached.sin_family == AF_INET) {
    516         unsigned char tid[4];
    517         debugf("Sending ping to cached node.\n");
    518         make_tid(tid, "pn", 0);
    519         rc = send_ping(s, (struct sockaddr*)&b->cached,
    520                        sizeof(struct sockaddr_in),
    521                        tid, 4);
    522         b->cached.sin_family = 0;
    523         return rc;
    524     }
    525     return 0;
     549    if(b->cached.ss_family == 0)
     550        return 0;
     551
     552    debugf("Sending ping to cached node.\n");
     553    make_tid(tid, "pn", 0);
     554    rc = send_ping((struct sockaddr*)&b->cached, b->cachedlen, tid, 4);
     555    b->cached.ss_family = 0;
     556    b->cachedlen = 0;
     557    return rc;
    526558}
    527559
    528560/* Split a bucket into two equal parts. */
    529561static struct bucket *
    530 split_bucket(int s, struct bucket *b)
     562split_bucket(struct bucket *b)
    531563{
    532564    struct bucket *new;
     
    543575        return NULL;
    544576
    545     send_cached_ping(s, b);
     577    new->af = b->af;
     578
     579    send_cached_ping(b);
    546580
    547581    memcpy(new->first, new_id, 20);
     
    564598/* Called whenever we send a request to a node. */
    565599static void
    566 pinged(int s, struct node *n, struct bucket *b)
     600pinged(struct node *n, struct bucket *b)
    567601{
    568602    n->pinged++;
    569603    n->pinged_time = now.tv_sec;
    570604    if(n->pinged >= 3)
    571         send_cached_ping(s, b ? b : find_bucket(n->id));
     605        send_cached_ping(b ? b : find_bucket(n->id, n->ss.ss_family));
    572606}
    573607
     
    575609   the node sent a message, 2 if it sent us a reply. */
    576610static struct node *
    577 new_node(int s, const unsigned char *id, struct sockaddr_in *sin,
    578          int confirm)
    579 {
    580     struct bucket *b = find_bucket(id);
     611new_node(const unsigned char *id, struct sockaddr *sa, int salen, int confirm)
     612{
     613    struct bucket *b = find_bucket(id, sa->sa_family);
    581614    struct node *n;
    582     int mybucket = in_bucket(myid, b);
     615    int mybucket, split;
     616
     617    if(b == NULL)
     618        return NULL;
    583619
    584620    if(id_cmp(id, myid) == 0)
    585621        return NULL;
     622
     623    mybucket = in_bucket(myid, b);
    586624
    587625    if(confirm == 2)
     
    593631            if(confirm || n->time < now.tv_sec - 15 * 60) {
    594632                /* Known node.  Update stuff. */
    595                 n->sin = *sin;
     633                memcpy((struct sockaddr*)&n->ss, sa, salen);
    596634                if(confirm)
    597635                    n->time = now.tv_sec;
     
    612650        if(n->pinged >= 3 && n->pinged_time < now.tv_sec - 15) {
    613651            memcpy(n->id, id, 20);
    614             n->sin = *sin;
     652            memcpy((struct sockaddr*)&n->ss, sa, salen);
    615653            n->time = confirm ? now.tv_sec : 0;
    616654            n->reply_time = confirm >= 2 ? now.tv_sec : 0;
    617655            n->pinged_time = 0;
    618656            n->pinged = 0;
    619             if(mybucket)
    620                 mybucket_grow_time = now.tv_sec;
     657            if(mybucket) {
     658                if(sa->sa_family == AF_INET)
     659                    mybucket_grow_time = now.tv_sec;
     660                else
     661                    mybucket6_grow_time = now.tv_sec;
     662            }
    621663            return n;
    622664        }
     
    639681                    debugf("Sending ping to dubious node.\n");
    640682                    make_tid(tid, "pn", 0);
    641                     send_ping(s,
    642                               (struct sockaddr*)&n->sin,
    643                               sizeof(struct sockaddr_in),
     683                    send_ping((struct sockaddr*)&n->ss, n->sslen,
    644684                              tid, 4);
    645685                    n->pinged++;
     
    651691        }
    652692
    653         /* If there's only one bucket, split even if there remain doubtful
    654            nodes.  This violates the spec, but it speeds up bootstrapping. */
    655         if(mybucket && (!dubious || buckets->next == NULL)) {
     693        split = 0;
     694        if(mybucket) {
     695            if(!dubious)
     696                split = 1;
     697            /* If there's only one bucket, split eagerly.  This is
     698               incorrect unless there's more than 8 nodes in the DHT. */
     699            else if(b->af == AF_INET && buckets->next == NULL)
     700                split = 1;
     701            else if(b->af == AF_INET6 && buckets6->next == NULL)
     702                split = 1;
     703        }
     704
     705        if(split) {
    656706            debugf("Splitting.\n");
    657             b = split_bucket(s, b);
    658             mybucket_grow_time = now.tv_sec;
    659             return new_node(s, id, sin, confirm);
     707            b = split_bucket(b);
     708            if(sa->sa_family == AF_INET)
     709                mybucket_grow_time = now.tv_sec;
     710            else
     711                mybucket6_grow_time = now.tv_sec;
     712            return new_node(id, sa, salen, confirm);
    660713        }
    661714
    662715        /* No space for this node.  Cache it away for later. */
    663         if(confirm || b->cached.sin_family == 0)
    664             b->cached = *sin;
     716        if(confirm || b->cached.ss_family == 0) {
     717            memcpy(&b->cached, sa, salen);
     718            b->cachedlen = salen;
     719        }
    665720
    666721        return NULL;
     
    672727        return NULL;
    673728    memcpy(n->id, id, 20);
    674     n->sin = *sin;
     729    memcpy(&n->ss, sa, salen);
     730    n->sslen = salen;
    675731    n->time = confirm ? now.tv_sec : 0;
    676732    n->reply_time = confirm >= 2 ? now.tv_sec : 0;
     
    678734    b->nodes = n;
    679735    b->count++;
    680     if(mybucket)
    681         mybucket_grow_time = now.tv_sec;
     736    if(mybucket) {
     737        if(sa->sa_family == AF_INET)
     738            mybucket_grow_time = now.tv_sec;
     739        else
     740            mybucket6_grow_time = now.tv_sec;
     741    }
    682742    return n;
    683743}
     
    687747   recover as soon as we find better ones. */
    688748static int
    689 expire_buckets(int s)
    690 {
    691     struct bucket *b = buckets;
    692 
     749expire_buckets(struct bucket *b)
     750{
    693751    while(b) {
    694752        struct node *n, *p;
     
    716774
    717775        if(changed)
    718             send_cached_ping(s, b);
     776            send_cached_ping(b);
    719777
    720778        b = b->next;
     
    730788
    731789static struct search *
    732 find_search(unsigned short tid)
     790find_search(unsigned short tid, int af)
    733791{
    734792    struct search *sr = searches;
    735793    while(sr) {
    736         if(sr->tid == tid)
     794        if(sr->tid == tid && sr->af == af)
    737795            return sr;
    738796        sr = sr->next;
     
    746804
    747805static int
    748 insert_search_node(unsigned char *id, struct sockaddr_in *sin,
     806insert_search_node(unsigned char *id,
     807                   struct sockaddr *sa, int salen,
    749808                   struct search *sr, int replied,
    750809                   unsigned char *token, int token_len)
     
    752811    struct search_node *n;
    753812    int i, j;
     813
     814    if(sa->sa_family != sr->af) {
     815        debugf("Attempted to insert node in the wrong family.\n");
     816        return 0;
     817    }
    754818
    755819    for(i = 0; i < sr->numnodes; i++) {
     
    778842
    779843found:
    780     n->sin = *sin;
     844    memcpy(&n->ss, sa, salen);
     845    n->sslen = salen;
    781846
    782847    if(replied) {
     
    830895/* This must always return 0 or 1, never -1, not even on failure (see below). */
    831896static int
    832 search_send_get_peers(int s, struct search *sr, struct search_node *n)
     897search_send_get_peers(struct search *sr, struct search_node *n)
    833898{
    834899    struct node *node;
     
    850915    debugf("Sending get_peers.\n");
    851916    make_tid(tid, "gp", sr->tid);
    852     send_get_peers(s, (struct sockaddr*)&n->sin,
    853                    sizeof(struct sockaddr_in), tid, 4, sr->id,
     917    send_get_peers((struct sockaddr*)&n->ss, n->sslen, tid, 4, sr->id, -1,
    854918                   n->reply_time >= now.tv_sec - 15);
    855919    n->pinged++;
     
    857921    /* If the node happens to be in our main routing table, mark it
    858922       as pinged. */
    859     node = find_node(n->id);
    860     if(node) pinged(s, node, NULL);
     923    node = find_node(n->id, n->ss.ss_family);
     924    if(node) pinged(node, NULL);
    861925    return 1;
    862926}
     
    865929   further requests. */
    866930static void
    867 search_step(int s, struct search *sr, dht_callback *callback, void *closure)
     931search_step(struct search *sr, dht_callback *callback, void *closure)
    868932{
    869933    int i, j;
     
    905969                    debugf("Sending announce_peer.\n");
    906970                    make_tid(tid, "ap", sr->tid);
    907                     send_announce_peer(s,
    908                                        (struct sockaddr*)&n->sin,
    909                                        sizeof(struct sockaddr_in),
     971                    send_announce_peer((struct sockaddr*)&n->ss,
     972                                       sizeof(struct sockaddr_storage),
    910973                                       tid, 4, sr->id, sr->port,
    911974                                       n->token, n->token_len,
     
    913976                    n->pinged++;
    914977                    n->request_time = now.tv_sec;
    915                     node = find_node(n->id);
    916                     if(node) pinged(s, node, NULL);
     978                    node = find_node(n->id, n->ss.ss_family);
     979                    if(node) pinged(node, NULL);
    917980                }
    918981                j++;
     
    930993    j = 0;
    931994    for(i = 0; i < sr->numnodes; i++) {
    932         j += search_send_get_peers(s, sr, &sr->nodes[i]);
     995        j += search_send_get_peers(sr, &sr->nodes[i]);
    933996        if(j >= 3)
    934997            break;
     
    9401003    sr->done = 1;
    9411004    if(callback)
    942         (*callback)(closure, DHT_EVENT_SEARCH_DONE, sr->id, NULL, 0);
     1005        (*callback)(closure,
     1006                    sr->af == AF_INET ?
     1007                    DHT_EVENT_SEARCH_DONE : DHT_EVENT_SEARCH_DONE6,
     1008                    sr->id, NULL, 0);
    9431009    sr->step_time = now.tv_sec;
    9441010}
     
    9841050    n = b->nodes;
    9851051    while(n) {
    986         insert_search_node(n->id, &n->sin, sr, 0, NULL, 0);
     1052        insert_search_node(n->id, (struct sockaddr*)&n->ss, n->sslen,
     1053                           sr, 0, NULL, 0);
    9871054        n = n->next;
    9881055    }
     
    9911058/* Start a search.  If port is non-zero, perform an announce when the
    9921059   search is complete. */
    993 int 
    994 dht_search(int s, const unsigned char *id, int port,
     1060int
     1061dht_search(const unsigned char *id, int port, int af,
    9951062           dht_callback *callback, void *closure)
    9961063{
    9971064    struct search *sr;
    998     struct bucket *b;
     1065    struct bucket *b = find_bucket(id, af);
     1066
     1067    if(b == NULL) {
     1068        errno = EAFNOSUPPORT;
     1069        return -1;
     1070    }
    9991071
    10001072    sr = searches;
    10011073    while(sr) {
    1002         if(id_cmp(sr->id, id) == 0)
     1074        if(sr->af == af && id_cmp(sr->id, id) == 0)
    10031075            break;
    10041076        sr = sr->next;
     
    10301102            return -1;
    10311103        }
     1104        sr->af = af;
    10321105        sr->tid = search_id++;
    10331106        sr->step_time = 0;
     
    10391112    sr->port = port;
    10401113
    1041     b = find_bucket(id);
    10421114    insert_search_bucket(b, sr);
    10431115
     
    10501122    }
    10511123    if(sr->numnodes < SEARCH_NODES)
    1052         insert_search_bucket(find_bucket(myid), sr);
    1053 
    1054     search_step(s, sr, callback, closure);
     1124        insert_search_bucket(find_bucket(myid, af), sr);
     1125
     1126    search_step(sr, callback, closure);
    10551127    search_time = now.tv_sec;
    10561128    return 1;
     
    10741146
    10751147static int
    1076 storage_store(const unsigned char *id, const unsigned char *ip,
    1077               unsigned short port)
    1078 {
    1079     int i;
     1148storage_store(const unsigned char *id, struct sockaddr *sa)
     1149{
     1150    int i, len;
    10801151    struct storage *st = storage;
     1152    unsigned char *ip;
     1153    unsigned short port;
    10811154
    10821155    st = find_storage(id);
    10831156
    10841157    if(st == NULL) {
     1158        if(numstorage >= DHT_MAX_HASHES)
     1159            return -1;
    10851160        st = calloc(1, sizeof(struct storage));
    10861161        if(st == NULL) return -1;
     
    10881163        st->next = storage;
    10891164        storage = st;
     1165        numstorage++;
     1166    }
     1167
     1168    if(sa->sa_family == AF_INET) {
     1169        struct sockaddr_in *sin = (struct sockaddr_in*)sa;
     1170        ip = (unsigned char*)&sin->sin_addr;
     1171        len = 4;
     1172        port = ntohs(sin->sin_port);
     1173    } else if(sa->sa_family == AF_INET6) {
     1174        struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sa;
     1175        ip = (unsigned char*)&sin6->sin6_addr;
     1176        len = 16;
     1177        port = ntohs(sin6->sin6_port);
    10901178    }
    10911179
    10921180    for(i = 0; i < st->numpeers; i++) {
    1093         if(st->peers[i].port == port && memcmp(st->peers[i].ip, ip, 4) == 0)
     1181        if(st->peers[i].port == port && st->peers[i].len == len &&
     1182           memcmp(st->peers[i].ip, ip, len) == 0)
    10941183            break;
    10951184    }
     1185
    10961186    if(i < st->numpeers) {
    10971187        /* Already there, only need to refresh */
     
    11041194            struct peer *new_peers;
    11051195            int n;
    1106             if(st->maxpeers > DHT_MAX_PEERS / 2)
     1196            if(st->maxpeers >= DHT_MAX_PEERS)
    11071197                return 0;
    11081198            n = st->maxpeers == 0 ? 2 : 2 * st->maxpeers;
     1199            n = MIN(n, DHT_MAX_PEERS);
    11091200            new_peers = realloc(st->peers, n * sizeof(struct peer));
    11101201            if(new_peers == NULL)
     
    11151206        p = &st->peers[st->numpeers++];
    11161207        p->time = now.tv_sec;
    1117         memcpy(p->ip, ip, 4);
     1208        p->len = len;
     1209        memcpy(p->ip, ip, len);
    11181210        p->port = port;
    11191211        return 1;
     
    11481240            else
    11491241                st = storage;
     1242            numstorage--;
     1243            if(numstorage < 0) {
     1244                debugf("Eek... numstorage became negative.\n");
     1245                numstorage = 0;
     1246            }
    11501247        } else {
    11511248            previous = st;
     
    11581255/* We've just found out that a node is buggy. */
    11591256static void
    1160 broken_node(int s, const unsigned char *id, struct sockaddr_in *sin)
     1257broken_node(const unsigned char *id, struct sockaddr *sa, int salen)
    11611258{
    11621259    int i;
     
    11681265        struct search *sr;
    11691266        /* Make the node easy to discard. */
    1170         n = find_node(id);
     1267        n = find_node(id, sa->sa_family);
    11711268        if(n) {
    11721269            n->pinged = 3;
    1173             pinged(s, n, NULL);
     1270            pinged(n, NULL);
    11741271        }
    11751272        /* Discard it from any searches in progress. */
     
    11831280    }
    11841281    /* And make sure we don't hear from it again. */
    1185     blacklist[next_blacklisted] = *sin;
     1282    memcpy(&blacklist[next_blacklisted], sa, salen);
    11861283    next_blacklisted = (next_blacklisted + 1) % DHT_MAX_BLACKLISTED;
    11871284}
     
    12081305
    12091306static void
    1210 make_token(const unsigned char *ipv4, unsigned short port, int old,
    1211            unsigned char *token_return)
    1212 {
     1307make_token(struct sockaddr *sa, int old, unsigned char *token_return)
     1308{
     1309    void *ip;
     1310    int iplen;
     1311    unsigned short port;
     1312
     1313    if(sa->sa_family == AF_INET) {
     1314        struct sockaddr_in *sin = (struct sockaddr_in*)sa;
     1315        ip = &sin->sin_addr;
     1316        iplen = 4;
     1317        port = htons(sin->sin_port);
     1318    } else if(sa->sa_family == AF_INET6) {
     1319        struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sa;
     1320        ip = &sin6->sin6_addr;
     1321        iplen = 16;
     1322        port = htons(sin6->sin6_port);
     1323    } else {
     1324        abort();
     1325    }
     1326
    12131327    dht_hash(token_return, TOKEN_SIZE,
    12141328             old ? oldsecret : secret, sizeof(secret),
    1215              ipv4, 4,
    1216              (unsigned char*)&port, 2);
     1329             ip, iplen, (unsigned char*)&port, 2);
    12171330}
    12181331static int
    1219 token_match(unsigned char *token, int token_len,
    1220             const unsigned char *ipv4, unsigned short port)
     1332token_match(unsigned char *token, int token_len, struct sockaddr *sa)
    12211333{
    12221334    unsigned char t[TOKEN_SIZE];
    12231335    if(token_len != TOKEN_SIZE)
    12241336        return 0;
    1225     make_token(ipv4, port, 0, t);
     1337    make_token(sa, 0, t);
    12261338    if(memcmp(t, token, TOKEN_SIZE) == 0)
    12271339        return 1;
    1228     make_token(ipv4, port, 1, t);
     1340    make_token(sa, 1, t);
    12291341    if(memcmp(t, token, TOKEN_SIZE) == 0)
    12301342        return 1;
     
    12331345
    12341346int
    1235 dht_nodes(int *good_return, int *dubious_return, int *cached_return,
     1347dht_nodes(int af, int *good_return, int *dubious_return, int *cached_return,
    12361348          int *incoming_return)
    12371349{
    12381350    int good = 0, dubious = 0, cached = 0, incoming = 0;
    1239     struct bucket *b = buckets;
     1351    struct bucket *b = af == AF_INET ? buckets : buckets6;
     1352
    12401353    while(b) {
    12411354        struct node *n = b->nodes;
     
    12501363            n = n->next;
    12511364        }
    1252         if(b->cached.sin_family == AF_INET)
     1365        if(b->cached.ss_family > 0)
    12531366            cached++;
    12541367        b = b->next;
     
    12641377    return good + dubious;
    12651378}
    1266                
     1379
     1380static void
     1381dump_bucket(FILE *f, struct bucket *b)
     1382{
     1383    struct node *n = b->nodes;
     1384    fprintf(f, "Bucket ");
     1385    print_hex(f, b->first, 20);
     1386    fprintf(f, " count %d age %d%s%s:\n",
     1387            b->count, (int)(now.tv_sec - b->time),
     1388            in_bucket(myid, b) ? " (mine)" : "",
     1389            b->cached.ss_family ? " (cached)" : "");
     1390    while(n) {
     1391        char buf[512];
     1392        unsigned short port;
     1393        fprintf(f, "    Node ");
     1394        print_hex(f, n->id, 20);
     1395        if(n->ss.ss_family == AF_INET) {
     1396            struct sockaddr_in *sin = (struct sockaddr_in*)&n->ss;
     1397            inet_ntop(AF_INET, &sin->sin_addr, buf, 512);
     1398            port = ntohs(sin->sin_port);
     1399        } else if(n->ss.ss_family == AF_INET6) {
     1400            struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&n->ss;
     1401            inet_ntop(AF_INET6, &sin6->sin6_addr, buf, 512);
     1402            port = ntohs(sin6->sin6_port);
     1403        } else {
     1404            snprintf(buf, 512, "unknown(%d)", n->ss.ss_family);
     1405            port = 0;
     1406        }
     1407
     1408        if(n->ss.ss_family == AF_INET6)
     1409            fprintf(f, " [%s]:%d ", buf, port);
     1410        else
     1411            fprintf(f, " %s:%d ", buf, port);
     1412        if(n->time != n->reply_time)
     1413            fprintf(f, "age %ld, %ld",
     1414                    (long)(now.tv_sec - n->time),
     1415                    (long)(now.tv_sec - n->reply_time));
     1416        else
     1417            fprintf(f, "age %ld", (long)(now.tv_sec - n->time));
     1418        if(n->pinged)
     1419            fprintf(f, " (%d)", n->pinged);
     1420        if(node_good(n))
     1421            fprintf(f, " (good)");
     1422        fprintf(f, "\n");
     1423        n = n->next;
     1424    }
     1425
     1426}
    12671427
    12681428void
     
    12701430{
    12711431    int i;
    1272     struct bucket *b = buckets;
     1432    struct bucket *b;
    12731433    struct storage *st = storage;
    12741434    struct search *sr = searches;
     
    12771437    print_hex(f, myid, 20);
    12781438    fprintf(f, "\n");
     1439
     1440    b = buckets;
    12791441    while(b) {
    1280         struct node *n = b->nodes;
    1281         fprintf(f, "Bucket ");
    1282         print_hex(f, b->first, 20);
    1283         fprintf(f, " count %d age %d%s%s:\n",
    1284                b->count, (int)(now.tv_sec - b->time),
    1285                in_bucket(myid, b) ? " (mine)" : "",
    1286                b->cached.sin_family ? " (cached)" : "");
    1287         while(n) {
    1288             char buf[512];
    1289             fprintf(f, "    Node ");
    1290             print_hex(f, n->id, 20);
    1291             inet_ntop(AF_INET, &n->sin.sin_addr, buf, 512);
    1292             fprintf(f, " %s:%d ", buf, ntohs(n->sin.sin_port));
    1293             if(n->time != n->reply_time)
    1294                 fprintf(f, "age %ld, %ld",
    1295                        (long)(now.tv_sec - n->time),
    1296                        (long)(now.tv_sec - n->reply_time));
    1297             else
    1298                 fprintf(f, "age %ld", (long)(now.tv_sec - n->time));
    1299             if(n->pinged)
    1300                 fprintf(f, " (%d)", n->pinged);
    1301             if(node_good(n))
    1302                 fprintf(f, " (good)");
    1303             fprintf(f, "\n");
    1304             n = n->next;
    1305         }
     1442        dump_bucket(f, b);
    13061443        b = b->next;
    13071444    }
     1445
     1446    fprintf(f, "\n");
     1447
     1448    b = buckets6;
     1449    while(b) {
     1450        dump_bucket(f, b);
     1451        b = b->next;
     1452    }
     1453
    13081454    while(sr) {
    1309         fprintf(f, "\nSearch id ");
     1455        fprintf(f, "\nSearch%s id ", sr->af == AF_INET6 ? " (IPv6)" : "");
    13101456        print_hex(f, sr->id, 20);
    13111457        fprintf(f, " age %d%s\n", (int)(now.tv_sec - sr->step_time),
     
    13221468                fprintf(f, " (%d)", n->pinged);
    13231469            fprintf(f, "%s%s.\n",
    1324                    find_node(n->id) ? " (known)" : "",
    1325                    n->replied ? " (replied)" : "");
     1470                    find_node(n->id, AF_INET) ? " (known)" : "",
     1471                    n->replied ? " (replied)" : "");
    13261472        }
    13271473        sr = sr->next;
    13281474    }
    13291475
    1330    
    13311476    while(st) {
    13321477        fprintf(f, "\nStorage ");
     
    13341479        fprintf(f, " %d/%d nodes:", st->numpeers, st->maxpeers);
    13351480        for(i = 0; i < st->numpeers; i++) {
    1336             char buf[20];
    1337             inet_ntop(AF_INET, st->peers[i].ip, buf, 20);
     1481            char buf[100];
     1482            if(st->peers[i].len == 4) {
     1483                inet_ntop(AF_INET, st->peers[i].ip, buf, 100);
     1484            } else if(st->peers[i].len == 16) {
     1485                buf[0] = '[';
     1486                inet_ntop(AF_INET6, st->peers[i].ip, buf + 1, 98);
     1487                strcat(buf, "]");
     1488            } else {
     1489                strcpy(buf, "???");
     1490            }
    13381491            fprintf(f, " %s:%u (%ld)",
    13391492                    buf, st->peers[i].port,
     
    13421495        st = st->next;
    13431496    }
    1344    
     1497
    13451498    fprintf(f, "\n\n");
    13461499    fflush(f);
     
    13481501
    13491502int
    1350 dht_init(int s, const unsigned char *id, const unsigned char *v)
     1503dht_init(int s, int s6, const unsigned char *id, const unsigned char *v)
    13511504{
    13521505    int rc;
    13531506
    1354     if(buckets) {
     1507    if(dht_socket >= 0 || dht_socket6 >= 0 || buckets || buckets6) {
    13551508        errno = EBUSY;
    13561509        return -1;
    13571510    }
    13581511
    1359     buckets = calloc(sizeof(struct bucket), 1);
    1360     if(buckets == NULL)
    1361         return -1;
    1362 
    13631512    searches = NULL;
    13641513    numsearches = 0;
    13651514
    13661515    storage = NULL;
    1367 
    1368     rc = fcntl(s, F_GETFL, 0);
    1369     if(rc < 0)
    1370         goto fail;
    1371 
    1372     rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK));
    1373     if(rc < 0)
    1374         goto fail;
     1516    numstorage = 0;
     1517
     1518    if(s >= 0) {
     1519        buckets = calloc(sizeof(struct bucket), 1);
     1520        if(buckets == NULL)
     1521            return -1;
     1522        buckets->af = AF_INET;
     1523
     1524        rc = fcntl(s, F_GETFL, 0);
     1525        if(rc < 0)
     1526            goto fail;
     1527
     1528        rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK));
     1529        if(rc < 0)
     1530            goto fail;
     1531    }
     1532
     1533    if(s6 >= 0) {
     1534        buckets6 = calloc(sizeof(struct bucket), 1);
     1535        if(buckets6 == NULL)
     1536            return -1;
     1537        buckets6->af = AF_INET6;
     1538
     1539        rc = fcntl(s6, F_GETFL, 0);
     1540        if(rc < 0)
     1541            goto fail;
     1542
     1543        rc = fcntl(s6, F_SETFL, (rc | O_NONBLOCK));
     1544        if(rc < 0)
     1545            goto fail;
     1546    }
    13751547
    13761548    memcpy(myid, id, 20);
     
    13861558
    13871559    mybucket_grow_time = now.tv_sec;
     1560    mybucket6_grow_time = now.tv_sec;
    13881561    confirm_nodes_time = now.tv_sec + random() % 3;
    13891562
     
    14011574        goto fail;
    14021575
    1403     expire_buckets(s);
     1576    dht_socket = s;
     1577    dht_socket6 = s6;
     1578
     1579    expire_buckets(buckets);
     1580    expire_buckets(buckets6);
    14041581
    14051582    return 1;
     
    14121589
    14131590int
    1414 dht_uninit(int s, int dofree)
    1415 {
     1591dht_uninit(int dofree)
     1592{
     1593    if(dht_socket < 0) {
     1594        errno = EINVAL;
     1595        return -1;
     1596    }
     1597
    14161598    if(!dofree)
    14171599        return 1;
     
    14621644}
    14631645
     1646static int
     1647neighbourhood_maintenance(int af)
     1648{
     1649    unsigned char id[20];
     1650    struct bucket *b = find_bucket(myid, af);
     1651    struct bucket *q;
     1652    struct node *n;
     1653
     1654    if(b == NULL)
     1655        return -1;
     1656
     1657    memcpy(id, myid, 20);
     1658    id[19] = random() & 0xFF;
     1659    q = b;
     1660    if(q->next && (q->count == 0 || (random() & 7) == 0))
     1661        q = b->next;
     1662    if(q->count == 0 || (random() & 7) == 0) {
     1663        struct bucket *r;
     1664        r = previous_bucket(b);
     1665        if(r && r->count > 0)
     1666            q = r;
     1667    }
     1668
     1669    if(q) {
     1670        int want = dht_socket >= 0 && dht_socket6 >= 0 ? (WANT4 | WANT6) : -1;
     1671        n = random_node(q);
     1672        if(n) {
     1673            unsigned char tid[4];
     1674            debugf("Sending find_node for%s neighborhood maintenance.\n",
     1675                   af == AF_INET6 ? " IPv6" : "");
     1676            make_tid(tid, "fn", 0);
     1677            send_find_node((struct sockaddr*)&n->ss, n->sslen,
     1678                           tid, 4, id, want,
     1679                           n->reply_time >= now.tv_sec - 15);
     1680            pinged(n, q);
     1681        }
     1682    }
     1683    return 1;
     1684}
     1685
     1686static int
     1687bucket_maintenance(int af)
     1688{
     1689    struct bucket *b;
     1690
     1691    b = af == AF_INET ? buckets : buckets6;
     1692
     1693    while(b) {
     1694        struct bucket *q;
     1695        if(b->time < now.tv_sec - 600) {
     1696            /* This bucket hasn't seen any positive confirmation for a long
     1697               time.  Pick a random id in this bucket's range, and send
     1698               a request to a random node. */
     1699            unsigned char id[20];
     1700            struct node *n;
     1701            int rc;
     1702
     1703            rc = bucket_random(b, id);
     1704            if(rc < 0)
     1705                memcpy(id, b->first, 20);
     1706
     1707            q = b;
     1708            /* If the bucket is empty, we try to fill it from a neighbour.
     1709               We also sometimes do it gratuitiously to recover from
     1710               buckets full of broken nodes. */
     1711            if(q->next && (q->count == 0 || (random() & 7) == 0))
     1712                q = b->next;
     1713            if(q->count == 0 || (random() & 7) == 0) {
     1714                struct bucket *r;
     1715                r = previous_bucket(b);
     1716                if(r && r->count > 0)
     1717                    q = r;
     1718            }
     1719
     1720            if(q) {
     1721                n = random_node(q);
     1722                if(n) {
     1723                    unsigned char tid[4];
     1724                    int want = -1;
     1725
     1726                    if(dht_socket >= 0 && dht_socket6 >= 0) {
     1727                        struct bucket *otherbucket;
     1728                        otherbucket =
     1729                            find_bucket(id, af == AF_INET ? AF_INET6 : AF_INET);
     1730                        if(otherbucket && otherbucket->count < 8)
     1731                            /* The corresponding bucket in the other family
     1732                               is emptyish -- querying both is useful. */
     1733                            want = WANT4 | WANT6;
     1734                        else if(random() % 37 == 0)
     1735                            /* Most of the time, this just adds overhead.
     1736                               However, it might help stitch back one of
     1737                               the DHTs after a network collapse, so query
     1738                               both, but only very occasionally. */
     1739                            want = WANT4 | WANT6;
     1740                    }
     1741
     1742                    debugf("Sending find_node for%s bucket maintenance.\n",
     1743                           af == AF_INET6 ? " IPv6" : "");
     1744                    make_tid(tid, "fn", 0);
     1745                    send_find_node((struct sockaddr*)&n->ss, n->sslen,
     1746                                   tid, 4, id, want,
     1747                                   n->reply_time >= now.tv_sec - 15);
     1748                    pinged(n, q);
     1749                    /* In order to avoid sending queries back-to-back,
     1750                       give up for now and reschedule us soon. */
     1751                    return 1;
     1752                }
     1753            }
     1754        }
     1755        b = b->next;
     1756    }
     1757    return 0;
     1758}
     1759
    14641760int
    1465 dht_periodic(int s, int available, time_t *tosleep,
     1761dht_periodic(int available, time_t *tosleep,
    14661762             dht_callback *callback, void *closure)
    14671763{
     1764    int i;
     1765
    14681766    gettimeofday(&now, NULL);
    14691767
    14701768    if(available) {
    1471         int rc, i, message;
     1769        int rc, message;
    14721770        unsigned char tid[16], id[20], info_hash[20], target[20];
    1473         unsigned char buf[1536], nodes[256], token[128];
     1771        unsigned char buf[1536], nodes[256], nodes6[1024], token[128];
    14741772        int tid_len = 16, token_len = 128;
    1475         int nodes_len = 256;
     1773        int nodes_len = 256, nodes6_len = 1024;
    14761774        unsigned short port;
    1477         unsigned char values[2048];
    1478         int values_len = 2048;
    1479         struct sockaddr_in source;
    1480         socklen_t source_len = sizeof(struct sockaddr_in);
     1775        unsigned char values[2048], values6[2048];
     1776        int values_len = 2048, values6_len = 2048;
     1777        int want, want4, want6;
     1778        struct sockaddr_storage source_storage;
     1779        struct sockaddr *source = (struct sockaddr*)&source_storage;
     1780        socklen_t sourcelen = sizeof(source_storage);
    14811781        unsigned short ttid;
    14821782
    1483         rc = recvfrom(s, buf, 1536, 0,
    1484                       (struct sockaddr*)&source, &source_len);
    1485         if(rc < 0) {
    1486             if(errno == EAGAIN)
    1487                 goto dontread;
    1488             else
    1489                 return rc;
    1490         }
    1491 
    1492         if(source_len != sizeof(struct sockaddr_in)) {
    1493             /* Hmm... somebody gave us an IPv6 socket. */
    1494             errno = EINVAL;
    1495             return -1;
    1496         }
     1783        rc = -1;
     1784        if(dht_socket >= 0) {
     1785            rc = recvfrom(dht_socket, buf, 1536, 0, source, &sourcelen);
     1786            if(rc < 0 && errno != EAGAIN) {
     1787                    return rc;
     1788            }
     1789        }
     1790        if(dht_socket6 >= 0 && rc < 0) {
     1791            rc = recvfrom(dht_socket6, buf, 1536, 0,
     1792                          source, &sourcelen);
     1793            if(rc < 0 && errno != EAGAIN) {
     1794                    return rc;
     1795            }
     1796        }
     1797
     1798        if(rc < 0 || sourcelen > sizeof(struct sockaddr_storage))
     1799            goto dontread;
    14971800
    14981801        for(i = 0; i < DHT_MAX_BLACKLISTED; i++) {
    1499             if(blacklist[i].sin_family == AF_INET &&
    1500                blacklist[i].sin_port == source.sin_port &&
    1501                memcmp(&blacklist[i].sin_addr, &source.sin_addr, 4) == 0) {
     1802            if(memcmp(&blacklist[i], source, sourcelen) == 0) {
    15021803                debugf("Received packet from blacklisted node.\n");
    15031804                goto dontread;
     
    15181819        message = parse_message(buf, rc, tid, &tid_len, id, info_hash,
    15191820                                target, &port, token, &token_len,
    1520                                 nodes, &nodes_len, values, &values_len);
    1521         if(id_cmp(id, zeroes) == 0) {
    1522             debugf("Message with no id: ");
     1821                                nodes, &nodes_len, nodes6, &nodes6_len,
     1822                                values, &values_len, values6, &values6_len,
     1823                                &want);
     1824
     1825        if(message < 0 || message == ERROR || id_cmp(id, zeroes) == 0) {
     1826            debugf("Unparseable message: ");
    15231827            debug_printable(buf, rc);
    15241828            debugf("\n");
     
    15371841                goto dontread;
    15381842            }
     1843        }
     1844
     1845        if(want > 0) {
     1846            want4 = (want & WANT4);
     1847            want6 = (want & WANT6);
     1848        } else {
     1849            want4 = source->sa_family == AF_INET;
     1850            want6 = source->sa_family == AF_INET6;
    15391851        }
    15401852
     
    15481860                   time-out all our searches that go through this node.
    15491861                   Kill it. */
    1550                 broken_node(s, id, &source);
     1862                broken_node(id, source, sourcelen);
    15511863                goto dontread;
    15521864            }
    15531865            if(tid_match(tid, "pn", NULL)) {
    15541866                debugf("Pong!\n");
    1555                 new_node(s, id, &source, 2);
     1867                new_node(id, source, sourcelen, 2);
    15561868            } else if(tid_match(tid, "fn", NULL) ||
    15571869                      tid_match(tid, "gp", NULL)) {
     
    15601872                if(tid_match(tid, "gp", &ttid)) {
    15611873                    gp = 1;
    1562                     sr = find_search(ttid);
     1874                    sr = find_search(ttid, source->sa_family);
    15631875                }
    1564                 debugf("Nodes found (%d)%s!\n", nodes_len / 26,
     1876                debugf("Nodes found (%d+%d)%s!\n", nodes_len/26, nodes6_len/38,
    15651877                       gp ? " for get_peers" : "");
    1566                 if(nodes_len % 26 != 0) {
     1878                if(nodes_len % 26 != 0 || nodes6_len % 38 != 0) {
    15671879                    debugf("Unexpected length for node info!\n");
    1568                     broken_node(s, id, &source);
     1880                    broken_node(id, source, sourcelen);
    15691881                } else if(gp && sr == NULL) {
    15701882                    debugf("Unknown search!\n");
    1571                     new_node(s, id, &source, 1);
     1883                    new_node(id, source, sourcelen, 1);
    15721884                } else {
    15731885                    int i;
    1574                     new_node(s, id, &source, 2);
     1886                    new_node(id, source, sourcelen, 2);
    15751887                    for(i = 0; i < nodes_len / 26; i++) {
    15761888                        unsigned char *ni = nodes + i * 26;
     
    15821894                        memcpy(&sin.sin_addr, ni + 20, 4);
    15831895                        memcpy(&sin.sin_port, ni + 24, 2);
    1584                         new_node(s, ni, &sin, 0);
    1585                         if(sr) {
    1586                             insert_search_node(ni, &sin, sr, 0, NULL, 0);
     1896                        new_node(ni, (struct sockaddr*)&sin, sizeof(sin), 0);
     1897                        if(sr && sr->af == AF_INET) {
     1898                            insert_search_node(ni,
     1899                                               (struct sockaddr*)&sin,
     1900                                               sizeof(sin),
     1901                                               sr, 0, NULL, 0);
     1902                        }
     1903                    }
     1904                    for(i = 0; i < nodes6_len / 38; i++) {
     1905                        unsigned char *ni = nodes6 + i * 38;
     1906                        struct sockaddr_in6 sin6;
     1907                        if(id_cmp(ni, myid) == 0)
     1908                            continue;
     1909                        memset(&sin6, 0, sizeof(sin6));
     1910                        sin6.sin6_family = AF_INET6;
     1911                        memcpy(&sin6.sin6_addr, ni + 20, 16);
     1912                        memcpy(&sin6.sin6_port, ni + 36, 2);
     1913                        new_node(ni, (struct sockaddr*)&sin6, sizeof(sin6), 0);
     1914                        if(sr && sr->af == AF_INET6) {
     1915                            insert_search_node(ni,
     1916                                               (struct sockaddr*)&sin6,
     1917                                               sizeof(sin6),
     1918                                               sr, 0, NULL, 0);
    15871919                        }
    15881920                    }
     
    15911923                           requests in flight has decreased.  Let's push
    15921924                           another request. */
    1593                         search_send_get_peers(s, sr, NULL);
     1925                        search_send_get_peers(sr, NULL);
    15941926                }
    15951927                if(sr) {
    1596                     insert_search_node(id, &source, sr,
     1928                    insert_search_node(id, source, sourcelen, sr,
    15971929                                       1, token, token_len);
    1598                     if(values_len > 0) {
    1599                         debugf("Got values (%d)!\n", values_len / 6);
     1930                    if(values_len > 0 || values6_len > 0) {
     1931                        debugf("Got values (%d+%d)!\n",
     1932                               values_len / 6, values6_len / 18);
    16001933                        if(callback) {
    1601                             (*callback)(closure, DHT_EVENT_VALUES,
    1602                                         sr->id, (void*)values, values_len);
     1934                            if(values_len > 0)
     1935                                (*callback)(closure, DHT_EVENT_VALUES, sr->id,
     1936                                            (void*)values, values_len);
     1937
     1938                            if(values6_len > 0)
     1939                                (*callback)(closure, DHT_EVENT_VALUES6, sr->id,
     1940                                            (void*)values6, values6_len);
    16031941                        }
    16041942                    }
     
    16071945                struct search *sr;
    16081946                debugf("Got reply to announce_peer.\n");
    1609                 sr = find_search(ttid);
     1947                sr = find_search(ttid, source->sa_family);
    16101948                if(!sr) {
    16111949                    debugf("Unknown search!\n");
    1612                     new_node(s, id, &source, 1);
     1950                    new_node(id, source, sourcelen, 1);
    16131951                } else {
    16141952                    int i;
    1615                     new_node(s, id, &source, 2);
     1953                    new_node(id, source, sourcelen, 2);
    16161954                    for(i = 0; i < sr->numnodes; i++)
    16171955                        if(id_cmp(sr->nodes[i].id, id) == 0) {
     
    16231961                        }
    16241962                    /* See comment for gp above. */
    1625                     search_send_get_peers(s, sr, NULL);
     1963                    search_send_get_peers(sr, NULL);
    16261964                }
    16271965            } else {
     
    16331971        case PING:
    16341972            debugf("Ping (%d)!\n", tid_len);
    1635             new_node(s, id, &source, 1);
     1973            new_node(id, source, sourcelen, 1);
    16361974            debugf("Sending pong.\n");
    1637             send_pong(s, (struct sockaddr*)&source, sizeof(source),
    1638                       tid, tid_len);
     1975            send_pong(source, sourcelen, tid, tid_len);
    16391976            break;
    16401977        case FIND_NODE:
    16411978            debugf("Find node!\n");
    1642             new_node(s, id, &source, 1);
    1643             debugf("Sending closest nodes.\n");
    1644             send_closest_nodes(s, (struct sockaddr*)&source, sizeof(source),
    1645                                tid, tid_len, target,
    1646                                NULL, 0, NULL, 0, NULL, 0);
     1979            new_node(id, source, sourcelen, 1);
     1980            debugf("Sending closest nodes (%d).\n", want);
     1981            send_closest_nodes(source, sourcelen,
     1982                               tid, tid_len, target, want,
     1983                               0, NULL, NULL, 0);
    16471984            break;
    16481985        case GET_PEERS:
    16491986            debugf("Get_peers!\n");
    1650             new_node(s, id, &source, 1);
     1987            new_node(id, source, sourcelen, 1);
    16511988            if(id_cmp(info_hash, zeroes) == 0) {
    16521989                debugf("Eek!  Got get_peers with no info_hash.\n");
     1990                send_error(source, sourcelen, tid, tid_len,
     1991                           203, "Get_peers with no info_hash");
    16531992                break;
    16541993            } else {
    16551994                struct storage *st = find_storage(info_hash);
    16561995                unsigned char token[TOKEN_SIZE];
    1657                 make_token((unsigned char*)&source.sin_addr,
    1658                            ntohs(source.sin_port),
    1659                            0, token);
     1996                make_token(source, 0, token);
    16601997                if(st && st->numpeers > 0) {
    1661                     int i0, n0, n1;
    1662                     i0 = random() % st->numpeers;
    1663                     /* We treat peers as a circular list, and choose 50
    1664                        peers starting at i0. */
    1665                     n0 = MIN(st->numpeers - i0, 50);
    1666                     n1 = n0 >= 50 ? 0 : MIN(50, i0);
    1667                     debugf("Sending found peers (%d).\n", n0 + n1);
    1668                     /* According to the spec, we should not be sending any
    1669                        nodes in this case.  However, this avoids breaking
    1670                        searches if data is stored at the wrong place, and
    1671                        is also what libtorrent and uTorrent do. */
    1672                     send_closest_nodes(s, (struct sockaddr*)&source,
    1673                                        sizeof(source), tid, tid_len,
    1674                                        info_hash,
    1675                                        st->peers + i0, n0,
    1676                                        st->peers, n1,
    1677                                        token, TOKEN_SIZE);
     1998                     debugf("Sending found%s peers.\n",
     1999                            source->sa_family == AF_INET6 ? " IPv6" : "");
     2000                     send_closest_nodes(source, sourcelen,
     2001                                        tid, tid_len,
     2002                                        info_hash, want,
     2003                                        source->sa_family, st,
     2004                                        token, TOKEN_SIZE);
    16782005                } else {
    16792006                    debugf("Sending nodes for get_peers.\n");
    1680                     send_closest_nodes(s, (struct sockaddr*)&source,
    1681                                        sizeof(source),
    1682                                        tid, tid_len, info_hash,
    1683                                        NULL, 0, NULL, 0,
    1684                                        token, TOKEN_SIZE);
     2007                    send_closest_nodes(source, sourcelen,
     2008                                       tid, tid_len, info_hash, want,
     2009                                       0, NULL, token, TOKEN_SIZE);
    16852010                }
    16862011            }
     
    16882013        case ANNOUNCE_PEER:
    16892014            debugf("Announce peer!\n");
    1690             new_node(s, id, &source, 1);
     2015            new_node(id, source, sourcelen, 1);
    16912016            if(id_cmp(info_hash, zeroes) == 0) {
    16922017                debugf("Announce_peer with no info_hash.\n");
     2018                send_error(source, sourcelen, tid, tid_len,
     2019                           203, "Announce_peer with no info_hash");
    16932020                break;
    16942021            }
    1695             if(!token_match(token, token_len,
    1696                             (unsigned char*)&source.sin_addr,
    1697                             ntohs(source.sin_port))) {
     2022            if(!token_match(token, token_len, source)) {
    16982023                debugf("Incorrect token for announce_peer.\n");
     2024                send_error(source, sourcelen, tid, tid_len,
     2025                           203, "Announce_peer with wrong token");
    16992026                break;
    17002027            }
    17012028            if(port == 0) {
    17022029                debugf("Announce_peer with forbidden port %d.\n", port);
     2030                send_error(source, sourcelen, tid, tid_len,
     2031                           203, "Announce_peer with forbidden port number");
    17032032                break;
    17042033            }
    1705             storage_store(info_hash,
    1706                           (unsigned char*)&source.sin_addr, port);
     2034            storage_store(info_hash, source);
     2035            /* Note that if storage_store failed, we lie to the requestor.
     2036               This is to prevent them from backtracking, and hence
     2037               polluting the DHT. */
    17072038            debugf("Sending peer announced.\n");
    1708             send_peer_announced(s, (struct sockaddr*)&source,
    1709                                 sizeof(source), tid, tid_len);
     2039            send_peer_announced(source, sourcelen, tid, tid_len);
    17102040        }
    17112041    }
     
    17162046
    17172047    if(now.tv_sec >= expire_stuff_time) {
    1718         expire_buckets(s);
     2048        expire_buckets(buckets);
     2049        expire_buckets(buckets6);
    17192050        expire_storage();
    17202051        expire_searches();
     
    17262057        while(sr) {
    17272058            if(!sr->done && sr->step_time + 5 <= now.tv_sec) {
    1728                 search_step(s, sr, callback, closure);
     2059                search_step(sr, callback, closure);
    17292060            }
    17302061            sr = sr->next;
    17312062        }
    1732                    
     2063
    17332064        search_time = 0;
    17342065
     
    17452076
    17462077    if(now.tv_sec >= confirm_nodes_time) {
    1747         struct bucket *b;
    17482078        int soon = 0;
    1749         b = buckets;
    1750         while(!soon && b) {
    1751             struct bucket *q;
    1752             if(b->time < now.tv_sec - 900) {
    1753                 /* This bucket hasn't seen any activity for a long
    1754                    time.  Pick a random id in this bucket's range, and
    1755                    send a request to a random node. */
    1756                 unsigned char id[20];
    1757                 struct node *n;
    1758                 int rc;
    1759                
    1760                 rc = bucket_random(b, id);
    1761                 if(rc < 0)
    1762                     memcpy(id, b->first, 20);
    1763                
    1764                 q = b;
    1765                 /* If the bucket is empty, we try to fill it from
    1766                    a neighbour.  We also sometimes do it gratuitiously
    1767                    to recover from buckets full of broken nodes. */
    1768                 if(q->next && (q->count == 0 || random() % 7 == 0))
    1769                     q = b->next;
    1770                 if(q->count == 0 || random() % 7 == 0) {
    1771                     struct bucket *r;
    1772                     r = previous_bucket(b);
    1773                     if(r && r->count > 0)
    1774                         q = r;
    1775                 }
    1776 
    1777                 if(q) {
    1778                     n = random_node(q);
    1779                     if(n) {
    1780                         unsigned char tid[4];
    1781                         debugf("Sending find_node "
    1782                                "for bucket maintenance.\n");
    1783                         make_tid(tid, "fn", 0);
    1784                         send_find_node(s, (struct sockaddr*)&n->sin,
    1785                                        sizeof(struct sockaddr_in),
    1786                                        tid, 4, id,
    1787                                        n->reply_time >= now.tv_sec - 15);
    1788                         pinged(s, n, q);
    1789                         /* In order to avoid sending queries back-to-back,
    1790                            give up for now and reschedule us soon. */
    1791                         soon = 1;
    1792                     }
    1793                 }
    1794             }
    1795             b = b->next;
    1796         }
    1797 
    1798         if(!soon && mybucket_grow_time >= now.tv_sec - 150) {
    1799             /* We've seen updates to our own bucket recently.  Try to
    1800                improve our neighbourship. */
    1801             unsigned char id[20];
    1802             struct bucket *b, *q;
    1803             struct node *n;
    1804            
    1805             memcpy(id, myid, 20);
    1806             id[19] = random() % 0xFF;
    1807             b = find_bucket(myid);
    1808             q = b;
    1809             if(q->next && (q->count == 0 || random() % 7 == 0))
    1810                 q = b->next;
    1811             if(q->count == 0 || random() % 7 == 0) {
    1812                 struct bucket *r;
    1813                 r = previous_bucket(b);
    1814                 if(r && r->count > 0)
    1815                     q = r;
    1816             }
    1817 
    1818             if(q) {
    1819                 n = random_node(q);
    1820                 if(n) {
    1821                     unsigned char tid[4];
    1822                     debugf("Sending find_node "
    1823                            "for neighborhood maintenance.\n");
    1824                     make_tid(tid, "fn", 0);
    1825                     send_find_node(s, (struct sockaddr*)&n->sin,
    1826                                    sizeof(struct sockaddr_in),
    1827                                    tid, 4, id,
    1828                                    n->reply_time >= now.tv_sec - 15);
    1829                     pinged(s, n, q);
    1830                 }
    1831             }
    1832             soon = 1;
    1833         }
    1834 
    1835         /* In order to maintain all buckets' age within 900 seconds, worst
    1836            case is roughly 40 seconds, assuming the table is 22 bits deep.
     2079
     2080        soon |= bucket_maintenance(AF_INET);
     2081        soon |= bucket_maintenance(AF_INET6);
     2082
     2083        if(!soon) {
     2084            if(mybucket_grow_time >= now.tv_sec - 150)
     2085                soon |= neighbourhood_maintenance(AF_INET);
     2086            if(mybucket6_grow_time >= now.tv_sec - 150)
     2087                soon |= neighbourhood_maintenance(AF_INET6);
     2088        }
     2089
     2090        /* In order to maintain all buckets' age within 600 seconds, worst
     2091           case is roughly 27 seconds, assuming the table is 22 bits deep.
    18372092           We want to keep a margin for neighborhood maintenance, so keep
    1838            this within 30 seconds. */
     2093           this within 25 seconds. */
    18392094        if(soon)
    1840             confirm_nodes_time = now.tv_sec + 10 + random() % 20;
     2095            confirm_nodes_time = now.tv_sec + 5 + random() % 20;
    18412096        else
    18422097            confirm_nodes_time = now.tv_sec + 60 + random() % 120;
     
    18542109            *tosleep = search_time - now.tv_sec;
    18552110    }
    1856    
    1857     return find_bucket(myid)->count > 2;
     2111
     2112    return 1;
    18582113}
    18592114
    18602115int
    1861 dht_get_nodes(struct sockaddr_in *sins, int num)
    1862 {
    1863     int i;
     2116dht_get_nodes(struct sockaddr_in *sin, int *num,
     2117              struct sockaddr_in6 *sin6, int *num6)
     2118{
     2119    int i, j;
    18642120    struct bucket *b;
    18652121    struct node *n;
     
    18692125    /* For restoring to work without discarding too many nodes, the list
    18702126       must start with the contents of our bucket. */
    1871     b = find_bucket(myid);
     2127    b = find_bucket(myid, AF_INET);
     2128    if(b == NULL)
     2129        goto no_ipv4;
     2130
    18722131    n = b->nodes;
    1873     while(n && i < num) {
     2132    while(n && i < *num) {
    18742133        if(node_good(n)) {
    1875             sins[i] = n->sin;
     2134            sin[i] = *(struct sockaddr_in*)&n->ss;
    18762135            i++;
    18772136        }
     
    18802139
    18812140    b = buckets;
    1882     while(b && i < num) {
     2141    while(b && i < *num) {
    18832142        if(!in_bucket(myid, b)) {
    18842143            n = b->nodes;
    1885             while(n && i < num) {
     2144            while(n && i < *num) {
    18862145                if(node_good(n)) {
    1887                     sins[i] = n->sin;
     2146                    sin[i] = *(struct sockaddr_in*)&n->ss;
    18882147                    i++;
    18892148                }
     
    18932152        b = b->next;
    18942153    }
    1895     return i;
     2154
     2155 no_ipv4:
     2156
     2157    j = 0;
     2158
     2159    b = find_bucket(myid, AF_INET6);
     2160    if(b == NULL)
     2161        goto no_ipv6;
     2162
     2163    n = b->nodes;
     2164    while(n && j < *num6) {
     2165        if(node_good(n)) {
     2166            sin6[j] = *(struct sockaddr_in6*)&n->ss;
     2167            j++;
     2168        }
     2169        n = n->next;
     2170    }
     2171
     2172    b = buckets6;
     2173    while(b && j < *num6) {
     2174        if(!in_bucket(myid, b)) {
     2175            n = b->nodes;
     2176            while(n && j < *num6) {
     2177                if(node_good(n)) {
     2178                    sin6[j] = *(struct sockaddr_in6*)&n->ss;
     2179                    j++;
     2180                }
     2181                n = n->next;
     2182            }
     2183        }
     2184        b = b->next;
     2185    }
     2186
     2187 no_ipv6:
     2188
     2189    *num = i;
     2190    *num6 = j;
     2191    return i + j;
    18962192}
    18972193
    18982194int
    1899 dht_insert_node(int s, const unsigned char *id, struct sockaddr_in *sin)
     2195dht_insert_node(const unsigned char *id, struct sockaddr *sa, int salen)
    19002196{
    19012197    struct node *n;
    1902     n = new_node(s, id, sin, 0);
     2198
     2199    if(sa->sa_family != AF_INET) {
     2200        errno = EAFNOSUPPORT;
     2201        return -1;
     2202    }
     2203
     2204    n = new_node(id, (struct sockaddr*)sa, salen, 0);
    19032205    return !!n;
    19042206}
    19052207
    19062208int
    1907 dht_ping_node(int s, struct sockaddr_in *sin)
     2209dht_ping_node(struct sockaddr *sa, int salen)
    19082210{
    19092211    unsigned char tid[4];
     2212
    19102213    debugf("Sending ping.\n");
    19112214    make_tid(tid, "pn", 0);
    1912     return send_ping(s, (struct sockaddr*)sin, sizeof(struct sockaddr_in),
    1913                      tid, 4);
     2215    return send_ping(sa, salen, tid, 4);
    19142216}
    19152217
     
    19342236    }
    19352237
     2238static int
     2239dht_send(const void *buf, size_t len, int flags,
     2240         const struct sockaddr *sa, int salen)
     2241{
     2242    int s;
     2243
     2244    if(salen == 0)
     2245        abort();
     2246
     2247    if(sa->sa_family == AF_INET)
     2248        s = dht_socket;
     2249    else if(sa->sa_family == AF_INET6)
     2250        s = dht_socket6;
     2251    else
     2252        s = -1;
     2253
     2254    if(s < 0) {
     2255        errno = EAFNOSUPPORT;
     2256        return -1;
     2257    }
     2258
     2259    return sendto(s, buf, len, flags, sa, salen);
     2260}
     2261
    19362262int
    1937 send_ping(int s, struct sockaddr *sa, int salen,
     2263send_ping(struct sockaddr *sa, int salen,
    19382264          const unsigned char *tid, int tid_len)
    19392265{
     
    19472273    ADD_V(buf, i, 512);
    19482274    rc = snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512);
    1949     return sendto(s, buf, i, 0, sa, salen);
     2275    return dht_send(buf, i, 0, sa, salen);
    19502276
    19512277 fail:
     
    19552281
    19562282int
    1957 send_pong(int s, struct sockaddr *sa, int salen,
     2283send_pong(struct sockaddr *sa, int salen,
    19582284          const unsigned char *tid, int tid_len)
    19592285{
     
    19662292    ADD_V(buf, i, 512);
    19672293    rc = snprintf(buf + i, 512 - i, "1:y1:re"); INC(i, rc, 512);
    1968     return sendto(s, buf, i, 0, sa, salen);
     2294    return dht_send(buf, i, 0, sa, salen);
    19692295
    19702296 fail:
     
    19742300
    19752301int
    1976 send_find_node(int s, struct sockaddr *sa, int salen,
     2302send_find_node(struct sockaddr *sa, int salen,
    19772303               const unsigned char *tid, int tid_len,
    1978                const unsigned char *target, int confirm)
     2304               const unsigned char *target, int want, int confirm)
    19792305{
    19802306    char buf[512];
     
    19842310    rc = snprintf(buf + i, 512 - i, "6:target20:"); INC(i, rc, 512);
    19852311    COPY(buf, i, target, 20, 512);
     2312    if(want > 0) {
     2313        rc = snprintf(buf + i, 512 - i, "4:wantl%s%se",
     2314                      (want & WANT4) ? "2:n4" : "",
     2315                      (want & WANT6) ? "2:n6" : "");
     2316        INC(i, rc, 512);
     2317    }
    19862318    rc = snprintf(buf + i, 512 - i, "e1:q9:find_node1:t%d:", tid_len);
    19872319    INC(i, rc, 512);
     
    19892321    ADD_V(buf, i, 512);
    19902322    rc = snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512);
    1991     return sendto(s, buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);
     2323    return dht_send(buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);
    19922324
    19932325 fail:
     
    19972329
    19982330int
    1999 send_nodes_peers(int s, struct sockaddr *sa, int salen,
     2331send_nodes_peers(struct sockaddr *sa, int salen,
    20002332                 const unsigned char *tid, int tid_len,
    20012333                 const unsigned char *nodes, int nodes_len,
    2002                  struct peer *peers1, int numpeers1,
    2003                  struct peer *peers2, int numpeers2,
     2334                 const unsigned char *nodes6, int nodes6_len,
     2335                 int af, struct storage *st,
    20042336                 const unsigned char *token, int token_len)
    20052337{
    20062338    char buf[2048];
    2007     int i = 0, rc, j;
     2339    int i = 0, rc, j0, j, k, len;
     2340
    20082341    rc = snprintf(buf + i, 2048 - i, "d1:rd2:id20:"); INC(i, rc, 2048);
    20092342    COPY(buf, i, myid, 20, 2048);
     
    20182351        COPY(buf, i, nodes, nodes_len, 2048);
    20192352    }
    2020     for(j = 0; j < numpeers1; j++) {
    2021         unsigned short swapped = htons(peers1[j].port);
    2022         rc = snprintf(buf + i, 2048 - i, "6:"); INC(i, rc, 2048);
    2023         COPY(buf, i, peers1[j].ip, 4, 2048);
    2024         COPY(buf, i, &swapped, 2, 2048);
    2025     }
    2026     for(j = 0; j < numpeers2; j++) {
    2027         unsigned short swapped = htons(peers2[j].port);
    2028         rc = snprintf(buf + i, 2048 - i, "6:"); INC(i, rc, 2048);
    2029         COPY(buf, i, peers2[j].ip, 4, 2048);
    2030         COPY(buf, i, &swapped, 2, 2048);
    2031     }
     2353    if(nodes6_len > 0) {
     2354         rc = snprintf(buf + i, 2048 - i, "6:nodes6%d:", nodes6_len);
     2355         INC(i, rc, 2048);
     2356         COPY(buf, i, nodes6, nodes6_len, 2048);
     2357    }
     2358
     2359    if(st && st->numpeers > 0) {
     2360        /* We treat the storage as a circular list, and serve a randomly
     2361           chosen slice.  In order to make sure we fit within 1024 octets,
     2362           we limit ourselves to 50 peers. */
     2363
     2364        len = af == AF_INET ? 4 : 16;
     2365        j0 = random() % st->numpeers;
     2366        j = j0;
     2367        k = 0;
     2368
     2369        rc = snprintf(buf + i, 2048 - i, "6:valuesl"); INC(i, rc, 2048);
     2370        do {
     2371            if(st->peers[j].len == len) {
     2372                unsigned short swapped;
     2373                swapped = htons(st->peers[j].port);
     2374                rc = snprintf(buf + i, 2048 - i, "%d:", len + 2);
     2375                INC(i, rc, 2048);
     2376                COPY(buf, i, st->peers[j].ip, len, 2048);
     2377                COPY(buf, i, &swapped, 2, 2048);
     2378                k++;
     2379            }
     2380            j = (j + 1) % st->numpeers;
     2381        } while(j != j0 && k < 50);
     2382        rc = snprintf(buf + i, 2048 - i, "e"); INC(i, rc, 2048);
     2383    }
     2384
    20322385    rc = snprintf(buf + i, 2048 - i, "e1:t%d:", tid_len); INC(i, rc, 2048);
    20332386    COPY(buf, i, tid, tid_len, 2048);
     
    20352388    rc = snprintf(buf + i, 2048 - i, "1:y1:re"); INC(i, rc, 2048);
    20362389
    2037     return sendto(s, buf, i, 0, sa, salen);
     2390    return dht_send(buf, i, 0, sa, salen);
    20382391
    20392392 fail:
     
    20462399                    const unsigned char *id, struct node *n)
    20472400{
    2048     int i;
     2401    int i, size;
     2402
     2403    if(n->ss.ss_family == AF_INET)
     2404        size = 26;
     2405    else if(n->ss.ss_family == AF_INET6)
     2406        size = 38;
     2407    else
     2408        abort();
     2409
    20492410    for(i = 0; i< numnodes; i++) {
    2050         if(id_cmp(nodes + 26 * i, id) == 0)
     2411        if(id_cmp(n->id, nodes + size * i) == 0)
    20512412            return numnodes;
    2052         if(xorcmp(n->id, nodes + 26 * i, id) < 0)
     2413        if(xorcmp(n->id, nodes + size * i, id) < 0)
    20532414            break;
    20542415    }
     
    20612422
    20622423    if(i < numnodes - 1)
    2063         memmove(nodes + 26 * (i + 1), nodes + 26 * i, 26 * (numnodes - i - 1));
    2064 
    2065     memcpy(nodes + 26 * i, n->id, 20);
    2066     memcpy(nodes + 26 * i + 20, &n->sin.sin_addr, 4);
    2067     memcpy(nodes + 26 * i + 24, &n->sin.sin_port, 2);
     2424        memmove(nodes + size * (i + 1), nodes + size * i,
     2425                size * (numnodes - i - 1));
     2426
     2427    if(n->ss.ss_family == AF_INET) {
     2428        struct sockaddr_in *sin = (struct sockaddr_in*)&n->ss;
     2429        memcpy(nodes + size * i, n->id, 20);
     2430        memcpy(nodes + size * i + 20, &sin->sin_addr, 4);
     2431        memcpy(nodes + size * i + 24, &sin->sin_port, 2);
     2432    } else if(n->ss.ss_family == AF_INET6) {
     2433        struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&n->ss;
     2434        memcpy(nodes + size * i, n->id, 20);
     2435        memcpy(nodes + size * i + 20, &sin6->sin6_addr, 16);
     2436        memcpy(nodes + size * i + 36, &sin6->sin6_port, 2);
     2437    } else {
     2438        abort();
     2439    }
    20682440
    20692441    return numnodes;
     
    20842456
    20852457int
    2086 send_closest_nodes(int s, struct sockaddr *sa, int salen,
     2458send_closest_nodes(struct sockaddr *sa, int salen,
    20872459                   const unsigned char *tid, int tid_len,
    2088                    const unsigned char *id,
    2089                    struct peer *peers1, int numpeers1,
    2090                    struct peer *peers2, int numpeers2,
     2460                   const unsigned char *id, int want,
     2461                   int af, struct storage *st,
    20912462                   const unsigned char *token, int token_len)
    20922463{
    20932464    unsigned char nodes[8 * 26];
    2094     int numnodes = 0;
     2465    unsigned char nodes6[8 * 38];
     2466    int numnodes = 0, numnodes6 = 0;
    20952467    struct bucket *b;
    20962468
    2097     b = find_bucket(id);
    2098     numnodes = buffer_closest_nodes(nodes, numnodes, id, b);
    2099     if(b->next)
    2100         numnodes = buffer_closest_nodes(nodes, numnodes, id, b->next);
    2101     b = previous_bucket(b);
    2102     if(b)
    2103         numnodes = buffer_closest_nodes(nodes, numnodes, id, b);
    2104 
    2105     return send_nodes_peers(s, sa, salen, tid, tid_len,
     2469    if(want < 0)
     2470        want = sa->sa_family == AF_INET ? WANT4 : WANT6;
     2471
     2472    if((want & WANT4)) {
     2473        b = find_bucket(id, AF_INET);
     2474        if(b) {
     2475            numnodes = buffer_closest_nodes(nodes, numnodes, id, b);
     2476            if(b->next)
     2477                numnodes = buffer_closest_nodes(nodes, numnodes, id, b->next);
     2478            b = previous_bucket(b);
     2479            if(b)
     2480                numnodes = buffer_closest_nodes(nodes, numnodes, id, b);
     2481        }
     2482    }
     2483
     2484    if((want & WANT6)) {
     2485        b = find_bucket(id, AF_INET6);
     2486        if(b) {
     2487            numnodes6 = buffer_closest_nodes(nodes6, numnodes6, id, b);
     2488            if(b->next)
     2489                numnodes6 =
     2490                    buffer_closest_nodes(nodes6, numnodes6, id, b->next);
     2491            b = previous_bucket(b);
     2492            if(b)
     2493                numnodes6 = buffer_closest_nodes(nodes6, numnodes6, id, b);
     2494        }
     2495    }
     2496    debugf("  (%d+%d nodes.)\n", numnodes, numnodes6);
     2497
     2498    return send_nodes_peers(sa, salen, tid, tid_len,
    21062499                            nodes, numnodes * 26,
    2107                             peers1, numpeers1, peers2, numpeers2,
    2108                             token, token_len);
     2500                            nodes6, numnodes6 * 38,
     2501                            af, st, token, token_len);
    21092502}
    21102503
    21112504int
    2112 send_get_peers(int s, struct sockaddr *sa, int salen,
     2505send_get_peers(struct sockaddr *sa, int salen,
    21132506               unsigned char *tid, int tid_len, unsigned char *infohash,
    2114                int confirm)
     2507               int want, int confirm)
    21152508{
    21162509    char buf[512];
     
    21212514    rc = snprintf(buf + i, 512 - i, "9:info_hash20:"); INC(i, rc, 512);
    21222515    COPY(buf, i, infohash, 20, 512);
     2516    if(want > 0) {
     2517        rc = snprintf(buf + i, 512 - i, "4:wantl%s%se",
     2518                      (want & WANT4) ? "2:n4" : "",
     2519                      (want & WANT6) ? "2:n6" : "");
     2520        INC(i, rc, 512);
     2521    }
    21232522    rc = snprintf(buf + i, 512 - i, "e1:q9:get_peers1:t%d:", tid_len);
    21242523    INC(i, rc, 512);
     
    21262525    ADD_V(buf, i, 512);
    21272526    rc = snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512);
    2128     return sendto(s, buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);
     2527    return dht_send(buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);
    21292528
    21302529 fail:
     
    21342533
    21352534int
    2136 send_announce_peer(int s, struct sockaddr *sa, int salen,
     2535send_announce_peer(struct sockaddr *sa, int salen,
    21372536                   unsigned char *tid, int tid_len,
    21382537                   unsigned char *infohash, unsigned short port,
     
    21562555    rc = snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512);
    21572556
    2158     return sendto(s, buf, i, confirm ? 0 : MSG_CONFIRM, sa, salen);
     2557    return dht_send(buf, i, confirm ? 0 : MSG_CONFIRM, sa, salen);
    21592558
    21602559 fail:
     
    21632562}
    21642563
    2165 int
    2166 send_peer_announced(int s, struct sockaddr *sa, int salen,
     2564static int
     2565send_peer_announced(struct sockaddr *sa, int salen,
    21672566                    unsigned char *tid, int tid_len)
    21682567{
     
    21752574    INC(i, rc, 512);
    21762575    COPY(buf, i, tid, tid_len, 512);
    2177     ADD_V(buf, i, 2048);
    2178     rc = snprintf(buf + i, 2048 - i, "1:y1:re"); INC(i, rc, 2048);
    2179     return sendto(s, buf, i, 0, sa, salen);
     2576    ADD_V(buf, i, 512);
     2577    rc = snprintf(buf + i, 512 - i, "1:y1:re"); INC(i, rc, 512);
     2578    return dht_send(buf, i, 0, sa, salen);
     2579
     2580 fail:
     2581    errno = ENOSPC;
     2582    return -1;
     2583}
     2584
     2585static int
     2586send_error(struct sockaddr *sa, int salen,
     2587           unsigned char *tid, int tid_len,
     2588           int code, const char *message)
     2589{
     2590    char buf[512];
     2591    int i = 0, rc;
     2592
     2593    rc = snprintf(buf + i, 512 - i, "d1:eli%de%d:",
     2594                  code, (int)strlen(message));
     2595    INC(i, rc, 512);
     2596    COPY(buf, i, message, (int)strlen(message), 512);
     2597    rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len); INC(i, rc, 512);
     2598    COPY(buf, i, tid, tid_len, 512);
     2599    ADD_V(buf, i, 512);
     2600    rc = snprintf(buf + i, 512 - i, "1:y1:ee"); INC(i, rc, 512);
     2601    return dht_send(buf, i, 0, sa, salen);
    21802602
    21812603 fail:
     
    22172639              unsigned char *token_return, int *token_len,
    22182640              unsigned char *nodes_return, int *nodes_len,
    2219               const unsigned char *values_return, int *values_len)
     2641              unsigned char *nodes6_return, int *nodes6_len,
     2642              unsigned char *values_return, int *values_len,
     2643              unsigned char *values6_return, int *values6_len,
     2644              int *want_return)
    22202645{
    22212646    const unsigned char *p;
     
    22932718            *token_len = 0;
    22942719    }
    2295        
    2296     if(nodes_return) {
     2720
     2721    if(nodes_len) {
    22972722        p = memmem(buf, buflen, "5:nodes", 7);
    22982723        if(p) {
     
    23102735    }
    23112736
    2312     if(values_return) {
     2737    if(nodes6_len) {
     2738        p = memmem(buf, buflen, "6:nodes6", 8);
     2739        if(p) {
     2740            long l;
     2741            char *q;
     2742            l = strtol((char*)p + 8, &q, 10);
     2743            if(q && *q == ':' && l > 0 && l < *nodes6_len) {
     2744                CHECK(q + 1, l);
     2745                memcpy(nodes6_return, q + 1, l);
     2746                *nodes6_len = l;
     2747            } else
     2748                *nodes6_len = 0;
     2749        } else
     2750            *nodes6_len = 0;
     2751    }
     2752
     2753    if(values_len || values6_len) {
    23132754        p = memmem(buf, buflen, "6:valuesl", 9);
    23142755        if(p) {
    23152756            int i = p - buf + 9;
    2316             int j = 0;
     2757            int j = 0, j6 = 0;
    23172758            while(1) {
    23182759                long l;
     
    23212762                if(q && *q == ':' && l > 0) {
    23222763                    CHECK(q + 1, l);
    2323                     if(j + l > *values_len)
    2324                         break;
    2325                     i = q + 1 + l - (char*)buf;
    2326                     /* BEP 32 allows heterogeneous values -- ignore IPv6 */
    2327                     if(l != 6) {
    2328                         debugf("Received weird value -- %d bytes.\n",
    2329                                (int)l);
    2330                         continue;
     2764                    if(l == 6) {
     2765                        if(j + l > *values_len)
     2766                            continue;
     2767                        i = q + 1 + l - (char*)buf;
     2768                        memcpy((char*)values_return + j, q + 1, l);
     2769                        j += l;
     2770                    } else if(l == 18) {
     2771                        if(j6 + l > *values6_len)
     2772                            continue;
     2773                        i = q + 1 + l - (char*)buf;
     2774                        memcpy((char*)values6_return + j6, q + 1, l);
     2775                        j6 += l;
     2776                    } else {
     2777                        debugf("Received weird value -- %d bytes.\n", (int)l);
     2778                        i = q + 1 + l - (char*)buf;
    23312779                    }
    2332                     memcpy((char*)values_return + j, q + 1, l);
    2333                     j += l;
    23342780                } else {
    23352781                    break;
     
    23382784            if(i >= buflen || buf[i] != 'e')
    23392785                debugf("eek... unexpected end for values.\n");
    2340             *values_len = j;
     2786            if(values_len)
     2787                *values_len = j;
     2788            if(values6_len)
     2789                *values6_len = j6;
    23412790        } else {
    23422791            *values_len = 0;
     2792            *values6_len = 0;
     2793        }
     2794    }
     2795
     2796    if(want_return) {
     2797        p = memmem(buf, buflen, "4:wantl", 7);
     2798        if(p) {
     2799            int i = p - buf + 7;
     2800            *want_return = 0;
     2801            while(buf[i] > '0' && buf[i] <= '9' && buf[i + 1] == ':' &&
     2802                  i + 2 + buf[i] - '0' < buflen) {
     2803                CHECK(buf + i + 2, buf[i] - '0');
     2804                if(buf[i] == '2' && memcmp(buf + i + 2, "n4", 2) == 0)
     2805                    *want_return |= WANT4;
     2806                else if(buf[i] == '2' && memcmp(buf + i + 2, "n6", 2) == 0)
     2807                    *want_return |= WANT6;
     2808                else
     2809                    debugf("eek... unexpected want flag (%c)\n", buf[i]);
     2810                i += 2 + buf[i] - '0';
     2811            }
     2812            if(i >= buflen || buf[i] != 'e')
     2813                debugf("eek... unexpected end for want.\n");
     2814        } else {
     2815            *want_return = -1;
    23432816        }
    23442817    }
    23452818
    23462819#undef CHECK
    2347                
     2820
    23482821    if(memmem(buf, buflen, "1:y1:r", 6))
    23492822        return REPLY;
     2823    if(memmem(buf, buflen, "1:y1:e", 6))
     2824        return ERROR;
    23502825    if(!memmem(buf, buflen, "1:y1:q", 6))
    23512826        return -1;
  • trunk/third-party/dht/dht.h

    r8440 r9549  
    2828#define DHT_EVENT_NONE 0
    2929#define DHT_EVENT_VALUES 1
    30 #define DHT_EVENT_SEARCH_DONE 2
     30#define DHT_EVENT_VALUES6 2
     31#define DHT_EVENT_SEARCH_DONE 3
     32#define DHT_EVENT_SEARCH_DONE6 4
    3133
    3234extern FILE *dht_debug;
    3335
    34 int dht_init(int s, const unsigned char *id, const unsigned char *v);
    35 int dht_insert_node(int s, const unsigned char *id, struct sockaddr_in *sin);
    36 int dht_ping_node(int s, struct sockaddr_in *sin);
    37 int dht_periodic(int s, int available, time_t *tosleep,
     36int dht_init(int s, int s6, const unsigned char *id, const unsigned char *v);
     37int dht_insert_node(const unsigned char *id, struct sockaddr *sa, int salen);
     38int dht_ping_node(struct sockaddr *sa, int salen);
     39int dht_periodic(int available, time_t *tosleep,
    3840                 dht_callback *callback, void *closure);
    39 int dht_search(int s, const unsigned char *id, int port,
     41int dht_search(const unsigned char *id, int port, int af,
    4042               dht_callback *callback, void *closure);
    41 int dht_nodes(int *good_return, int *dubious_return, int *cached_return,
     43int dht_nodes(int af,
     44              int *good_return, int *dubious_return, int *cached_return,
    4245              int *incoming_return);
    4346void dht_dump_tables(FILE *f);
    44 int dht_get_nodes(struct sockaddr_in *sins, int num);
    45 int dht_uninit(int s, int dofree);
     47int dht_get_nodes(struct sockaddr_in *sin, int *num,
     48                  struct sockaddr_in6 *sin6, int *num6);
     49int dht_uninit(int dofree);
    4650
    4751/* This must be provided by the user. */
Note: See TracChangeset for help on using the changeset viewer.