diff options
Diffstat (limited to 'trackerlogic.c')
-rw-r--r-- | trackerlogic.c | 89 |
1 files changed, 44 insertions, 45 deletions
diff --git a/trackerlogic.c b/trackerlogic.c index 34a12e7..38be9f7 100644 --- a/trackerlogic.c +++ b/trackerlogic.c | |||
@@ -25,6 +25,9 @@ | |||
25 | #include "ot_fullscrape.h" | 25 | #include "ot_fullscrape.h" |
26 | #include "ot_livesync.h" | 26 | #include "ot_livesync.h" |
27 | 27 | ||
28 | /* Forward declaration */ | ||
29 | size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ); | ||
30 | |||
28 | void free_peerlist( ot_peerlist *peer_list ) { | 31 | void free_peerlist( ot_peerlist *peer_list ) { |
29 | if( peer_list->peers.data ) { | 32 | if( peer_list->peers.data ) { |
30 | if( OT_PEERLIST_HASBUCKETS( peer_list ) ) { | 33 | if( OT_PEERLIST_HASBUCKETS( peer_list ) ) { |
@@ -43,34 +46,36 @@ extern size_t g_this_peerid_len; | |||
43 | extern char *g_this_peerid_data; | 46 | extern char *g_this_peerid_data; |
44 | #endif | 47 | #endif |
45 | 48 | ||
46 | ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer WANT_SYNC_PARAM( int from_sync ) ) { | 49 | size_t add_peer_to_torrent_and_return_peers( ot_hash *hash, ot_peer *peer, PROTO_FLAG proto, size_t amount, char * reply ) { |
47 | int exactmatch; | 50 | int exactmatch, delta_torrentcount = 0; |
51 | size_t reply_size; | ||
48 | ot_torrent *torrent; | 52 | ot_torrent *torrent; |
49 | ot_peer *peer_dest; | 53 | ot_peer *peer_dest; |
50 | ot_vector *torrents_list = mutex_bucket_lock_by_hash( hash ); | 54 | ot_vector *torrents_list = mutex_bucket_lock_by_hash( hash ); |
51 | 55 | ||
52 | if( !accesslist_hashisvalid( hash ) ) { | 56 | if( !accesslist_hashisvalid( hash ) ) { |
53 | mutex_bucket_unlock_by_hash( hash ); | 57 | mutex_bucket_unlock_by_hash( hash, 0 ); |
54 | return NULL; | 58 | return 0; |
55 | } | 59 | } |
56 | 60 | ||
57 | torrent = vector_find_or_insert( torrents_list, (void*)hash, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); | 61 | torrent = vector_find_or_insert( torrents_list, (void*)hash, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); |
58 | if( !torrent ) { | 62 | if( !torrent ) { |
59 | mutex_bucket_unlock_by_hash( hash ); | 63 | mutex_bucket_unlock_by_hash( hash, 0 ); |
60 | return NULL; | 64 | return 0; |
61 | } | 65 | } |
62 | 66 | ||
63 | if( !exactmatch ) { | 67 | if( !exactmatch ) { |
64 | /* Create a new torrent entry, then */ | 68 | /* Create a new torrent entry, then */ |
65 | int i; for(i=0;i<20;i+=4) WRITE32(&torrent->hash,i,READ32(hash,i)); | 69 | int i; for(i=0;i<20;i+=4) WRITE32(&torrent->hash,i,READ32(hash,i)); |
66 | 70 | ||
67 | if( !( torrent->peer_list = malloc( sizeof (ot_peerlist) ) ) ) { | 71 | if( !( torrent->peer_list = malloc( sizeof (ot_peerlist) ) ) ) { |
68 | vector_remove_torrent( torrents_list, torrent ); | 72 | vector_remove_torrent( torrents_list, torrent ); |
69 | mutex_bucket_unlock_by_hash( hash ); | 73 | mutex_bucket_unlock_by_hash( hash, 0 ); |
70 | return NULL; | 74 | return 0; |
71 | } | 75 | } |
72 | 76 | ||
73 | byte_zero( torrent->peer_list, sizeof( ot_peerlist ) ); | 77 | byte_zero( torrent->peer_list, sizeof( ot_peerlist ) ); |
78 | delta_torrentcount = 1; | ||
74 | } else | 79 | } else |
75 | clean_single_torrent( torrent ); | 80 | clean_single_torrent( torrent ); |
76 | 81 | ||
@@ -79,8 +84,8 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer WANT_SYNC_PARAM( | |||
79 | /* Check for peer in torrent */ | 84 | /* Check for peer in torrent */ |
80 | peer_dest = vector_find_or_insert_peer( &(torrent->peer_list->peers), peer, &exactmatch ); | 85 | peer_dest = vector_find_or_insert_peer( &(torrent->peer_list->peers), peer, &exactmatch ); |
81 | if( !peer_dest ) { | 86 | if( !peer_dest ) { |
82 | mutex_bucket_unlock_by_hash( hash ); | 87 | mutex_bucket_unlock_by_hash( hash, delta_torrentcount ); |
83 | return NULL; | 88 | return 0; |
84 | } | 89 | } |
85 | 90 | ||
86 | /* Tell peer that it's fresh */ | 91 | /* Tell peer that it's fresh */ |
@@ -94,7 +99,7 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer WANT_SYNC_PARAM( | |||
94 | if( !exactmatch ) { | 99 | if( !exactmatch ) { |
95 | 100 | ||
96 | #ifdef WANT_SYNC_LIVE | 101 | #ifdef WANT_SYNC_LIVE |
97 | if( !from_sync ) | 102 | if( proto == FLAG_MCA ) |
98 | livesync_tell( hash, peer ); | 103 | livesync_tell( hash, peer ); |
99 | else | 104 | else |
100 | OT_PEERFLAG( peer ) |= PEER_FLAG_FROM_SYNC; | 105 | OT_PEERFLAG( peer ) |= PEER_FLAG_FROM_SYNC; |
@@ -118,17 +123,17 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer WANT_SYNC_PARAM( | |||
118 | printf( " %d.%d.%d.%d:%d\t%d %02X %s\n", _ip[0], _ip[1], _ip[2], _ip[3], OT_PEERTIME( peer_dest ), *(uint16_t*)( ((char*)peer_dest)+4 ), OT_PEERFLAG(peer_dest), g_this_peerid_data ? g_this_peerid_data : "-" ); | 123 | printf( " %d.%d.%d.%d:%d\t%d %02X %s\n", _ip[0], _ip[1], _ip[2], _ip[3], OT_PEERTIME( peer_dest ), *(uint16_t*)( ((char*)peer_dest)+4 ), OT_PEERFLAG(peer_dest), g_this_peerid_data ? g_this_peerid_data : "-" ); |
119 | } | 124 | } |
120 | #endif | 125 | #endif |
121 | 126 | ||
122 | #ifdef WANT_SYNC_LIVE | 127 | #ifdef WANT_SYNC_LIVE |
123 | /* Won't live sync peers that come back too fast. Only exception: | 128 | /* Won't live sync peers that come back too fast. Only exception: |
124 | fresh "completed" reports */ | 129 | fresh "completed" reports */ |
125 | if( !from_sync ) { | 130 | if( proto != FLAG_MCA ) { |
126 | if( OT_PEERTIME( peer_dest ) > OT_CLIENT_SYNC_RENEW_BOUNDARY || | 131 | if( OT_PEERTIME( peer_dest ) > OT_CLIENT_SYNC_RENEW_BOUNDARY || |
127 | ( !(OT_PEERFLAG(peer_dest) & PEER_FLAG_COMPLETED ) && (OT_PEERFLAG(peer) & PEER_FLAG_COMPLETED ) ) ) | 132 | ( !(OT_PEERFLAG(peer_dest) & PEER_FLAG_COMPLETED ) && (OT_PEERFLAG(peer) & PEER_FLAG_COMPLETED ) ) ) |
128 | livesync_tell( hash, peer ); | 133 | livesync_tell( hash, peer ); |
129 | } | 134 | } |
130 | #endif | 135 | #endif |
131 | 136 | ||
132 | if( (OT_PEERFLAG(peer_dest) & PEER_FLAG_SEEDING ) && !(OT_PEERFLAG(peer) & PEER_FLAG_SEEDING ) ) | 137 | if( (OT_PEERFLAG(peer_dest) & PEER_FLAG_SEEDING ) && !(OT_PEERFLAG(peer) & PEER_FLAG_SEEDING ) ) |
133 | torrent->peer_list->seed_count--; | 138 | torrent->peer_list->seed_count--; |
134 | if( !(OT_PEERFLAG(peer_dest) & PEER_FLAG_SEEDING ) && (OT_PEERFLAG(peer) & PEER_FLAG_SEEDING ) ) | 139 | if( !(OT_PEERFLAG(peer_dest) & PEER_FLAG_SEEDING ) && (OT_PEERFLAG(peer) & PEER_FLAG_SEEDING ) ) |
@@ -141,14 +146,15 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer WANT_SYNC_PARAM( | |||
141 | 146 | ||
142 | *(uint64_t*)(peer_dest) = *(uint64_t*)(peer); | 147 | *(uint64_t*)(peer_dest) = *(uint64_t*)(peer); |
143 | #ifdef WANT_SYNC | 148 | #ifdef WANT_SYNC |
144 | /* In order to avoid an unlock/lock between add_peers and return_peers, | 149 | if( proto == FLAG_MCA ) { |
145 | we only unlock the bucket if return_peers won't do the job: either | 150 | mutex_bucket_unlock_by_hash( hash, delta_torrentcount ); |
146 | if we return NULL or if no reply is expected, i.e. when called | 151 | return 0; |
147 | from livesync code. */ | 152 | } |
148 | if( from_sync ) | ||
149 | mutex_bucket_unlock_by_hash( hash ); | ||
150 | #endif | 153 | #endif |
151 | return torrent; | 154 | |
155 | reply_size = return_peers_for_torrent( torrent, amount, reply, proto ); | ||
156 | mutex_bucket_unlock_by_hash( &torrent->hash, delta_torrentcount ); | ||
157 | return reply_size; | ||
152 | } | 158 | } |
153 | 159 | ||
154 | static size_t return_peers_all( ot_peerlist *peer_list, char *reply ) { | 160 | static size_t return_peers_all( ot_peerlist *peer_list, char *reply ) { |
@@ -186,7 +192,7 @@ static size_t return_peers_selection( ot_peerlist *peer_list, size_t amount, cha | |||
186 | num_buckets = bucket_list->size; | 192 | num_buckets = bucket_list->size; |
187 | bucket_list = (ot_vector *)bucket_list->data; | 193 | bucket_list = (ot_vector *)bucket_list->data; |
188 | } | 194 | } |
189 | 195 | ||
190 | /* Make fixpoint arithmetic as exact as possible */ | 196 | /* Make fixpoint arithmetic as exact as possible */ |
191 | #define MAXPRECBIT (1<<(8*sizeof(int)-3)) | 197 | #define MAXPRECBIT (1<<(8*sizeof(int)-3)) |
192 | while( !(shifted_pc & MAXPRECBIT ) ) { shifted_pc <<= 1; shift++; } | 198 | while( !(shifted_pc & MAXPRECBIT ) ) { shifted_pc <<= 1; shift++; } |
@@ -220,9 +226,6 @@ static size_t return_peers_selection( ot_peerlist *peer_list, size_t amount, cha | |||
220 | /* Compiles a list of random peers for a torrent | 226 | /* Compiles a list of random peers for a torrent |
221 | * reply must have enough space to hold 92+6*amount bytes | 227 | * reply must have enough space to hold 92+6*amount bytes |
222 | * does not yet check not to return self | 228 | * does not yet check not to return self |
223 | * the bucket, torrent resides in has been locked by the | ||
224 | add_peer call, the ot_torrent * was gathered from, so we | ||
225 | have to unlock it here. | ||
226 | */ | 229 | */ |
227 | size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ) { | 230 | size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ) { |
228 | ot_peerlist *peer_list = torrent->peer_list; | 231 | ot_peerlist *peer_list = torrent->peer_list; |
@@ -230,7 +233,7 @@ size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply | |||
230 | 233 | ||
231 | if( amount > peer_list->peer_count ) | 234 | if( amount > peer_list->peer_count ) |
232 | amount = peer_list->peer_count; | 235 | amount = peer_list->peer_count; |
233 | 236 | ||
234 | if( proto == FLAG_TCP ) { | 237 | if( proto == FLAG_TCP ) { |
235 | int erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM; | 238 | int erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM; |
236 | r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zde8:intervali%ie12:min intervali%ie5:peers%zd:", peer_list->seed_count, peer_list->down_count, peer_list->peer_count-peer_list->seed_count, erval, erval/2, 6*amount ); | 239 | r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zde8:intervali%ie12:min intervali%ie5:peers%zd:", peer_list->seed_count, peer_list->down_count, peer_list->peer_count-peer_list->seed_count, erval, erval/2, 6*amount ); |
@@ -251,13 +254,12 @@ size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply | |||
251 | if( proto == FLAG_TCP ) | 254 | if( proto == FLAG_TCP ) |
252 | *r++ = 'e'; | 255 | *r++ = 'e'; |
253 | 256 | ||
254 | mutex_bucket_unlock_by_hash( &torrent->hash ); | ||
255 | return r - reply; | 257 | return r - reply; |
256 | } | 258 | } |
257 | 259 | ||
258 | /* Fetches scrape info for a specific torrent */ | 260 | /* Fetches scrape info for a specific torrent */ |
259 | size_t return_udp_scrape_for_torrent( ot_hash *hash, char *reply ) { | 261 | size_t return_udp_scrape_for_torrent( ot_hash *hash, char *reply ) { |
260 | int exactmatch; | 262 | int exactmatch, delta_torrentcount = 0; |
261 | ot_vector *torrents_list = mutex_bucket_lock_by_hash( hash ); | 263 | ot_vector *torrents_list = mutex_bucket_lock_by_hash( hash ); |
262 | ot_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); | 264 | ot_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); |
263 | 265 | ||
@@ -269,20 +271,22 @@ size_t return_udp_scrape_for_torrent( ot_hash *hash, char *reply ) { | |||
269 | if( clean_single_torrent( torrent ) ) { | 271 | if( clean_single_torrent( torrent ) ) { |
270 | vector_remove_torrent( torrents_list, torrent ); | 272 | vector_remove_torrent( torrents_list, torrent ); |
271 | memset( reply, 0, 12); | 273 | memset( reply, 0, 12); |
274 | delta_torrentcount = -1; | ||
272 | } else { | 275 | } else { |
273 | r[0] = htonl( torrent->peer_list->seed_count ); | 276 | r[0] = htonl( torrent->peer_list->seed_count ); |
274 | r[1] = htonl( torrent->peer_list->down_count ); | 277 | r[1] = htonl( torrent->peer_list->down_count ); |
275 | r[2] = htonl( torrent->peer_list->peer_count-torrent->peer_list->seed_count ); | 278 | r[2] = htonl( torrent->peer_list->peer_count-torrent->peer_list->seed_count ); |
276 | } | 279 | } |
277 | } | 280 | } |
278 | mutex_bucket_unlock_by_hash( hash ); | 281 | mutex_bucket_unlock_by_hash( hash, 0 ); |
279 | return 12; | 282 | return 12; |
280 | } | 283 | } |
281 | 284 | ||
282 | /* Fetches scrape info for a specific torrent */ | 285 | /* Fetches scrape info for a specific torrent */ |
283 | size_t return_tcp_scrape_for_torrent( ot_hash *hash_list, int amount, char *reply ) { | 286 | size_t return_tcp_scrape_for_torrent( ot_hash *hash_list, int amount, char *reply ) { |
284 | char *r = reply; | 287 | char *r = reply; |
285 | int exactmatch, i; | 288 | int exactmatch, i; |
289 | int delta_torrentcount = 0; | ||
286 | 290 | ||
287 | r += sprintf( r, "d5:filesd" ); | 291 | r += sprintf( r, "d5:filesd" ); |
288 | 292 | ||
@@ -294,6 +298,7 @@ size_t return_tcp_scrape_for_torrent( ot_hash *hash_list, int amount, char *repl | |||
294 | if( exactmatch ) { | 298 | if( exactmatch ) { |
295 | if( clean_single_torrent( torrent ) ) { | 299 | if( clean_single_torrent( torrent ) ) { |
296 | vector_remove_torrent( torrents_list, torrent ); | 300 | vector_remove_torrent( torrents_list, torrent ); |
301 | delta_torrentcount = -1; | ||
297 | } else { | 302 | } else { |
298 | int j; | 303 | int j; |
299 | *r++='2';*r++='0';*r++=':'; | 304 | *r++='2';*r++='0';*r++=':'; |
@@ -302,7 +307,7 @@ size_t return_tcp_scrape_for_torrent( ot_hash *hash_list, int amount, char *repl | |||
302 | torrent->peer_list->seed_count, torrent->peer_list->down_count, torrent->peer_list->peer_count-torrent->peer_list->seed_count ); | 307 | torrent->peer_list->seed_count, torrent->peer_list->down_count, torrent->peer_list->peer_count-torrent->peer_list->seed_count ); |
303 | } | 308 | } |
304 | } | 309 | } |
305 | mutex_bucket_unlock_by_hash( hash ); | 310 | mutex_bucket_unlock_by_hash( hash, delta_torrentcount ); |
306 | } | 311 | } |
307 | 312 | ||
308 | *r++ = 'e'; *r++ = 'e'; | 313 | *r++ = 'e'; *r++ = 'e'; |
@@ -337,7 +342,7 @@ size_t remove_peer_from_torrent( ot_hash *hash, ot_peer *peer, char *reply, PROT | |||
337 | int erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM; | 342 | int erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM; |
338 | reply_size = sprintf( reply, "d8:completei%zde10:incompletei%zde8:intervali%ie12:min intervali%ie5:peers0:e", peer_list->seed_count, peer_list->peer_count - peer_list->seed_count, erval, erval / 2 ); | 343 | reply_size = sprintf( reply, "d8:completei%zde10:incompletei%zde8:intervali%ie12:min intervali%ie5:peers0:e", peer_list->seed_count, peer_list->peer_count - peer_list->seed_count, erval, erval / 2 ); |
339 | } | 344 | } |
340 | 345 | ||
341 | /* Handle UDP reply */ | 346 | /* Handle UDP reply */ |
342 | if( proto == FLAG_UDP ) { | 347 | if( proto == FLAG_UDP ) { |
343 | ((uint32_t*)reply)[2] = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM ); | 348 | ((uint32_t*)reply)[2] = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM ); |
@@ -346,7 +351,7 @@ size_t remove_peer_from_torrent( ot_hash *hash, ot_peer *peer, char *reply, PROT | |||
346 | reply_size = 20; | 351 | reply_size = 20; |
347 | } | 352 | } |
348 | 353 | ||
349 | mutex_bucket_unlock_by_hash( hash ); | 354 | mutex_bucket_unlock_by_hash( hash, 0 ); |
350 | return reply_size; | 355 | return reply_size; |
351 | } | 356 | } |
352 | 357 | ||
@@ -355,12 +360,7 @@ void exerr( char * message ) { | |||
355 | exit( 111 ); | 360 | exit( 111 ); |
356 | } | 361 | } |
357 | 362 | ||
358 | int trackerlogic_init( const char * const serverdir ) { | 363 | void trackerlogic_init( ) { |
359 | if( serverdir && chdir( serverdir ) ) { | ||
360 | fprintf( stderr, "Could not chdir() to %s, because %s\n", serverdir, strerror(errno) ); | ||
361 | return -1; | ||
362 | } | ||
363 | |||
364 | srandom( time(NULL) ); | 364 | srandom( time(NULL) ); |
365 | g_tracker_id = random(); | 365 | g_tracker_id = random(); |
366 | 366 | ||
@@ -371,12 +371,10 @@ int trackerlogic_init( const char * const serverdir ) { | |||
371 | accesslist_init( ); | 371 | accesslist_init( ); |
372 | livesync_init( ); | 372 | livesync_init( ); |
373 | stats_init( ); | 373 | stats_init( ); |
374 | |||
375 | return 0; | ||
376 | } | 374 | } |
377 | 375 | ||
378 | void trackerlogic_deinit( void ) { | 376 | void trackerlogic_deinit( void ) { |
379 | int bucket; | 377 | int bucket, delta_torrentcount = 0; |
380 | size_t j; | 378 | size_t j; |
381 | 379 | ||
382 | /* Free all torrents... */ | 380 | /* Free all torrents... */ |
@@ -386,10 +384,11 @@ void trackerlogic_deinit( void ) { | |||
386 | for( j=0; j<torrents_list->size; ++j ) { | 384 | for( j=0; j<torrents_list->size; ++j ) { |
387 | ot_torrent *torrent = ((ot_torrent*)(torrents_list->data)) + j; | 385 | ot_torrent *torrent = ((ot_torrent*)(torrents_list->data)) + j; |
388 | free_peerlist( torrent->peer_list ); | 386 | free_peerlist( torrent->peer_list ); |
387 | delta_torrentcount -= 1; | ||
389 | } | 388 | } |
390 | free( torrents_list->data ); | 389 | free( torrents_list->data ); |
391 | } | 390 | } |
392 | mutex_bucket_unlock( bucket ); | 391 | mutex_bucket_unlock( bucket, delta_torrentcount ); |
393 | } | 392 | } |
394 | 393 | ||
395 | /* Deinitialise background worker threads */ | 394 | /* Deinitialise background worker threads */ |