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; }
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; }
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; }
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; }
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; }
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; }
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 ) {