diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | opentracker.c | 3 | ||||
| -rw-r--r-- | trackerlogic.c | 348 | ||||
| -rw-r--r-- | trackerlogic.h | 38 |
4 files changed, 195 insertions, 196 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | CC?=gcc | 1 | CC?=gcc |
| 2 | FEATURES=#-DWANT_CLOSED_TRACKER -DWANT_IP_FROM_QUERY_STRING -D_DEBUG_HTTPERROR | 2 | FEATURES=#-DWANT_CLOSED_TRACKER -DWANT_UTORRENT1600_WORKAROUND #-DWANT_IP_FROM_QUERY_STRING -D_DEBUG_HTTPERROR -DWANT_TRACKER_SYNC |
| 3 | OPTS_debug=-g -ggdb #-pg # -fprofile-arcs -ftest-coverage | 3 | OPTS_debug=-g -ggdb #-pg # -fprofile-arcs -ftest-coverage |
| 4 | OPTS_production=-s -Os | 4 | OPTS_production=-s -Os |
| 5 | CFLAGS+=-I../libowfat -Wall -pipe -Wextra #-pedantic #-ansi | 5 | CFLAGS+=-I../libowfat -Wall -pipe -Wextra #-pedantic #-ansi |
diff --git a/opentracker.c b/opentracker.c index cfa051a..d9336da 100644 --- a/opentracker.c +++ b/opentracker.c | |||
| @@ -243,7 +243,7 @@ static void httpresponse( const int64 s, char *data, size_t l ) { | |||
| 243 | for( c = data+4; *c == '/'; ++c); | 243 | for( c = data+4; *c == '/'; ++c); |
| 244 | 244 | ||
| 245 | switch( scan_urlencoded_query( &c, data = c, SCAN_PATH ) ) { | 245 | switch( scan_urlencoded_query( &c, data = c, SCAN_PATH ) ) { |
| 246 | 246 | #ifdef WANT_TRACKER_SYNC | |
| 247 | /****************************** | 247 | /****************************** |
| 248 | * S Y N C * | 248 | * S Y N C * |
| 249 | ******************************/ | 249 | ******************************/ |
| @@ -286,6 +286,7 @@ LOG_TO_STDERR( "sync: %d.%d.%d.%d\n", h->ip[0], h->ip[1], h->ip[2], h->ip[3] ); | |||
| 286 | reply_size = 2; | 286 | reply_size = 2; |
| 287 | 287 | ||
| 288 | break; | 288 | break; |
| 289 | #endif | ||
| 289 | /****************************** | 290 | /****************************** |
| 290 | * S T A T S * | 291 | * S T A T S * |
| 291 | ******************************/ | 292 | ******************************/ |
diff --git a/trackerlogic.c b/trackerlogic.c index 3560834..3aa3752 100644 --- a/trackerlogic.c +++ b/trackerlogic.c | |||
| @@ -20,7 +20,8 @@ | |||
| 20 | #include "byte.h" | 20 | #include "byte.h" |
| 21 | 21 | ||
| 22 | /* GLOBAL VARIABLES */ | 22 | /* GLOBAL VARIABLES */ |
| 23 | static ot_vector all_torrents[256]; | 23 | static ot_vector all_torrents[OT_BUCKET_COUNT]; |
| 24 | static ot_time all_torrents_clean[OT_BUCKET_COUNT]; | ||
| 24 | static ot_vector changeset; | 25 | static ot_vector changeset; |
| 25 | #if defined ( WANT_BLACKLISTING ) || defined( WANT_CLOSED_TRACKER ) | 26 | #if defined ( WANT_BLACKLISTING ) || defined( WANT_CLOSED_TRACKER ) |
| 26 | static ot_vector accesslist; | 27 | static ot_vector accesslist; |
| @@ -28,7 +29,8 @@ static ot_vector accesslist; | |||
| 28 | #endif | 29 | #endif |
| 29 | 30 | ||
| 30 | static size_t changeset_size = 0; | 31 | static size_t changeset_size = 0; |
| 31 | static time_t last_clean_time = 0; | 32 | |
| 33 | static int clean_single_torrent( ot_torrent *torrent ); | ||
| 32 | 34 | ||
| 33 | /* Converter function from memory to human readable hex strings | 35 | /* Converter function from memory to human readable hex strings |
| 34 | - definitely not thread safe!!! | 36 | - definitely not thread safe!!! |
| @@ -127,19 +129,10 @@ static void free_peerlist( ot_peerlist *peer_list ) { | |||
| 127 | free( peer_list ); | 129 | free( peer_list ); |
| 128 | } | 130 | } |
| 129 | 131 | ||
| 130 | /* This is the non-generic delete from vector-operation specialized for torrents in buckets. | 132 | static void vector_remove_torrent( ot_vector *vector, ot_torrent *match ) { |
| 131 | it returns 0 if the hash wasn't found in vector | ||
| 132 | 1 if the torrent was removed from vector | ||
| 133 | */ | ||
| 134 | static int vector_remove_torrent( ot_vector *vector, ot_hash *hash ) { | ||
| 135 | int exactmatch; | ||
| 136 | ot_torrent *end = ((ot_torrent*)vector->data) + vector->size; | 133 | ot_torrent *end = ((ot_torrent*)vector->data) + vector->size; |
| 137 | ot_torrent *match; | ||
| 138 | 134 | ||
| 139 | if( !vector->size ) return 0; | 135 | if( !vector->size ) return; |
| 140 | |||
| 141 | match = binary_search( hash, vector->data, vector->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); | ||
| 142 | if( !exactmatch ) return 0; | ||
| 143 | 136 | ||
| 144 | /* If this is being called after a unsuccessful malloc() for peer_list | 137 | /* If this is being called after a unsuccessful malloc() for peer_list |
| 145 | in add_peer_to_torrent, match->peer_list actually might be NULL */ | 138 | in add_peer_to_torrent, match->peer_list actually might be NULL */ |
| @@ -150,14 +143,13 @@ static int vector_remove_torrent( ot_vector *vector, ot_hash *hash ) { | |||
| 150 | vector->space /= OT_VECTOR_SHRINK_RATIO; | 143 | vector->space /= OT_VECTOR_SHRINK_RATIO; |
| 151 | vector->data = realloc( vector->data, vector->space * sizeof( ot_torrent ) ); | 144 | vector->data = realloc( vector->data, vector->space * sizeof( ot_torrent ) ); |
| 152 | } | 145 | } |
| 153 | return 1; | ||
| 154 | } | 146 | } |
| 155 | 147 | ||
| 156 | ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer, int from_changeset ) { | 148 | ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer, int from_changeset ) { |
| 157 | int exactmatch; | 149 | int exactmatch; |
| 158 | ot_torrent *torrent; | 150 | ot_torrent *torrent; |
| 159 | ot_peer *peer_dest; | 151 | ot_peer *peer_dest; |
| 160 | ot_vector *torrents_list = &all_torrents[*hash[0]], *peer_pool; | 152 | ot_vector *torrents_list = hash_to_bucket( all_torrents, hash ), *peer_pool; |
| 161 | int base_pool = 0; | 153 | int base_pool = 0; |
| 162 | 154 | ||
| 163 | #ifdef WANT_ACCESS_CONTROL | 155 | #ifdef WANT_ACCESS_CONTROL |
| @@ -179,13 +171,14 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer, int from_changese | |||
| 179 | memmove( &torrent->hash, hash, sizeof( ot_hash ) ); | 171 | memmove( &torrent->hash, hash, sizeof( ot_hash ) ); |
| 180 | 172 | ||
| 181 | if( !( torrent->peer_list = malloc( sizeof (ot_peerlist) ) ) ) { | 173 | if( !( torrent->peer_list = malloc( sizeof (ot_peerlist) ) ) ) { |
| 182 | vector_remove_torrent( torrents_list, hash ); | 174 | vector_remove_torrent( torrents_list, torrent ); |
| 183 | return NULL; | 175 | return NULL; |
| 184 | } | 176 | } |
| 185 | 177 | ||
| 186 | byte_zero( torrent->peer_list, sizeof( ot_peerlist ) ); | 178 | byte_zero( torrent->peer_list, sizeof( ot_peerlist ) ); |
| 187 | torrent->peer_list->base = NOW; | 179 | torrent->peer_list->base = NOW; |
| 188 | } | 180 | } else |
| 181 | clean_single_torrent( torrent ); | ||
| 189 | 182 | ||
| 190 | /* Sanitize flags: Whoever claims to have completed download, must be a seeder */ | 183 | /* Sanitize flags: Whoever claims to have completed download, must be a seeder */ |
| 191 | if( ( OT_FLAG( peer ) & ( PEER_FLAG_COMPLETED | PEER_FLAG_SEEDING ) ) == PEER_FLAG_COMPLETED ) | 184 | if( ( OT_FLAG( peer ) & ( PEER_FLAG_COMPLETED | PEER_FLAG_SEEDING ) ) == PEER_FLAG_COMPLETED ) |
| @@ -208,27 +201,37 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer, int from_changese | |||
| 208 | if( !exactmatch ) { | 201 | if( !exactmatch ) { |
| 209 | int i; | 202 | int i; |
| 210 | memmove( peer_dest, peer, sizeof( ot_peer ) ); | 203 | memmove( peer_dest, peer, sizeof( ot_peer ) ); |
| 204 | torrent->peer_list->peer_count++; | ||
| 211 | 205 | ||
| 212 | if( OT_FLAG( peer ) & PEER_FLAG_COMPLETED ) | 206 | if( OT_FLAG( peer ) & PEER_FLAG_COMPLETED ) |
| 213 | torrent->peer_list->downloaded++; | 207 | torrent->peer_list->down_count++; |
| 214 | 208 | ||
| 215 | if( OT_FLAG(peer) & PEER_FLAG_SEEDING ) | 209 | if( OT_FLAG(peer) & PEER_FLAG_SEEDING ) { |
| 216 | torrent->peer_list->seed_count[ base_pool ]++; | 210 | torrent->peer_list->seed_counts[ base_pool ]++; |
| 211 | torrent->peer_list->seed_count++; | ||
| 212 | } | ||
| 217 | 213 | ||
| 218 | for( i= base_pool + 1; i<OT_POOLS_COUNT; ++i ) { | 214 | for( i= base_pool + 1; i<OT_POOLS_COUNT; ++i ) { |
| 219 | switch( vector_remove_peer( &torrent->peer_list->peers[i], peer, 0 ) ) { | 215 | switch( vector_remove_peer( &torrent->peer_list->peers[i], peer, 0 ) ) { |
| 220 | case 0: continue; | 216 | case 0: continue; |
| 221 | case 2: torrent->peer_list->seed_count[i]--; | 217 | case 2: torrent->peer_list->seed_counts[i]--; |
| 222 | case 1: default: return torrent; | 218 | torrent->peer_list->seed_count--; |
| 219 | case 1: default: | ||
| 220 | torrent->peer_list->peer_count--; | ||
| 221 | return torrent; | ||
| 223 | } | 222 | } |
| 224 | } | 223 | } |
| 225 | } else { | 224 | } else { |
| 226 | if( (OT_FLAG(peer_dest) & PEER_FLAG_SEEDING ) && !(OT_FLAG(peer) & PEER_FLAG_SEEDING ) ) | 225 | if( (OT_FLAG(peer_dest) & PEER_FLAG_SEEDING ) && !(OT_FLAG(peer) & PEER_FLAG_SEEDING ) ) { |
| 227 | torrent->peer_list->seed_count[ base_pool ]--; | 226 | torrent->peer_list->seed_counts[ base_pool ]--; |
| 228 | if( !(OT_FLAG(peer_dest) & PEER_FLAG_SEEDING ) && (OT_FLAG(peer) & PEER_FLAG_SEEDING ) ) | 227 | torrent->peer_list->seed_count--; |
| 229 | torrent->peer_list->seed_count[ base_pool ]++; | 228 | } |
| 229 | if( !(OT_FLAG(peer_dest) & PEER_FLAG_SEEDING ) && (OT_FLAG(peer) & PEER_FLAG_SEEDING ) ) { | ||
| 230 | torrent->peer_list->seed_counts[ base_pool ]++; | ||
| 231 | torrent->peer_list->seed_count++; | ||
| 232 | } | ||
| 230 | if( !(OT_FLAG( peer_dest ) & PEER_FLAG_COMPLETED ) && (OT_FLAG( peer ) & PEER_FLAG_COMPLETED ) ) | 233 | if( !(OT_FLAG( peer_dest ) & PEER_FLAG_COMPLETED ) && (OT_FLAG( peer ) & PEER_FLAG_COMPLETED ) ) |
| 231 | torrent->peer_list->downloaded++; | 234 | torrent->peer_list->down_count++; |
| 232 | if( OT_FLAG( peer_dest ) & PEER_FLAG_COMPLETED ) | 235 | if( OT_FLAG( peer_dest ) & PEER_FLAG_COMPLETED ) |
| 233 | OT_FLAG( peer ) |= PEER_FLAG_COMPLETED; | 236 | OT_FLAG( peer ) |= PEER_FLAG_COMPLETED; |
| 234 | 237 | ||
| @@ -245,29 +248,25 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer, int from_changese | |||
| 245 | * does not yet check not to return self | 248 | * does not yet check not to return self |
| 246 | */ | 249 | */ |
| 247 | size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, int is_tcp ) { | 250 | size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, int is_tcp ) { |
| 248 | char *r = reply; | 251 | char *r = reply; |
| 249 | size_t peer_count, seed_count, index; | 252 | ot_peerlist *peer_list = torrent->peer_list; |
| 250 | 253 | size_t index; | |
| 251 | for( peer_count = seed_count = index = 0; index < OT_POOLS_COUNT; ++index ) { | ||
| 252 | peer_count += torrent->peer_list->peers[index].size; | ||
| 253 | seed_count += torrent->peer_list->seed_count[index]; | ||
| 254 | } | ||
| 255 | 254 | ||
| 256 | if( peer_count < amount ) | 255 | if( peer_list->peer_count < amount ) |
| 257 | amount = peer_count; | 256 | amount = peer_list->peer_count; |
| 258 | 257 | ||
| 259 | if( is_tcp ) | 258 | if( is_tcp ) |
| 260 | r += sprintf( r, "d8:completei%zde10:incompletei%zde8:intervali%ie5:peers%zd:", seed_count, peer_count-seed_count, OT_CLIENT_REQUEST_INTERVAL_RANDOM, 6*amount ); | 259 | r += sprintf( r, "d8:completei%zde10:incompletei%zde8:intervali%ie5:peers%zd:", peer_list->seed_count, peer_list->peer_count-peer_list->seed_count, OT_CLIENT_REQUEST_INTERVAL_RANDOM, 6*amount ); |
| 261 | else { | 260 | else { |
| 262 | *(ot_dword*)(r+0) = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM ); | 261 | *(ot_dword*)(r+0) = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM ); |
| 263 | *(ot_dword*)(r+4) = htonl( peer_count ); | 262 | *(ot_dword*)(r+4) = htonl( peer_list->peer_count ); |
| 264 | *(ot_dword*)(r+8) = htonl( seed_count ); | 263 | *(ot_dword*)(r+8) = htonl( peer_list->seed_count ); |
| 265 | r += 12; | 264 | r += 12; |
| 266 | } | 265 | } |
| 267 | 266 | ||
| 268 | if( amount ) { | 267 | if( amount ) { |
| 269 | unsigned int pool_offset, pool_index = 0;; | 268 | unsigned int pool_offset, pool_index = 0;; |
| 270 | unsigned int shifted_pc = peer_count; | 269 | unsigned int shifted_pc = peer_list->peer_count; |
| 271 | unsigned int shifted_step = 0; | 270 | unsigned int shifted_step = 0; |
| 272 | unsigned int shift = 0; | 271 | unsigned int shift = 0; |
| 273 | 272 | ||
| @@ -279,7 +278,7 @@ size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply | |||
| 279 | 278 | ||
| 280 | /* Initialize somewhere in the middle of peers so that | 279 | /* Initialize somewhere in the middle of peers so that |
| 281 | fixpoint's aliasing doesn't alway miss the same peers */ | 280 | fixpoint's aliasing doesn't alway miss the same peers */ |
| 282 | pool_offset = random() % peer_count; | 281 | pool_offset = random() % peer_list->peer_count; |
| 283 | 282 | ||
| 284 | for( index = 0; index < amount; ++index ) { | 283 | for( index = 0; index < amount; ++index ) { |
| 285 | /* This is the aliased, non shifted range, next value may fall into */ | 284 | /* This is the aliased, non shifted range, next value may fall into */ |
| @@ -287,12 +286,12 @@ size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply | |||
| 287 | ( ( index * shifted_step ) >> shift ); | 286 | ( ( index * shifted_step ) >> shift ); |
| 288 | pool_offset += 1 + random() % diff; | 287 | pool_offset += 1 + random() % diff; |
| 289 | 288 | ||
| 290 | while( pool_offset >= torrent->peer_list->peers[pool_index].size ) { | 289 | while( pool_offset >= peer_list->peers[pool_index].size ) { |
| 291 | pool_offset -= torrent->peer_list->peers[pool_index].size; | 290 | pool_offset -= peer_list->peers[pool_index].size; |
| 292 | pool_index = ( pool_index + 1 ) % OT_POOLS_COUNT; | 291 | pool_index = ( pool_index + 1 ) % OT_POOLS_COUNT; |
| 293 | } | 292 | } |
| 294 | 293 | ||
| 295 | memmove( r, ((ot_peer*)torrent->peer_list->peers[pool_index].data) + pool_offset, 6 ); | 294 | memmove( r, ((ot_peer*)peer_list->peers[pool_index].data) + pool_offset, 6 ); |
| 296 | r += 6; | 295 | r += 6; |
| 297 | } | 296 | } |
| 298 | } | 297 | } |
| @@ -316,10 +315,10 @@ static void fix_mmapallocation( void *buf, size_t old_alloc, size_t new_alloc ) | |||
| 316 | size_t return_fullscrape_for_tracker( char **reply ) { | 315 | size_t return_fullscrape_for_tracker( char **reply ) { |
| 317 | size_t torrent_count = 0, j; | 316 | size_t torrent_count = 0, j; |
| 318 | size_t allocated, replysize; | 317 | size_t allocated, replysize; |
| 319 | int i, k; | 318 | int i; |
| 320 | char *r; | 319 | char *r; |
| 321 | 320 | ||
| 322 | for( i=0; i<256; ++i ) | 321 | for( i=0; i<OT_BUCKET_COUNT; ++i ) |
| 323 | torrent_count += all_torrents[i].size; | 322 | torrent_count += all_torrents[i].size; |
| 324 | 323 | ||
| 325 | /* one extra for pro- and epilogue */ | 324 | /* one extra for pro- and epilogue */ |
| @@ -327,20 +326,15 @@ size_t return_fullscrape_for_tracker( char **reply ) { | |||
| 327 | if( !( r = *reply = mmap( NULL, allocated, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 ) ) ) return 0; | 326 | if( !( r = *reply = mmap( NULL, allocated, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 ) ) ) return 0; |
| 328 | 327 | ||
| 329 | memmove( r, "d5:filesd", 9 ); r += 9; | 328 | memmove( r, "d5:filesd", 9 ); r += 9; |
| 330 | for( i=0; i<256; ++i ) { | 329 | for( i=0; i<OT_BUCKET_COUNT; ++i ) { |
| 331 | ot_vector *torrents_list = &all_torrents[i]; | 330 | ot_vector *torrents_list = all_torrents + i; |
| 332 | for( j=0; j<torrents_list->size; ++j ) { | 331 | for( j=0; j<torrents_list->size; ++j ) { |
| 333 | ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list; | 332 | ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list; |
| 334 | ot_hash *hash =&( ((ot_torrent*)(torrents_list->data))[j] ).hash; | 333 | ot_hash *hash =&( ((ot_torrent*)(torrents_list->data))[j] ).hash; |
| 335 | size_t peers = 0, seeds = 0; | 334 | if( peer_list->peer_count || peer_list->down_count ) { |
| 336 | for( k=0; k<OT_POOLS_COUNT; ++k ) { | ||
| 337 | peers += peer_list->peers[k].size; | ||
| 338 | seeds += peer_list->seed_count[k]; | ||
| 339 | } | ||
| 340 | if( peers || peer_list->downloaded ) { | ||
| 341 | *r++='2'; *r++='0'; *r++=':'; | 335 | *r++='2'; *r++='0'; *r++=':'; |
| 342 | memmove( r, hash, 20 ); r+=20; | 336 | memmove( r, hash, 20 ); r+=20; |
| 343 | r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee", seeds, peer_list->downloaded, peers-seeds ); | 337 | r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee", peer_list->seed_count, peer_list->down_count, peer_list->peer_count-peer_list->seed_count ); |
| 344 | } | 338 | } |
| 345 | } | 339 | } |
| 346 | } | 340 | } |
| @@ -359,19 +353,19 @@ size_t return_memstat_for_tracker( char **reply ) { | |||
| 359 | int i, k; | 353 | int i, k; |
| 360 | char *r; | 354 | char *r; |
| 361 | 355 | ||
| 362 | for( i=0; i<256; ++i ) { | 356 | for( i=0; i<OT_BUCKET_COUNT; ++i ) { |
| 363 | ot_vector *torrents_list = &all_torrents[i]; | 357 | ot_vector *torrents_list = all_torrents + i; |
| 364 | torrent_count += torrents_list->size; | 358 | torrent_count += torrents_list->size; |
| 365 | } | 359 | } |
| 366 | 360 | ||
| 367 | allocated = 256*32 + (43+OT_POOLS_COUNT*32)*torrent_count; | 361 | allocated = OT_BUCKET_COUNT*32 + (43+OT_POOLS_COUNT*32)*torrent_count; |
| 368 | if( !( r = *reply = mmap( NULL, allocated, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 ) ) ) return 0; | 362 | if( !( r = *reply = mmap( NULL, allocated, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 ) ) ) return 0; |
| 369 | 363 | ||
| 370 | for( i=0; i<256; ++i ) | 364 | for( i=0; i<OT_BUCKET_COUNT; ++i ) |
| 371 | r += sprintf( r, "%02X: %08X %08X\n", i, (unsigned int)all_torrents[i].size, (unsigned int)all_torrents[i].space ); | 365 | r += sprintf( r, "%02X: %08X %08X\n", i, (unsigned int)all_torrents[i].size, (unsigned int)all_torrents[i].space ); |
| 372 | 366 | ||
| 373 | for( i=0; i<256; ++i ) { | 367 | for( i=0; i<OT_BUCKET_COUNT; ++i ) { |
| 374 | ot_vector *torrents_list = &all_torrents[i]; | 368 | ot_vector *torrents_list = all_torrents + i; |
| 375 | for( j=0; j<torrents_list->size; ++j ) { | 369 | for( j=0; j<torrents_list->size; ++j ) { |
| 376 | ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list; | 370 | ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list; |
| 377 | ot_hash *hash =&( ((ot_torrent*)(torrents_list->data))[j] ).hash; | 371 | ot_hash *hash =&( ((ot_torrent*)(torrents_list->data))[j] ).hash; |
| @@ -389,9 +383,8 @@ size_t return_memstat_for_tracker( char **reply ) { | |||
| 389 | 383 | ||
| 390 | /* Fetches scrape info for a specific torrent */ | 384 | /* Fetches scrape info for a specific torrent */ |
| 391 | size_t return_udp_scrape_for_torrent( ot_hash *hash, char *reply ) { | 385 | size_t return_udp_scrape_for_torrent( ot_hash *hash, char *reply ) { |
| 392 | int exactmatch, i; | 386 | int exactmatch ; |
| 393 | size_t peers = 0, seeds = 0; | 387 | ot_vector *torrents_list = hash_to_bucket( all_torrents, hash ); |
| 394 | ot_vector *torrents_list = &all_torrents[*hash[0]]; | ||
| 395 | ot_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); | 388 | ot_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); |
| 396 | 389 | ||
| 397 | if( !exactmatch ) { | 390 | if( !exactmatch ) { |
| @@ -399,13 +392,14 @@ size_t return_udp_scrape_for_torrent( ot_hash *hash, char *reply ) { | |||
| 399 | } else { | 392 | } else { |
| 400 | ot_dword *r = (ot_dword*) reply; | 393 | ot_dword *r = (ot_dword*) reply; |
| 401 | 394 | ||
| 402 | for( i=0; i<OT_POOLS_COUNT; ++i ) { | 395 | if( clean_single_torrent( torrent ) ) { |
| 403 | peers += torrent->peer_list->peers[i].size; | 396 | vector_remove_torrent( torrents_list, torrent ); |
| 404 | seeds += torrent->peer_list->seed_count[i]; | 397 | memset( reply, 0, 12); |
| 398 | } else { | ||
| 399 | r[0] = htonl( torrent->peer_list->seed_count ); | ||
| 400 | r[1] = htonl( torrent->peer_list->down_count ); | ||
| 401 | r[2] = htonl( torrent->peer_list->peer_count-torrent->peer_list->seed_count ); | ||
| 405 | } | 402 | } |
| 406 | r[0] = htonl( seeds ); | ||
| 407 | r[1] = htonl( torrent->peer_list->downloaded ); | ||
| 408 | r[2] = htonl( peers-seeds ); | ||
| 409 | } | 403 | } |
| 410 | return 12; | 404 | return 12; |
| 411 | } | 405 | } |
| @@ -413,31 +407,30 @@ size_t return_udp_scrape_for_torrent( ot_hash *hash, char *reply ) { | |||
| 413 | /* Fetches scrape info for a specific torrent */ | 407 | /* Fetches scrape info for a specific torrent */ |
| 414 | size_t return_tcp_scrape_for_torrent( ot_hash *hash_list, int amount, char *reply ) { | 408 | size_t return_tcp_scrape_for_torrent( ot_hash *hash_list, int amount, char *reply ) { |
| 415 | char *r = reply; | 409 | char *r = reply; |
| 416 | int exactmatch, i, j; | 410 | int exactmatch, i; |
| 417 | 411 | ||
| 418 | r += sprintf( r, "d5:filesd" ); | 412 | r += sprintf( r, "d5:filesd" ); |
| 419 | 413 | ||
| 420 | for( i=0; i<amount; ++i ) { | 414 | for( i=0; i<amount; ++i ) { |
| 421 | ot_hash *hash = hash_list + i; | 415 | ot_hash *hash = hash_list + i; |
| 422 | ot_vector *torrents_list = &all_torrents[*hash[0]]; | 416 | ot_vector *torrents_list = hash_to_bucket( all_torrents, hash ); |
| 423 | ot_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); | 417 | ot_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); |
| 424 | size_t peers = 0, seeds = 0; | ||
| 425 | 418 | ||
| 426 | if( !exactmatch ) continue; | 419 | if( !exactmatch ) continue; |
| 427 | 420 | if( clean_single_torrent( torrent ) ) { | |
| 428 | for( j=0; j<OT_POOLS_COUNT; ++j ) { | 421 | vector_remove_torrent( torrents_list, torrent ); |
| 429 | peers += torrent->peer_list->peers[j].size; | 422 | } else { |
| 430 | seeds += torrent->peer_list->seed_count[j]; | 423 | memmove( r, "20:", 3 ); memmove( r+3, hash, 20 ); |
| 424 | r += sprintf( r+23, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee", | ||
| 425 | torrent->peer_list->seed_count, torrent->peer_list->down_count, torrent->peer_list->peer_count-torrent->peer_list->seed_count ) + 23; | ||
| 431 | } | 426 | } |
| 432 | |||
| 433 | memmove( r, "20:", 3 ); memmove( r+3, hash, 20 ); | ||
| 434 | r += sprintf( r+23, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee", seeds, torrent->peer_list->downloaded, peers-seeds ) + 23; | ||
| 435 | } | 427 | } |
| 436 | 428 | ||
| 437 | *r++ = 'e'; *r++ = 'e'; | 429 | *r++ = 'e'; *r++ = 'e'; |
| 438 | return r - reply; | 430 | return r - reply; |
| 439 | } | 431 | } |
| 440 | 432 | ||
| 433 | #ifdef WANT_TRACKER_SYNC | ||
| 441 | /* Throw away old changeset */ | 434 | /* Throw away old changeset */ |
| 442 | static void release_changeset( void ) { | 435 | static void release_changeset( void ) { |
| 443 | ot_byte **changeset_ptrs = (ot_byte**)(changeset.data); | 436 | ot_byte **changeset_ptrs = (ot_byte**)(changeset.data); |
| @@ -548,86 +541,91 @@ size_t return_changeset_for_tracker( char **reply ) { | |||
| 548 | 541 | ||
| 549 | return r; | 542 | return r; |
| 550 | } | 543 | } |
| 544 | #endif | ||
| 551 | 545 | ||
| 552 | /* Clean up all torrents, remove timedout pools and | 546 | /* Clean a single torrent |
| 553 | torrents, also prepare new changeset */ | 547 | return 1 if torrent timed out |
| 554 | void clean_all_torrents( void ) { | 548 | */ |
| 555 | int i, k; | 549 | static int clean_single_torrent( ot_torrent *torrent ) { |
| 556 | size_t j; | 550 | ot_peerlist *peer_list = torrent->peer_list; |
| 557 | time_t time_now = NOW; | 551 | size_t peers_count = 0, seeds_count; |
| 558 | size_t peers_count; | 552 | time_t timedout = (int)( NOW - peer_list->base ); |
| 559 | ot_dword diff; struct timeval tv1, tv2; gettimeofday( &tv1, NULL ); | 553 | int i; |
| 560 | |||
| 561 | if( time_now <= last_clean_time ) | ||
| 562 | return; | ||
| 563 | last_clean_time = time_now; | ||
| 564 | |||
| 565 | release_changeset(); | ||
| 566 | 554 | ||
| 567 | for( i=0; i<256; ++i ) { | 555 | /* Torrent has idled out */ |
| 568 | ot_vector *torrents_list = &all_torrents[i]; | 556 | if( timedout > OT_TORRENT_TIMEOUT ) |
| 569 | for( j=0; j<torrents_list->size; ++j ) { | 557 | return 1; |
| 570 | ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list; | ||
| 571 | ot_hash *hash =&( ((ot_torrent*)(torrents_list->data))[j] ).hash; | ||
| 572 | 558 | ||
| 573 | time_t timedout = (int)( time_now - peer_list->base ); | 559 | /* Nothing to be cleaned here? Test if torrent is worth keeping */ |
| 560 | if( timedout > OT_POOLS_COUNT ) { | ||
| 561 | if( !peer_list->peer_count ) | ||
| 562 | return peer_list->down_count ? 0 : 1; | ||
| 563 | timedout = OT_POOLS_COUNT; | ||
| 564 | } | ||
| 574 | 565 | ||
| 575 | /* Torrent has idled out */ | 566 | /* Release vectors that have timed out */ |
| 576 | if( timedout > OT_TORRENT_TIMEOUT ) { | 567 | for( i = OT_POOLS_COUNT - timedout; i < OT_POOLS_COUNT; ++i ) |
| 577 | vector_remove_torrent( torrents_list, hash ); | 568 | free( peer_list->peers[i].data); |
| 578 | --j; continue; | ||
| 579 | } | ||
| 580 | 569 | ||
| 581 | /* If nothing to be cleaned here, handle next torrent */ | 570 | /* Shift vectors back by the amount of pools that were shifted out */ |
| 582 | if( timedout > OT_POOLS_COUNT ) { | 571 | memmove( peer_list->peers + timedout, peer_list->peers, sizeof( ot_vector ) * ( OT_POOLS_COUNT - timedout ) ); |
| 572 | byte_zero( peer_list->peers, sizeof( ot_vector ) * timedout ); | ||
| 583 | 573 | ||
| 584 | peers_count = 0; | 574 | /* Shift back seed counts as well */ |
| 585 | for( k = 0; k < OT_POOLS_COUNT; ++k ) | 575 | memmove( peer_list->seed_counts + timedout, peer_list->seed_counts, sizeof( size_t ) * ( OT_POOLS_COUNT - timedout ) ); |
| 586 | peers_count += peer_list->peers[k].size; | 576 | byte_zero( peer_list->seed_counts, sizeof( size_t ) * timedout ); |
| 587 | 577 | ||
| 588 | if( !peers_count ) { | 578 | /* Save the block modified within last OT_POOLS_TIMEOUT --- XXX no sync for now |
| 589 | if( !peer_list->downloaded ) { | 579 | if( peer_list->peers[1].size ) |
| 590 | vector_remove_torrent( torrents_list, hash ); | 580 | add_pool_to_changeset( hash, peer_list->peers[1].data, peer_list->peers[1].size ); |
| 591 | --j; | 581 | */ |
| 592 | } | ||
| 593 | continue; | ||
| 594 | } | ||
| 595 | 582 | ||
| 596 | timedout = OT_POOLS_COUNT; | 583 | peers_count = seeds_count = 0; |
| 597 | } | 584 | for( i = 0; i < OT_POOLS_COUNT; ++i ) { |
| 585 | peers_count += peer_list->peers[i].size; | ||
| 586 | seeds_count += peer_list->seed_counts[i]; | ||
| 587 | } | ||
| 588 | peer_list->seed_count = seeds_count; | ||
| 589 | peer_list->peer_count = peers_count; | ||
| 598 | 590 | ||
| 599 | /* Release vectors that have timed out */ | 591 | if( peers_count ) |
| 600 | for( k = OT_POOLS_COUNT - timedout; k < OT_POOLS_COUNT; ++k ) | 592 | peer_list->base = NOW; |
| 601 | free( peer_list->peers[k].data); | 593 | else { |
| 594 | /* When we got here, the last time that torrent | ||
| 595 | has been touched is OT_POOLS_COUNT units before */ | ||
| 596 | peer_list->base = NOW - OT_POOLS_COUNT; | ||
| 597 | } | ||
| 598 | return 0; | ||
| 599 | } | ||
| 602 | 600 | ||
| 603 | /* Shift vectors back by the amount of pools that were shifted out */ | 601 | /* Clean up all peers in current bucket, remove timedout pools and |
| 604 | memmove( peer_list->peers + timedout, peer_list->peers, sizeof( ot_vector ) * ( OT_POOLS_COUNT - timedout ) ); | 602 | torrents */ |
| 605 | byte_zero( peer_list->peers, sizeof( ot_vector ) * timedout ); | 603 | void clean_all_torrents( void ) { |
| 604 | ot_vector *torrents_list; | ||
| 605 | size_t i; | ||
| 606 | static int bucket; | ||
| 607 | ot_time time_now = NOW; | ||
| 606 | 608 | ||
| 607 | /* Shift back seed counts as well */ | 609 | /* No sync for now |
| 608 | memmove( peer_list->seed_count + timedout, peer_list->seed_count, sizeof( size_t ) * ( OT_POOLS_COUNT - timedout ) ); | 610 | release_changeset(); |
| 609 | byte_zero( peer_list->seed_count, sizeof( size_t ) * timedout ); | 611 | */ |
| 610 | 612 | ||
| 611 | /* Save the block modified within last OT_POOLS_TIMEOUT */ | 613 | /* Search for an uncleaned bucked */ |
| 612 | if( peer_list->peers[1].size ) | 614 | while( ( all_torrents_clean[bucket] == time_now ) && ( ++bucket < OT_BUCKET_COUNT ) ); |
| 613 | add_pool_to_changeset( hash, peer_list->peers[1].data, peer_list->peers[1].size ); | 615 | if( bucket >= OT_BUCKET_COUNT ) { |
| 616 | bucket = 0; return; | ||
| 617 | } | ||
| 614 | 618 | ||
| 615 | peers_count = 0; | 619 | all_torrents_clean[bucket] = time_now; |
| 616 | for( k = 0; k < OT_POOLS_COUNT; ++k ) | ||
| 617 | peers_count += peer_list->peers[k].size; | ||
| 618 | 620 | ||
| 619 | if( peers_count ) { | 621 | torrents_list = all_torrents + bucket; |
| 620 | peer_list->base = time_now; | 622 | for( i=0; i<torrents_list->size; ++i ) { |
| 621 | } else { | 623 | ot_torrent *torrent = ((ot_torrent*)(torrents_list->data)) + i; |
| 622 | /* When we got here, the last time that torrent | 624 | if( clean_single_torrent( torrent ) ) { |
| 623 | has been touched is OT_POOLS_COUNT units before */ | 625 | vector_remove_torrent( torrents_list, torrent ); |
| 624 | peer_list->base = time_now - OT_POOLS_COUNT; | 626 | --i; continue; |
| 625 | } | ||
| 626 | } | 627 | } |
| 627 | } | 628 | } |
| 628 | |||
| 629 | gettimeofday( &tv2, NULL ); diff = ( tv2.tv_sec - tv1.tv_sec ) * 1000000 + tv2.tv_usec - tv1.tv_usec; | ||
| 630 | fprintf( stderr, "Cleanup time taken: %u\n", diff ); | ||
| 631 | } | 629 | } |
| 632 | 630 | ||
| 633 | typedef struct { size_t val; ot_torrent * torrent; } ot_record; | 631 | typedef struct { size_t val; ot_torrent * torrent; } ot_record; |
| @@ -637,37 +635,31 @@ size_t return_stats_for_tracker( char *reply, int mode ) { | |||
| 637 | size_t torrent_count = 0, peer_count = 0, seed_count = 0, j; | 635 | size_t torrent_count = 0, peer_count = 0, seed_count = 0, j; |
| 638 | ot_record top5s[5], top5c[5]; | 636 | ot_record top5s[5], top5c[5]; |
| 639 | char *r = reply; | 637 | char *r = reply; |
| 640 | int i,k; | 638 | int i; |
| 641 | 639 | ||
| 642 | byte_zero( top5s, sizeof( top5s ) ); | 640 | byte_zero( top5s, sizeof( top5s ) ); |
| 643 | byte_zero( top5c, sizeof( top5c ) ); | 641 | byte_zero( top5c, sizeof( top5c ) ); |
| 644 | 642 | ||
| 645 | for( i=0; i<256; ++i ) { | 643 | for( i=0; i<OT_BUCKET_COUNT; ++i ) { |
| 646 | ot_vector *torrents_list = &all_torrents[i]; | 644 | ot_vector *torrents_list = all_torrents + i; |
| 647 | torrent_count += torrents_list->size; | 645 | torrent_count += torrents_list->size; |
| 648 | for( j=0; j<torrents_list->size; ++j ) { | 646 | for( j=0; j<torrents_list->size; ++j ) { |
| 649 | ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list; | 647 | ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list; |
| 650 | size_t local_peers = 0, local_seeds = 0; | ||
| 651 | |||
| 652 | for( k=0; k<OT_POOLS_COUNT; ++k ) { | ||
| 653 | local_peers += peer_list->peers[k].size; | ||
| 654 | local_seeds += peer_list->seed_count[k]; | ||
| 655 | } | ||
| 656 | if( mode == STATS_TOP5 ) { | 648 | if( mode == STATS_TOP5 ) { |
| 657 | int idx = 4; while( (idx >= 0) && ( local_peers > top5c[idx].val ) ) --idx; | 649 | int idx = 4; while( (idx >= 0) && ( peer_list->peer_count > top5c[idx].val ) ) --idx; |
| 658 | if ( idx++ != 4 ) { | 650 | if ( idx++ != 4 ) { |
| 659 | memmove( top5c + idx + 1, top5c + idx, ( 4 - idx ) * sizeof( ot_record ) ); | 651 | memmove( top5c + idx + 1, top5c + idx, ( 4 - idx ) * sizeof( ot_record ) ); |
| 660 | top5c[idx].val = local_peers; | 652 | top5c[idx].val = peer_list->peer_count; |
| 661 | top5c[idx].torrent = (ot_torrent*)(torrents_list->data) + j; | 653 | top5c[idx].torrent = (ot_torrent*)(torrents_list->data) + j; |
| 662 | } | 654 | } |
| 663 | idx = 4; while( (idx >= 0) && ( local_seeds > top5s[idx].val ) ) --idx; | 655 | idx = 4; while( (idx >= 0) && ( peer_list->seed_count > top5s[idx].val ) ) --idx; |
| 664 | if ( idx++ != 4 ) { | 656 | if ( idx++ != 4 ) { |
| 665 | memmove( top5s + idx + 1, top5s + idx, ( 4 - idx ) * sizeof( ot_record ) ); | 657 | memmove( top5s + idx + 1, top5s + idx, ( 4 - idx ) * sizeof( ot_record ) ); |
| 666 | top5s[idx].val = local_seeds; | 658 | top5s[idx].val = peer_list->seed_count; |
| 667 | top5s[idx].torrent = (ot_torrent*)(torrents_list->data) + j; | 659 | top5s[idx].torrent = (ot_torrent*)(torrents_list->data) + j; |
| 668 | } | 660 | } |
| 669 | } | 661 | } |
| 670 | peer_count += local_peers; seed_count += local_seeds; | 662 | peer_count += peer_list->peer_count; seed_count += peer_list->seed_count; |
| 671 | } | 663 | } |
| 672 | } | 664 | } |
| 673 | if( mode == STATS_TOP5 ) { | 665 | if( mode == STATS_TOP5 ) { |
| @@ -708,8 +700,8 @@ size_t return_stats_for_slash24s( char *reply, size_t amount, ot_dword thresh ) | |||
| 708 | 700 | ||
| 709 | r += sprintf( r, "Stats for all /24s with more than %u announced torrents:\n\n", thresh ); | 701 | r += sprintf( r, "Stats for all /24s with more than %u announced torrents:\n\n", thresh ); |
| 710 | 702 | ||
| 711 | for( i=0; i<256; ++i ) { | 703 | for( i=0; i<OT_BUCKET_COUNT; ++i ) { |
| 712 | ot_vector *torrents_list = &all_torrents[i]; | 704 | ot_vector *torrents_list = all_torrents + i; |
| 713 | for( j=0; j<torrents_list->size; ++j ) { | 705 | for( j=0; j<torrents_list->size; ++j ) { |
| 714 | ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list; | 706 | ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list; |
| 715 | for( k=0; k<OT_POOLS_COUNT; ++k ) { | 707 | for( k=0; k<OT_POOLS_COUNT; ++k ) { |
| @@ -787,8 +779,8 @@ size_t return_stats_for_slash24s_old( char *reply, size_t amount, ot_dword thres | |||
| 787 | 779 | ||
| 788 | r += sprintf( r, "Stats for all /24s with more than %d announced torrents:\n\n", ((int)thresh) ); | 780 | r += sprintf( r, "Stats for all /24s with more than %d announced torrents:\n\n", ((int)thresh) ); |
| 789 | 781 | ||
| 790 | for( i=0; i<256; ++i ) { | 782 | for( i=0; i<OT_BUCKET_COUNT; ++i ) { |
| 791 | ot_vector *torrents_list = &all_torrents[i]; | 783 | ot_vector *torrents_list = all_torrents + i; |
| 792 | for( j=0; j<torrents_list->size; ++j ) { | 784 | for( j=0; j<torrents_list->size; ++j ) { |
| 793 | ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list; | 785 | ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list; |
| 794 | for( k=0; k<OT_POOLS_COUNT; ++k ) { | 786 | for( k=0; k<OT_POOLS_COUNT; ++k ) { |
| @@ -828,9 +820,10 @@ size_t return_stats_for_slash24s_old( char *reply, size_t amount, ot_dword thres | |||
| 828 | 820 | ||
| 829 | size_t remove_peer_from_torrent( ot_hash *hash, ot_peer *peer, char *reply, int is_tcp ) { | 821 | size_t remove_peer_from_torrent( ot_hash *hash, ot_peer *peer, char *reply, int is_tcp ) { |
| 830 | int exactmatch; | 822 | int exactmatch; |
| 831 | size_t peer_count, seed_count, index; | 823 | size_t index; |
| 832 | ot_vector *torrents_list = &all_torrents[*hash[0]]; | 824 | ot_vector *torrents_list = hash_to_bucket( all_torrents, hash ); |
| 833 | ot_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); | 825 | ot_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); |
| 826 | ot_peerlist *peer_list; | ||
| 834 | 827 | ||
| 835 | if( !exactmatch ) { | 828 | if( !exactmatch ) { |
| 836 | if( is_tcp ) | 829 | if( is_tcp ) |
| @@ -842,33 +835,27 @@ size_t remove_peer_from_torrent( ot_hash *hash, ot_peer *peer, char *reply, int | |||
| 842 | return (size_t)20; | 835 | return (size_t)20; |
| 843 | } | 836 | } |
| 844 | 837 | ||
| 845 | for( peer_count = seed_count = index = 0; index<OT_POOLS_COUNT; ++index ) { | 838 | peer_list = torrent->peer_list; |
| 846 | peer_count += torrent->peer_list->peers[index].size; | 839 | for( index = 0; index<OT_POOLS_COUNT; ++index ) { |
| 847 | seed_count += torrent->peer_list->seed_count[index]; | 840 | switch( vector_remove_peer( &peer_list->peers[index], peer, index == 0 ) ) { |
| 848 | |||
| 849 | switch( vector_remove_peer( &torrent->peer_list->peers[index], peer, index == 0 ) ) { | ||
| 850 | case 0: continue; | 841 | case 0: continue; |
| 851 | case 2: torrent->peer_list->seed_count[index]--; | 842 | case 2: peer_list->seed_counts[index]--; |
| 852 | seed_count--; | 843 | peer_list->seed_count--; |
| 853 | case 1: default: | 844 | case 1: default: |
| 854 | peer_count--; | 845 | peer_list->peer_count--; |
| 855 | goto exit_loop; | 846 | goto exit_loop; |
| 856 | } | 847 | } |
| 857 | } | 848 | } |
| 858 | 849 | ||
| 859 | exit_loop: | 850 | exit_loop: |
| 860 | for( ++index; index < OT_POOLS_COUNT; ++index ) { | ||
| 861 | peer_count += torrent->peer_list->peers[index].size; | ||
| 862 | seed_count += torrent->peer_list->seed_count[index]; | ||
| 863 | } | ||
| 864 | 851 | ||
| 865 | if( is_tcp ) | 852 | if( is_tcp ) |
| 866 | return sprintf( reply, "d8:completei%zde10:incompletei%zde8:intervali%ie5:peers0:e", seed_count, peer_count - seed_count, OT_CLIENT_REQUEST_INTERVAL_RANDOM ); | 853 | return sprintf( reply, "d8:completei%zde10:incompletei%zde8:intervali%ie5:peers0:e", peer_list->seed_count, peer_list->peer_count - peer_list->seed_count, OT_CLIENT_REQUEST_INTERVAL_RANDOM ); |
| 867 | 854 | ||
| 868 | /* else { Handle UDP reply */ | 855 | /* else { Handle UDP reply */ |
| 869 | ((ot_dword*)reply)[2] = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM ); | 856 | ((ot_dword*)reply)[2] = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM ); |
| 870 | ((ot_dword*)reply)[3] = peer_count - seed_count; | 857 | ((ot_dword*)reply)[3] = peer_list->peer_count - peer_list->seed_count; |
| 871 | ((ot_dword*)reply)[4] = seed_count; | 858 | ((ot_dword*)reply)[4] = peer_list->seed_count; |
| 872 | return (size_t)20; | 859 | return (size_t)20; |
| 873 | } | 860 | } |
| 874 | 861 | ||
| @@ -893,7 +880,7 @@ void deinit_logic( void ) { | |||
| 893 | size_t j; | 880 | size_t j; |
| 894 | 881 | ||
| 895 | /* Free all torrents... */ | 882 | /* Free all torrents... */ |
| 896 | for(i=0; i<256; ++i ) { | 883 | for(i=0; i<OT_BUCKET_COUNT; ++i ) { |
| 897 | if( all_torrents[i].size ) { | 884 | if( all_torrents[i].size ) { |
| 898 | ot_torrent *torrents_list = (ot_torrent*)all_torrents[i].data; | 885 | ot_torrent *torrents_list = (ot_torrent*)all_torrents[i].data; |
| 899 | for( j=0; j<all_torrents[i].size; ++j ) | 886 | for( j=0; j<all_torrents[i].size; ++j ) |
| @@ -902,6 +889,7 @@ void deinit_logic( void ) { | |||
| 902 | } | 889 | } |
| 903 | } | 890 | } |
| 904 | byte_zero( all_torrents, sizeof (all_torrents)); | 891 | byte_zero( all_torrents, sizeof (all_torrents)); |
| 892 | byte_zero( all_torrents_clean, sizeof (all_torrents_clean)); | ||
| 905 | byte_zero( &changeset, sizeof( changeset ) ); | 893 | byte_zero( &changeset, sizeof( changeset ) ); |
| 906 | changeset_size = 0; | 894 | changeset_size = 0; |
| 907 | } | 895 | } |
diff --git a/trackerlogic.h b/trackerlogic.h index 96b59f3..fd8f48a 100644 --- a/trackerlogic.h +++ b/trackerlogic.h | |||
| @@ -20,6 +20,16 @@ typedef ot_byte ot_hash[20]; | |||
| 20 | typedef ot_dword ot_ip; | 20 | typedef ot_dword ot_ip; |
| 21 | typedef time_t ot_time; | 21 | typedef time_t ot_time; |
| 22 | 22 | ||
| 23 | #define OT_VECTOR_MIN_MEMBERS 4 | ||
| 24 | #define OT_VECTOR_GROW_RATIO 8 | ||
| 25 | #define OT_VECTOR_SHRINK_THRESH 6 | ||
| 26 | #define OT_VECTOR_SHRINK_RATIO 4 | ||
| 27 | typedef struct { | ||
| 28 | void *data; | ||
| 29 | size_t size; | ||
| 30 | size_t space; | ||
| 31 | } ot_vector; | ||
| 32 | |||
| 23 | /* Some tracker behaviour tunable */ | 33 | /* Some tracker behaviour tunable */ |
| 24 | #define OT_CLIENT_TIMEOUT 30 | 34 | #define OT_CLIENT_TIMEOUT 30 |
| 25 | #define OT_CLIENT_TIMEOUT_CHECKINTERVAL 10 | 35 | #define OT_CLIENT_TIMEOUT_CHECKINTERVAL 10 |
| @@ -32,8 +42,13 @@ typedef time_t ot_time; | |||
| 32 | 42 | ||
| 33 | #define OT_CLIENT_REQUEST_INTERVAL_RANDOM ( OT_CLIENT_REQUEST_INTERVAL - OT_CLIENT_REQUEST_VARIATION/2 + (int)( random( ) % OT_CLIENT_REQUEST_VARIATION ) ) | 43 | #define OT_CLIENT_REQUEST_INTERVAL_RANDOM ( OT_CLIENT_REQUEST_INTERVAL - OT_CLIENT_REQUEST_VARIATION/2 + (int)( random( ) % OT_CLIENT_REQUEST_VARIATION ) ) |
| 34 | 44 | ||
| 35 | /* We maintain a list of 256 pointers to sorted list of ot_torrent structs | 45 | /* We maintain a list of 4096 pointers to sorted list of ot_torrent structs |
| 36 | Sort key is, of course, its hash */ | 46 | Sort key is, of course, its hash */ |
| 47 | #define OT_BUCKET_COUNT 1024 | ||
| 48 | static inline ot_vector *hash_to_bucket( ot_vector *vectors, ot_hash *hash ) { | ||
| 49 | unsigned char *local_hash = hash[0]; | ||
| 50 | return vectors + ( ( local_hash[0] << 2 ) | ( local_hash[1] >> 6 ) ); | ||
| 51 | } | ||
| 37 | 52 | ||
| 38 | /* This list points to 9 pools of peers each grouped in five-minute-intervals | 53 | /* This list points to 9 pools of peers each grouped in five-minute-intervals |
| 39 | thus achieving a timeout of 2700s or 45 minutes | 54 | thus achieving a timeout of 2700s or 45 minutes |
| @@ -45,16 +60,6 @@ typedef time_t ot_time; | |||
| 45 | extern time_t g_now; | 60 | extern time_t g_now; |
| 46 | #define NOW (g_now/OT_POOLS_TIMEOUT) | 61 | #define NOW (g_now/OT_POOLS_TIMEOUT) |
| 47 | 62 | ||
| 48 | #define OT_VECTOR_MIN_MEMBERS 4 | ||
| 49 | #define OT_VECTOR_GROW_RATIO 8 | ||
| 50 | #define OT_VECTOR_SHRINK_THRESH 6 | ||
| 51 | #define OT_VECTOR_SHRINK_RATIO 4 | ||
| 52 | typedef struct { | ||
| 53 | void *data; | ||
| 54 | size_t size; | ||
| 55 | size_t space; | ||
| 56 | } ot_vector; | ||
| 57 | |||
| 58 | typedef struct { | 63 | typedef struct { |
| 59 | ot_byte data[8]; | 64 | ot_byte data[8]; |
| 60 | } ot_peer; | 65 | } ot_peer; |
| @@ -71,8 +76,10 @@ static const ot_byte PEER_FLAG_STOPPED = 0x20; | |||
| 71 | 76 | ||
| 72 | typedef struct { | 77 | typedef struct { |
| 73 | ot_time base; | 78 | ot_time base; |
| 74 | size_t seed_count[ OT_POOLS_COUNT ]; | 79 | size_t seed_count; |
| 75 | size_t downloaded; | 80 | size_t peer_count; |
| 81 | size_t down_count; | ||
| 82 | size_t seed_counts[ OT_POOLS_COUNT ]; | ||
| 76 | ot_vector peers[ OT_POOLS_COUNT ]; | 83 | ot_vector peers[ OT_POOLS_COUNT ]; |
| 77 | } ot_peerlist; | 84 | } ot_peerlist; |
| 78 | 85 | ||
| @@ -100,9 +107,12 @@ size_t return_stats_for_tracker( char *reply, int mode ); | |||
| 100 | size_t return_stats_for_slash24s( char *reply, size_t amount, ot_dword thresh ); | 107 | size_t return_stats_for_slash24s( char *reply, size_t amount, ot_dword thresh ); |
| 101 | size_t return_stats_for_slash24s_old( char *reply, size_t amount, ot_dword thresh ); | 108 | size_t return_stats_for_slash24s_old( char *reply, size_t amount, ot_dword thresh ); |
| 102 | size_t return_memstat_for_tracker( char **reply ); | 109 | size_t return_memstat_for_tracker( char **reply ); |
| 110 | void clean_all_torrents( void ); | ||
| 111 | |||
| 112 | #ifdef WANT_TRACKER_SYNC | ||
| 103 | size_t return_changeset_for_tracker( char **reply ); | 113 | size_t return_changeset_for_tracker( char **reply ); |
| 104 | int add_changeset_to_tracker( ot_byte *data, size_t len ); | 114 | int add_changeset_to_tracker( ot_byte *data, size_t len ); |
| 105 | void clean_all_torrents( void ); | 115 | #endif |
| 106 | 116 | ||
| 107 | #if defined ( WANT_BLACKLISTING ) || defined ( WANT_CLOSED_TRACKER ) | 117 | #if defined ( WANT_BLACKLISTING ) || defined ( WANT_CLOSED_TRACKER ) |
| 108 | int accesslist_addentry( ot_hash *hash ); | 118 | int accesslist_addentry( ot_hash *hash ); |
