예제 #1
0
static int
bootstrap_af(tr_session *session)
{
    if( bootstrap_done(session, AF_INET6) )
        return AF_INET;
    else if ( bootstrap_done(session, AF_INET) )
        return AF_INET6;
    else
        return 0;
}
예제 #2
0
static int
bootstrap_done( tr_session *session, int af )
{
    int status;

    if(af == 0)
        return
            bootstrap_done(session, AF_INET) &&
            bootstrap_done(session, AF_INET6);

    status = tr_dhtStatus(session, af, NULL);
    return status == TR_DHT_STOPPED || status >= TR_DHT_FIREWALLED;
}
예제 #3
0
static void
bootstrap_from_name( const char *name, tr_port port, int af )
{
    struct addrinfo hints, *info, *infop;
    char pp[10];
    int rc;

    memset(&hints, 0, sizeof(hints));
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_family = af;
    /* No, just passing p + 1 to gai won't work. */
    tr_snprintf(pp, sizeof(pp), "%d", (int)port);

    rc = getaddrinfo(name, pp, &hints, &info);
    if(rc != 0) {
        tr_nerr("DHT", "%s:%s: %s", name, pp, gai_strerror(rc));
        return;
    }

    infop = info;
    while(infop) {
        dht_ping_node(infop->ai_addr, infop->ai_addrlen);

        nap(15);

        if(bootstrap_done(session, af))
            break;
        infop = infop->ai_next;
    }
    freeaddrinfo(info);
}
예제 #4
0
static void
dht_bootstrap(void *closure)
{
    struct bootstrap_closure *cl = closure;
    int i;
    int num = cl->len / 6, num6 = cl->len6 / 18;

    if(session != cl->session)
        return;

    if(cl->len > 0)
        tr_ninf( "DHT", "Bootstrapping from %d nodes", num );

    if(cl->len6 > 0)
        tr_ninf( "DHT", "Bootstrapping from %d IPv6 nodes", num6 );


    for(i = 0; i < MAX(num, num6); i++) {
        if( i < num && !bootstrap_done(cl->session, AF_INET) ) {
            tr_port port;
            struct tr_address addr;

            memset(&addr, 0, sizeof(addr));
            addr.type = TR_AF_INET;
            memcpy(&addr.addr.addr4, &cl->nodes[i * 6], 4);
            memcpy(&port, &cl->nodes[i * 6 + 4], 2);
            port = ntohs(port);
            tr_dhtAddNode(cl->session, &addr, port, 1);
        }
        if( i < num6 && !bootstrap_done(cl->session, AF_INET6) ) {
            tr_port port;
            struct tr_address addr;

            memset(&addr, 0, sizeof(addr));
            addr.type = TR_AF_INET6;
            memcpy(&addr.addr.addr6, &cl->nodes6[i * 18], 16);
            memcpy(&port, &cl->nodes6[i * 18 + 16], 2);
            port = ntohs(port);
            tr_dhtAddNode(cl->session, &addr, port, 1);
        }

        /* Our DHT code is able to take up to 9 nodes in a row without
           dropping any.  After that, it takes some time to split buckets.
           So ping the first 8 nodes quickly, then slow down. */
        if(i < 8)
            nap(2);
        else
            nap(15);

        if(bootstrap_done( session, 0 ))
            break;
    }

    if(!bootstrap_done(cl->session, 0)) {
        char *bootstrap_file;
        FILE *f = NULL;

        bootstrap_file =
            tr_buildPath(cl->session->configDir, "dht.bootstrap", NULL);

        if(bootstrap_file)
            f = fopen(bootstrap_file, "rb");
        if(f != NULL) {
            tr_ninf("DHT", "Attempting manual bootstrap");
            for(;;) {
                char buf[201];
                char *p;
                int port = 0;

                p = fgets(buf, 200, f);
                if( p == NULL )
                    break;

                p = memchr(buf, ' ', strlen(buf));
                if(p != NULL)
                    port = atoi(p + 1);
                if(p == NULL || port <= 0 || port >= 0x10000) {
                    tr_nerr("DHT", "Couldn't parse %s", buf);
                    continue;
                }

                *p = '\0';

                bootstrap_from_name( buf, port, bootstrap_af(session) );

                if(bootstrap_done(cl->session, 0))
                    break;
            }
        }

        tr_free( bootstrap_file );
    }

    /* We really don't want to abuse our bootstrap nodes.
       Be glacially slow. */
    if(!bootstrap_done(cl->session, 0))
        nap(30);

    if(!bootstrap_done(cl->session, 0)) {
        tr_ninf("DHT", "Attempting bootstrap from dht.transmissionbt.com");
        bootstrap_from_name( "dht.transmissionbt.com", 6881,
                             bootstrap_af(session) );
    }

    if( cl->nodes )
        tr_free( cl->nodes );
    if( cl->nodes6 )
        tr_free( cl->nodes6 );
    tr_free( closure );
    tr_ndbg( "DHT", "Finished bootstrapping" );
}
예제 #5
0
static void
dht_bootstrap (void *closure)
{
    struct bootstrap_closure *cl = closure;
    int i;
    int num = cl->len / 6, num6 = cl->len6 / 18;

    if (session != cl->session)
        return;

    if (cl->len > 0)
        tr_logAddNamedInfo ("DHT", "Bootstrapping from %d IPv4 nodes", num);

    if (cl->len6 > 0)
        tr_logAddNamedInfo ("DHT", "Bootstrapping from %d IPv6 nodes", num6);


    for (i = 0; i < MAX (num, num6); i++) {
        if (i < num && !bootstrap_done (cl->session, AF_INET)) {
            tr_port port;
            struct tr_address addr;

            memset (&addr, 0, sizeof (addr));
            addr.type = TR_AF_INET;
            memcpy (&addr.addr.addr4, &cl->nodes[i * 6], 4);
            memcpy (&port, &cl->nodes[i * 6 + 4], 2);
            port = ntohs (port);
            tr_dhtAddNode (cl->session, &addr, port, 1);
        }
        if (i < num6 && !bootstrap_done (cl->session, AF_INET6)) {
            tr_port port;
            struct tr_address addr;

            memset (&addr, 0, sizeof (addr));
            addr.type = TR_AF_INET6;
            memcpy (&addr.addr.addr6, &cl->nodes6[i * 18], 16);
            memcpy (&port, &cl->nodes6[i * 18 + 16], 2);
            port = ntohs (port);
            tr_dhtAddNode (cl->session, &addr, port, 1);
        }

        /* Our DHT code is able to take up to 9 nodes in a row without
           dropping any. After that, it takes some time to split buckets.
           So ping the first 8 nodes quickly, then slow down. */
        if (i < 8)
            nap (2);
        else
            nap (15);

        if (bootstrap_done (session, 0))
            break;
    }

    if (!bootstrap_done (cl->session, 0)) {
        char *bootstrap_file;
        tr_sys_file_t f = TR_BAD_SYS_FILE;

        bootstrap_file =
            tr_buildPath (cl->session->configDir, "dht.bootstrap", NULL);

        if (bootstrap_file)
            f = tr_sys_file_open (bootstrap_file, TR_SYS_FILE_READ, 0, NULL);
        if (f != TR_BAD_SYS_FILE) {
            tr_logAddNamedInfo ("DHT", "Attempting manual bootstrap");
            for (;;) {
                char buf[201];
                char *p;
                int port = 0;

                if (!tr_sys_file_read_line (f, buf, 200, NULL))
                    break;

                p = memchr (buf, ' ', strlen (buf));
                if (p != NULL)
                    port = atoi (p + 1);
                if (p == NULL || port <= 0 || port >= 0x10000) {
                    tr_logAddNamedError ("DHT", "Couldn't parse %s", buf);
                    continue;
                }

                *p = '\0';

                bootstrap_from_name (buf, port, bootstrap_af (session));

                if (bootstrap_done (cl->session, 0))
                    break;
            }
            tr_sys_file_close (f, NULL);
        }

        tr_free (bootstrap_file);
    }

    if (!bootstrap_done (cl->session, 0)) {
        for (i = 0; i < 6; i++) {
            /* We don't want to abuse our bootstrap nodes, so be very
               slow.  The initial wait is to give other nodes a chance
               to contact us before we attempt to contact a bootstrap
               node, for example because we've just been restarted. */
            nap (40);
            if (bootstrap_done (cl->session, 0))
                break;
            if (i == 0)
                tr_logAddNamedInfo ("DHT",
                        "Attempting bootstrap from dht.transmissionbt.com");
            bootstrap_from_name ("dht.transmissionbt.com", 6881,
                                 bootstrap_af (session));
        }
    }

    if (cl->nodes)
        tr_free (cl->nodes);
    if (cl->nodes6)
        tr_free (cl->nodes6);
    tr_free (closure);
    tr_logAddNamedDbg ("DHT", "Finished bootstrapping");
}