Ignore:
Timestamp:
Nov 24, 2009, 1:59:51 AM (13 years ago)
Author:
charles
Message:

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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}
Note: See TracChangeset for help on using the changeset viewer.