summaryrefslogtreecommitdiff
path: root/trackerlogic.c
diff options
context:
space:
mode:
Diffstat (limited to 'trackerlogic.c')
-rw-r--r--trackerlogic.c177
1 files changed, 85 insertions, 92 deletions
diff --git a/trackerlogic.c b/trackerlogic.c
index 4587300..a19f9d4 100644
--- a/trackerlogic.c
+++ b/trackerlogic.c
@@ -1,6 +1,5 @@
1// THIS REALLY BELONGS INTO A HEADER FILE 1#include "trackerlogic.h"
2// 2
3//
4#include <stdlib.h> 3#include <stdlib.h>
5#include <string.h> 4#include <string.h>
6#include <stdio.h> 5#include <stdio.h>
@@ -9,77 +8,51 @@
9#include <sys/mman.h> 8#include <sys/mman.h>
10#include <unistd.h> 9#include <unistd.h>
11#include <time.h> 10#include <time.h>
11#include <glob.h>
12 12
13/* Should be called BYTE, WORD, DWORD - but some OSs already have that and there's no #iftypedef */ 13// Helper functions for binary_find
14/* They mark memory used as data instead of integer or human readable string -
15 they should be cast before used as integer/text */
16typedef unsigned char ot_byte;
17typedef unsigned short ot_word;
18typedef unsigned long ot_dword;
19
20typedef unsigned long ot_time;
21typedef ot_byte ot_hash[20];
22typedef ot_byte ot_ip[ 4/*0*/ ];
23// tunables
24const unsigned long OT_TIMEOUT = 2700;
25const unsigned long OT_HUGE_FILESIZE = 1024*1024*256; // Thats 256MB per file, enough for 204800 peers of 128 bytes
26
27#define OT_COMPACT_ONLY
28
29#define MEMMOVE memmove
30#define BZERO bzero
31#define FORMAT_FIXED_STRING sprintf
32#define FORMAT_FORMAT_STRING sprintf
33#define BINARY_FIND binary_search
34#define NOW time(NULL)
35
36typedef struct ot_peer {
37#ifndef OT_COMPACT_ONLY
38 ot_hash id;
39 ot_hash key;
40#endif
41 ot_ip ip;
42 ot_word port;
43 ot_time death;
44 ot_byte flags;
45} *ot_peer;
46ot_byte PEER_FLAG_SEEDING = 0x80;
47ot_byte PEER_IP_LENGTH_MASK = 0x3f;
48
49typedef struct {
50 ot_hash hash;
51 ot_peer peer_list;
52 unsigned long peer_count;
53 unsigned long seed_count;
54} *ot_torrent;
55
56void *map_file( char *file_name );
57void unmap_file( char *file_name, void *map, unsigned long real_size );
58
59// This behaves quite like bsearch but allows to find
60// the insertion point for inserts after unsuccessful searches
61// in this case exactmatch is 0 on exit
62// 14//
15int compare_hash( const void *hash1, const void *hash2 ) { return memcmp( hash1, hash2, sizeof( ot_hash )); }
16int compare_ip_port( const void *peer1, const void *peer2 ) { return memcmp( &((ot_peer)peer1)->ip, &((ot_peer)peer2)->ip, 6); }
17
63void *binary_search( const void *key, const void *base, 18void *binary_search( const void *key, const void *base,
64 const unsigned long member_count, const unsigned long member_size, 19 unsigned long member_count, const unsigned long member_size,
65 int (*compar) (const void *, const void *), 20 int (*compar) (const void *, const void *),
66 int *exactmatch ); 21 int *exactmatch ) {
22 ot_byte *lookat = ((ot_byte*)base) + member_size * (member_count >> 1);
23 *exactmatch = 1;
67 24
68int compare_hash( const void *hash1, const void *hash2 ) { return memcmp( hash1, hash2, sizeof( ot_hash )); } 25 while( member_count ) {
69int compare_ip_port( const void *peer1, const void *peer2 ) { return memcmp( peer1, peer2, 6); } 26 int cmp = compar((void*)lookat, key);
27 if (cmp == 0) return (void *)lookat;
28 if (cmp < 0) {
29 base = (void*)(lookat + member_size);
30 --member_count;
31 }
32 member_count >>= 1;
33 lookat = ((ot_byte*)base) + member_size * (member_count >> 1);
34 }
35 *exactmatch = 0;
36 return (void*)lookat;
70 37
38}
39
40// Converter function from memory to human readable hex strings
41// * definitely not thread safe!!!
71// 42//
72// 43char ths[1+2*20];char *to_hex(ot_byte*s){char*m="0123456789ABCDEF";char*e=ths+40;char*t=ths;while(t<e){*t++=m[*s>>4];*t++=m[*s++&15];}*t=0;return ths;}
73// END OF STUFF THAT BELONGS INTO A HEADER FILE
74 44
45// GLOBAL VARIABLES
46//
75unsigned long torrents_count = 0; 47unsigned long torrents_count = 0;
76ot_torrent torrents_list = 0; 48ot_torrent torrents_list = 0;
77ot_byte *scratch_space = 0; 49ot_byte *scratch_space = 0;
78 50
79// Converter function from memory to human readable hex strings 51#define SETINVALID( i ) (scratch_space[index] = 3);
80// * definitely not thread safe!!! 52#define SETSELECTED( i ) (scratch_space[index] = 1);
81// 53#define TESTSELECTED( i ) (scratch_space[index] == 1 )
82char ths[1+2*20];char *to_hex(ot_byte*s){char*m="0123456789ABCDEF";char*e=ths+40;char*t=ths;while(t<e){*t++=m[*s>>4];*t++=m[*s++&15];}*t=0;return ths;} 54#define TESTSET( i ) (scratch_space[index])
55#define RANDOM random()
83 56
84ot_torrent add_peer_to_torrent( ot_hash hash, ot_peer peer ) { 57ot_torrent add_peer_to_torrent( ot_hash hash, ot_peer peer ) {
85 ot_torrent torrent; 58 ot_torrent torrent;
@@ -122,12 +95,6 @@ ot_torrent add_peer_to_torrent( ot_hash hash, ot_peer peer ) {
122 return torrent; 95 return torrent;
123} 96}
124 97
125#define SETINVALID( i ) (scratch_space[index] = 3);
126#define SETSELECTED( i ) (scratch_space[index] = 1);
127#define TESTSELECTED( i ) (scratch_space[index] == 1 )
128#define TESTSET( i ) (scratch_space[index])
129#define RANDOM random()
130
131inline int TESTVALIDPEER( ot_peer p ) { return p->death > NOW; } 98inline int TESTVALIDPEER( ot_peer p ) { return p->death > NOW; }
132 99
133// Compiles a list of random peers for a torrent 100// Compiles a list of random peers for a torrent
@@ -249,30 +216,8 @@ void dispose_torrent( ot_torrent torrent ) {
249 torrents_count--; 216 torrents_count--;
250} 217}
251 218
252void *binary_search( const void *key, const void *base,
253 unsigned long member_count, const unsigned long member_size,
254 int (*compar) (const void *, const void *),
255 int *exactmatch ) {
256 ot_byte *lookat = ((ot_byte*)base) + member_size * (member_count >> 1);
257 *exactmatch = 1;
258
259 while( member_count ) {
260 int cmp = compar((void*)lookat, key);
261 if (cmp == 0) return (void *)lookat;
262 if (cmp < 0) {
263 base = (void*)(lookat + member_size);
264 --member_count;
265 }
266 member_count >>= 1;
267 lookat = ((ot_byte*)base) + member_size * (member_count >> 1);
268 }
269 *exactmatch = 0;
270 return (void*)lookat;
271
272}
273
274// This function maps a "huge" file into process space 219// This function maps a "huge" file into process space
275// * no name will aqcuire anonymous growable memory 220// * giving no name will aqcuire anonymous growable memory
276// * memory will not be "freed" from systems vm if once used, until unmap_file 221// * memory will not be "freed" from systems vm if once used, until unmap_file
277// * I guess, we should be checking for more errors... 222// * I guess, we should be checking for more errors...
278// 223//
@@ -281,6 +226,8 @@ void *map_file( char *file_name ) {
281 if( file_name ) { 226 if( file_name ) {
282 int file_desc=open(file_name,O_RDWR|O_CREAT|O_NDELAY,0644); 227 int file_desc=open(file_name,O_RDWR|O_CREAT|O_NDELAY,0644);
283 if( file_desc < 0) return 0; 228 if( file_desc < 0) return 0;
229 lseek( file_desc, OT_HUGE_FILESIZE, SEEK_SET );
230
284 map=mmap(0,OT_HUGE_FILESIZE,PROT_READ|PROT_WRITE,MAP_SHARED,file_desc,0); 231 map=mmap(0,OT_HUGE_FILESIZE,PROT_READ|PROT_WRITE,MAP_SHARED,file_desc,0);
285 close(file_desc); 232 close(file_desc);
286 } else 233 } else
@@ -295,14 +242,60 @@ void unmap_file( char *file_name, void *map, unsigned long real_size ) {
295 truncate( file_name, real_size ); 242 truncate( file_name, real_size );
296} 243}
297 244
245void count_peers_and_seeds( ot_peer peer_list, unsigned long *peers, unsigned long *seeds ) {
246 *peers = *seeds = 0;
247 if( peer_list[*peers].ip )
248 do {
249 *seeds += peer_list[*peers++].flags & PEER_FLAG_SEEDING ? 1 : 0;
250 } while( compare_ip_port( peer_list + *peers, peer_list + *peers - 1 ) < 0 );
251}
252
298int init_logic( ) { 253int init_logic( ) {
254 glob_t globber;
255 int i;
256
299 scratch_space = map_file( "" ); 257 scratch_space = map_file( "" );
300 torrents_list = map_file( "" ); 258 torrents_list = map_file( "" );
301 torrents_count = 0; 259 torrents_count = 0;
302 260
261 if( !scratch_space || !torrents_list ) {
262 if( scratch_space || torrents_list )
263 unmap_file( "", scratch_space ? (void*)scratch_space : (void*)torrents_list, 0 );
264 return -1;
265 }
266
303 // Scan directory for filenames in the form [0-9A-F]{20} 267 // Scan directory for filenames in the form [0-9A-F]{20}
304 // ... 268 // * I know this looks ugly, but I've seen A-F to match umlauts as well in strange locales
269 // * lower case for .. better being safe than sorry, this is not expansive here :)
270 if( !glob(
271 "[0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef]"
272 "[0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef]"
273 "[0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef]"
274 "[0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef]"
275 "[0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef]"
276 "[0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef]"
277 "[0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef]"
278 "[0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef]"
279 "[0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef]"
280 "[0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef]"
281 , GLOB_NOCHECK, 0, &globber) )
282 {
283 for( i=0; i<globber.gl_matchc; ++i ) {
284#ifdef _DEBUG
285 printf( "Found dir: %s\n", globber.gl_pathv[i] );
286#endif
287
288 if( ( torrents_list[torrents_count].peer_list = map_file( globber.gl_pathv[i] ) ) ) {
289 MEMMOVE( &torrents_list[torrents_count].hash, globber.gl_pathv[i], sizeof( ot_hash ) );
290 count_peers_and_seeds( torrents_list[torrents_count].peer_list,
291 &torrents_list[torrents_count].peer_count,
292 &torrents_list[torrents_count].seed_count );
293 torrents_count++;
294 }
295 }
296 }
305 297
298 globfree( &globber );
306 return 0; 299 return 0;
307} 300}
308 301