summaryrefslogtreecommitdiff
path: root/trackerlogic.c
diff options
context:
space:
mode:
Diffstat (limited to 'trackerlogic.c')
-rw-r--r--trackerlogic.c89
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 */
29size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto );
30
28void free_peerlist( ot_peerlist *peer_list ) { 31void 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;
43extern char *g_this_peerid_data; 46extern char *g_this_peerid_data;
44#endif 47#endif
45 48
46ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer WANT_SYNC_PARAM( int from_sync ) ) { 49size_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
154static size_t return_peers_all( ot_peerlist *peer_list, char *reply ) { 160static 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*/
227size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ) { 230size_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 */
259size_t return_udp_scrape_for_torrent( ot_hash *hash, char *reply ) { 261size_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 */
283size_t return_tcp_scrape_for_torrent( ot_hash *hash_list, int amount, char *reply ) { 286size_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
358int trackerlogic_init( const char * const serverdir ) { 363void 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
378void trackerlogic_deinit( void ) { 376void 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 */