summaryrefslogtreecommitdiff
path: root/trackerlogic.c
diff options
context:
space:
mode:
Diffstat (limited to 'trackerlogic.c')
-rw-r--r--trackerlogic.c125
1 files changed, 62 insertions, 63 deletions
diff --git a/trackerlogic.c b/trackerlogic.c
index 85e8156..2b8ffaf 100644
--- a/trackerlogic.c
+++ b/trackerlogic.c
@@ -22,8 +22,7 @@
22#include <sys/stat.h> 22#include <sys/stat.h>
23#endif 23#endif
24 24
25// GLOBAL VARIABLES 25/* GLOBAL VARIABLES */
26//
27static ot_vector all_torrents[256]; 26static ot_vector all_torrents[256];
28 27
29#ifdef WANT_CLOSED_TRACKER 28#ifdef WANT_CLOSED_TRACKER
@@ -36,36 +35,37 @@ int g_check_blacklist = 1;
36static ot_torrent* const OT_TORRENT_ON_BLACKLIST = (ot_torrent*)2; 35static ot_torrent* const OT_TORRENT_ON_BLACKLIST = (ot_torrent*)2;
37#endif 36#endif
38 37
39// This function gives us a binary search that returns a pointer, even if 38/* This function gives us a binary search that returns a pointer, even if
40// no exact match is found. In that case it sets exactmatch 0 and gives 39 no exact match is found. In that case it sets exactmatch 0 and gives
41// calling functions the chance to insert data 40 calling functions the chance to insert data
42// 41*/
43static void *binary_search( const void *key, const void *base, unsigned long member_count, const unsigned long member_size, 42static void *binary_search( const void * const key, const void * base, const size_t member_count, const size_t member_size,
44 int compare_size, int *exactmatch ) { 43 size_t compare_size, int *exactmatch ) {
44 size_t mc = member_count;
45 ot_byte *lookat = ((ot_byte*)base) + member_size * (member_count >> 1); 45 ot_byte *lookat = ((ot_byte*)base) + member_size * (member_count >> 1);
46 *exactmatch = 1; 46 *exactmatch = 1;
47 47
48 while( member_count ) { 48 while( mc ) {
49 int cmp = memcmp( lookat, key, compare_size); 49 int cmp = memcmp( lookat, key, compare_size);
50 if (cmp == 0) return (void *)lookat; 50 if (cmp == 0) return (void *)lookat;
51 if (cmp < 0) { 51 if (cmp < 0) {
52 base = (void*)(lookat + member_size); 52 base = (void*)(lookat + member_size);
53 --member_count; 53 --mc;
54 } 54 }
55 member_count >>= 1; 55 mc >>= 1;
56 lookat = ((ot_byte*)base) + member_size * (member_count >> 1); 56 lookat = ((ot_byte*)base) + member_size * (mc >> 1);
57 } 57 }
58 *exactmatch = 0; 58 *exactmatch = 0;
59 return (void*)lookat; 59 return (void*)lookat;
60} 60}
61 61
62// Converter function from memory to human readable hex strings 62/* Converter function from memory to human readable hex strings
63// * definitely not thread safe!!! 63 - definitely not thread safe!!!
64// 64*/
65char ths[2+2*20]="-";char*to_hex(ot_byte*s){char*m="0123456789ABCDEF";char*e=ths+41;char*t=ths+1;while(t<e){*t++=m[*s>>4];*t++=m[*s++&15];}*t=0;return ths+1;} 65char ths[2+2*20]="-";char*to_hex(ot_byte*s){char*m="0123456789ABCDEF";char*e=ths+41;char*t=ths+1;while(t<e){*t++=m[*s>>4];*t++=m[*s++&15];}*t=0;return ths+1;}
66 66
67static void *vector_find_or_insert( ot_vector *vector, void *key, size_t member_size, int compare_size, int *exactmatch ) { 67static void *vector_find_or_insert( ot_vector *vector, void *key, size_t member_size, int compare_size, int *exactmatch ) {
68 ot_byte *match = BINARY_FIND( key, vector->data, vector->size, member_size, compare_size, exactmatch ); 68 ot_byte *match = binary_search( key, vector->data, vector->size, member_size, compare_size, exactmatch );
69 69
70 if( *exactmatch ) return match; 70 if( *exactmatch ) return match;
71 71
@@ -74,13 +74,13 @@ static void *vector_find_or_insert( ot_vector *vector, void *key, size_t member_
74 ot_byte *new_data = realloc( vector->data, new_space * member_size ); 74 ot_byte *new_data = realloc( vector->data, new_space * member_size );
75 if( !new_data ) return NULL; 75 if( !new_data ) return NULL;
76 76
77 // Adjust pointer if it moved by realloc 77 /* Adjust pointer if it moved by realloc */
78 match = new_data + (match - (ot_byte*)vector->data); 78 match = new_data + (match - (ot_byte*)vector->data);
79 79
80 vector->data = new_data; 80 vector->data = new_data;
81 vector->space = new_space; 81 vector->space = new_space;
82 } 82 }
83 MEMMOVE( match + member_size, match, ((ot_byte*)vector->data) + member_size * vector->size - match ); 83 memmove( match + member_size, match, ((ot_byte*)vector->data) + member_size * vector->size - match );
84 vector->size++; 84 vector->size++;
85 return match; 85 return match;
86} 86}
@@ -91,11 +91,11 @@ static int vector_remove_peer( ot_vector *vector, ot_peer *peer ) {
91 ot_peer *match; 91 ot_peer *match;
92 92
93 if( !vector->size ) return 0; 93 if( !vector->size ) return 0;
94 match = BINARY_FIND( peer, vector->data, vector->size, sizeof( ot_peer ), OT_PEER_COMPARE_SIZE, &exactmatch ); 94 match = binary_search( peer, vector->data, vector->size, sizeof( ot_peer ), OT_PEER_COMPARE_SIZE, &exactmatch );
95 95
96 if( !exactmatch ) return 0; 96 if( !exactmatch ) return 0;
97 exactmatch = ( OT_FLAG( match ) & PEER_FLAG_SEEDING ) ? 2 : 1; 97 exactmatch = ( OT_FLAG( match ) & PEER_FLAG_SEEDING ) ? 2 : 1;
98 MEMMOVE( match, match + 1, sizeof(ot_peer) * ( end - match - 1 ) ); 98 memmove( match, match + 1, sizeof(ot_peer) * ( end - match - 1 ) );
99 if( ( --vector->size * OT_VECTOR_SHRINK_THRESH < vector->space ) && ( vector->space > OT_VECTOR_MIN_MEMBERS ) ) { 99 if( ( --vector->size * OT_VECTOR_SHRINK_THRESH < vector->space ) && ( vector->space > OT_VECTOR_MIN_MEMBERS ) ) {
100 vector->space /= OT_VECTOR_SHRINK_RATIO; 100 vector->space /= OT_VECTOR_SHRINK_RATIO;
101 vector->data = realloc( vector->data, vector->space * sizeof( ot_peer ) ); 101 vector->data = realloc( vector->data, vector->space * sizeof( ot_peer ) );
@@ -117,15 +117,15 @@ static int vector_remove_torrent( ot_vector *vector, ot_hash *hash ) {
117 ot_torrent *match; 117 ot_torrent *match;
118 118
119 if( !vector->size ) return 0; 119 if( !vector->size ) return 0;
120 match = BINARY_FIND( hash, vector->data, vector->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); 120 match = binary_search( hash, vector->data, vector->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
121 121
122 if( !exactmatch ) return 0; 122 if( !exactmatch ) return 0;
123 123
124 // If this is being called after a unsuccessful malloc() for peer_list 124 /* If this is being called after a unsuccessful malloc() for peer_list
125 // in add_peer_to_torrent, match->peer_list actually might be NULL 125 in add_peer_to_torrent, match->peer_list actually might be NULL */
126 if( match->peer_list) free_peerlist( match->peer_list ); 126 if( match->peer_list) free_peerlist( match->peer_list );
127 127
128 MEMMOVE( match, match + 1, sizeof(ot_torrent) * ( end - match - 1 ) ); 128 memmove( match, match + 1, sizeof(ot_torrent) * ( end - match - 1 ) );
129 if( ( --vector->size * OT_VECTOR_SHRINK_THRESH < vector->space ) && ( vector->space > OT_VECTOR_MIN_MEMBERS ) ) { 129 if( ( --vector->size * OT_VECTOR_SHRINK_THRESH < vector->space ) && ( vector->space > OT_VECTOR_MIN_MEMBERS ) ) {
130 vector->space /= OT_VECTOR_SHRINK_RATIO; 130 vector->space /= OT_VECTOR_SHRINK_RATIO;
131 vector->data = realloc( vector->data, vector->space * sizeof( ot_torrent ) ); 131 vector->data = realloc( vector->data, vector->space * sizeof( ot_torrent ) );
@@ -133,22 +133,21 @@ static int vector_remove_torrent( ot_vector *vector, ot_hash *hash ) {
133 return 1; 133 return 1;
134} 134}
135 135
136// Returns 1, if torrent is gone, 0 otherwise 136/* Returns 1, if torrent is gone, 0 otherwise */
137static int clean_peerlist( ot_peerlist *peer_list ) { 137static int clean_peerlist( ot_peerlist *peer_list ) {
138 long timedout = NOW-peer_list->base; 138 int i, timedout = (int)( NOW - peer_list->base );
139 int i;
140 139
141 if( !timedout ) return 0; 140 if( !timedout ) return 0;
142 if( timedout > OT_POOLS_COUNT ) timedout = OT_POOLS_COUNT; 141 if( timedout > OT_POOLS_COUNT ) timedout = OT_POOLS_COUNT;
143 142
144 for( i=OT_POOLS_COUNT-timedout; i<OT_POOLS_COUNT; ++i ) 143 for( i = OT_POOLS_COUNT - timedout; i < OT_POOLS_COUNT; ++i )
145 free( peer_list->peers[i].data); 144 free( peer_list->peers[i].data);
146 145
147 MEMMOVE( peer_list->peers + timedout, peer_list->peers, sizeof( ot_vector ) * (OT_POOLS_COUNT-timedout) ); 146 memmove( peer_list->peers + timedout, peer_list->peers, sizeof( ot_vector ) * (OT_POOLS_COUNT-timedout) );
148 byte_zero( peer_list->peers, sizeof( ot_vector ) * timedout ); 147 byte_zero( peer_list->peers, sizeof( ot_vector ) * timedout );
149 148
150 MEMMOVE( peer_list->seed_count + timedout, peer_list->seed_count, sizeof( unsigned long ) * (OT_POOLS_COUNT-timedout) ); 149 memmove( peer_list->seed_count + timedout, peer_list->seed_count, sizeof( size_t ) * ( OT_POOLS_COUNT - timedout) );
151 byte_zero( peer_list->seed_count, sizeof( unsigned long ) * timedout ); 150 byte_zero( peer_list->seed_count, sizeof( size_t ) * timedout );
152 151
153 peer_list->base = NOW; 152 peer_list->base = NOW;
154 return timedout == OT_POOLS_COUNT; 153 return timedout == OT_POOLS_COUNT;
@@ -178,8 +177,8 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) {
178 if( !torrent ) return NULL; 177 if( !torrent ) return NULL;
179 178
180 if( !exactmatch ) { 179 if( !exactmatch ) {
181 // Create a new torrent entry, then 180 /* Create a new torrent entry, then */
182 MEMMOVE( &torrent->hash, hash, sizeof( ot_hash ) ); 181 memmove( &torrent->hash, hash, sizeof( ot_hash ) );
183 182
184 torrent->peer_list = malloc( sizeof (ot_peerlist) ); 183 torrent->peer_list = malloc( sizeof (ot_peerlist) );
185 if( !torrent->peer_list ) { 184 if( !torrent->peer_list ) {
@@ -195,11 +194,11 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) {
195 peer_pool = &torrent->peer_list->peers[0]; 194 peer_pool = &torrent->peer_list->peers[0];
196 peer_dest = vector_find_or_insert( peer_pool, (void*)peer, sizeof( ot_peer ), OT_PEER_COMPARE_SIZE, &exactmatch ); 195 peer_dest = vector_find_or_insert( peer_pool, (void*)peer, sizeof( ot_peer ), OT_PEER_COMPARE_SIZE, &exactmatch );
197 196
198 // If we hadn't had a match in current pool, create peer there and 197 /* If we hadn't had a match in current pool, create peer there and
199 // remove it from all older pools 198 remove it from all older pools */
200 if( !exactmatch ) { 199 if( !exactmatch ) {
201 int i; 200 int i;
202 MEMMOVE( peer_dest, peer, sizeof( ot_peer ) ); 201 memmove( peer_dest, peer, sizeof( ot_peer ) );
203 if( OT_FLAG(peer) & PEER_FLAG_SEEDING ) 202 if( OT_FLAG(peer) & PEER_FLAG_SEEDING )
204 torrent->peer_list->seed_count[0]++; 203 torrent->peer_list->seed_count[0]++;
205 for( i=1; i<OT_POOLS_COUNT; ++i ) { 204 for( i=1; i<OT_POOLS_COUNT; ++i ) {
@@ -221,27 +220,30 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) {
221 return torrent; 220 return torrent;
222} 221}
223 222
224// Compiles a list of random peers for a torrent 223/* Compiles a list of random peers for a torrent
225// * reply must have enough space to hold 24+6*amount bytes 224 * reply must have enough space to hold 24+6*amount bytes
226// * Selector function can be anything, maybe test for seeds, etc. 225 * Selector function can be anything, maybe test for seeds, etc.
227// * RANDOM may return huge values 226 * RANDOM may return huge values
228// * does not yet check not to return self 227 * does not yet check not to return self
229// 228*/
230size_t return_peers_for_torrent( ot_torrent *torrent, unsigned long amount, char *reply ) { 229size_t return_peers_for_torrent( ot_torrent *torrent, unsigned int amount, char *reply ) {
231 char *r = reply; 230 char *r = reply;
232 unsigned long peer_count, seed_count, index; 231 unsigned int peer_count, seed_count, index;
233 signed long pool_offset = -1, pool_index = 0; 232 int pool_offset = -1, pool_index = 0, wert = -1;
234 signed long wert = -1;
235 233
236#ifdef WANT_CLOSED_TRACKER 234#ifdef WANT_CLOSED_TRACKER
237 if( torrent == OT_TORRENT_NOT_ON_WHITELIST ) { 235 if( torrent == OT_TORRENT_NOT_ON_WHITELIST ) {
238 return( FORMAT_FORMAT_STRING( reply, "d14:failure reason43:This torrent is not served by this tracker.e" ) ); 236 const char * const notvalid = "d14:failure reason43:This torrent is not served by this tracker.e";
237 memmove( reply, notvalid, sizeof(notvalid));
238 return sizeof(notvalid);
239 } 239 }
240#endif 240#endif
241 241
242#ifdef WANT_BLACKLIST 242#ifdef WANT_BLACKLIST
243 if( torrent == OT_TORRENT_ON_BLACKLIST ) { 243 if( torrent == OT_TORRENT_ON_BLACKLIST ) {
244 return( FORMAT_FORMAT_STRING( reply, "d14:failure reason29:This torrent is black listed.e" ) ); 244 const char * const blacklisted = "d14:failure reason29:This torrent is black listed.e";
245 memmove( reply, blacklisted, sizeof(blacklisted));
246 return sizeof(blacklisted);
245 } 247 }
246#endif 248#endif
247 249
@@ -251,23 +253,19 @@ size_t return_peers_for_torrent( ot_torrent *torrent, unsigned long amount, char
251 } 253 }
252 if( peer_count < amount ) amount = peer_count; 254 if( peer_count < amount ) amount = peer_count;
253 255
254 r += FORMAT_FORMAT_STRING( r, "d8:completei%lie10:incompletei%lie8:intervali600e5:peers%li:", seed_count, peer_count-seed_count, 6*amount ); 256 r += sprintf( r, "d8:completei%ie10:incompletei%ie8:intervali600e5:peers%i:", seed_count, peer_count-seed_count, 6*amount );
255 for( index = 0; index < amount; ++index ) { 257 for( index = 0; index < amount; ++index ) {
256 double step = 1.8*((double)( peer_count - wert - 1 ))/((double)( amount - index )); 258 double step = 1.8*((double)( peer_count - wert - 1 ))/((double)( amount - index ));
257 int off = random() % (int)floor( step ); 259 int off = random() % (int)floor( step );
258 off = 1 + ( off % ( peer_count - wert - 1 )); 260 off = 1 + ( off % ( peer_count - wert - 1 ));
259 wert += off; pool_offset += off; 261 wert += off; pool_offset += off;
260 262
261 // In some rare occasions random gets the last peer a round to early
262 // correct that and return last peer twice
263 // if( wert >= peer_count ) { wert--; pool_offset--; }
264
265 while( pool_offset >= torrent->peer_list->peers[pool_index].size ) { 263 while( pool_offset >= torrent->peer_list->peers[pool_index].size ) {
266 pool_offset -= torrent->peer_list->peers[pool_index].size; 264 pool_offset -= torrent->peer_list->peers[pool_index].size;
267 pool_index++; 265 pool_index++;
268 } 266 }
269 267
270 MEMMOVE( r, ((ot_peer*)torrent->peer_list->peers[pool_index].data) + pool_offset, 6 ); 268 memmove( r, ((ot_peer*)torrent->peer_list->peers[pool_index].data) + pool_offset, 6 );
271 r += 6; 269 r += 6;
272 } 270 }
273 *r++ = 'e'; 271 *r++ = 'e';
@@ -275,12 +273,12 @@ size_t return_peers_for_torrent( ot_torrent *torrent, unsigned long amount, char
275 return r - reply; 273 return r - reply;
276} 274}
277 275
278// Fetches scrape info for a specific torrent 276/* Fetches scrape info for a specific torrent */
279size_t return_scrape_for_torrent( ot_hash *hash, char *reply ) { 277size_t return_scrape_for_torrent( ot_hash *hash, char *reply ) {
280 char *r = reply; 278 char *r = reply;
281 int exactmatch, peers = 0, seeds = 0, i; 279 int exactmatch, peers = 0, seeds = 0, i;
282 ot_vector *torrents_list = &all_torrents[*hash[0]]; 280 ot_vector *torrents_list = &all_torrents[*hash[0]];
283 ot_torrent *torrent = BINARY_FIND( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); 281 ot_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
284 282
285 if( !exactmatch ) return 0; 283 if( !exactmatch ) return 0;
286 clean_peerlist( torrent->peer_list ); 284 clean_peerlist( torrent->peer_list );
@@ -290,8 +288,8 @@ size_t return_scrape_for_torrent( ot_hash *hash, char *reply ) {
290 seeds += torrent->peer_list->seed_count[i]; 288 seeds += torrent->peer_list->seed_count[i];
291 } 289 }
292 290
293 MEMMOVE( r, "d5:filesd20:", 12 ); MEMMOVE( r+12, hash, 20 ); 291 memmove( r, "d5:filesd20:", 12 ); memmove( r+12, hash, 20 );
294 r += FORMAT_FORMAT_STRING( r+32, "d8:completei%de10:downloadedi%lde10:incompletei%deeee", seeds, torrent->peer_list->downloaded, peers-seeds ) + 32; 292 r += sprintf( r+32, "d8:completei%de10:downloadedi%de10:incompletei%deeee", seeds, torrent->peer_list->downloaded, peers-seeds ) + 32;
295 293
296 return r - reply; 294 return r - reply;
297} 295}
@@ -299,11 +297,11 @@ size_t return_scrape_for_torrent( ot_hash *hash, char *reply ) {
299void remove_peer_from_torrent( ot_hash *hash, ot_peer *peer ) { 297void remove_peer_from_torrent( ot_hash *hash, ot_peer *peer ) {
300 int exactmatch, i; 298 int exactmatch, i;
301 ot_vector *torrents_list = &all_torrents[*hash[0]]; 299 ot_vector *torrents_list = &all_torrents[*hash[0]];
302 ot_torrent *torrent = BINARY_FIND( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); 300 ot_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
303 301
304 if( !exactmatch ) return; 302 if( !exactmatch ) return;
305 303
306 // Maybe this does the job 304 /* Maybe this does the job */
307 if( clean_peerlist( torrent->peer_list ) ) { 305 if( clean_peerlist( torrent->peer_list ) ) {
308#ifdef WANT_CLOSED_TRACKER 306#ifdef WANT_CLOSED_TRACKER
309 if( !g_closedtracker ) 307 if( !g_closedtracker )
@@ -332,7 +330,7 @@ int init_logic( char *serverdir ) {
332 330
333 srandom( time(NULL)); 331 srandom( time(NULL));
334 332
335 // Initialize control structures 333 /* Initialize control structures */
336 byte_zero( all_torrents, sizeof (all_torrents)); 334 byte_zero( all_torrents, sizeof (all_torrents));
337 335
338 return 0; 336 return 0;
@@ -340,7 +338,8 @@ int init_logic( char *serverdir ) {
340 338
341void deinit_logic( ) { 339void deinit_logic( ) {
342 int i, j; 340 int i, j;
343 // Free all torrents... 341
342 /* Free all torrents... */
344 for(i=0; i<256; ++i ) { 343 for(i=0; i<256; ++i ) {
345 if( all_torrents[i].size ) { 344 if( all_torrents[i].size ) {
346 ot_torrent *torrents_list = (ot_torrent*)all_torrents[i].data; 345 ot_torrent *torrents_list = (ot_torrent*)all_torrents[i].data;