Пример #1
0
void
tr_ctorSetFilesWanted( tr_ctor                * ctor,
                       const tr_file_index_t  * files,
                       tr_file_index_t          fileCount,
                       tr_bool                  wanted )
{
    tr_file_index_t ** myfiles = wanted ? &ctor->want : &ctor->notWant;
    tr_file_index_t * mycount = wanted ? &ctor->wantSize : &ctor->notWantSize;

    tr_free( *myfiles );
    *myfiles = tr_memdup( files, sizeof(tr_file_index_t)*fileCount );
    *mycount = fileCount;
}
Пример #2
0
void
tr_ctorSetFilePriorities( tr_ctor                * ctor,
                          const tr_file_index_t  * files,
                          tr_file_index_t          fileCount,
                          tr_priority_t            priority )
{
    tr_file_index_t ** myfiles;
    tr_file_index_t * mycount;

    switch( priority ) {
        case TR_PRI_LOW: myfiles = &ctor->low; mycount = &ctor->lowSize; break;
        case TR_PRI_HIGH: myfiles = &ctor->high; mycount = &ctor->highSize; break;
        default /*TR_PRI_NORMAL*/: myfiles = &ctor->normal; mycount = &ctor->normalSize; break;
    }

    tr_free( *myfiles );
    *myfiles = tr_memdup( files, sizeof(tr_file_index_t)*fileCount );
    *mycount = fileCount;
}
Пример #3
0
tr_magnet_info *
tr_magnetParse( const char * uri )
{
    bool got_checksum = false;
    int trCount = 0;
    int wsCount = 0;
    char * tr[MAX_TRACKERS];
    char * ws[MAX_WEBSEEDS];
    char * displayName = NULL;
    uint8_t sha1[SHA_DIGEST_LENGTH];
    tr_magnet_info * info = NULL;

    if( ( uri != NULL ) && !memcmp( uri, "magnet:?", 8 ) )
    {
        const char * walk;

        for( walk=uri+8; walk && *walk; )
        {
            const char * key = walk;
            const char * delim = strchr( key, '=' );
            const char * val = delim == NULL ? NULL : delim + 1;
            const char * next = strchr( delim == NULL ? key : val, '&' );
            int keylen, vallen;

            if( delim != NULL )
                keylen = delim - key;
            else if( next != NULL )
                keylen = next - key;
            else
                keylen = strlen( key );

            if( val == NULL )
                vallen = 0;
            else if( next != NULL )
                vallen = next - val;
            else
                vallen = strlen( val );

            if( ( keylen==2 ) && !memcmp( key, "xt", 2 ) && val && !memcmp( val, "urn:btih:", 9 ) )
            {
                const char * hash = val + 9;
                const int hashlen = vallen - 9;

                if( hashlen == 40 ) {
                    tr_hex_to_sha1( sha1, hash );
                    got_checksum = true;
                }
                else if( hashlen == 32 ) {
                    base32_to_sha1( sha1, hash, hashlen );
                    got_checksum = true;
                }
            }

            if( ( vallen > 0 ) && ( keylen==2 ) && !memcmp( key, "dn", 2 ) )
                displayName = tr_http_unescape( val, vallen );

            if( ( vallen > 0 ) && ( trCount < MAX_TRACKERS ) ) {
                int i;
                if( ( keylen==2 ) && !memcmp( key, "tr", 2 ) )
                    tr[trCount++] = tr_http_unescape( val, vallen );
                else if( ( sscanf( key, "tr.%d=", &i ) == 1 ) && ( i > 0 ) ) /* ticket #3341 */
                    tr[trCount++] = tr_http_unescape( val, vallen );
            }

            if( ( vallen > 0 ) && ( keylen==2 ) && !memcmp( key, "ws", 2 ) && ( wsCount < MAX_WEBSEEDS ) )
                ws[wsCount++] = tr_http_unescape( val, vallen );

            walk = next != NULL ? next + 1 : NULL;
        }
    }

    if( got_checksum )
    {
        info = tr_new0( tr_magnet_info, 1 );
        info->displayName = displayName;
        info->trackerCount = trCount;
        info->trackers = tr_memdup( tr, sizeof(char*) * trCount );
        info->webseedCount = wsCount;
        info->webseeds = tr_memdup( ws, sizeof(char*) * wsCount );
        memcpy( info->hash, sha1, sizeof(uint8_t) * SHA_DIGEST_LENGTH );
    }

    return info;
}
Пример #4
0
int
tr_dhtInit(tr_session *ss, const tr_address * tr_addr)
{
    struct sockaddr_in sin;
    tr_benc benc;
    int rc;
    tr_bool have_id = FALSE;
    char * dat_file;
    uint8_t * nodes = NULL, * nodes6 = NULL;
    const uint8_t * raw;
    size_t len, len6;
    struct bootstrap_closure * cl;

    if( session ) /* already initialized */
        return -1;

    dht_port = tr_sessionGetPeerPort(ss);
    if(dht_port <= 0)
        return -1;

    tr_ndbg( "DHT", "Initializing DHT" );

    dht_socket = socket(PF_INET, SOCK_DGRAM, 0);
    if(dht_socket < 0)
        goto fail;

    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    memcpy(&sin.sin_addr, &tr_addr->addr.addr4, sizeof (struct in_addr));
    sin.sin_port = htons(dht_port);
    rc = bind(dht_socket, (struct sockaddr*)&sin, sizeof(sin));
    if(rc < 0)
        goto fail;

    if(tr_globalIPv6())
        rebind_ipv6(TRUE);

    if( getenv( "TR_DHT_VERBOSE" ) != NULL )
        dht_debug = stderr;

    dat_file = tr_buildPath( ss->configDir, "dht.dat", NULL );
    rc = tr_bencLoadFile( &benc, TR_FMT_BENC, dat_file );
    tr_free( dat_file );
    if(rc == 0) {
        have_id = tr_bencDictFindRaw(&benc, "id", &raw, &len);
        if( have_id && len==20 )
            memcpy( myid, raw, len );
        if( dht_socket >= 0 &&
            tr_bencDictFindRaw( &benc, "nodes", &raw, &len ) && !(len%6) ) {
                nodes = tr_memdup( raw, len );
        }
        if( dht6_socket > 0 &&
            tr_bencDictFindRaw( &benc, "nodes6", &raw, &len6 ) && !(len6%18) ) {
            nodes6 = tr_memdup( raw, len6 );
        }
        tr_bencFree( &benc );
    }

    if(nodes == NULL)
        len = 0;
    if(nodes6 == NULL)
        len6 = 0;

    if( have_id )
        tr_ninf( "DHT", "Reusing old id" );
    else {
        /* Note that DHT ids need to be distributed uniformly,
         * so it should be something truly random. */
        tr_ninf( "DHT", "Generating new id" );
        tr_cryptoRandBuf( myid, 20 );
    }

    rc = dht_init( dht_socket, dht6_socket, myid, NULL );
    if( rc < 0 )
        goto fail;

    session = ss;

    cl = tr_new( struct bootstrap_closure, 1 );
    cl->session = session;
    cl->nodes = nodes;
    cl->nodes6 = nodes6;
    cl->len = len;
    cl->len6 = len6;
    tr_threadNew( dht_bootstrap, cl );

    dht_event = event_new( session->event_base, dht_socket, EV_READ, event_callback, NULL );
    tr_timerAdd( dht_event, 0, tr_cryptoWeakRandInt( 1000000 ) );

    if( dht6_socket >= 0 )
    {
        dht6_event = event_new( session->event_base, dht6_socket, EV_READ, event_callback, NULL );
        tr_timerAdd( dht6_event, 0, tr_cryptoWeakRandInt( 1000000 ) );
    }

    tr_ndbg( "DHT", "DHT initialized" );

    return 1;

    fail:
    {
        const int save = errno;
        close(dht_socket);
        if( dht6_socket >= 0 )
            close(dht6_socket);
        dht_socket = dht6_socket = -1;
        session = NULL;
        tr_ndbg( "DHT", "DHT initialization failed (errno = %d)", save );
        errno = save;
    }

    return -1;
}
Пример #5
0
int
tr_dhtInit(tr_session *ss)
{
    tr_benc benc;
    int rc;
    bool have_id = false;
    char * dat_file;
    uint8_t * nodes = NULL, * nodes6 = NULL;
    const uint8_t * raw;
    size_t len, len6;
    struct bootstrap_closure * cl;

    if( session ) /* already initialized */
        return -1;

    tr_ndbg( "DHT", "Initializing DHT" );

    if( getenv( "TR_DHT_VERBOSE" ) != NULL )
        dht_debug = stderr;

    dat_file = tr_buildPath( ss->configDir, "dht.dat", NULL );
    rc = tr_bencLoadFile( &benc, TR_FMT_BENC, dat_file );
    tr_free( dat_file );
    if(rc == 0) {
        have_id = tr_bencDictFindRaw(&benc, "id", &raw, &len);
        if( have_id && len==20 )
            memcpy( myid, raw, len );
        if( ss->udp_socket >= 0 &&
            tr_bencDictFindRaw( &benc, "nodes", &raw, &len ) && !(len%6) ) {
                nodes = tr_memdup( raw, len );
        }
        if( ss->udp6_socket > 0 &&
            tr_bencDictFindRaw( &benc, "nodes6", &raw, &len6 ) && !(len6%18) ) {
            nodes6 = tr_memdup( raw, len6 );
        }
        tr_bencFree( &benc );
    }

    if(nodes == NULL)
        len = 0;
    if(nodes6 == NULL)
        len6 = 0;

    if( have_id )
        tr_ninf( "DHT", "Reusing old id" );
    else {
        /* Note that DHT ids need to be distributed uniformly,
         * so it should be something truly random. */
        tr_ninf( "DHT", "Generating new id" );
        tr_cryptoRandBuf( myid, 20 );
    }

    rc = dht_init( ss->udp_socket, ss->udp6_socket, myid, NULL );
    if( rc < 0 )
        goto fail;

    session = ss;

    cl = tr_new( struct bootstrap_closure, 1 );
    cl->session = session;
    cl->nodes = nodes;
    cl->nodes6 = nodes6;
    cl->len = len;
    cl->len6 = len6;
    tr_threadNew( dht_bootstrap, cl );

    dht_timer = evtimer_new( session->event_base, timer_callback, session );
    tr_timerAdd( dht_timer, 0, tr_cryptoWeakRandInt( 1000000 ) );

    tr_ndbg( "DHT", "DHT initialized" );

    return 1;

 fail:
    tr_ndbg( "DHT", "DHT initialization failed (errno = %d)", errno );
    session = NULL;
    return -1;
}
Пример #6
0
int
tr_dhtInit (tr_session *ss)
{
    tr_variant benc;
    int rc;
    bool have_id = false;
    char * dat_file;
    uint8_t * nodes = NULL, * nodes6 = NULL;
    const uint8_t * raw;
    size_t len, len6;
    struct bootstrap_closure * cl;

    if (session) /* already initialized */
        return -1;

    tr_logAddNamedDbg ("DHT", "Initializing DHT");

    if (tr_env_key_exists ("TR_DHT_VERBOSE"))
        dht_debug = stderr;

    dat_file = tr_buildPath (ss->configDir, "dht.dat", NULL);
    rc = tr_variantFromFile (&benc, TR_VARIANT_FMT_BENC, dat_file, NULL) ? 0 : -1;
    tr_free (dat_file);
    if (rc == 0) {
        have_id = tr_variantDictFindRaw (&benc, TR_KEY_id, &raw, &len);
        if (have_id && len==20)
            memcpy (myid, raw, len);
        if (ss->udp_socket != TR_BAD_SOCKET &&
            tr_variantDictFindRaw (&benc, TR_KEY_nodes, &raw, &len) && ! (len%6)) {
                nodes = tr_memdup (raw, len);
        }
        if (ss->udp6_socket != TR_BAD_SOCKET &&
            tr_variantDictFindRaw (&benc, TR_KEY_nodes6, &raw, &len6) && ! (len6%18)) {
            nodes6 = tr_memdup (raw, len6);
        }
        tr_variantFree (&benc);
    }

    if (nodes == NULL)
        len = 0;
    if (nodes6 == NULL)
        len6 = 0;

    if (have_id)
        tr_logAddNamedInfo ("DHT", "Reusing old id");
    else {
        /* Note that DHT ids need to be distributed uniformly,
         * so it should be something truly random. */
        tr_logAddNamedInfo ("DHT", "Generating new id");
        tr_rand_buffer (myid, 20);
    }

    rc = dht_init (ss->udp_socket, ss->udp6_socket, myid, NULL);
    if (rc < 0)
        goto fail;

    session = ss;

    cl = tr_new (struct bootstrap_closure, 1);
    cl->session = session;
    cl->nodes = nodes;
    cl->nodes6 = nodes6;
    cl->len = len;
    cl->len6 = len6;
    tr_threadNew (dht_bootstrap, cl);

    dht_timer = evtimer_new (session->event_base, timer_callback, session);
    tr_timerAdd (dht_timer, 0, tr_rand_int_weak (1000000));

    tr_logAddNamedDbg ("DHT", "DHT initialized");

    return 1;

 fail:
    tr_logAddNamedDbg ("DHT", "DHT initialization failed (errno = %d)", errno);
    session = NULL;
    return -1;
}
Пример #7
0
    if( cb == NULL )
    {
        cb = tr_new( struct cache_block, 1 );
        cb->tor = torrent;
        cb->piece = piece;
        cb->offset = offset;
        cb->length = length;
        cb->block = _tr_block( torrent, piece, offset );
        cb->buf = NULL;
        tr_ptrArrayInsertSorted( &cache->blocks, cb, cache_block_compare );
    }

    cb->time = tr_time();

    tr_free( cb->buf );
    cb->buf = tr_memdup( writeme, cb->length );

    ++cache->cache_writes;
    cache->cache_write_bytes += cb->length;

    return cacheTrim( cache );
}

int
tr_cacheReadBlock( tr_cache         * cache,
                   tr_torrent       * torrent,
                   tr_piece_index_t   piece,
                   uint32_t           offset,
                   uint32_t           len,
                   uint8_t          * setme )
{